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入口。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值