STM8S:Debug调试正常,烧录程序运行不正常

最近有一个项目需要用到STM8S103F3单片机。在开始之前以为会很容易,可是实际操作起来,却遇到不少问题 。其中最令我感到困惑的一个问题是:我在调试程序的时候程序可以运行正常,但当我把程序烧录进去断电重启后却运行不正常。

试了很多方法,都没有找到问题所在。最后,我把Start-up file 选择默认的就可以。之前不知道在哪里看到过可以不使用系统的默认启动文件,可以直接在stm8_interrupt_vector.c中将_stext()改为main();现在看来真的是害死个让人。
关于STM8S的启动过程:
1)首先bootloader(ROM中)从0x6000地址启动。 2)从bootloader跳转到0x8000(内部FLASH起始地址),0x8000后面才是软件设计可以控制的。很多人不明白的是stm8库里面提供的相关代码,具体流程如下: a)中断向量表:大家都知道0x8000地址放的是中断函数的地址,而‘0x82’则是stm8内部的中断指令。程序执行到这会自动跳转到中断向量地址所在函数。 b)mian函数到底从哪开始? 这也许是大家最纳闷的了,起始原来很简单:关键是stm8有个复位中断,定义在 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 */" }; 复制代码 复位中断的地址就是0x8000后面的第一个跳转地址,复位后程序自然会跳转到‘_stext’所在地址。‘_stext’在哪里?从‘extern void @near _stext(); /* startup routine */’可以知道它定义在别的文件中,这个文件就是stm8的启动文件,用汇编写的crtsi0.sm8,在cosmic安装目录下可以找到: ; 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 ; 将zero page中未初始化的变量区域清0 zero: "ldw x,#__suzp ; start of uninitialized zpage ;__suzp为未初始化区域的首地址,也就是.ubsct的起始地址" jra loop ; test segment end first zbcl: "ld (x),a ; clear byte ;清0" incw x ; next byte;地址加1 loop: "cpw x,#__endzp ; end of zpage ;__endzp为zeropage内未初始化变量的结束地址,也就是.ubsct的结束地址," ;_endzp定义在.lkf(链接文件里),这句的意思是比较现地址是否为.ubsct的结束地址。 "jrne zbcl ; no, continue ;如果.ubsct未初始化完成跳转到abcl继续进行,jrne:不等于则跳转" ; ; reset uninitialized data in bss "; 将ram中的未初始化变量区域清0,也就是清零.bss段所在区域" "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 复制代码 从启动代码中自然会找到call _main入口。 

你可能感兴趣的:(STM8S:Debug调试正常,烧录程序运行不正常)