分成BL1BL2後為什麼printf不能輸出變數的結果,可以輸出字串?
在學習嵌入式程式時,編寫一個倒計數自啟動命令的過程中,使用了wdt定時器中斷isr_wdt,由於原來編寫的程式bin大於16KB,故分成了BL1和BL2兩部分程式碼,IRQ_handle:部分的程式碼放在了BL2的start.S的尾部。程式碼如下:
#define WTCON 0xE2700000
#define SVC_STACK 0xd0037d80 //ARM的棧是滿減棧,所以從高位地址開始
#define IRQ_STACK 0XD0037f80 //ARM的棧是滿減棧,所以從高位地址開始
.global _start // 把_start連結屬性改為外部,這樣其他檔案就可以看見_start了
.global IRQ_handle
_start:
// 第1步:關看門狗(向WTCON的bit5寫入0即可)
ldr r0, =WTCON
ldr r1, =0x0
str r1, [r0]
// 第2步:初始化時鐘
bl clock_init
// 第3步:設定SVC棧
ldr sp, =SVC_STACK
// 第4步:開/關icache
mrc p15,0,r0,c1,c0,0; // 讀出cp15的c1到r0中
//bic r0, r0, #(1<<12) // bit12 置0 關icache
orr r0, r0, #(1<<12) // bit12 置1 開icache
mcr p15,0,r0,c1,c0,0;
bl main
// 從這裡之後就可以開始呼叫C程式了
//bl led_blink // led_blink是C語言實現的一個函式
// 彙編最後的這個死迴圈不能丟
b .
//在這個彙編函式中,用來做中斷irq模式下的現場保護和恢復,並且呼叫真正的中斷處理程式
IRQ_handle:
//設定IRQ下的棧
ldr sp, =IRQ_STACK
//儲存LR(暫存返回地址的)
//因為有流水線,在中斷來臨時(此時地址為a),返回地址應該是在當前指令的下一條指令地址為a+4,
//但是PC此時指向的是返回地址(地址為a+4)的下一條指令(此時地址為a+8),
//所以PC的值會比真正的執行的程式碼地址(地址為a)多8個位元組,這就是流水線的效果。
sub lr, lr, #4
//儲存r0~r12和lr到irq模式下的棧裡面去
stmfd sp!, {r0-r12, lr}
//接著呼叫真正的中斷處理程式isr的函式(此函式在int.c中的void irq_handler(void))來處理中斷,
bl irq_handler
//上面的中斷處理完成後,接著來恢復處理現場,其實就是做中斷返回,關鍵是將r0-r12, pc, cpsr一起恢復
ldmfd sp!, {r0-r12, pc}^
在main函式中使用了printf 函式,但是不能輸出變數的結果:
int g_bootdelay = 3;
int main(void)
{
shell_init();//所有初始化(包括繫結中斷、使能中斷等)
// 自動倒數執行預設命令
// 在這裡等待使用者按按鍵,如果沒按就倒計時,如果按了就結束倒計時和自動執行直接
// 進入shell死迴圈。如果一直沒按按鍵時間到了也進入shell死迴圈
puts("aston#");
printf("%d", g_bootdelay); //此句不能輸出3,輸出只是一個%.
/*
while ((!g_isgo) && (!is_key_press()));
//while (!((g_isgo) || (is_key_press())));
intc_disable(NUM_WDT);
// 也可以在這裡通過判斷g_isgo的值來判斷是不是倒數結束,執行自動命令
if (g_isgo)
{
lcd_test();
}
// 執行shell死迴圈
shell_loop();
*/
//while(1)
return 0;
}
// wdt的中斷處理程式
void isr_wdt(void)
{
static int i = 0;
// 看門狗定時器時間到了時候應該做的有意義的事情
printf("wdt interrupt, i = %d...\n", i++); //此句也不能輸出,輸出結果是:%
// 計時,然後時間沒到的時候在螢幕上列印倒數計數,時間到了自動執行命令
// 執行完命令進入shell的死迴圈
//puts("aston#");
//g_bootdelay--;
//putchar('\b');
printf("%d", g_bootdelay); //此句也不能輸出,輸出結果是:%
/*
if (g_bootdelay == 0)
{
g_isgo = 1;
// 把要自動執行的命令新增到這裡,但是這裡是中斷處理程式,不適合執行長程式碼
// 所以放在外面要好一些
//printf("g_isgo = 1.\n");
// 關閉wdt
//intc_disable(NUM_WDT);
}
*/
// 清中斷
intc_clearvectaddr();
rWTCLRINT = 1;
}
為什麼在沒有分成BL1和BL2的情況下,也在使用此中斷函式 isr_wdt()的裡面和main函式裡使用printf函式時輸出結果正常,而當在有BL1和BL2的情況下,也使用此中斷isr_wdt的裡面和main函式裡使用printf函式時輸出結果就不正常呢?出現不正常的結果是不是BL1和BL2的內容沒有調整對(IRQ_handle:是不是放在BL1的start.S中的尾部?),網上好多帖子說中斷裡不能使用printf函式,但是我的分成BL1和BL2的時候程式中,中斷裡使用printf函式都正常著呢?
哪位朋友給予指點!不勝感激!