| 
  |||||||||||
| 技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機 | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計 | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe  | 
  
請教:44B0X在跑uc/os時,硬件連續(xù)兩次重新啟動的問題 | 
  
| 作者:碧水長天 欄目:ARM技術(shù) | 
44B0X在跑uc/os時,硬件連續(xù)兩次重新啟動的疑惑 問題描述: 44B0X開發(fā)板在移植好uc/os-ii之后,我創(chuàng)建了兩個任務(wù)task1和task2,優(yōu)先級分別為0和1。 其中,main函數(shù)從串口輸出字符串“uc/os is running” task1從串口輸出字符串“task1”之后,被掛起1個時鐘節(jié)拍,task2從串口輸出字符串“task2”后,被掛起1個時鐘節(jié)拍。 空閑任務(wù)idletask中,我在其hook函數(shù)中添加了從串口輸出字符串“idletask”的代碼。 系統(tǒng)以RTC的中斷為系統(tǒng)的時鐘節(jié)拍中斷,禁用FIQ,使用IRQ,非矢量中斷模式,時鐘節(jié)拍數(shù)為每秒1個。 運行時,從串口檢測到輸入信息如下: uc/os is running task1 //首先運行task1,該輸出正常 task2 //task1被掛起后,task2工作,該輸出正常 idletask //task1和task2均被掛起,于是os運行空閑任務(wù),該輸出正常 idletask idletask task1 //第一個時鐘中斷來臨,OS進(jìn)行一次任務(wù)調(diào)度,于是運行task1,輸出字符串后task1被掛起 task2 uc/os is running //系統(tǒng)重新啟動,我在44binit.s中的reset入口地址開始處加了蜂鳴器開啟的指令,能證明PC重新從0X0啟動 task1 task2 idletask idletask idletask task1 //和第一次運行一樣 task2 uc/os is running //系統(tǒng)重新啟動,我在44binit.s中的reset入口地址開始處加了蜂鳴器開啟的指令,能證明PC重新從0X0啟動 task1 task2 idletask //之后一直運行空閑任務(wù),task1、task2都不再被調(diào)度了.... idletask idletask idletask idletask idletask idletask idletask idletask idletask idletask idletask ... 這個問題困擾我好幾天了,請教高人,指點一下在下,謝謝。  * - 本貼最后修改時間:2005-11-29 22:23:13 修改者:碧水長天  | 
  
| 2樓: | >>參與討論 | 
| 作者: 碧水長天 于 2005/11/29 22:29:00 發(fā)布:
         唉,高手好象都很忙 自己頂一下,希望有高手點撥一下,這個問題困擾我一個星期多了, 在第2個時鐘節(jié)拍中斷到來之前,我關(guān)掉全局中斷,但執(zhí)行到了task2中的OSTimeDly(1)語句后板子又重新啟動....  | 
  |
