1. 程式人生 > >分成BL1BL2後為什麼printf不能輸出變數的結果,可以輸出字串?

分成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函式都正常著呢?

哪位朋友給予指點!不勝感激!