1 /***************************************************************************
3 * Copyright (C) 2017 by Bohdan Tymkiv *
4 * bohdan.tymkiv@cypress.com bohdan200@gmail.com *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 ***************************************************************************/
27 #include "target/target.h"
28 #include "target/cortex_m.h"
29 #include "target/breakpoints.h"
30 #include "target/target_type.h"
31 #include "time_support.h"
32 #include "target/algorithm.h"
34 /**************************************************************************************************
35 * PSoC6 device definitions
36 *************************************************************************************************/
37 #define MFLASH_SECTOR_SIZE (256u * 1024u)
38 #define WFLASH_SECTOR_SIZE (32u * 1024u)
40 #define MEM_BASE_MFLASH 0x10000000u
41 #define MEM_BASE_WFLASH 0x14000000u
42 #define MEM_WFLASH_SIZE 32768u
43 #define MEM_BASE_SFLASH 0x16000000u
44 #define RAM_STACK_WA_SIZE 2048u
45 #define PSOC6_SPCIF_GEOMETRY 0x4025F00Cu
47 #define PROTECTION_UNKNOWN 0x00u
48 #define PROTECTION_VIRGIN 0x01u
49 #define PROTECTION_NORMAL 0x02u
50 #define PROTECTION_SECURE 0x03u
51 #define PROTECTION_DEAD 0x04u
53 #define MEM_BASE_IPC 0x40230000u
54 #define IPC_STRUCT_SIZE 0x20u
55 #define MEM_IPC(n) (MEM_BASE_IPC + (n) * IPC_STRUCT_SIZE)
56 #define MEM_IPC_ACQUIRE(n) (MEM_IPC(n) + 0x00u)
57 #define MEM_IPC_NOTIFY(n) (MEM_IPC(n) + 0x08u)
58 #define MEM_IPC_DATA(n) (MEM_IPC(n) + 0x0Cu)
59 #define MEM_IPC_LOCK_STATUS(n) (MEM_IPC(n) + 0x10u)
61 #define MEM_BASE_IPC_INTR 0x40231000u
62 #define IPC_INTR_STRUCT_SIZE 0x20u
63 #define MEM_IPC_INTR(n) (MEM_BASE_IPC_INTR + (n) * IPC_INTR_STRUCT_SIZE)
64 #define MEM_IPC_INTR_MASK(n) (MEM_IPC_INTR(n) + 0x08u)
65 #define IPC_ACQUIRE_SUCCESS_MSK 0x80000000u
66 #define IPC_LOCK_ACQUIRED_MSK 0x80000000u
69 #define IPC_INTR_ID 0u
70 #define IPC_TIMEOUT_MS 1000
72 #define SROMAPI_SIID_REQ 0x00000001u
73 #define SROMAPI_SIID_REQ_FAMILY_REVISION (SROMAPI_SIID_REQ | 0x000u)
74 #define SROMAPI_SIID_REQ_SIID_PROTECTION (SROMAPI_SIID_REQ | 0x100u)
75 #define SROMAPI_WRITEROW_REQ 0x05000100u
76 #define SROMAPI_PROGRAMROW_REQ 0x06000100u
77 #define SROMAPI_ERASESECTOR_REQ 0x14000100u
78 #define SROMAPI_ERASEALL_REQ 0x0A000100u
79 #define SROMAPI_ERASEROW_REQ 0x1C000100u
81 #define SROMAPI_STATUS_MSK 0xF0000000u
82 #define SROMAPI_STAT_SUCCESS 0xA0000000u
83 #define SROMAPI_DATA_LOCATION_MSK 0x00000001u
84 #define SROMAPI_CALL_TIMEOUT_MS 1500
86 struct psoc6_target_info
{
89 uint32_t main_flash_sz
;
104 static struct row_region safe_sflash_regions
[] = {
105 {0x16000800, 0x800}, /* SFLASH: User Data */
106 {0x16001A00, 0x200}, /* SFLASH: NAR */
107 {0x16005A00, 0xC00}, /* SFLASH: Public Key */
108 {0x16007C00, 0x400}, /* SFLASH: TOC2 */
111 #define SFLASH_NUM_REGIONS (sizeof(safe_sflash_regions) / sizeof(safe_sflash_regions[0]))
113 static struct working_area
*g_stack_area
;
114 /**************************************************************************************************
115 * Initializes timeout_s structure with given timeout in milliseconds
116 *************************************************************************************************/
117 static void timeout_init(struct timeout
*to
, long timeout_ms
)
119 to
->start_time
= timeval_ms();
120 to
->timeout_ms
= timeout_ms
;
123 /**************************************************************************************************
124 * Returns true if given timeout_s object has expired
125 *************************************************************************************************/
126 static bool timeout_expired(struct timeout
*to
)
128 return (timeval_ms() - to
->start_time
) > to
->timeout_ms
;
131 /**************************************************************************************************
132 * Prepares PSoC6 for running pseudo flash algorithm. This function allocates Working Area for
133 * the algorithm and for CPU Stack.
134 *************************************************************************************************/
135 static int sromalgo_prepare(struct target
*target
)
139 /* Initialize Vector Table Offset register (in case FW modified it) */
140 hr
= target_write_u32(target
, 0xE000ED08, 0x00000000);
144 /* Allocate Working Area for Stack and Flash algorithm */
145 hr
= target_alloc_working_area(target
, RAM_STACK_WA_SIZE
, &g_stack_area
);
149 /* Restore THUMB bit in xPSR register */
150 const struct armv7m_common
*cm
= target_to_armv7m(target
);
151 hr
= cm
->store_core_reg_u32(target
, ARMV7M_xPSR
, 0x01000000);
158 /* Something went wrong, free allocated area */
160 target_free_working_area(target
, g_stack_area
);
167 /**************************************************************************************************
168 * Releases working area
169 *************************************************************************************************/
170 static int sromalgo_release(struct target
*target
)
174 /* Free Stack/Flash algorithm working area */
176 hr
= target_free_working_area(target
, g_stack_area
);
183 /**************************************************************************************************
184 * Runs pseudo flash algorithm. Algorithm itself consist of couple of NOPs followed by BKPT
185 * instruction. The trick here is that NMI has already been posted to CM0 via IPC structure
186 * prior to calling this function. CM0 will immediately jump to NMI handler and execute
188 * This approach is borrowed from PSoC4 Flash Driver.
189 *************************************************************************************************/
190 static int sromalgo_run(struct target
*target
)
194 struct armv7m_algorithm armv7m_info
;
195 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
196 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
198 struct reg_param reg_params
;
199 init_reg_param(®_params
, "sp", 32, PARAM_OUT
);
200 buf_set_u32(reg_params
.value
, 0, 32, g_stack_area
->address
+ g_stack_area
->size
);
202 /* mov r8, r8; mov r8, r8 */
203 hr
= target_write_u32(target
, g_stack_area
->address
+ 0, 0x46C046C0);
207 /* mov r8, r8; bkpt #0 */
208 hr
= target_write_u32(target
, g_stack_area
->address
+ 4, 0xBE0046C0);
212 hr
= target_run_algorithm(target
, 0, NULL
, 1, ®_params
, g_stack_area
->address
,
213 0, SROMAPI_CALL_TIMEOUT_MS
, &armv7m_info
);
215 destroy_reg_param(®_params
);
220 /**************************************************************************************************
221 * Waits for expected IPC lock status.
222 * PSoC6 uses IPC structures for inter-core communication. Same IPCs are used to invoke SROM API.
223 * IPC structure must be locked prior to invoking any SROM API. This ensures nothing else in the
224 * system will use same IPC thus corrupting our data. Locking is performed by ipc_acquire(), this
225 * function ensures that IPC is actually in expected state
226 *************************************************************************************************/
227 static int ipc_poll_lock_stat(struct target
*target
, uint32_t ipc_id
, bool lock_expected
)
233 timeout_init(&to
, IPC_TIMEOUT_MS
);
235 while (!timeout_expired(&to
)) {
236 /* Process any server requests */
239 /* Read IPC Lock status */
240 hr
= target_read_u32(target
, MEM_IPC_LOCK_STATUS(ipc_id
), ®_val
);
241 if (hr
!= ERROR_OK
) {
242 LOG_ERROR("Unable to read IPC Lock Status register");
246 bool is_locked
= (reg_val
& IPC_LOCK_ACQUIRED_MSK
) != 0;
248 if (lock_expected
== is_locked
)
252 if (target
->coreid
) {
253 LOG_WARNING("SROM API calls via CM4 target are supported on single-core PSoC6 devices only. "
254 "Please perform all Flash-related operations via CM0+ target on dual-core devices.");
257 LOG_ERROR("Timeout polling IPC Lock Status");
258 return ERROR_TARGET_TIMEOUT
;
261 /**************************************************************************************************
262 * Acquires IPC structure
263 * PSoC6 uses IPC structures for inter-core communication. Same IPCs are used to invoke SROM API.
264 * IPC structure must be locked prior to invoking any SROM API. This ensures nothing else in the
265 * system will use same IPC thus corrupting our data. This function locks the IPC.
266 *************************************************************************************************/
267 static int ipc_acquire(struct target
*target
, char ipc_id
)
270 bool is_acquired
= false;
274 timeout_init(&to
, IPC_TIMEOUT_MS
);
276 while (!timeout_expired(&to
)) {
279 hr
= target_write_u32(target
, MEM_IPC_ACQUIRE(ipc_id
), IPC_ACQUIRE_SUCCESS_MSK
);
280 if (hr
!= ERROR_OK
) {
281 LOG_ERROR("Unable to write to IPC Acquire register");
285 /* Check if data is written on first step */
286 hr
= target_read_u32(target
, MEM_IPC_ACQUIRE(ipc_id
), ®_val
);
287 if (hr
!= ERROR_OK
) {
288 LOG_ERROR("Unable to read IPC Acquire register");
292 is_acquired
= (reg_val
& IPC_ACQUIRE_SUCCESS_MSK
) != 0;
294 /* If IPC structure is acquired, the lock status should be set */
295 hr
= ipc_poll_lock_stat(target
, ipc_id
, true);
301 LOG_ERROR("Timeout acquiring IPC structure");
306 /**************************************************************************************************
307 * Invokes SROM API functions which are responsible for Flash operations
308 *************************************************************************************************/
309 static int call_sromapi(struct target
*target
,
310 uint32_t req_and_params
,
311 uint32_t working_area
,
316 bool is_data_in_ram
= (req_and_params
& SROMAPI_DATA_LOCATION_MSK
) == 0;
318 hr
= ipc_acquire(target
, IPC_ID
);
323 hr
= target_write_u32(target
, MEM_IPC_DATA(IPC_ID
), working_area
);
325 hr
= target_write_u32(target
, MEM_IPC_DATA(IPC_ID
), req_and_params
);
330 /* Enable notification interrupt of IPC_INTR_STRUCT0(CM0+) for IPC_STRUCT2 */
331 hr
= target_write_u32(target
, MEM_IPC_INTR_MASK(IPC_INTR_ID
), 1u << (16 + IPC_ID
));
335 hr
= target_write_u32(target
, MEM_IPC_NOTIFY(IPC_ID
), 1);
339 hr
= sromalgo_run(target
);
343 /* Poll lock status */
344 hr
= ipc_poll_lock_stat(target
, IPC_ID
, false);
350 hr
= target_read_u32(target
, working_area
, data_out
);
352 hr
= target_read_u32(target
, MEM_IPC_DATA(IPC_ID
), data_out
);
354 if (hr
!= ERROR_OK
) {
355 LOG_ERROR("Error reading SROM API Status location");
359 bool is_success
= (*data_out
& SROMAPI_STATUS_MSK
) == SROMAPI_STAT_SUCCESS
;
361 LOG_ERROR("SROM API execution failed. Status: 0x%08X", (uint32_t)*data_out
);
362 return ERROR_TARGET_FAILURE
;
368 /**************************************************************************************************
369 * Retrieves SiliconID and Protection status of the target device
370 *************************************************************************************************/
371 static int get_silicon_id(struct target
*target
, uint32_t *si_id
, uint8_t *protection
)
374 uint32_t family_rev
, siid_prot
;
376 hr
= sromalgo_prepare(target
);
380 /* Read FamilyID and Revision */
381 hr
= call_sromapi(target
, SROMAPI_SIID_REQ_FAMILY_REVISION
, 0, &family_rev
);
385 /* Read SiliconID and Protection */
386 hr
= call_sromapi(target
, SROMAPI_SIID_REQ_SIID_PROTECTION
, 0, &siid_prot
);
390 *si_id
= (siid_prot
& 0x0000FFFF) << 16;
391 *si_id
|= (family_rev
& 0x00FF0000) >> 8;
392 *si_id
|= (family_rev
& 0x000000FF) >> 0;
394 *protection
= (siid_prot
& 0x000F0000) >> 0x10;
396 hr
= sromalgo_release(target
);
400 /**************************************************************************************************
401 * Translates Protection status to openocd-friendly boolean value
402 *************************************************************************************************/
403 static int psoc6_protect_check(struct flash_bank
*bank
)
407 struct psoc6_target_info
*psoc6_info
= bank
->driver_priv
;
408 int hr
= get_silicon_id(bank
->target
, &psoc6_info
->silicon_id
, &psoc6_info
->protection
);
412 switch (psoc6_info
->protection
) {
413 case PROTECTION_VIRGIN
:
414 case PROTECTION_NORMAL
:
418 case PROTECTION_UNKNOWN
:
419 case PROTECTION_SECURE
:
420 case PROTECTION_DEAD
:
426 for (int i
= 0; i
< bank
->num_sectors
; i
++)
427 bank
->sectors
[i
].is_protected
= is_protected
;
432 /**************************************************************************************************
433 * Life Cycle transition is not currently supported
434 *************************************************************************************************/
435 static int psoc6_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
442 LOG_WARNING("Life Cycle transition for PSoC6 is not supported");
446 /**************************************************************************************************
447 * Translates Protection status to string
448 *************************************************************************************************/
449 static const char *protection_to_str(uint8_t protection
)
451 switch (protection
) {
452 case PROTECTION_VIRGIN
:
455 case PROTECTION_NORMAL
:
458 case PROTECTION_SECURE
:
461 case PROTECTION_DEAD
:
464 case PROTECTION_UNKNOWN
:
471 /**************************************************************************************************
472 * Displays human-readable information about acquired device
473 *************************************************************************************************/
474 static int psoc6_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
476 struct psoc6_target_info
*psoc6_info
= bank
->driver_priv
;
478 if (psoc6_info
->is_probed
== false)
481 int hr
= get_silicon_id(bank
->target
, &psoc6_info
->silicon_id
, &psoc6_info
->protection
);
485 snprintf(buf
, buf_size
,
486 "PSoC6 Silicon ID: 0x%08X\n"
488 "Main Flash size: %d kB\n"
489 "Work Flash size: 32 kB\n",
490 psoc6_info
->silicon_id
,
491 protection_to_str(psoc6_info
->protection
),
492 psoc6_info
->main_flash_sz
/ 1024);
497 /**************************************************************************************************
498 * Returns true if flash bank name represents Supervisory Flash
499 *************************************************************************************************/
500 static bool is_sflash_bank(struct flash_bank
*bank
)
502 for (size_t i
= 0; i
< SFLASH_NUM_REGIONS
; i
++) {
503 if (bank
->base
== safe_sflash_regions
[i
].addr
)
510 /**************************************************************************************************
511 * Returns true if flash bank name represents Work Flash
512 *************************************************************************************************/
513 static inline bool is_wflash_bank(struct flash_bank
*bank
)
515 return (bank
->base
== MEM_BASE_WFLASH
);
518 /**************************************************************************************************
519 * Returns true if flash bank name represents Main Flash
520 *************************************************************************************************/
521 static inline bool is_mflash_bank(struct flash_bank
*bank
)
523 return (bank
->base
== MEM_BASE_MFLASH
);
526 /**************************************************************************************************
527 * Probes the device and populates related data structures with target flash geometry data.
528 * This is done in non-intrusive way, no SROM API calls are involved so GDB can safely attach to a
530 * Function assumes that size of Work Flash is 32kB (true for all current part numbers)
531 *************************************************************************************************/
532 static int psoc6_probe(struct flash_bank
*bank
)
534 struct target
*target
= bank
->target
;
535 struct psoc6_target_info
*psoc6_info
= bank
->driver_priv
;
539 /* Retrieve data from SPCIF_GEOMATRY */
541 target_read_u32(target
, PSOC6_SPCIF_GEOMETRY
, &geom
);
542 uint32_t row_sz_lg2
= (geom
& 0xF0) >> 4;
543 uint32_t row_sz
= (0x01 << row_sz_lg2
);
544 uint32_t row_cnt
= 1 + ((geom
& 0x00FFFF00) >> 8);
545 uint32_t bank_cnt
= 1 + ((geom
& 0xFF000000) >> 24);
547 /* Calculate size of Main Flash*/
548 uint32_t flash_sz_bytes
= bank_cnt
* row_cnt
* row_sz
;
552 bank
->sectors
= NULL
;
555 size_t bank_size
= 0;
557 if (is_mflash_bank(bank
))
558 bank_size
= flash_sz_bytes
;
559 else if (is_wflash_bank(bank
))
560 bank_size
= MEM_WFLASH_SIZE
;
561 else if (is_sflash_bank(bank
)) {
562 for (size_t i
= 0; i
< SFLASH_NUM_REGIONS
; i
++) {
563 if (safe_sflash_regions
[i
].addr
== bank
->base
) {
564 bank_size
= safe_sflash_regions
[i
].size
;
570 if (bank_size
== 0) {
571 LOG_ERROR("Invalid Flash Bank base address in config file");
572 return ERROR_FLASH_BANK_INVALID
;
575 size_t num_sectors
= bank_size
/ row_sz
;
576 bank
->size
= bank_size
;
577 bank
->chip_width
= 4;
579 bank
->erased_value
= 0;
580 bank
->default_padded_value
= 0;
582 bank
->num_sectors
= num_sectors
;
583 bank
->sectors
= calloc(num_sectors
, sizeof(struct flash_sector
));
584 for (size_t i
= 0; i
< num_sectors
; i
++) {
585 bank
->sectors
[i
].size
= row_sz
;
586 bank
->sectors
[i
].offset
= i
* row_sz
;
587 bank
->sectors
[i
].is_erased
= -1;
588 bank
->sectors
[i
].is_protected
= -1;
591 psoc6_info
->is_probed
= true;
592 psoc6_info
->main_flash_sz
= flash_sz_bytes
;
593 psoc6_info
->row_sz
= row_sz
;
598 /**************************************************************************************************
599 * Probes target device only if it hasn't been probed yet
600 *************************************************************************************************/
601 static int psoc6_auto_probe(struct flash_bank
*bank
)
603 struct psoc6_target_info
*psoc6_info
= bank
->driver_priv
;
606 if (psoc6_info
->is_probed
)
609 hr
= psoc6_probe(bank
);
614 /**************************************************************************************************
615 * Erases single sector (256k) on target device
616 *************************************************************************************************/
617 static int psoc6_erase_sector(struct flash_bank
*bank
, struct working_area
*wa
, uint32_t addr
)
619 struct target
*target
= bank
->target
;
621 LOG_DEBUG("Erasing SECTOR @%08X", addr
);
623 int hr
= target_write_u32(target
, wa
->address
, SROMAPI_ERASESECTOR_REQ
);
627 hr
= target_write_u32(target
, wa
->address
+ 0x04, addr
);
632 hr
= call_sromapi(target
, SROMAPI_ERASESECTOR_REQ
, wa
->address
, &data_out
);
634 LOG_ERROR("SECTOR @%08X not erased!", addr
);
639 /**************************************************************************************************
640 * Erases single row (512b) on target device
641 *************************************************************************************************/
642 static int psoc6_erase_row(struct flash_bank
*bank
, struct working_area
*wa
, uint32_t addr
)
644 struct target
*target
= bank
->target
;
646 LOG_DEBUG("Erasing ROW @%08X", addr
);
648 int hr
= target_write_u32(target
, wa
->address
, SROMAPI_ERASEROW_REQ
);
652 hr
= target_write_u32(target
, wa
->address
+ 0x04, addr
);
657 hr
= call_sromapi(target
, SROMAPI_ERASEROW_REQ
, wa
->address
, &data_out
);
659 LOG_ERROR("ROW @%08X not erased!", addr
);
664 /**************************************************************************************************
665 * Performs Erase operation.
666 * Function will try to use biggest erase block possible to speedup the operation
667 *************************************************************************************************/
668 static int psoc6_erase(struct flash_bank
*bank
, int first
, int last
)
670 struct target
*target
= bank
->target
;
671 struct psoc6_target_info
*psoc6_info
= bank
->driver_priv
;
672 const uint32_t sector_size
= is_wflash_bank(bank
) ? WFLASH_SECTOR_SIZE
: MFLASH_SECTOR_SIZE
;
675 struct working_area
*wa
;
677 if (is_sflash_bank(bank
)) {
678 LOG_INFO("Erase operation on Supervisory Flash is not required, skipping");
682 hr
= sromalgo_prepare(target
);
686 hr
= target_alloc_working_area(target
, psoc6_info
->row_sz
+ 32, &wa
);
690 /* Number of rows in single sector */
691 const int rows_in_sector
= sector_size
/ psoc6_info
->row_sz
;
693 while (last
>= first
) {
694 /* Erase Sector if we are on sector boundary and erase size covers whole sector */
695 if ((first
% rows_in_sector
) == 0 &&
696 (last
- first
+ 1) >= rows_in_sector
) {
697 hr
= psoc6_erase_sector(bank
, wa
, bank
->base
+ first
* psoc6_info
->row_sz
);
701 for (int i
= first
; i
< first
+ rows_in_sector
; i
++)
702 bank
->sectors
[i
].is_erased
= 1;
704 first
+= rows_in_sector
;
706 /* Perform Row Erase otherwise */
707 hr
= psoc6_erase_row(bank
, wa
, bank
->base
+ first
* psoc6_info
->row_sz
);
711 bank
->sectors
[first
].is_erased
= 1;
717 target_free_working_area(target
, wa
);
719 sromalgo_release(target
);
724 /**************************************************************************************************
725 * Programs single Flash Row
726 *************************************************************************************************/
727 static int psoc6_program_row(struct flash_bank
*bank
,
729 const uint8_t *buffer
,
732 struct target
*target
= bank
->target
;
733 struct psoc6_target_info
*psoc6_info
= bank
->driver_priv
;
734 struct working_area
*wa
;
735 const uint32_t sromapi_req
= is_sflash
? SROMAPI_WRITEROW_REQ
: SROMAPI_PROGRAMROW_REQ
;
739 LOG_DEBUG("Programming ROW @%08X", addr
);
741 hr
= target_alloc_working_area(target
, psoc6_info
->row_sz
+ 32, &wa
);
745 hr
= target_write_u32(target
, wa
->address
, sromapi_req
);
749 hr
= target_write_u32(target
,
755 hr
= target_write_u32(target
, wa
->address
+ 0x08, addr
);
759 hr
= target_write_u32(target
, wa
->address
+ 0x0C, wa
->address
+ 0x10);
763 hr
= target_write_buffer(target
, wa
->address
+ 0x10, psoc6_info
->row_sz
, buffer
);
767 hr
= call_sromapi(target
, sromapi_req
, wa
->address
, &data_out
);
770 target_free_working_area(target
, wa
);
777 /**************************************************************************************************
778 * Programs set of Rows
779 *************************************************************************************************/
780 static int psoc6_program(struct flash_bank
*bank
,
781 const uint8_t *buffer
,
785 struct target
*target
= bank
->target
;
786 struct psoc6_target_info
*psoc6_info
= bank
->driver_priv
;
787 const bool is_sflash
= is_sflash_bank(bank
);
790 hr
= sromalgo_prepare(target
);
794 uint8_t page_buf
[psoc6_info
->row_sz
];
797 uint32_t row_offset
= offset
% psoc6_info
->row_sz
;
798 uint32_t aligned_addr
= bank
->base
+ offset
- row_offset
;
799 uint32_t row_bytes
= MIN(psoc6_info
->row_sz
- row_offset
, count
);
801 memset(page_buf
, 0, sizeof(page_buf
));
802 memcpy(&page_buf
[row_offset
], buffer
, row_bytes
);
804 hr
= psoc6_program_row(bank
, aligned_addr
, page_buf
, is_sflash
);
805 if (hr
!= ERROR_OK
) {
806 LOG_ERROR("Failed to program Flash at address 0x%08X", aligned_addr
);
815 hr
= sromalgo_release(target
);
819 /**************************************************************************************************
820 * Performs Mass Erase of given flash bank
821 * Syntax: psoc6 mass_erase bank_id
822 *************************************************************************************************/
823 COMMAND_HANDLER(psoc6_handle_mass_erase_command
)
826 return ERROR_COMMAND_SYNTAX_ERROR
;
828 struct flash_bank
*bank
;
829 int hr
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
833 hr
= psoc6_erase(bank
, 0, bank
->num_sectors
- 1);
838 /**************************************************************************************************
839 * Simulates broken Vector Catch
840 * Function will try to determine entry point of user application. If it succeeds it will set HW
841 * breakpoint at that address, issue SW Reset and remove the breakpoint afterwards.
842 * In case of CM0, SYSRESETREQ is used. This allows to reset all peripherals. Boot code will
843 * reset CM4 anyway, so using SYSRESETREQ is safe here.
844 * In case of CM4, VECTRESET is used instead of SYSRESETREQ to not disturb CM0 core.
845 *************************************************************************************************/
846 int handle_reset_halt(struct target
*target
)
850 bool is_cm0
= (target
->coreid
== 0);
852 /* Halt target device */
853 if (target
->state
!= TARGET_HALTED
) {
854 hr
= target_halt(target
);
858 target_wait_state(target
, TARGET_HALTED
, IPC_TIMEOUT_MS
);
863 /* Read Vector Offset register */
865 const uint32_t vt_offset_reg
= is_cm0
? 0x402102B0 : 0x402102C0;
866 hr
= target_read_u32(target
, vt_offset_reg
, &vt_base
);
870 /* Invalid value means flash is empty */
871 vt_base
&= 0xFFFFFF00;
872 if ((vt_base
== 0) || (vt_base
== 0xFFFFFF00))
875 /* Read Reset Vector value*/
876 hr
= target_read_u32(target
, vt_base
+ 4, &reset_addr
);
880 /* Invalid value means flash is empty */
881 if ((reset_addr
== 0) || (reset_addr
== 0xFFFFFF00))
885 /* Set breakpoint at User Application entry point */
886 hr
= breakpoint_add(target
, reset_addr
, 2, BKPT_HARD
);
890 const struct armv7m_common
*cm
= target_to_armv7m(target
);
893 /* Reset the CM0 by asserting SYSRESETREQ. This will also reset CM4 */
894 LOG_INFO("psoc6.cm0: bkpt @0x%08X, issuing SYSRESETREQ", reset_addr
);
895 hr
= mem_ap_write_atomic_u32(cm
->debug_ap
,
897 AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
899 /* Wait for bootcode and initialize DAP */
901 dap_dp_init(cm
->debug_ap
->dap
);
903 LOG_INFO("psoc6.cm4: bkpt @0x%08X, issuing VECTRESET", reset_addr
);
904 hr
= mem_ap_write_atomic_u32(cm
->debug_ap
,
906 AIRCR_VECTKEY
| AIRCR_VECTRESET
);
911 target_wait_state(target
, TARGET_HALTED
, IPC_TIMEOUT_MS
);
913 /* Remove the break point */
914 breakpoint_remove(target
, reset_addr
);
919 COMMAND_HANDLER(psoc6_handle_reset_halt
)
922 return ERROR_COMMAND_SYNTAX_ERROR
;
924 struct target
*target
= get_current_target(CMD_CTX
);
925 return handle_reset_halt(target
);
928 FLASH_BANK_COMMAND_HANDLER(psoc6_flash_bank_command
)
930 struct psoc6_target_info
*psoc6_info
;
934 hr
= ERROR_COMMAND_SYNTAX_ERROR
;
936 psoc6_info
= calloc(1, sizeof(struct psoc6_target_info
));
937 psoc6_info
->is_probed
= false;
938 bank
->driver_priv
= psoc6_info
;
943 static const struct command_registration psoc6_exec_command_handlers
[] = {
945 .name
= "mass_erase",
946 .handler
= psoc6_handle_mass_erase_command
,
947 .mode
= COMMAND_EXEC
,
949 .help
= "Erases entire Main Flash",
952 .name
= "reset_halt",
953 .handler
= psoc6_handle_reset_halt
,
954 .mode
= COMMAND_EXEC
,
956 .help
= "Tries to simulate broken Vector Catch",
958 COMMAND_REGISTRATION_DONE
961 static const struct command_registration psoc6_command_handlers
[] = {
965 .help
= "PSoC 6 flash command group",
967 .chain
= psoc6_exec_command_handlers
,
969 COMMAND_REGISTRATION_DONE
972 struct flash_driver psoc6_flash
= {
974 .commands
= psoc6_command_handlers
,
975 .flash_bank_command
= psoc6_flash_bank_command
,
976 .erase
= psoc6_erase
,
977 .protect
= psoc6_protect
,
978 .write
= psoc6_program
,
979 .read
= default_flash_read
,
980 .probe
= psoc6_probe
,
981 .auto_probe
= psoc6_auto_probe
,
982 .erase_check
= default_flash_blank_check
,
983 .protect_check
= psoc6_protect_check
,
984 .info
= psoc6_get_info
,
985 .free_driver_priv
= default_flash_free_driver_priv
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)