| 3樓: | >>參與討論 | 
| 作者: 碧水長天 于 2005/11/30 20:39:00 發(fā)布:
         上代碼,請高手看看,尤其是中斷安裝代碼,謝謝 //1 main.c代碼 #include "..\inc\option.h" #include "..\inc\def.h" #include "..\inc\44b.h" #include "..\inc\44blib.h" #include "..\mylcd\lcd320.h" #include "..\myip\hardware.h" #include "..\ucos\includes.h" #define IRQ_VECTOR_OFFSET (0x18) #define RTC_OR_TIME0 0 volatile static int isrCount = 0; // tick counter //中斷向量的安裝 unsigned int ISR_Install(unsigned int offset, void *pf_ISR) { unsigned int pOldEntry; // _ISR_STARTADDRESS :0x7ffff00 offset += _ISR_STARTADDRESS; //offset = HandleIRQ(0x7ffff18) // 舊的中斷服務(wù)的入口地址 pOldEntry = *((unsigned int *)offset); // //將OSTICKISR的入口地址賦給offset所指向的內(nèi)容 *((unsigned int *)offset) = (unsigned int)pf_ISR; return pOldEntry; } #if RTC_OR_TIME0 //tick中斷切換,為1則選擇RTC中斷,為0則選擇timer0中斷 //tick初始化,設(shè)置tick中斷,使能tick中斷服務(wù) void tick_init(unsigned CHAR div) { rRTCCON = (unsigned CHAR)1; //RTC讀寫使能,1/32768,不復(fù)位 rTICNT = (unsigned CHAR)(div | 0x80); //tick = 0x80/div rRTCCON = (unsigned CHAR)0; //禁止讀寫RTC rI_ISPC = (unsigned int)(0x01 << 20); //清除TICNT的pending rINTMSK &= (unsigned int)(~(0x01 << 20)); //允許TICNT的中斷服務(wù) } void tick_hook(void) //清除中斷請求標(biāo)志,OSTickISR調(diào)用 { rI_ISPC =((unsigned int)1) << 20; isrCount++; } #else //保證div void tick_init(unsigned CHAR div) { rTCFG0=0x00f; //Timer0,死區(qū)時間長度為0,預(yù)分頻值為0x0f rTCFG1=0x04; //中斷模式,mux=1/32 rTCNTB0=(U16) 250 * div;//tick_cyc = div * (250*1/(60 000/15/32)) = 2 * div ms rTCON=0x02; //手動更新Timer0的設(shè)置 rTCON=0x09; //自動重載,啟動定時器 rI_ISPC = (unsigned int)(0x01 << 13); //清除TICNT的pending rINTMSK &= (unsigned int)(~(0x01 << 13)); //允許TICNT的中斷服務(wù) } void tick_hook(void) //清除中斷請求標(biāo)志,OSTickISR調(diào)用 { rI_ISPC =((unsigned int)1) << 13; isrCount++; } #endif //中斷控制初始化 void intcon_init(void) { rINTMOD = 0; // 所有中斷均為IRQ方式 rI_ISPC = 0x7ffffff; // 清除所有中斷請求 rINTCON = 0x05; // //非矢量中斷,IRQ使能,FIQ禁用 } //全局中斷開關(guān)控制 void globle_int_enable(unsigned CHAR bEnabled) { if(bEnabled) rINTMSK &= ~(((unsigned int)0x01) << 26); else rINTMSK |= ((unsigned int)0x01) << 26; } void sys_init(void) { PortInit();//設(shè)置端口功能,LCD globle_int_enable(0); //關(guān)全局中斷 intcon_init(); //中斷初始化 //Uart_Select(0); //Uart_Init(0, 57600); //串口選擇和初始化 //InitNic(0); //0號網(wǎng)卡初始化 //LCD_Init(); //LCD顯示初始化 //LCD_ChangeMode(DspTxtMode); //顯示模式為文本模式 ISR_Install(IRQ_VECTOR_OFFSET, (void *)OSTickISR); //安裝tick中斷服務(wù)程序 } //-----------------主函數(shù)開始------------------ #define N_TASKS 5 // 任務(wù)數(shù) #define TASK_STK_SIZE 512 // 任務(wù)?臻g大小 OS_STK TaskStk[N_TASKS][TASK_STK_SIZE];// 開辟任務(wù)棧,5*512*32/8 bytes void Task1(void *); void Task2(void *); extern int Image$$RO$$Limit; extern int Image$$RW$$Base; int Main(int argc, CHAR **argv) { int task_1 = 0, task_2 = 0; sys_init(); //系統(tǒng)初始化,含端口,中斷,串口,網(wǎng)卡,LCD控制 //Uart_Printf("\n***************uc/os v2.51*************************"); //Uart_Printf("\n*************** for 44b0x ************************"); Uart_Printf("\nuc/os is running"); OSInit(); OSTaskCreate(Task1, &task_1, &TaskStk[0][TASK_STK_SIZE-1], 1); OSTaskCreate(Task2, &task_2, &TaskStk[1][TASK_STK_SIZE-1], 2); OSStart(); return 0; } void Task1(void * pParam) { #if RTC_OR_TIME0 tick_init(63); //tick節(jié)拍初始化,2 ticks /s #else tick_init(250); //tick節(jié)拍初始化,2 ticks /s #endif globle_int_enable(1); //全局中斷開 while(1) { OSSchedLock(); Uart_Printf( "\ntask1" ); &  | 
  |
