STM8S: Debugging is normal, but burning program is not running normally

Publisher:荣耀使者Latest update time:2018-09-05 Source: eefocusKeywords:STM8S Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Recently, there is a project that needs to use the STM8S103F3 microcontroller. I thought it would be easy before I started, but in practice, I encountered many problems. One of the most confusing problems is that when I debug the program, the program can run normally, but when I burn the program into it and power off and restart, it does not run normally.


I tried many methods but couldn't find the problem. Finally, I changed the Start-up file to the default one. I saw somewhere that I could not use the default startup file of the system, and I could directly change _stext() to main() in stm8_interrupt_vector.c. Now it seems that it is really a dead end.

About the startup process of STM8S:

1) First, the bootloader (in ROM) starts from address 0x6000.

2) Jump from bootloader to 0x8000 (internal FLASH start address). The address after 0x8000 can be controlled by software design. What many people don’t understand is the relevant code provided in the stm8 library. The specific process is as follows:

a) Interrupt vector table: As we all know, the address 0x8000 is the address of the interrupt function, and '0x82' is the interrupt instruction inside stm8. When the program executes here, it will automatically jump to the function where the interrupt vector address is located.

b) Where does the mian function start?

This may be the most puzzling thing for everyone. It turns out to be very simple: the key is that stm8 has a reset interrupt, defined in

stm8_interrupt_vector.c中:

"(void @near (*)())0x8200,"

"_stext, /* RESET */”"

extern void @near _stext(); /* startup routine */

void @near (* const _vectab[])() =

{



"(void @near (*)())0x8200,"

"_stext, /* RESET */"



"(void @near (*)())0x8200,"

"TRAP_IRQHandler, /* TRAP - Software interrupt */"



"(void @near (*)())0x8200,"

"TLI_IRQHandler, /* irq0 - External Top Level interrupt (TLI) */"



"(void @near (*)())0x8200,"

"AWU_IRQHandler, /* irq1 - Auto Wake Up from Halt interrupt */"

"(void @near (*)())0x8200,"

"CLK_IRQHandler, /* irq2 - Clock Controller interrupt */"

"(void @near (*)())0x8200,"

"EXTI_PORTA_IRQHandler, /* irq3 - External interrupt 0 (GPIOA) */"

"(void @near (*)())0x8200,"

"EXTI_PORTB_IRQHandler, /* irq4 - External interrupt 1 (GPIOB) */"

"(void @near (*)())0x8200,"

"EXTI_PORTC_IRQHandler, /* irq5 - External interrupt 2 (GPIOC) */"

"(void @near (*)())0x8200,"

"EXTI_PORTD_IRQHandler, /* irq6 - External interrupt 3 (GPIOD) */"

"(void @near (*)())0x8200,"

"EXTI_PORTE_IRQHandler, /* irq7 - External interrupt 4 (GPIOE) */"



#ifdef STM8S208

"(void @near (*)())0x8200,"

"CAN_RX_IRQHandler, /* irq8 - CAN Rx interrupt */"

"(void @near (*)())0x8200,"

"CAN_TX_IRQHandler, /* irq9 - CAN Tx/ER/SC interrupt */"



#elif defined (STM8S903)

"(void @near (*)())0x8200,"

"EXTI_PORTF_IRQHandler, /* irq8 - External interrupt 5 (GPIOF) */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq9 - Reserved */"

"#else /*STM8S207, STM8S105 or STM8S103*/"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq8 - Reserved */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq9 - Reserved */"

#endif /*STM8S208*/

"(void @near (*)())0x8200,"

"SPI_IRQHandler, /* irq10 - SPI End of transfer interrupt */"

"(void @near (*)())0x8200,"

"TIM1_UPD_OVF_TRG_BRK_IRQHandler, /* irq11 - TIM1 Update/Overflow/Trigger/Break interrupt */"

"(void @near (*)())0x8200,"

"TIM1_CAP_COM_IRQHandler, /* irq12 - TIM1 Capture/Compare interrupt */"



#ifdef STM8S903

"(void @near (*)())0x8200,"

"TIM5_UPD_OVF_BRK_TRG_IRQHandler, /* irq13 - TIM5 Update/Overflow/Break/Trigger interrupt */"

"(void @near (*)())0x8200,"

"TIM5_CAP_COM_IRQHandler, /* irq14 - TIM5 Capture/Compare interrupt */"



"#else /*STM8S208, STM8S207, STM8S105 or STM8S103*/"

"(void @near (*)())0x8200,"

"TIM2_UPD_OVF_BRK_IRQHandler, /* irq13 - TIM2 Update/Overflow/Break interrupt */"

"(void @near (*)())0x8200,"

"TIM2_CAP_COM_IRQHandler, /* irq14 - TIM2 Capture/Compare interrupt */"

#endif /*STM8S903*/



#if defined (STM8S208) || defined(STM8S207) || defined(STM8S105)

"(void @near (*)())0x8200,"

"TIM3_UPD_OVF_BRK_IRQHandler, /* irq15 - TIM3 Update/Overflow/Break interrupt */"

"(void @near (*)())0x8200,"

"TIM3_CAP_COM_IRQHandler, /* irq16 - TIM3 Capture/Compare interrupt */"

#else

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq15 - Reserved */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq16 - Reserved */"

"#endif /*STM8S208, STM8S207 or STM8S105*/"



#ifdef STM8S105

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq17 - Reserved */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq18 - Reserved */"

#else

"(void @near (*)())0x8200,"

"UART1_TX_IRQHandler, /* irq17 - UART1 Tx complete interrupt */"

"(void @near (*)())0x8200,"

"UART1_RX_IRQHandler, /* irq18 - UART1 Rx interrupt */"

#endif /*STM8S105*/

"(void @near (*)())0x8200,"

"I2C_IRQHandler, /* irq19 - I2C interrupt */"

#if defined(STM8S208) || defined(STM8S207)

"(void @near (*)())0x8200,"

"UART3_TX_IRQHandler, /* irq20 - UART3 Tx interrupt */"

"(void @near (*)())0x8200,"

"UART3_RX_IRQHandler, /* irq21 - UART3 Rx interrupt */"

#elif defined (STM8S105)

"(void @near (*)())0x8200,"

"UART2_TX_IRQHandler, /* irq20 - UART2 Tx interrupt */"

"(void @near (*)())0x8200,"

"UART2_RX_IRQHandler, /* irq21 - UART2 Rx interrupt */"

"#else /* STM8S103, STM8S903 */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq20 - Reserved */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq21 - Reserved */"

"#endif /* STM8S208, STM8S207 */"

#if defined(STM8S208) || defined(STM8S207)

"(void @near (*)())0x8200,"

"ADC2_IRQHandler, /* irq22 - ADC2 end of conversion interrupt */"

"#else /* STM8S105, STM8S103, STM8S903 */"

"(void @near (*)())0x8200,"

"ADC1_IRQHandler, /* irq22 - ADC1 end of conversion/Analog watchdog interrupts */"

"#endif /* STM8S208, STM8S207 */"

#ifdef STM8S903

"(void @near (*)())0x8200,"

"TIM6_UPD_OVF_TRG_IRQHandler, /* irq23 - TIM6 Update/Overflow/Trigger interrupt */"

#else

"(void @near (*)())0x8200,"

"TIM4_UPD_OVF_IRQHandler, /* irq23 - TIM4 Update/Overflow interrupt */"

#endif /*STM8S903*/

"(void @near (*)())0x8200,"

"EEPROM_EEC_IRQHandler, /* irq24 - FLASH interrupt */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq25 - Reserved */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq26 - Reserved */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq27 - Reserved */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq28 - Reserved */"

"(void @near (*)())0x8200,"

"NonHandledInterrupt, /* irq29 - Reserved */"

};


