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

来源:互联网 发布:仙界网络直播间txt八零 编辑:程序博客网 时间:2024/05/07 10:13

最近有一个项目需要用到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 ; incrementincw 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中未初始化的变量区域清0zero:"ldw x,#__suzp ; start of uninitialized zpage ;__suzp为未初始化区域的首地址,也就是.ubsct的起始地址"jra loop ; test segment end firstzbcl:"ld (x),a ; clear byte ;清0"incw x ; next byte;地址加1loop:"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 firstbbcl:"ld (x),a ; clear byte"incw x ; next byteok:"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入口。
原创粉丝点击