| 4樓: | >>參與討論 | 
| 作者: PandaFeng 于 2005/11/30 20:41:00 發(fā)布:
         re: 把編譯器的優(yōu)化選項關(guān)掉。 接管 Undefined,PrefetchAbort, DataAbort 看看哪一個有中斷,分析寄存器的值,可以縮小查找范圍 把其中的一個任務(wù)先去掉 祝你好運  | 
  |
| 5樓: | >>參與討論 | 
| 作者: 碧水長天 于 2005/11/30 20:49:00 發(fā)布:
         謝謝樓上的兄弟的指點,我再上OS_CPU_A.S文件,也許關(guān)鍵代碼有錯 該代碼原自網(wǎng)友YJ的移植,我研讀了好幾遍并部分做了注釋,尤其在OSIntCtxSW部分,未發(fā)現(xiàn)問題,也許我忽略了某些地方,請高手指點,萬分感謝! AREA |subr|, CODE, READONLY ;/*********************************************************************** ; 函數(shù): OSStartHighRdy ; 作用:在OS開始時調(diào)用優(yōu)先級最高的就緒任務(wù) ; 參數(shù): void ; 數(shù)出: None ; 返回: void ; 注意: 在OSStart()中調(diào)用 ;*********************************************************************/ EXPORT OSStartHighRdy ;聲明此函數(shù)被其他文件使用 IMPORT OSTaskSwHook ;聲明此函數(shù)/參量在其他文件中定義 IMPORT OSTCBHighRdy IMPORT OSRunning OSStartHighRdy ;使就緒表中任務(wù)最高的優(yōu)先級的任務(wù)開始運行 ;******************************************************** ;調(diào)用用戶定義的OSTaskSwHook()函數(shù) ;OSRunning = Ture ;得到將要運行的這個最高優(yōu)先級任務(wù)的堆棧指針 ;從該任務(wù)(上一行提到的任務(wù))堆棧中恢復(fù)所有CPU寄存器 ;執(zhí)行中斷返回指令 ;*********************************************************** BL OSTaskSwHook ; 調(diào)用用戶的Hook函數(shù),空函數(shù) LDR r4,=OSRunning ; 聲明多任務(wù)OS開始運行 MOV r5, #1 STRB r5, [r4] ; OSRunning = true(0000 0001b) ;get the highrdy's TCB pointer LDR r4, =OSTCBHighRdy ; 得到最高優(yōu)先級任務(wù)的任務(wù)塊地址 LDR r4, [r4] ; 任務(wù)塊中的第一個參數(shù)即任務(wù)的堆棧 LDR sp, [r4] ; 切換到新任務(wù)的堆棧 LDMFD sp!, {r4} ;從新任務(wù)堆棧中讀取第一個參數(shù)(CPSR)到(r4) MSR cpsr_cxsf, r4 ;再傳給cpsr,相當(dāng)于從任務(wù)堆棧恢復(fù)CPSR,CPU切換到該任務(wù)所在的模式 LDMFD sp!, {r0-r12,lr,pc} ;依次恢復(fù)該任務(wù)r0~r12,lr,pc燃拇嫫鰨琍C切換到該任務(wù) ;/*********************************************************************** ; Function: OS_TASK_SW ; Purpose: 任務(wù)級切換 ; Parameters: void ; Outputs: None ; Returns: void ; Notes: ; The whole function is executed in CRITICAL state. See OSSched(). ; On entry, OSTCBCur and OSPrioCur hold the current TCB and priority ; and OSTCBHighRdy and OSPrioHighRdy contain the same for the task ; to be SWITCHed to. ; 在進(jìn)入時, ; The following code assumes that the virtual MEMORY is directly ; mapped into physical MEMORY. If this is not true, the cache must ; be flushed at context SWITCH to avoid address aliasing. ; ;*********************************************************************/ EXPORT OSCtxSw IMPORT OSPrioCur IMPORT OSPrioHighRdy IMPORT OSTCBCur IMPORT OSTaskSwHook IMPORT OSTCBHighRdy OSCtxSw ;****************************************** ;保存CPU寄存器 ;在當(dāng)前任務(wù)控制塊中保存當(dāng)前任務(wù)的堆棧指針 ;調(diào)用OSTaskSwHook() ;OSTCBCur = OSTCBHighRdy ;OSPrioCur = OSPriHighRdy ;得到將要開始運行的任務(wù)的堆棧指針 ;從新任務(wù)的任務(wù)堆棧中恢復(fù)處理器所有寄存器的值 ;執(zhí)行中斷返回指令 ;******************************************保存CPU寄存器 STMFD sp!, {lr} ; PUSH pc (lr is actually be PUSHed in place of PC) ;OS_Sched()調(diào)用OSCtxSw到這里之后,lr的值就是pc的值, ;因為是任務(wù)級調(diào)用而非異常 STMFD sp!, {r0-r12,lr} ; PUSH lr & register file MRS r4, cpsr ;通過MRS指令將cpsr入棧 STMFD sp!, {r4} ; PUSH current psr ; 被掛起的當(dāng)前任務(wù)的寄存器保存完畢,下面接著保存該任務(wù)的堆棧指針 &nbs  | 
  |
