|
本帖最后由 niujia 于 2015-7-17 00:18 編輯
1 在flash中跑程序時(shí),能進(jìn)入中斷,但在ram中跑時(shí),進(jìn)不了中斷的原因。
看以下的中斷配置函數(shù)可以知道,要在ram中調(diào)試程序,需要定義VECT_TAB_RAM。
定義方法a:在Project\Options for taget 'xxx'的對(duì)話框的c/c++中定義宏VECT_TAB_RAM
定義方法b:在程序中直接定義
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
#endif
NVIC_InitStructure.NVIC_IRQChannel =ADC1_2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
2 SysTickHandler 函數(shù)不能進(jìn)入。
原先初始化的語句為
SysTick_Config();
修改為以下時(shí)可以進(jìn)入
SysTick_Config();
SysTick_CounterCmd(SysTick_Counter_Enable);
3 如何解決鏈接時(shí)錯(cuò)誤"..\obj\LowCostDA.axf: Error: L6218E: Undefinedsymbol assert_failed (referred from stm32f10x_flash.o)."?
如果所加入的庫是STM32F10xD.LIB(即調(diào)試模式庫),則需要在無論什么得放添加函數(shù)定義
void assert_failed(u8* file, u32 line)
{
while (1)
{
}
}
如果所加入的庫是STM32F10xR.LIB(即發(fā)布模式庫),則不會(huì)報(bào)錯(cuò)。
4 打開中斷的時(shí)機(jī)不正確,導(dǎo)致無法進(jìn)行任務(wù)切換。
由于我過早地打開了 SysTick 中斷,而我在SysTickHandler 中有如下語句:
{
...
OS_ENTER_CRITICAL();
OSIntNesting++;
OS_EXIT_CRITICAL();
OSTimeTick();
OSIntExit();
...
}
因?yàn)榇蜷_過早,因此 OSIntNesting++能夠執(zhí)行,而OSIntExit函數(shù)卻沒有把OSIntNesting減1.因此,導(dǎo)致了無法進(jìn)行任務(wù)切換。
注意2點(diǎn)可以避免該情況:
a 同時(shí)使用 OSIntExit(); 和OSIntEnter(); 而不是像我這樣使用OSIntNesting++和OSIntExit()。
b 開中斷要在操作系統(tǒng)初始化后完成,即在OSStart之后。
5 程序中只要使用了printf函數(shù),就會(huì)執(zhí)行到BKTP語句掛掉。
解決方法:Project\Options Target選項(xiàng)頁中選中 UseMicroLIB
關(guān)于 MicroLIB的詳細(xì)說明見網(wǎng)友文章
6 參考99的rtc時(shí)鐘的使用方法,出現(xiàn)問題并順利解決。
在程序中我修改當(dāng)前時(shí)間是調(diào)用的以下函數(shù)
void Time_SetUnixTime(time_t t)
{
RTC_WaitForLastTask();
RTC_SetCounter((u32)t);
RTC_WaitForLastTask();
return;
}
但是程序會(huì)一直運(yùn)行在 RTC_WaitForLastTask 中無法出來。
最終順利解決。
99所介紹的程序啟動(dòng)是配置rtc的函數(shù)如下:
void RTC_Config(void)
{
//我們?cè)贐KP的后備寄存器1中,存了一個(gè)特殊字符0xA5A5
//第一次上電或后備電源掉電后,該寄存器數(shù)據(jù)丟失,
//表明RTC數(shù)據(jù)丟失,需要重新配置
if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
{
//重新配置RTC
RTC_Configuration();
//配置完成后,向后備寄存器中寫特殊字符0xA5A5
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
}
else
{
//若后備寄存器沒有掉電,則無需重新配置RTC
//這里我們可以利用RCC_GetFlagStatus()函數(shù)查看本次復(fù)位類型
if (RCC_GetFlagStatus(RCC_FLAG_PORRST) !=RESET)
{
//這是上電復(fù)位
}
else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) !=RESET)
{
//這是外部RST管腳復(fù)位
}
//清除RCC中復(fù)位標(biāo)志
RCC_ClearFlag();
//雖然RTC模塊不需要重新配置,且掉電后依靠后備電池依然運(yùn)行
//但是每次上電后,還是要使能RTCCLK???????
//RCC_RTCCLKCmd(ENABLE);
//等待RTC時(shí)鐘與APB1時(shí)鐘同步
//RTC_WaitForSynchro();
//使能秒中斷
RTC_ITConfig(RTC_IT_SEC, ENABLE);
//等待操作完成
RTC_WaitForLastTask();
}
#ifdef RTCClockOutput_Enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR |RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
BKP_TamperPinCmd(DISABLE);
BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
#endif
return;
}
要調(diào)用Time_SetUnixTime設(shè)置時(shí)間 應(yīng)該在if分支里邊。
而不是在else分支里邊。
我正好是犯了這樣的錯(cuò)誤。
7 關(guān)于堆棧對(duì)齊的問題
程序中出現(xiàn)了一個(gè)奇怪的問題
char g_cpTask2Buffer[200];
void Task2(void *arg)
{
...
sprintf(g_cpTask2Buffer,"%.3f",ADCInfoArray[0].m_fVolt);
...
}
ADCInfoArray[0].m_fVolt是一個(gè)float值。
在執(zhí)行完 sprintf后,無論m_fVolt是多少,始終得到的g_cpTask2Buffer的內(nèi)容都是"0.000"。
調(diào)試了好幾天的匯編終于解決了問題,根源竟然是ucos的堆棧需要以8字節(jié)對(duì)齊。
Task2是一個(gè)ucos的任務(wù),Stack2 是Task2的任務(wù)堆棧。
如果是以下形式則出錯(cuò):
Stack2 0x200084ac Data 804 main.o(.bss)
Stack3 0x200087d0 Data 800 main.o(.bss)
如果是以下形式則不出錯(cuò):
Stack2 0x200084ac Data 800 main.o(.bss)
Stack3 0x200087cc Data 800 main.o(.bss)
為什么 sprintf在Task2的中,但是執(zhí)行結(jié)果的正確與否卻看起來似乎與Task3的任務(wù)堆棧Stack3相關(guān)?
原因是,任務(wù) Task2 的堆棧頂實(shí)際上位于Stack2 + (Stack2STKSIZE -1),該值正好與Stack3
相連。
為什么堆棧必須要8字節(jié)對(duì)齊?
因?yàn)樵趨R編中有這樣的語句:
BIC r0,r2,#0x07
該句得到double型值(在處理過程中,m_fVolt先從float被轉(zhuǎn)換為double型) 的存儲(chǔ)地址。
該匯編的意思是把r2的最低一個(gè)字節(jié)的二進(jìn)制最后3位清零,即把r2變?yōu)樾稳?6進(jìn)制xxxxxxx0或者xxxxxxx8,然后放入r0。
可以看到該地址必然是8字節(jié)對(duì)齊的。
最根本的原因我仍然沒有找到,但算是解決了問題。
8 外部sram用作堆棧的一個(gè)問題
系統(tǒng)中使用了ucos,由于任務(wù)堆棧的空間需要的比較多,因此把其放到了外部sram中,使用這樣的語句:
OS_STK Stack1[STKSIZE] __at (Bank1_SRAM3_ADDR) ;
但是沒有想到的是,在使用sdio方式操作sd卡時(shí),總是出現(xiàn)SDIO_IT_TXUNDERR 中斷。
沒有好的解決辦法,只能老老實(shí)實(shí)地把任務(wù)堆棧放入片內(nèi)的sram。
想來,恐怕原因是系統(tǒng)在和SD卡交換數(shù)據(jù)時(shí)用到了任務(wù)堆棧區(qū),而任務(wù)堆棧區(qū)所在的片外的sram速度不夠快導(dǎo)致的問題。
雖然問題湊合解決了,但是問題仍然存在:
外部sram到底能怎么用? 如果外部sram能和片內(nèi)的sram一樣方便地使用就好了。
看到這篇博客的朋友,有沒有什么好的解決辦法?
9 鬧鐘中斷的問題(RTCAlarm)
打算在standby模式下使用鬧鐘中斷,但由于standby模式調(diào)試不方便,因此在正常運(yùn)行狀態(tài)下先測試鬧鐘中斷。
沒想到遇到了問題:
關(guān)掉了RTC_IRQHandler,只打開RTCAlarm_IRQHandler。但是依然能進(jìn)入RTC_IRQHandler中斷函數(shù),但不是正常狀態(tài)下的進(jìn),而是不停地進(jìn)中斷,
而且RTC_GetITStatus(RTC_IT_SEC)得到狀態(tài)也確實(shí)不是秒中斷發(fā)生。
同時(shí),也會(huì)進(jìn)RTCAlarm_IRQHandler中斷,也不是正常狀態(tài)下的進(jìn),而是不停地進(jìn)中斷,而且RTC_GetITStatus(RTC_IT_ALR)得到狀態(tài)也確實(shí)不是鬧鐘中斷發(fā)生。
最終找到了問題所在:
一定要在RTCAlarm_IRQHandler函數(shù)中有這句:EXTI_ClearITPendingBit(EXTI_Line17);
|
|