The address of the reset interrupt is the first jump address after 0x8000. After reset, the program will naturally jump to the address of '_stext'. Where is '_stext'? From 'extern void @near _stext(); /* startup routine */', we can know that it is defined in another file. This file is the startup file of stm8, crtsi0.sm8 written in assembly language, which can be found in the cosmic installation directory:

; C STARTUP FOR STM8

; WITH AUTOMATIC DATA INITIALISATION

; Copyright (c) 2006 by COSMIC Software

;

"xref _main, __memory, __idesc__, __stack"

"xref.b c_x, c_y, __endzp"

"xdef _exit, __stext"

;

; start address of zpage

;

switch .ubsct

__suzp:

;

; start address of bss

;

switch .bss

__sbss:

;

; startup routine from reset vector

;

switch .text

__stext:

;

; initialize stack pointer

;

"ldw x,#__stack ; stack pointer"

"ldw sp,x ; in place"

;

; setup initialized data

;

"ldw y,__idesc__ ; data start address"

"ldw x,#__idesc__+2 ; descriptor address"

ibcl:

"ld a,(x) ; test flag byte"

jreq zero ; no more segment

"bcp a,#$60 ; test for moveable code segment"

"jreq qbcl ; yes, skip it"

"ldw c_x,x ; save pointer"

"ldw x,(3,x) ; move end address"

"ldw c_y,x ; in memory"

"ldw x,c_x ; reload pointer"

"ldw x,(1,x) ; start address"

dbcl:

"ld a,(y) ; transfer"

"ld (x),a ; byte"

incw x ; increment

incw y ; pointers

"cpw y,c_y ; last byte ?"

"jrne dbcl ; no, loop again"

"ldw x,c_x ; reload pointer"

qbcl:

"addw x,#5 ; next descriptor"

jra ibcl ; and loop

;

; reset uninitialized data in zero page

; Clear the uninitialized variable area in the zero page to 0

zero:

"ldw x,#__suzp ; start of uninitialized zpage ;__suzp is the first address of the uninitialized area, that is, the starting address of .ubsct"

jra loop ; test segment end first

zbcl:

"ld (x),a ; clear byte ;清0"

incw x ; next byte; add 1 to the address

loop:

"cpw x,#__endzp; end of zpage;__endzp is the end address of uninitialized variables in zeropage, that is, the end address of .ubsct,"

;_endzp is defined in .lkf (link file). This sentence means to compare whether the current address is the end address of .ubsct.

"jrne zbcl; no, continue; if .ubsct is not initialized, jump to abcl to continue, jrne: if not equal, jump"

;

; reset uninitialized data in bss

"; Clear the uninitialized variable area in RAM to 0, that is, clear the area where the .bss segment is located"

"ldw x,#__sbss ; start address"

jra ok ; test segment end first

bbcl:

"ld (x),a ; clear byte"

incw x ; next byte

ok:

"cpw x,#__memory ; compare end"

"jrne bbcl ; not equal, continue"

; execute main() function

; may be called by a 'jp' instruction if no return expected

;

call _main ; execute main

_exit:

jra _exit ; and stay here

;

end


You will naturally find the call _main entry from the startup code.


Keywords:STM8S Reference address:STM8S: Debugging is normal, but burning program is not running normally

Previous article:Two methods of outputting debugging information for STM32
Next article:Internal clock switching of stm8s

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号