| 6樓: | >>參與討論 | 
| 作者: 碧水長天 于 2005/11/30 21:17:00 發(fā)布:
         優(yōu)化策略如下: Optimization Level: MINIMUM Optimization Criterion: for time (for space也選過,情況依舊) 也寫了abort異常的處理,但是板子并沒有運行到abort的ISR,而是在OS中直接重新啟動,即從0X0開始運行。 另外還有一個問題,在axd中的調(diào)試中,在44binit.s的堆棧初始化子程序中(即 執(zhí)行bl InitStacks然后進(jìn)入InitStacks代碼),有時連續(xù)運行會出錯,單步運行則從來不會出錯。 也讓我有時很迷惑。  | 
  |
| 7樓: | >>參與討論 | 
| 作者: PandaFeng 于 2005/12/1 0:03:00 發(fā)布:
         可能與硬件有關(guān) 把系統(tǒng)時鐘頻率調(diào)低一點。 改一下代碼段的起始地址,看看現(xiàn)象有沒有不同? 最好測一下RAM。  | 
  |
| 8樓: | >>參與討論 | 
| 作者: 碧水長天 于 2005/12/1 17:41:00 發(fā)布:
         謝謝PandaFeng站友的提示 今天我按UC/OS的教材的測試步驟重新測試了一些OS,建立一個測試任務(wù)TestTask,在不掛接節(jié)拍中斷時,當(dāng)TestTask任務(wù)調(diào)用OSTimeDly()函數(shù)掛起自身時,OS能調(diào)度而進(jìn)入空閑任務(wù),這就說明OSCtxSW()函數(shù)正常,而OSIntCtxSW()函數(shù)屬于前者的一部分,因此也應(yīng)該正常。 當(dāng)按上面的代碼初始化中斷和安裝好中斷之后,程序能進(jìn)入OSTickISR,我在OSTickISR用點亮LED和B . 指令觀察,發(fā)現(xiàn)系統(tǒng)在兩種情況下崩潰(表現(xiàn)現(xiàn)象為程序重ROM的0X0啟動): 1.在運行OSIntCtxSW的恢復(fù)任務(wù)的PC指針時; 2.當(dāng)不執(zhí)行OSIntCtxSW,即在BL OSIntExit返回后,在OSTickISR的最后一條指令恢復(fù)PC指針時; 初步認(rèn)為是OSTickISR可能有問題。但是一條一條研讀,未發(fā)現(xiàn)問題。 在這里,我注意到一個異常,請大蝦指點。 1.44BINIT.S中初始化各模式的堆棧之后,在執(zhí)行MOV PC,LR之前,我在AXD。(連上44B0X開發(fā)板后使用AXD調(diào)試)中觀察當(dāng)前模式下的CPSR和SPSR,發(fā)現(xiàn)CPSR突然被改成IRQ模式!而SPSR仍然是SVC模式意味著進(jìn)入MAIN后,CPSR卻仍然是IRQ模式,那么,在任務(wù)級別的切換OSCtxSW,可能不會發(fā)生問題,若進(jìn)入了OSTickISR,那么就可能發(fā)生問題了,過程描述請見下面初始化代碼,尤其是最后面兩條匯編指令。 ;**************************************************** ;* The function for initializing stack * ;**************************************************** InitStacks ;Don't use DRAM,such as stmfd,ldmfd...... ;SVCstack is initialized before ;Under toolkit ver 2.50, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1' mrs r0,cpsr bic r0,r0,#MODEMASK orr r1,r0,#UNDEFMODE|NOINT msr cpsr_cxsf,r1 ;UndefMode ldr sp,=UndefStack orr r1,r0,#ABORTMODE|NOINT msr cpsr_cxsf,r1 ;AbortMode ldr sp,=AbortStack orr r1,r0,#IRQMODE|NOINT msr cpsr_cxsf,r1 ;IRQMode ldr sp,=IRQStack orr r1,r0,#FIQMODE|NOINT msr cpsr_cxsf,r1 ;FIQMode ldr sp,=FIQStack bic r0,r0,#MODEMASK|NOINT orr r1,r0,#SVCMODE msr cpsr_cxsf,r1 ;執(zhí)行完此語句后,CPSR和SPSR都是SVC模式 ldr sp,=SVCStack ; 而執(zhí)行完此語句后,CPSR突然變成了IRQ模式!! (有時執(zhí)行到main卻發(fā)現(xiàn)CPSR和SPSR都是SVC模式)。 ;USER mode is not initialized. ;當(dāng) mov pc,lr ;The LR register may be not valid for the mode changes. 這樣,執(zhí)行到MAIN后,CPSR仍然是IRQ模式!! 如果進(jìn)入OSTickISR,那么將可能導(dǎo)致問題,不知道我分析得對否? 我下次將用SWI指令調(diào)用任務(wù)切換函數(shù),將進(jìn)入main后的模式定為user模式。 不知道這樣是否可以。 唉,這個問題,困擾我好久了,uc/os沒搞定,很多樂趣無法享受得到。我還想玩uc/linux呢。 盼望有高人能點醒我這個arm小菜鳥。 也謝謝所有關(guān)注過這個問題的站友!  | 
  |
