2 OpenOCD STM8 target driver
3 Copyright (C) 2017 Ake Rehnman
4 ake.rehnman(at)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 3 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/>.
24 #include <helper/log.h>
26 #include "target_type.h"
28 #include "jtag/jtag.h"
29 #include "jtag/hla/hla_transport.h"
30 #include "jtag/hla/hla_interface.h"
31 #include "jtag/hla/hla_layout.h"
33 #include "breakpoints.h"
34 #include "algorithm.h"
37 static struct reg_cache
*stm8_build_reg_cache(struct target
*target
);
38 static int stm8_read_core_reg(struct target
*target
, unsigned int num
);
39 static int stm8_write_core_reg(struct target
*target
, unsigned int num
);
40 static int stm8_save_context(struct target
*target
);
41 static void stm8_enable_breakpoints(struct target
*target
);
42 static int stm8_unset_breakpoint(struct target
*target
,
43 struct breakpoint
*breakpoint
);
44 static int stm8_set_breakpoint(struct target
*target
,
45 struct breakpoint
*breakpoint
);
46 static void stm8_enable_watchpoints(struct target
*target
);
47 static int stm8_unset_watchpoint(struct target
*target
,
48 struct watchpoint
*watchpoint
);
59 { 0, "pc", 32, REG_TYPE_UINT32
, "general", "org.gnu.gdb.stm8.core", 0 },
60 { 1, "a", 8, REG_TYPE_UINT8
, "general", "org.gnu.gdb.stm8.core", 0 },
61 { 2, "x", 16, REG_TYPE_UINT16
, "general", "org.gnu.gdb.stm8.core", 0 },
62 { 3, "y", 16, REG_TYPE_UINT16
, "general", "org.gnu.gdb.stm8.core", 0 },
63 { 4, "sp", 16, REG_TYPE_UINT16
, "general", "org.gnu.gdb.stm8.core", 0 },
64 { 5, "cc", 8, REG_TYPE_UINT8
, "general", "org.gnu.gdb.stm8.core", 0 },
67 #define STM8_NUM_REGS ARRAY_SIZE(stm8_regs)
78 #define DM_REGS 0x7f00
79 #define DM_REG_A 0x7f00
80 #define DM_REG_PC 0x7f01
81 #define DM_REG_X 0x7f04
82 #define DM_REG_Y 0x7f06
83 #define DM_REG_SP 0x7f08
84 #define DM_REG_CC 0x7f0a
86 #define DM_BKR1E 0x7f90
87 #define DM_BKR2E 0x7f93
90 #define DM_CSR1 0x7f98
91 #define DM_CSR2 0x7f99
105 #define FLASH_CR1_STM8S 0x505A
106 #define FLASH_CR2_STM8S 0x505B
107 #define FLASH_NCR2_STM8S 0x505C
108 #define FLASH_IAPSR_STM8S 0x505F
109 #define FLASH_PUKR_STM8S 0x5062
110 #define FLASH_DUKR_STM8S 0x5064
112 #define FLASH_CR1_STM8L 0x5050
113 #define FLASH_CR2_STM8L 0x5051
114 #define FLASH_NCR2_STM8L 0
115 #define FLASH_PUKR_STM8L 0x5052
116 #define FLASH_DUKR_STM8L 0x5053
117 #define FLASH_IAPSR_STM8L 0x5054
124 #define WR_PG_DIS 0x01
134 #define SAFE_MASK 0x80
135 #define NO_ACCESS 0x40
139 #define SWIM_RST 0x04
143 #define SWIM_CSR 0x7f80
145 #define STM8_BREAK 0x8B
154 struct stm8_algorithm
{
158 struct stm8_core_reg
{
160 struct target
*target
;
161 struct stm8_common
*stm8_common
;
165 /* break on execute */
171 /* break on read, write and execute */
175 struct stm8_comparator
{
178 uint32_t reg_address
;
179 enum hw_break_type type
;
182 static inline struct hl_interface_s
*target_to_adapter(struct target
*target
)
184 return target
->tap
->priv
;
187 static int stm8_adapter_read_memory(struct target
*target
,
188 uint32_t addr
, int size
, int count
, void *buf
)
191 struct hl_interface_s
*adapter
= target_to_adapter(target
);
193 ret
= adapter
->layout
->api
->read_mem(adapter
->handle
,
194 addr
, size
, count
, buf
);
200 static int stm8_adapter_write_memory(struct target
*target
,
201 uint32_t addr
, int size
, int count
, const void *buf
)
204 struct hl_interface_s
*adapter
= target_to_adapter(target
);
206 ret
= adapter
->layout
->api
->write_mem(adapter
->handle
,
207 addr
, size
, count
, buf
);
213 static int stm8_write_u8(struct target
*target
,
214 uint32_t addr
, uint8_t val
)
218 struct hl_interface_s
*adapter
= target_to_adapter(target
);
221 ret
= adapter
->layout
->api
->write_mem(adapter
->handle
, addr
, 1, 1, buf
);
227 static int stm8_read_u8(struct target
*target
,
228 uint32_t addr
, uint8_t *val
)
231 struct hl_interface_s
*adapter
= target_to_adapter(target
);
233 ret
= adapter
->layout
->api
->read_mem(adapter
->handle
, addr
, 1, 1, val
);
239 static int stm8_set_speed(struct target
*target
, int speed
)
241 struct hl_interface_s
*adapter
= target_to_adapter(target
);
242 adapter
->layout
->api
->speed(adapter
->handle
, speed
, 0);
247 <enable == 0> Disables interrupts.
248 If interrupts are enabled they are masked and the cc register
251 <enable == 1> Enables interrupts.
252 Enable interrupts is actually restoring I1 I0 state from previous
253 call with enable == 0. Note that if stepping and breaking on a sim
254 instruction will NOT work since the interrupt flags are restored on
255 debug_entry. We don't have any way for the debugger to exclusively
256 disable the interrupts
258 static int stm8_enable_interrupts(struct target
*target
, int enable
)
260 struct stm8_common
*stm8
= target_to_stm8(target
);
265 return ERROR_OK
; /* cc was not stashed */
266 /* fetch current cc */
267 stm8_read_u8(target
, DM_REG_CC
, &cc
);
269 cc
&= ~(CC_I0
+ CC_I1
);
270 /* restore I1 & I0 from stash*/
271 cc
|= (stm8
->cc
& (CC_I0
+CC_I1
));
272 /* update current cc */
273 stm8_write_u8(target
, DM_REG_CC
, cc
);
274 stm8
->cc_valid
= false;
276 stm8_read_u8(target
, DM_REG_CC
, &cc
);
277 if ((cc
& CC_I0
) && (cc
& CC_I1
))
278 return ERROR_OK
; /* interrupts already masked */
281 stm8
->cc_valid
= true;
282 /* mask interrupts (disable) */
283 cc
|= (CC_I0
+ CC_I1
);
284 stm8_write_u8(target
, DM_REG_CC
, cc
);
290 static int stm8_set_hwbreak(struct target
*target
,
291 struct stm8_comparator comparator_list
[])
296 /* Refer to Table 4 in UM0470 */
304 if (!comparator_list
[0].used
) {
305 comparator_list
[0].type
= HWBRK_EXEC
;
306 comparator_list
[0].bp_value
= -1;
309 if (!comparator_list
[1].used
) {
310 comparator_list
[1].type
= HWBRK_EXEC
;
311 comparator_list
[1].bp_value
= -1;
314 if ((comparator_list
[0].type
== HWBRK_EXEC
)
315 && (comparator_list
[1].type
== HWBRK_EXEC
)) {
316 comparator_list
[0].reg_address
= 0;
317 comparator_list
[1].reg_address
= 1;
320 if ((comparator_list
[0].type
== HWBRK_EXEC
)
321 && (comparator_list
[1].type
!= HWBRK_EXEC
)) {
322 comparator_list
[0].reg_address
= 0;
323 comparator_list
[1].reg_address
= 1;
324 switch (comparator_list
[1].type
) {
338 if ((comparator_list
[1].type
== HWBRK_EXEC
)
339 && (comparator_list
[0].type
!= HWBRK_EXEC
)) {
340 comparator_list
[0].reg_address
= 1;
341 comparator_list
[1].reg_address
= 0;
342 switch (comparator_list
[0].type
) {
356 if ((comparator_list
[0].type
!= HWBRK_EXEC
)
357 && (comparator_list
[1].type
!= HWBRK_EXEC
)) {
358 if ((comparator_list
[0].type
!= comparator_list
[1].type
)) {
359 LOG_ERROR("data hw breakpoints must be of same type");
360 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
364 for (i
= 0; i
< 2; i
++) {
365 data
= comparator_list
[i
].bp_value
;
366 addr
= comparator_list
[i
].reg_address
;
373 ret
= stm8_adapter_write_memory(target
, DM_BKR1E
, 1, 3, buf
);
374 LOG_DEBUG("DM_BKR1E=%" PRIx32
, data
);
375 } else if (addr
== 1) {
376 ret
= stm8_adapter_write_memory(target
, DM_BKR2E
, 1, 3, buf
);
377 LOG_DEBUG("DM_BKR2E=%" PRIx32
, data
);
379 LOG_DEBUG("addr=%" PRIu32
, addr
);
386 ret
= stm8_write_u8(target
, DM_CR1
,
387 (bc
<< 3) + (bir
<< 2) + (biw
<< 1));
388 LOG_DEBUG("DM_CR1=%" PRIx8
, buf
[0]);
396 /* read DM control and status regs */
397 static int stm8_read_dm_csrx(struct target
*target
, uint8_t *csr1
,
403 ret
= stm8_adapter_read_memory(target
, DM_CSR1
, 1, sizeof(buf
), buf
);
413 /* set or clear the single step flag in DM */
414 static int stm8_config_step(struct target
*target
, int enable
)
419 ret
= stm8_read_dm_csrx(target
, &csr1
, &csr2
);
427 ret
= stm8_write_u8(target
, DM_CSR1
, csr1
);
433 /* set the stall flag in DM */
434 static int stm8_debug_stall(struct target
*target
)
439 ret
= stm8_read_dm_csrx(target
, &csr1
, &csr2
);
443 ret
= stm8_write_u8(target
, DM_CSR2
, csr2
);
449 static int stm8_configure_break_unit(struct target
*target
)
451 /* get pointers to arch-specific information */
452 struct stm8_common
*stm8
= target_to_stm8(target
);
454 if (stm8
->bp_scanned
)
457 stm8
->num_hw_bpoints
= 2;
458 stm8
->num_hw_bpoints_avail
= stm8
->num_hw_bpoints
;
460 stm8
->hw_break_list
= calloc(stm8
->num_hw_bpoints
,
461 sizeof(struct stm8_comparator
));
463 stm8
->hw_break_list
[0].reg_address
= 0;
464 stm8
->hw_break_list
[1].reg_address
= 1;
466 LOG_DEBUG("hw breakpoints: numinst %i numdata %i", stm8
->num_hw_bpoints
,
467 stm8
->num_hw_bpoints
);
469 stm8
->bp_scanned
= true;
474 static int stm8_examine_debug_reason(struct target
*target
)
479 retval
= stm8_read_dm_csrx(target
, &csr1
, &csr2
);
480 if (retval
== ERROR_OK
)
481 LOG_DEBUG("csr1 = 0x%02X csr2 = 0x%02X", csr1
, csr2
);
483 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
484 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)) {
486 if (retval
!= ERROR_OK
)
490 /* halted on reset */
491 target
->debug_reason
= DBG_REASON_UNDEFINED
;
493 if (csr1
& (BK1F
+BK2F
))
494 /* we have halted on a breakpoint (or wp)*/
495 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
498 /* we have halted on a breakpoint */
499 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
506 static int stm8_debug_entry(struct target
*target
)
508 struct stm8_common
*stm8
= target_to_stm8(target
);
510 /* restore interrupts */
511 stm8_enable_interrupts(target
, 1);
513 stm8_save_context(target
);
515 /* make sure stepping disabled STE bit in CSR1 cleared */
516 stm8_config_step(target
, 0);
518 /* attempt to find halt reason */
519 stm8_examine_debug_reason(target
);
521 LOG_DEBUG("entered debug state at PC 0x%" PRIx32
", target->state: %s",
522 buf_get_u32(stm8
->core_cache
->reg_list
[STM8_PC
].value
, 0, 32),
523 target_state_name(target
));
528 /* clear stall flag in DM and flush instruction pipe */
529 static int stm8_exit_debug(struct target
*target
)
534 ret
= stm8_read_dm_csrx(target
, &csr1
, &csr2
);
538 ret
= stm8_write_u8(target
, DM_CSR2
, csr2
);
544 ret
= stm8_write_u8(target
, DM_CSR2
, csr2
);
550 static int stm8_read_regs(struct target
*target
, uint32_t regs
[])
555 ret
= stm8_adapter_read_memory(target
, DM_REGS
, 1, sizeof(buf
), buf
);
559 regs
[0] = be_to_h_u24(buf
+DM_REG_PC
-DM_REGS
);
560 regs
[1] = buf
[DM_REG_A
-DM_REGS
];
561 regs
[2] = be_to_h_u16(buf
+DM_REG_X
-DM_REGS
);
562 regs
[3] = be_to_h_u16(buf
+DM_REG_Y
-DM_REGS
);
563 regs
[4] = be_to_h_u16(buf
+DM_REG_SP
-DM_REGS
);
564 regs
[5] = buf
[DM_REG_CC
-DM_REGS
];
569 static int stm8_write_regs(struct target
*target
, uint32_t regs
[])
574 h_u24_to_be(buf
+DM_REG_PC
-DM_REGS
, regs
[0]);
575 buf
[DM_REG_A
-DM_REGS
] = regs
[1];
576 h_u16_to_be(buf
+DM_REG_X
-DM_REGS
, regs
[2]);
577 h_u16_to_be(buf
+DM_REG_Y
-DM_REGS
, regs
[3]);
578 h_u16_to_be(buf
+DM_REG_SP
-DM_REGS
, regs
[4]);
579 buf
[DM_REG_CC
-DM_REGS
] = regs
[5];
581 ret
= stm8_adapter_write_memory(target
, DM_REGS
, 1, sizeof(buf
), buf
);
588 static int stm8_get_core_reg(struct reg
*reg
)
591 struct stm8_core_reg
*stm8_reg
= reg
->arch_info
;
592 struct target
*target
= stm8_reg
->target
;
593 struct stm8_common
*stm8_target
= target_to_stm8(target
);
595 if (target
->state
!= TARGET_HALTED
)
596 return ERROR_TARGET_NOT_HALTED
;
598 retval
= stm8_target
->read_core_reg(target
, stm8_reg
->num
);
603 static int stm8_set_core_reg(struct reg
*reg
, uint8_t *buf
)
605 struct stm8_core_reg
*stm8_reg
= reg
->arch_info
;
606 struct target
*target
= stm8_reg
->target
;
607 uint32_t value
= buf_get_u32(buf
, 0, reg
->size
);
609 if (target
->state
!= TARGET_HALTED
)
610 return ERROR_TARGET_NOT_HALTED
;
612 buf_set_u32(reg
->value
, 0, 32, value
);
619 static int stm8_save_context(struct target
*target
)
623 /* get pointers to arch-specific information */
624 struct stm8_common
*stm8
= target_to_stm8(target
);
626 /* read core registers */
627 stm8_read_regs(target
, stm8
->core_regs
);
629 for (i
= 0; i
< STM8_NUM_REGS
; i
++) {
630 if (!stm8
->core_cache
->reg_list
[i
].valid
)
631 stm8
->read_core_reg(target
, i
);
637 static int stm8_restore_context(struct target
*target
)
641 /* get pointers to arch-specific information */
642 struct stm8_common
*stm8
= target_to_stm8(target
);
644 for (i
= 0; i
< STM8_NUM_REGS
; i
++) {
645 if (stm8
->core_cache
->reg_list
[i
].dirty
)
646 stm8
->write_core_reg(target
, i
);
649 /* write core regs */
650 stm8_write_regs(target
, stm8
->core_regs
);
655 static int stm8_unlock_flash(struct target
*target
)
659 struct stm8_common
*stm8
= target_to_stm8(target
);
661 /* check if flash is unlocked */
662 stm8_read_u8(target
, stm8
->flash_iapsr
, data
);
663 if (~data
[0] & PUL
) {
665 stm8_write_u8(target
, stm8
->flash_pukr
, 0x56);
666 stm8_write_u8(target
, stm8
->flash_pukr
, 0xae);
669 stm8_read_u8(target
, stm8
->flash_iapsr
, data
);
675 static int stm8_unlock_eeprom(struct target
*target
)
679 struct stm8_common
*stm8
= target_to_stm8(target
);
681 /* check if eeprom is unlocked */
682 stm8_read_u8(target
, stm8
->flash_iapsr
, data
);
683 if (~data
[0] & DUL
) {
685 stm8_write_u8(target
, stm8
->flash_dukr
, 0xae);
686 stm8_write_u8(target
, stm8
->flash_dukr
, 0x56);
689 stm8_read_u8(target
, stm8
->flash_iapsr
, data
);
695 static int stm8_write_flash(struct target
*target
, enum mem_type type
,
697 uint32_t size
, uint32_t count
, uint32_t blocksize_param
,
698 const uint8_t *buffer
)
700 struct stm8_common
*stm8
= target_to_stm8(target
);
705 uint32_t blocksize
= 0;
711 stm8_unlock_flash(target
);
714 stm8_unlock_eeprom(target
);
717 stm8_unlock_eeprom(target
);
721 LOG_ERROR("BUG: wrong mem_type %d", type
);
726 /* we don't support short writes */
731 bytecnt
= count
* size
;
734 if ((bytecnt
>= blocksize_param
) && ((address
& (blocksize_param
-1)) == 0)) {
736 stm8_write_u8(target
, stm8
->flash_cr2
, PRG
+ opt
);
737 if (stm8
->flash_ncr2
)
738 stm8_write_u8(target
, stm8
->flash_ncr2
, ~(PRG
+ opt
));
739 blocksize
= blocksize_param
;
741 if ((bytecnt
>= 4) && ((address
& 0x3) == 0)) {
743 stm8_write_u8(target
, stm8
->flash_cr2
, WPRG
+ opt
);
744 if (stm8
->flash_ncr2
)
745 stm8_write_u8(target
, stm8
->flash_ncr2
, ~(WPRG
+ opt
));
748 if (blocksize
!= 1) {
750 stm8_write_u8(target
, stm8
->flash_cr2
, opt
);
751 if (stm8
->flash_ncr2
)
752 stm8_write_u8(target
, stm8
->flash_ncr2
, ~opt
);
756 res
= stm8_adapter_write_memory(target
, address
, 1, blocksize
, buffer
);
759 address
+= blocksize
;
761 bytecnt
-= blocksize
;
763 /* lets hang here until end of program (EOP) */
764 for (i
= 0; i
< 16; i
++) {
765 stm8_read_u8(target
, stm8
->flash_iapsr
, &iapsr
);
775 /* disable write access */
776 res
= stm8_write_u8(target
, stm8
->flash_iapsr
, 0x0);
784 static int stm8_write_memory(struct target
*target
, target_addr_t address
,
785 uint32_t size
, uint32_t count
,
786 const uint8_t *buffer
)
788 struct stm8_common
*stm8
= target_to_stm8(target
);
790 LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR
791 ", size: 0x%8.8" PRIx32
792 ", count: 0x%8.8" PRIx32
,
793 address
, size
, count
);
795 if (target
->state
!= TARGET_HALTED
)
796 LOG_WARNING("target not halted");
800 if ((address
>= stm8
->flashstart
) && (address
<= stm8
->flashend
))
801 retval
= stm8_write_flash(target
, FLASH
, address
, size
, count
,
802 stm8
->blocksize
, buffer
);
803 else if ((address
>= stm8
->eepromstart
) && (address
<= stm8
->eepromend
))
804 retval
= stm8_write_flash(target
, EEPROM
, address
, size
, count
,
805 stm8
->blocksize
, buffer
);
806 else if ((address
>= stm8
->optionstart
) && (address
<= stm8
->optionend
))
807 retval
= stm8_write_flash(target
, OPTION
, address
, size
, count
, 0, buffer
);
809 retval
= stm8_adapter_write_memory(target
, address
, size
, count
,
812 if (retval
!= ERROR_OK
)
813 return ERROR_TARGET_FAILURE
;
818 static int stm8_read_memory(struct target
*target
, target_addr_t address
,
819 uint32_t size
, uint32_t count
, uint8_t *buffer
)
821 LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR
822 ", size: 0x%8.8" PRIx32
823 ", count: 0x%8.8" PRIx32
,
824 address
, size
, count
);
826 if (target
->state
!= TARGET_HALTED
)
827 LOG_WARNING("target not halted");
830 retval
= stm8_adapter_read_memory(target
, address
, size
, count
, buffer
);
832 if (retval
!= ERROR_OK
)
833 return ERROR_TARGET_FAILURE
;
838 static int stm8_init(struct command_context
*cmd_ctx
, struct target
*target
)
840 stm8_build_reg_cache(target
);
845 static int stm8_poll(struct target
*target
)
847 int retval
= ERROR_OK
;
851 LOG_DEBUG("target->state=%d", target
->state
);
854 /* read dm_csrx control regs */
855 retval
= stm8_read_dm_csrx(target
, &csr1
, &csr2
);
856 if (retval
!= ERROR_OK
) {
857 LOG_DEBUG("stm8_read_dm_csrx failed retval=%d", retval
);
859 We return ERROR_OK here even if we didn't get an answer.
860 openocd will call target_wait_state until we get target state TARGET_HALTED
865 /* check for processor halted */
867 if (target
->state
!= TARGET_HALTED
) {
868 if (target
->state
== TARGET_UNKNOWN
)
869 LOG_DEBUG("DM_CSR2_STALL already set during server startup.");
871 retval
= stm8_debug_entry(target
);
872 if (retval
!= ERROR_OK
) {
873 LOG_DEBUG("stm8_debug_entry failed retval=%d", retval
);
874 return ERROR_TARGET_FAILURE
;
877 if (target
->state
== TARGET_DEBUG_RUNNING
) {
878 target
->state
= TARGET_HALTED
;
879 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
881 target
->state
= TARGET_HALTED
;
882 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
886 target
->state
= TARGET_RUNNING
;
888 LOG_DEBUG("csr1 = 0x%02X csr2 = 0x%02X", csr1
, csr2
);
893 static int stm8_halt(struct target
*target
)
895 LOG_DEBUG("target->state: %s", target_state_name(target
));
897 if (target
->state
== TARGET_HALTED
) {
898 LOG_DEBUG("target was already halted");
902 if (target
->state
== TARGET_UNKNOWN
)
903 LOG_WARNING("target was in unknown state when halt was requested");
905 if (target
->state
== TARGET_RESET
) {
906 /* we came here in a reset_halt or reset_init sequence
907 * debug entry was already prepared in stm8_assert_reset()
909 target
->debug_reason
= DBG_REASON_DBGRQ
;
915 /* break processor */
916 stm8_debug_stall(target
);
918 target
->debug_reason
= DBG_REASON_DBGRQ
;
923 static int stm8_reset_assert(struct target
*target
)
926 struct hl_interface_s
*adapter
= target_to_adapter(target
);
927 struct stm8_common
*stm8
= target_to_stm8(target
);
928 bool use_srst_fallback
= true;
930 enum reset_types jtag_reset_config
= jtag_get_reset_config();
932 if (jtag_reset_config
& RESET_HAS_SRST
) {
933 jtag_add_reset(0, 1);
934 res
= adapter
->layout
->api
->assert_srst(adapter
->handle
, 0);
937 /* hardware srst supported */
938 use_srst_fallback
= false;
939 else if (res
!= ERROR_COMMAND_NOTFOUND
)
940 /* some other failure */
944 if (use_srst_fallback
) {
945 LOG_DEBUG("Hardware srst not supported, falling back to swim reset");
946 res
= adapter
->layout
->api
->reset(adapter
->handle
);
951 /* registers are now invalid */
952 register_cache_invalidate(stm8
->core_cache
);
954 target
->state
= TARGET_RESET
;
955 target
->debug_reason
= DBG_REASON_NOTHALTED
;
957 if (target
->reset_halt
) {
958 res
= target_halt(target
);
966 static int stm8_reset_deassert(struct target
*target
)
969 struct hl_interface_s
*adapter
= target_to_adapter(target
);
971 enum reset_types jtag_reset_config
= jtag_get_reset_config();
973 if (jtag_reset_config
& RESET_HAS_SRST
) {
974 res
= adapter
->layout
->api
->assert_srst(adapter
->handle
, 1);
975 if ((res
!= ERROR_OK
) && (res
!= ERROR_COMMAND_NOTFOUND
))
979 /* virtual deassert reset, we need it for the internal
982 jtag_add_reset(0, 0);
984 /* The cpu should now be stalled. If halt was requested
985 let poll detect the stall */
986 if (target
->reset_halt
)
989 /* Instead of going thrugh saving context, polling and
990 then resuming target again just clear stall and proceed. */
991 target
->state
= TARGET_RUNNING
;
992 return stm8_exit_debug(target
);
995 /* stm8_single_step_core() is only used for stepping over breakpoints
996 from stm8_resume() */
997 static int stm8_single_step_core(struct target
*target
)
999 struct stm8_common
*stm8
= target_to_stm8(target
);
1001 /* configure single step mode */
1002 stm8_config_step(target
, 1);
1004 /* disable interrupts while stepping */
1005 if (!stm8
->enable_step_irq
)
1006 stm8_enable_interrupts(target
, 0);
1008 /* exit debug mode */
1009 stm8_exit_debug(target
);
1011 stm8_debug_entry(target
);
1016 static int stm8_resume(struct target
*target
, int current
,
1017 target_addr_t address
, int handle_breakpoints
,
1018 int debug_execution
)
1020 struct stm8_common
*stm8
= target_to_stm8(target
);
1021 struct breakpoint
*breakpoint
= NULL
;
1024 LOG_DEBUG("%d " TARGET_ADDR_FMT
" %d %d", current
, address
,
1025 handle_breakpoints
, debug_execution
);
1027 if (target
->state
!= TARGET_HALTED
) {
1028 LOG_WARNING("target not halted");
1029 return ERROR_TARGET_NOT_HALTED
;
1032 if (!debug_execution
) {
1033 target_free_all_working_areas(target
);
1034 stm8_enable_breakpoints(target
);
1035 stm8_enable_watchpoints(target
);
1036 struct stm8_comparator
*comparator_list
= stm8
->hw_break_list
;
1037 stm8_set_hwbreak(target
, comparator_list
);
1040 /* current = 1: continue on current pc,
1041 otherwise continue at <address> */
1043 buf_set_u32(stm8
->core_cache
->reg_list
[STM8_PC
].value
,
1045 stm8
->core_cache
->reg_list
[STM8_PC
].dirty
= true;
1046 stm8
->core_cache
->reg_list
[STM8_PC
].valid
= true;
1050 resume_pc
= address
;
1052 resume_pc
= buf_get_u32(
1053 stm8
->core_cache
->reg_list
[STM8_PC
].value
,
1056 stm8_restore_context(target
);
1058 /* the front-end may request us not to handle breakpoints */
1059 if (handle_breakpoints
) {
1060 /* Single step past breakpoint at current address */
1061 breakpoint
= breakpoint_find(target
, resume_pc
);
1063 LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT
,
1064 breakpoint
->address
);
1065 stm8_unset_breakpoint(target
, breakpoint
);
1066 stm8_single_step_core(target
);
1067 stm8_set_breakpoint(target
, breakpoint
);
1071 /* disable interrupts if we are debugging */
1072 if (debug_execution
)
1073 stm8_enable_interrupts(target
, 0);
1075 /* exit debug mode */
1076 stm8_exit_debug(target
);
1077 target
->debug_reason
= DBG_REASON_NOTHALTED
;
1079 /* registers are now invalid */
1080 register_cache_invalidate(stm8
->core_cache
);
1082 if (!debug_execution
) {
1083 target
->state
= TARGET_RUNNING
;
1084 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
1085 LOG_DEBUG("target resumed at 0x%" PRIx32
"", resume_pc
);
1087 target
->state
= TARGET_DEBUG_RUNNING
;
1088 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
1089 LOG_DEBUG("target debug resumed at 0x%" PRIx32
"", resume_pc
);
1095 static int stm8_init_flash_regs(bool enable_stm8l
, struct stm8_common
*stm8
)
1097 stm8
->enable_stm8l
= enable_stm8l
;
1099 if (stm8
->enable_stm8l
) {
1100 stm8
->flash_cr2
= FLASH_CR2_STM8L
;
1101 stm8
->flash_ncr2
= FLASH_NCR2_STM8L
;
1102 stm8
->flash_iapsr
= FLASH_IAPSR_STM8L
;
1103 stm8
->flash_dukr
= FLASH_DUKR_STM8L
;
1104 stm8
->flash_pukr
= FLASH_PUKR_STM8L
;
1106 stm8
->flash_cr2
= FLASH_CR2_STM8S
;
1107 stm8
->flash_ncr2
= FLASH_NCR2_STM8S
;
1108 stm8
->flash_iapsr
= FLASH_IAPSR_STM8S
;
1109 stm8
->flash_dukr
= FLASH_DUKR_STM8S
;
1110 stm8
->flash_pukr
= FLASH_PUKR_STM8S
;
1115 static int stm8_init_arch_info(struct target
*target
,
1116 struct stm8_common
*stm8
, struct jtag_tap
*tap
)
1118 target
->endianness
= TARGET_BIG_ENDIAN
;
1119 target
->arch_info
= stm8
;
1120 stm8
->common_magic
= STM8_COMMON_MAGIC
;
1121 stm8
->fast_data_area
= NULL
;
1122 stm8
->blocksize
= 0x80;
1123 stm8
->flashstart
= 0x8000;
1124 stm8
->flashend
= 0xffff;
1125 stm8
->eepromstart
= 0x4000;
1126 stm8
->eepromend
= 0x43ff;
1127 stm8
->optionstart
= 0x4800;
1128 stm8
->optionend
= 0x487F;
1130 /* has breakpoint/watchpoint unit been scanned */
1131 stm8
->bp_scanned
= false;
1132 stm8
->hw_break_list
= NULL
;
1134 stm8
->read_core_reg
= stm8_read_core_reg
;
1135 stm8
->write_core_reg
= stm8_write_core_reg
;
1137 stm8_init_flash_regs(0, stm8
);
1142 static int stm8_target_create(struct target
*target
,
1146 struct stm8_common
*stm8
= calloc(1, sizeof(struct stm8_common
));
1148 stm8_init_arch_info(target
, stm8
, target
->tap
);
1149 stm8_configure_break_unit(target
);
1154 static int stm8_read_core_reg(struct target
*target
, unsigned int num
)
1158 /* get pointers to arch-specific information */
1159 struct stm8_common
*stm8
= target_to_stm8(target
);
1161 if (num
>= STM8_NUM_REGS
)
1162 return ERROR_COMMAND_SYNTAX_ERROR
;
1164 reg_value
= stm8
->core_regs
[num
];
1165 LOG_DEBUG("read core reg %i value 0x%" PRIx32
"", num
, reg_value
);
1166 buf_set_u32(stm8
->core_cache
->reg_list
[num
].value
, 0, 32, reg_value
);
1167 stm8
->core_cache
->reg_list
[num
].valid
= true;
1168 stm8
->core_cache
->reg_list
[num
].dirty
= false;
1173 static int stm8_write_core_reg(struct target
*target
, unsigned int num
)
1177 /* get pointers to arch-specific information */
1178 struct stm8_common
*stm8
= target_to_stm8(target
);
1180 if (num
>= STM8_NUM_REGS
)
1181 return ERROR_COMMAND_SYNTAX_ERROR
;
1183 reg_value
= buf_get_u32(stm8
->core_cache
->reg_list
[num
].value
, 0, 32);
1184 stm8
->core_regs
[num
] = reg_value
;
1185 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", num
, reg_value
);
1186 stm8
->core_cache
->reg_list
[num
].valid
= true;
1187 stm8
->core_cache
->reg_list
[num
].dirty
= false;
1192 static int stm8_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[],
1193 int *reg_list_size
, enum target_register_class reg_class
)
1195 /* get pointers to arch-specific information */
1196 struct stm8_common
*stm8
= target_to_stm8(target
);
1199 *reg_list_size
= STM8_NUM_REGS
;
1200 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
1202 for (i
= 0; i
< STM8_NUM_REGS
; i
++)
1203 (*reg_list
)[i
] = &stm8
->core_cache
->reg_list
[i
];
1208 static const struct reg_arch_type stm8_reg_type
= {
1209 .get
= stm8_get_core_reg
,
1210 .set
= stm8_set_core_reg
,
1213 static struct reg_cache
*stm8_build_reg_cache(struct target
*target
)
1215 /* get pointers to arch-specific information */
1216 struct stm8_common
*stm8
= target_to_stm8(target
);
1218 int num_regs
= STM8_NUM_REGS
;
1219 struct reg_cache
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
1220 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
1221 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
1222 struct stm8_core_reg
*arch_info
= malloc(
1223 sizeof(struct stm8_core_reg
) * num_regs
);
1224 struct reg_feature
*feature
;
1227 /* Build the process context cache */
1228 cache
->name
= "stm8 registers";
1230 cache
->reg_list
= reg_list
;
1231 cache
->num_regs
= num_regs
;
1233 stm8
->core_cache
= cache
;
1235 for (i
= 0; i
< num_regs
; i
++) {
1236 arch_info
[i
].num
= stm8_regs
[i
].id
;
1237 arch_info
[i
].target
= target
;
1238 arch_info
[i
].stm8_common
= stm8
;
1240 reg_list
[i
].name
= stm8_regs
[i
].name
;
1241 reg_list
[i
].size
= stm8_regs
[i
].bits
;
1243 reg_list
[i
].value
= calloc(1, 4);
1244 reg_list
[i
].valid
= false;
1245 reg_list
[i
].type
= &stm8_reg_type
;
1246 reg_list
[i
].arch_info
= &arch_info
[i
];
1248 reg_list
[i
].reg_data_type
= calloc(1, sizeof(struct reg_data_type
));
1249 if (reg_list
[i
].reg_data_type
)
1250 reg_list
[i
].reg_data_type
->type
= stm8_regs
[i
].type
;
1252 LOG_ERROR("unable to allocate reg type list");
1256 reg_list
[i
].dirty
= false;
1257 reg_list
[i
].group
= stm8_regs
[i
].group
;
1258 reg_list
[i
].number
= stm8_regs
[i
].id
;
1259 reg_list
[i
].exist
= true;
1260 reg_list
[i
].caller_save
= true; /* gdb defaults to true */
1262 feature
= calloc(1, sizeof(struct reg_feature
));
1264 feature
->name
= stm8_regs
[i
].feature
;
1265 reg_list
[i
].feature
= feature
;
1267 LOG_ERROR("unable to allocate feature list");
1273 static void stm8_free_reg_cache(struct target
*target
)
1275 struct stm8_common
*stm8
= target_to_stm8(target
);
1276 struct reg_cache
*cache
;
1280 cache
= stm8
->core_cache
;
1285 for (i
= 0; i
< cache
->num_regs
; i
++) {
1286 reg
= &cache
->reg_list
[i
];
1289 free(reg
->reg_data_type
);
1293 free(cache
->reg_list
[0].arch_info
);
1294 free(cache
->reg_list
);
1297 stm8
->core_cache
= NULL
;
1300 static void stm8_deinit(struct target
*target
)
1302 struct stm8_common
*stm8
= target_to_stm8(target
);
1304 free(stm8
->hw_break_list
);
1306 stm8_free_reg_cache(target
);
1311 static int stm8_arch_state(struct target
*target
)
1313 struct stm8_common
*stm8
= target_to_stm8(target
);
1315 LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32
"",
1316 debug_reason_name(target
),
1317 buf_get_u32(stm8
->core_cache
->reg_list
[STM8_PC
].value
, 0, 32));
1322 static int stm8_step(struct target
*target
, int current
,
1323 target_addr_t address
, int handle_breakpoints
)
1325 LOG_DEBUG("%" PRIx32
" " TARGET_ADDR_FMT
" %" PRIx32
,
1326 current
, address
, handle_breakpoints
);
1328 /* get pointers to arch-specific information */
1329 struct stm8_common
*stm8
= target_to_stm8(target
);
1330 struct breakpoint
*breakpoint
= NULL
;
1332 if (target
->state
!= TARGET_HALTED
) {
1333 LOG_WARNING("target not halted");
1334 return ERROR_TARGET_NOT_HALTED
;
1337 /* current = 1: continue on current pc, otherwise continue at <address> */
1339 buf_set_u32(stm8
->core_cache
->reg_list
[STM8_PC
].value
, 0, 32, address
);
1340 stm8
->core_cache
->reg_list
[STM8_PC
].dirty
= true;
1341 stm8
->core_cache
->reg_list
[STM8_PC
].valid
= true;
1344 /* the front-end may request us not to handle breakpoints */
1345 if (handle_breakpoints
) {
1346 breakpoint
= breakpoint_find(target
,
1347 buf_get_u32(stm8
->core_cache
->reg_list
[STM8_PC
].value
, 0, 32));
1349 stm8_unset_breakpoint(target
, breakpoint
);
1352 /* restore context */
1353 stm8_restore_context(target
);
1355 /* configure single step mode */
1356 stm8_config_step(target
, 1);
1358 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
1360 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
1362 /* disable interrupts while stepping */
1363 if (!stm8
->enable_step_irq
)
1364 stm8_enable_interrupts(target
, 0);
1366 /* exit debug mode */
1367 stm8_exit_debug(target
);
1369 /* registers are now invalid */
1370 register_cache_invalidate(stm8
->core_cache
);
1372 LOG_DEBUG("target stepped ");
1373 stm8_debug_entry(target
);
1376 stm8_set_breakpoint(target
, breakpoint
);
1378 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
1383 static void stm8_enable_breakpoints(struct target
*target
)
1385 struct breakpoint
*breakpoint
= target
->breakpoints
;
1387 /* set any pending breakpoints */
1388 while (breakpoint
) {
1389 if (breakpoint
->set
== 0)
1390 stm8_set_breakpoint(target
, breakpoint
);
1391 breakpoint
= breakpoint
->next
;
1395 static int stm8_set_breakpoint(struct target
*target
,
1396 struct breakpoint
*breakpoint
)
1398 struct stm8_common
*stm8
= target_to_stm8(target
);
1399 struct stm8_comparator
*comparator_list
= stm8
->hw_break_list
;
1402 if (breakpoint
->set
) {
1403 LOG_WARNING("breakpoint already set");
1407 if (breakpoint
->type
== BKPT_HARD
) {
1410 while (comparator_list
[bp_num
].used
&& (bp_num
< stm8
->num_hw_bpoints
))
1412 if (bp_num
>= stm8
->num_hw_bpoints
) {
1413 LOG_ERROR("Can not find free breakpoint register (bpid: %" PRIu32
")",
1414 breakpoint
->unique_id
);
1415 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1417 breakpoint
->set
= bp_num
+ 1;
1418 comparator_list
[bp_num
].used
= true;
1419 comparator_list
[bp_num
].bp_value
= breakpoint
->address
;
1420 comparator_list
[bp_num
].type
= HWBRK_EXEC
;
1422 retval
= stm8_set_hwbreak(target
, comparator_list
);
1423 if (retval
!= ERROR_OK
)
1426 LOG_DEBUG("bpid: %" PRIu32
", bp_num %i bp_value 0x%" PRIx32
"",
1427 breakpoint
->unique_id
,
1428 bp_num
, comparator_list
[bp_num
].bp_value
);
1429 } else if (breakpoint
->type
== BKPT_SOFT
) {
1430 LOG_DEBUG("bpid: %" PRIu32
, breakpoint
->unique_id
);
1431 if (breakpoint
->length
== 1) {
1432 uint8_t verify
= 0x55;
1434 retval
= target_read_u8(target
, breakpoint
->address
,
1435 breakpoint
->orig_instr
);
1436 if (retval
!= ERROR_OK
)
1438 retval
= target_write_u8(target
, breakpoint
->address
, STM8_BREAK
);
1439 if (retval
!= ERROR_OK
)
1442 retval
= target_read_u8(target
, breakpoint
->address
, &verify
);
1443 if (retval
!= ERROR_OK
)
1445 if (verify
!= STM8_BREAK
) {
1446 LOG_ERROR("Unable to set breakpoint at address " TARGET_ADDR_FMT
1447 " - check that memory is read/writable",
1448 breakpoint
->address
);
1449 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1452 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1454 breakpoint
->set
= 1; /* Any nice value but 0 */
1460 static int stm8_add_breakpoint(struct target
*target
,
1461 struct breakpoint
*breakpoint
)
1463 struct stm8_common
*stm8
= target_to_stm8(target
);
1466 if (breakpoint
->type
== BKPT_HARD
) {
1467 if (stm8
->num_hw_bpoints_avail
< 1) {
1468 LOG_INFO("no hardware breakpoint available");
1469 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1472 ret
= stm8_set_breakpoint(target
, breakpoint
);
1473 if (ret
!= ERROR_OK
)
1476 stm8
->num_hw_bpoints_avail
--;
1480 ret
= stm8_set_breakpoint(target
, breakpoint
);
1481 if (ret
!= ERROR_OK
)
1487 static int stm8_unset_breakpoint(struct target
*target
,
1488 struct breakpoint
*breakpoint
)
1490 /* get pointers to arch-specific information */
1491 struct stm8_common
*stm8
= target_to_stm8(target
);
1492 struct stm8_comparator
*comparator_list
= stm8
->hw_break_list
;
1495 if (!breakpoint
->set
) {
1496 LOG_WARNING("breakpoint not set");
1500 if (breakpoint
->type
== BKPT_HARD
) {
1501 int bp_num
= breakpoint
->set
- 1;
1502 if ((bp_num
< 0) || (bp_num
>= stm8
->num_hw_bpoints
)) {
1503 LOG_DEBUG("Invalid comparator number in breakpoint (bpid: %" PRIu32
")",
1504 breakpoint
->unique_id
);
1507 LOG_DEBUG("bpid: %" PRIu32
" - releasing hw: %d",
1508 breakpoint
->unique_id
,
1510 comparator_list
[bp_num
].used
= false;
1511 retval
= stm8_set_hwbreak(target
, comparator_list
);
1512 if (retval
!= ERROR_OK
)
1515 /* restore original instruction (kept in target endianness) */
1516 LOG_DEBUG("bpid: %" PRIu32
, breakpoint
->unique_id
);
1517 if (breakpoint
->length
== 1) {
1518 uint8_t current_instr
;
1520 /* check that user program has not
1521 modified breakpoint instruction */
1522 retval
= target_read_memory(target
, breakpoint
->address
, 1, 1,
1523 (uint8_t *)¤t_instr
);
1524 if (retval
!= ERROR_OK
)
1527 if (current_instr
== STM8_BREAK
) {
1528 retval
= target_write_memory(target
, breakpoint
->address
, 1, 1,
1529 breakpoint
->orig_instr
);
1530 if (retval
!= ERROR_OK
)
1536 breakpoint
->set
= 0;
1541 static int stm8_remove_breakpoint(struct target
*target
,
1542 struct breakpoint
*breakpoint
)
1544 /* get pointers to arch-specific information */
1545 struct stm8_common
*stm8
= target_to_stm8(target
);
1547 if (target
->state
!= TARGET_HALTED
) {
1548 LOG_WARNING("target not halted");
1549 return ERROR_TARGET_NOT_HALTED
;
1552 if (breakpoint
->set
)
1553 stm8_unset_breakpoint(target
, breakpoint
);
1555 if (breakpoint
->type
== BKPT_HARD
)
1556 stm8
->num_hw_bpoints_avail
++;
1561 static int stm8_set_watchpoint(struct target
*target
,
1562 struct watchpoint
*watchpoint
)
1564 struct stm8_common
*stm8
= target_to_stm8(target
);
1565 struct stm8_comparator
*comparator_list
= stm8
->hw_break_list
;
1569 if (watchpoint
->set
) {
1570 LOG_WARNING("watchpoint already set");
1574 while (comparator_list
[wp_num
].used
&& (wp_num
< stm8
->num_hw_bpoints
))
1576 if (wp_num
>= stm8
->num_hw_bpoints
) {
1577 LOG_ERROR("Can not find free hw breakpoint");
1578 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1581 if (watchpoint
->length
!= 1) {
1582 LOG_ERROR("Only watchpoints of length 1 are supported");
1583 return ERROR_TARGET_UNALIGNED_ACCESS
;
1586 enum hw_break_type enable
= 0;
1588 switch (watchpoint
->rw
) {
1599 LOG_ERROR("BUG: watchpoint->rw neither read, write nor access");
1602 comparator_list
[wp_num
].used
= true;
1603 comparator_list
[wp_num
].bp_value
= watchpoint
->address
;
1604 comparator_list
[wp_num
].type
= enable
;
1606 ret
= stm8_set_hwbreak(target
, comparator_list
);
1607 if (ret
!= ERROR_OK
) {
1608 comparator_list
[wp_num
].used
= false;
1612 watchpoint
->set
= wp_num
+ 1;
1614 LOG_DEBUG("wp_num %i bp_value 0x%" PRIx32
"",
1616 comparator_list
[wp_num
].bp_value
);
1621 static int stm8_add_watchpoint(struct target
*target
,
1622 struct watchpoint
*watchpoint
)
1625 struct stm8_common
*stm8
= target_to_stm8(target
);
1627 if (stm8
->num_hw_bpoints_avail
< 1) {
1628 LOG_INFO("no hardware watchpoints available");
1629 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1632 ret
= stm8_set_watchpoint(target
, watchpoint
);
1633 if (ret
!= ERROR_OK
)
1636 stm8
->num_hw_bpoints_avail
--;
1640 static void stm8_enable_watchpoints(struct target
*target
)
1642 struct watchpoint
*watchpoint
= target
->watchpoints
;
1644 /* set any pending watchpoints */
1645 while (watchpoint
) {
1646 if (watchpoint
->set
== 0)
1647 stm8_set_watchpoint(target
, watchpoint
);
1648 watchpoint
= watchpoint
->next
;
1652 static int stm8_unset_watchpoint(struct target
*target
,
1653 struct watchpoint
*watchpoint
)
1655 /* get pointers to arch-specific information */
1656 struct stm8_common
*stm8
= target_to_stm8(target
);
1657 struct stm8_comparator
*comparator_list
= stm8
->hw_break_list
;
1659 if (!watchpoint
->set
) {
1660 LOG_WARNING("watchpoint not set");
1664 int wp_num
= watchpoint
->set
- 1;
1665 if ((wp_num
< 0) || (wp_num
>= stm8
->num_hw_bpoints
)) {
1666 LOG_DEBUG("Invalid hw comparator number in watchpoint");
1669 comparator_list
[wp_num
].used
= false;
1670 watchpoint
->set
= 0;
1672 stm8_set_hwbreak(target
, comparator_list
);
1677 static int stm8_remove_watchpoint(struct target
*target
,
1678 struct watchpoint
*watchpoint
)
1680 /* get pointers to arch-specific information */
1681 struct stm8_common
*stm8
= target_to_stm8(target
);
1683 if (target
->state
!= TARGET_HALTED
) {
1684 LOG_WARNING("target not halted");
1685 return ERROR_TARGET_NOT_HALTED
;
1688 if (watchpoint
->set
)
1689 stm8_unset_watchpoint(target
, watchpoint
);
1691 stm8
->num_hw_bpoints_avail
++;
1696 static int stm8_examine(struct target
*target
)
1700 /* get pointers to arch-specific information */
1701 struct stm8_common
*stm8
= target_to_stm8(target
);
1702 struct hl_interface_s
*adapter
= target_to_adapter(target
);
1704 if (!target_was_examined(target
)) {
1705 if (!stm8
->swim_configured
) {
1706 /* set SWIM_CSR = 0xa0 (enable mem access & mask reset) */
1707 LOG_DEBUG("writing A0 to SWIM_CSR (SAFE_MASK + SWIM_DM)");
1708 retval
= stm8_write_u8(target
, SWIM_CSR
, SAFE_MASK
+ SWIM_DM
);
1709 if (retval
!= ERROR_OK
)
1711 /* set high speed */
1712 LOG_DEBUG("writing B0 to SWIM_CSR (SAFE_MASK + SWIM_DM + HS)");
1713 retval
= stm8_write_u8(target
, SWIM_CSR
, SAFE_MASK
+ SWIM_DM
+ HS
);
1714 if (retval
!= ERROR_OK
)
1716 retval
= stm8_set_speed(target
, 1);
1717 if (retval
== ERROR_OK
)
1718 stm8
->swim_configured
= true;
1720 Now is the time to deassert reset if connect_under_reset.
1721 Releasing reset line will cause the option bytes to load.
1722 The core will still be stalled.
1724 if (adapter
->param
.connect_under_reset
)
1725 stm8_reset_deassert(target
);
1727 LOG_INFO("trying to reconnect");
1729 retval
= adapter
->layout
->api
->state(adapter
->handle
);
1730 if (retval
!= ERROR_OK
) {
1731 LOG_ERROR("reconnect failed");
1735 /* read dm_csrx control regs */
1736 retval
= stm8_read_dm_csrx(target
, &csr1
, &csr2
);
1737 if (retval
!= ERROR_OK
) {
1738 LOG_ERROR("state query failed");
1743 target_set_examined(target
);
1751 /** Checks whether a memory region is erased. */
1752 static int stm8_blank_check_memory(struct target
*target
,
1753 struct target_memory_check_block
*blocks
, int num_blocks
, uint8_t erased_value
)
1755 struct working_area
*erase_check_algorithm
;
1756 struct reg_param reg_params
[2];
1757 struct mem_param mem_params
[2];
1758 struct stm8_algorithm stm8_info
;
1760 static const uint8_t stm8_erase_check_code
[] = {
1761 #include "../../contrib/loaders/erase_check/stm8_erase_check.inc"
1764 if (erased_value
!= 0xff) {
1765 LOG_ERROR("Erase value 0x%02" PRIx8
" not yet supported for STM8",
1770 /* make sure we have a working area */
1771 if (target_alloc_working_area(target
, sizeof(stm8_erase_check_code
),
1772 &erase_check_algorithm
) != ERROR_OK
)
1773 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1775 target_write_buffer(target
, erase_check_algorithm
->address
,
1776 sizeof(stm8_erase_check_code
), stm8_erase_check_code
);
1778 stm8_info
.common_magic
= STM8_COMMON_MAGIC
;
1780 init_mem_param(&mem_params
[0], 0x0, 3, PARAM_OUT
);
1781 buf_set_u32(mem_params
[0].value
, 0, 24, blocks
[0].address
);
1783 init_mem_param(&mem_params
[1], 0x3, 3, PARAM_OUT
);
1784 buf_set_u32(mem_params
[1].value
, 0, 24, blocks
[0].size
);
1786 init_reg_param(®_params
[0], "a", 32, PARAM_IN_OUT
);
1787 buf_set_u32(reg_params
[0].value
, 0, 32, erased_value
);
1789 init_reg_param(®_params
[1], "sp", 32, PARAM_OUT
);
1790 buf_set_u32(reg_params
[1].value
, 0, 32, erase_check_algorithm
->address
);
1792 int retval
= target_run_algorithm(target
, 2, mem_params
, 2, reg_params
,
1793 erase_check_algorithm
->address
+ 6,
1794 erase_check_algorithm
->address
+ (sizeof(stm8_erase_check_code
) - 1),
1797 if (retval
== ERROR_OK
)
1798 blocks
[0].result
= (*(reg_params
[0].value
) == 0xff);
1800 destroy_mem_param(&mem_params
[0]);
1801 destroy_mem_param(&mem_params
[1]);
1802 destroy_reg_param(®_params
[0]);
1804 target_free_working_area(target
, erase_check_algorithm
);
1806 if (retval
!= ERROR_OK
)
1809 return 1; /* only one block has been checked */
1812 static int stm8_checksum_memory(struct target
*target
, target_addr_t address
,
1813 uint32_t count
, uint32_t *checksum
)
1815 /* let image_calculate_checksum() take care of business */
1816 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1819 /* run to exit point. return error if exit point was not reached. */
1820 static int stm8_run_and_wait(struct target
*target
, uint32_t entry_point
,
1821 int timeout_ms
, uint32_t exit_point
, struct stm8_common
*stm8
)
1825 /* This code relies on the target specific resume() and
1826 poll()->debug_entry() sequence to write register values to the
1827 processor and the read them back */
1828 retval
= target_resume(target
, 0, entry_point
, 0, 1);
1829 if (retval
!= ERROR_OK
)
1832 retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
);
1833 /* If the target fails to halt due to the breakpoint, force a halt */
1834 if (retval
!= ERROR_OK
|| target
->state
!= TARGET_HALTED
) {
1835 retval
= target_halt(target
);
1836 if (retval
!= ERROR_OK
)
1838 retval
= target_wait_state(target
, TARGET_HALTED
, 500);
1839 if (retval
!= ERROR_OK
)
1841 return ERROR_TARGET_TIMEOUT
;
1844 pc
= buf_get_u32(stm8
->core_cache
->reg_list
[STM8_PC
].value
, 0, 32);
1845 if (exit_point
&& (pc
!= exit_point
)) {
1846 LOG_DEBUG("failed algorithm halted at 0x%" PRIx32
" ", pc
);
1847 return ERROR_TARGET_TIMEOUT
;
1853 static int stm8_run_algorithm(struct target
*target
, int num_mem_params
,
1854 struct mem_param
*mem_params
, int num_reg_params
,
1855 struct reg_param
*reg_params
, target_addr_t entry_point
,
1856 target_addr_t exit_point
, int timeout_ms
, void *arch_info
)
1858 struct stm8_common
*stm8
= target_to_stm8(target
);
1860 uint32_t context
[STM8_NUM_REGS
];
1861 int retval
= ERROR_OK
;
1863 LOG_DEBUG("Running algorithm");
1865 /* NOTE: stm8_run_algorithm requires that each
1866 algorithm uses a software breakpoint
1867 at the exit point */
1869 if (stm8
->common_magic
!= STM8_COMMON_MAGIC
) {
1870 LOG_ERROR("current target isn't a STM8 target");
1871 return ERROR_TARGET_INVALID
;
1874 if (target
->state
!= TARGET_HALTED
) {
1875 LOG_WARNING("target not halted");
1876 return ERROR_TARGET_NOT_HALTED
;
1879 /* refresh core register cache */
1880 for (unsigned int i
= 0; i
< STM8_NUM_REGS
; i
++) {
1881 if (!stm8
->core_cache
->reg_list
[i
].valid
)
1882 stm8
->read_core_reg(target
, i
);
1883 context
[i
] = buf_get_u32(stm8
->core_cache
->reg_list
[i
].value
, 0, 32);
1886 for (int i
= 0; i
< num_mem_params
; i
++) {
1887 retval
= target_write_buffer(target
, mem_params
[i
].address
,
1888 mem_params
[i
].size
, mem_params
[i
].value
);
1889 if (retval
!= ERROR_OK
)
1893 for (int i
= 0; i
< num_reg_params
; i
++) {
1894 struct reg
*reg
= register_get_by_name(stm8
->core_cache
,
1895 reg_params
[i
].reg_name
, 0);
1898 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
1899 return ERROR_COMMAND_SYNTAX_ERROR
;
1902 if (reg_params
[i
].size
!= 32) {
1903 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
1904 reg_params
[i
].reg_name
);
1905 return ERROR_COMMAND_SYNTAX_ERROR
;
1908 stm8_set_core_reg(reg
, reg_params
[i
].value
);
1911 retval
= stm8_run_and_wait(target
, entry_point
,
1912 timeout_ms
, exit_point
, stm8
);
1914 if (retval
!= ERROR_OK
)
1917 for (int i
= 0; i
< num_mem_params
; i
++) {
1918 if (mem_params
[i
].direction
!= PARAM_OUT
) {
1919 retval
= target_read_buffer(target
, mem_params
[i
].address
,
1920 mem_params
[i
].size
, mem_params
[i
].value
);
1921 if (retval
!= ERROR_OK
)
1926 for (int i
= 0; i
< num_reg_params
; i
++) {
1927 if (reg_params
[i
].direction
!= PARAM_OUT
) {
1928 struct reg
*reg
= register_get_by_name(stm8
->core_cache
,
1929 reg_params
[i
].reg_name
, 0);
1931 LOG_ERROR("BUG: register '%s' not found",
1932 reg_params
[i
].reg_name
);
1933 return ERROR_COMMAND_SYNTAX_ERROR
;
1936 if (reg_params
[i
].size
!= 32) {
1937 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
1938 reg_params
[i
].reg_name
);
1939 return ERROR_COMMAND_SYNTAX_ERROR
;
1942 buf_set_u32(reg_params
[i
].value
,
1943 0, 32, buf_get_u32(reg
->value
, 0, 32));
1947 /* restore everything we saved before */
1948 for (unsigned int i
= 0; i
< STM8_NUM_REGS
; i
++) {
1950 regvalue
= buf_get_u32(stm8
->core_cache
->reg_list
[i
].value
, 0, 32);
1951 if (regvalue
!= context
[i
]) {
1952 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
,
1953 stm8
->core_cache
->reg_list
[i
].name
, context
[i
]);
1954 buf_set_u32(stm8
->core_cache
->reg_list
[i
].value
,
1956 stm8
->core_cache
->reg_list
[i
].valid
= true;
1957 stm8
->core_cache
->reg_list
[i
].dirty
= true;
1964 int stm8_jim_configure(struct target
*target
, Jim_GetOptInfo
*goi
)
1966 struct stm8_common
*stm8
= target_to_stm8(target
);
1971 arg
= Jim_GetString(goi
->argv
[0], NULL
);
1972 if (!strcmp(arg
, "-blocksize")) {
1973 e
= Jim_GetOpt_String(goi
, &arg
, NULL
);
1977 if (goi
->argc
== 0) {
1978 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
,
1979 "-blocksize ?bytes? ...");
1983 e
= Jim_GetOpt_Wide(goi
, &w
);
1987 stm8
->blocksize
= w
;
1988 LOG_DEBUG("blocksize=%8.8x", stm8
->blocksize
);
1991 if (!strcmp(arg
, "-flashstart")) {
1992 e
= Jim_GetOpt_String(goi
, &arg
, NULL
);
1996 if (goi
->argc
== 0) {
1997 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
,
1998 "-flashstart ?address? ...");
2002 e
= Jim_GetOpt_Wide(goi
, &w
);
2006 stm8
->flashstart
= w
;
2007 LOG_DEBUG("flashstart=%8.8x", stm8
->flashstart
);
2010 if (!strcmp(arg
, "-flashend")) {
2011 e
= Jim_GetOpt_String(goi
, &arg
, NULL
);
2015 if (goi
->argc
== 0) {
2016 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
,
2017 "-flashend ?address? ...");
2021 e
= Jim_GetOpt_Wide(goi
, &w
);
2026 LOG_DEBUG("flashend=%8.8x", stm8
->flashend
);
2029 if (!strcmp(arg
, "-eepromstart")) {
2030 e
= Jim_GetOpt_String(goi
, &arg
, NULL
);
2034 if (goi
->argc
== 0) {
2035 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
,
2036 "-eepromstart ?address? ...");
2040 e
= Jim_GetOpt_Wide(goi
, &w
);
2044 stm8
->eepromstart
= w
;
2045 LOG_DEBUG("eepromstart=%8.8x", stm8
->eepromstart
);
2048 if (!strcmp(arg
, "-eepromend")) {
2049 e
= Jim_GetOpt_String(goi
, &arg
, NULL
);
2053 if (goi
->argc
== 0) {
2054 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
,
2055 "-eepromend ?address? ...");
2059 e
= Jim_GetOpt_Wide(goi
, &w
);
2063 stm8
->eepromend
= w
;
2064 LOG_DEBUG("eepromend=%8.8x", stm8
->eepromend
);
2067 if (!strcmp(arg
, "-optionstart")) {
2068 e
= Jim_GetOpt_String(goi
, &arg
, NULL
);
2072 if (goi
->argc
== 0) {
2073 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
,
2074 "-optionstart ?address? ...");
2078 e
= Jim_GetOpt_Wide(goi
, &w
);
2082 stm8
->optionstart
= w
;
2083 LOG_DEBUG("optionstart=%8.8x", stm8
->optionstart
);
2086 if (!strcmp(arg
, "-optionend")) {
2087 e
= Jim_GetOpt_String(goi
, &arg
, NULL
);
2091 if (goi
->argc
== 0) {
2092 Jim_WrongNumArgs(goi
->interp
, goi
->argc
, goi
->argv
,
2093 "-optionend ?address? ...");
2097 e
= Jim_GetOpt_Wide(goi
, &w
);
2101 stm8
->optionend
= w
;
2102 LOG_DEBUG("optionend=%8.8x", stm8
->optionend
);
2105 if (!strcmp(arg
, "-enable_step_irq")) {
2106 e
= Jim_GetOpt_String(goi
, &arg
, NULL
);
2110 stm8
->enable_step_irq
= true;
2111 LOG_DEBUG("enable_step_irq=%8.8x", stm8
->enable_step_irq
);
2114 if (!strcmp(arg
, "-enable_stm8l")) {
2115 e
= Jim_GetOpt_String(goi
, &arg
, NULL
);
2119 stm8
->enable_stm8l
= true;
2120 LOG_DEBUG("enable_stm8l=%8.8x", stm8
->enable_stm8l
);
2121 stm8_init_flash_regs(stm8
->enable_stm8l
, stm8
);
2124 return JIM_CONTINUE
;
2127 COMMAND_HANDLER(stm8_handle_enable_step_irq_command
)
2130 struct target
*target
= get_current_target(CMD_CTX
);
2131 struct stm8_common
*stm8
= target_to_stm8(target
);
2132 bool enable
= stm8
->enable_step_irq
;
2135 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], enable
);
2136 stm8
->enable_step_irq
= enable
;
2138 msg
= stm8
->enable_step_irq
? "enabled" : "disabled";
2139 command_print(CMD_CTX
, "enable_step_irq = %s", msg
);
2143 COMMAND_HANDLER(stm8_handle_enable_stm8l_command
)
2146 struct target
*target
= get_current_target(CMD_CTX
);
2147 struct stm8_common
*stm8
= target_to_stm8(target
);
2148 bool enable
= stm8
->enable_stm8l
;
2151 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], enable
);
2152 stm8
->enable_stm8l
= enable
;
2154 msg
= stm8
->enable_stm8l
? "enabled" : "disabled";
2155 command_print(CMD_CTX
, "enable_stm8l = %s", msg
);
2156 stm8_init_flash_regs(stm8
->enable_stm8l
, stm8
);
2160 static const struct command_registration stm8_exec_command_handlers
[] = {
2162 .name
= "enable_step_irq",
2163 .handler
= stm8_handle_enable_step_irq_command
,
2164 .mode
= COMMAND_ANY
,
2165 .help
= "Enable/disable irq handling during step",
2169 .name
= "enable_stm8l",
2170 .handler
= stm8_handle_enable_stm8l_command
,
2171 .mode
= COMMAND_ANY
,
2172 .help
= "Enable/disable STM8L flash programming",
2175 COMMAND_REGISTRATION_DONE
2178 const struct command_registration stm8_command_handlers
[] = {
2181 .mode
= COMMAND_ANY
,
2182 .help
= "stm8 command group",
2184 .chain
= stm8_exec_command_handlers
,
2186 COMMAND_REGISTRATION_DONE
2189 struct target_type stm8_target
= {
2193 .arch_state
= stm8_arch_state
,
2196 .resume
= stm8_resume
,
2199 .assert_reset
= stm8_reset_assert
,
2200 .deassert_reset
= stm8_reset_deassert
,
2202 .get_gdb_reg_list
= stm8_get_gdb_reg_list
,
2204 .read_memory
= stm8_read_memory
,
2205 .write_memory
= stm8_write_memory
,
2206 .checksum_memory
= stm8_checksum_memory
,
2207 .blank_check_memory
= stm8_blank_check_memory
,
2209 .run_algorithm
= stm8_run_algorithm
,
2211 .add_breakpoint
= stm8_add_breakpoint
,
2212 .remove_breakpoint
= stm8_remove_breakpoint
,
2213 .add_watchpoint
= stm8_add_watchpoint
,
2214 .remove_watchpoint
= stm8_remove_watchpoint
,
2216 .commands
= stm8_command_handlers
,
2217 .target_create
= stm8_target_create
,
2218 .init_target
= stm8_init
,
2219 .examine
= stm8_examine
,
2221 .deinit_target
= stm8_deinit
,
2222 .target_jim_configure
= stm8_jim_configure
,
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)