| 9樓: | >>參與討論 | 
| 作者: PandaFeng 于 2005/12/1 22:00:00 發(fā)布:
         是否打開了某個中斷,而有沒有設(shè)向量。 是否打開了某個中斷源,而又沒有設(shè)向量。 當(dāng)發(fā)生中斷時,向量地址又為0,所以產(chǎn)生了"Reset"。 從沒有產(chǎn)生Abort中斷,可以推想。 watchdog 的可能性較大。  | 
  |
| 10樓: | >>參與討論 | 
| 作者: 碧水長天 于 2005/12/2 17:20:00 發(fā)布:
         謝謝PandaFeng和斑竹及其他關(guān)注的站友,今天有新的進(jìn)展 PandaFeng您好,謝謝您的指點。 在44BINIT.s中,WDT在第2條指令就開始了禁止的操作,各中斷也禁止了,只有task1中初始化時鐘節(jié)拍中斷之后才開全局中斷。 如下: ;**************************************************** ;* START * ;**************************************************** ResetHandler ldr r0,=WTCON ;watch dog disable ldr r1,=0x0 str r1,[r0] ldr r0,=INTMSK ldr r1,=0x07ffffff ;all interrupt disable str r1,[r0] ... 另外,請您分析一下這個現(xiàn)象: 今天下午在一次AXD調(diào)試中,我發(fā)現(xiàn)44BINIT.s在初始化堆棧(BL InitStacks)之后,CPSR保持為SVC模式不變,于是一路全速執(zhí)行,發(fā)現(xiàn)測試任務(wù)和系統(tǒng)的空閑任務(wù)能正常切換(看LED輸出結(jié)果),和前面一個帖子預(yù)期的一樣。這就意味著,OS能正常使用了。這就證明我的軟件部分是正確的。 于是燒錄到FLASH里去,卻崩潰了,情況和先前描述的一樣。 再進(jìn)入axd環(huán)境,單步觀察44BINIT.s中的InitStacks的代碼,發(fā)現(xiàn)在最后初始化SVC堆棧完成之后,CPSR仍然莫名其妙改變成了IRQ模式,這樣,一直執(zhí)行到MAIN,仍然是IRQ模式,當(dāng)發(fā)生真正的時鐘中斷時,系統(tǒng)就崩潰了。 為什么44Binit.s初始化堆棧會出現(xiàn)CPSR異常改變的現(xiàn)象呢????? 請看下圖:注意橢圓框起來的內(nèi)容 http://file.21ic.com.cn/upload/img/200511/200512217231635492.jpg  * - 本貼最后修改時間:2005-12-2 17:24:53 修改者:碧水長天 
  | 
  |
| 11樓: | >>參與討論 | 
| 作者: PandaFeng 于 2005/12/3 5:19:00 發(fā)布:
         不太清楚 或許是被FLASH的啟動代碼影響了。 我一直用IAR 的IDE,ADS 才用過兩三個星期,而且是一年前的事了。 對它并不熟悉。 燒錄到FLASH里后崩潰了,是否指BOOT代碼都不能通過嗎? 單純的點燈程序?qū)懙?a target="_blank" href="http://www.udpf.com.cn/stock-ic/FLASH.html">FLASH里,正常嗎? 其實,我是假定ucos是正常的,因為沒有產(chǎn)生abort。 在我的調(diào)試中,數(shù)據(jù)稍有異常,abort 中斷是很容易產(chǎn)生的。 下面是IAR DEBUG前對44B寄存器寫的值,可以參考一下。 AXD也有相關(guān)的設(shè)置,只是命令名不同。 例如: __writeMEMORY32(0x11110112, 0x01c80000, "MEMORY"); 相當(dāng)于rBWSCON = 0x11110112; 順便說一下,IAR Embedded Workbench IDE 很好用。 { __message "Init memery\n"; __writeMEMORY32(0x00000001, 0x1C00000, "MEMORY"); __writeMEMORY32(0x07FFFFFF, 0x1E0000C, "MEMORY"); __writeMEMORY32(0x00000000, 0x1D30000, "MEMORY"); __writeMEMORY32(0x80001B1B, 0x1C40000, "MEMORY"); __writeMEMORY32(0x11110112, 0x01c80000, "MEMORY"); __writeMEMORY32(0x00000600, 0x01c80004, "MEMORY"); __writeMEMORY32(0x00007ffc, 0x01c80008, "MEMORY"); __writeMEMORY32(0x00007ffc, 0x01c8000c, "MEMORY"); __writeMEMORY32(0x00007ffc, 0x01c80010, "MEMORY"); __writeMEMORY32(0x00007ffc, 0x01c80014, "MEMORY"); __writeMEMORY32(0x00007ffc, 0x01c80018, "MEMORY"); __writeMEMORY32(0x00018000, 0x01c8001c, "MEMORY"); __writeMEMORY32(0x00018000, 0x01c80020, "MEMORY"); __writeMEMORY32(0x0086041a, 0x01c80024, "MEMORY"); __writeMEMORY32(0x00000010, 0x01C80028, "MEMORY"); __writeMEMORY32(0x00000020, 0x01C8002C, "MEMORY"); __writeMEMORY32(0x00000020, 0x01C80030, "MEMORY"); __writeMEMORY32(0x00018021, 0x01D80000, "MEMORY"); __message "Init Completed\n"; }  | 
  |
  | 
    
 
  | 
  
| 免費注冊為維庫電子開發(fā)網(wǎng)會員,參與電子工程師社區(qū)討論,點此進(jìn)入 | 
Copyright © 1998-2006 www.udpf.com.cn 浙ICP證030469號  |