2010-10-12 127 views
3

* UPDATE *STM32 printf的問題

這裏是我發現了什麼。每當我在那裏有這個功能,它實際上不會讓代碼鎖定。實際上,讀RTC I2C函數的執行速度非常慢,但代碼仍然可以正常運行,但每次讀RTC時都必須等待很長時間才能通過。所以最終發生的情況是RTC有一個報警中斷,並且這引發了ISR內部的其他I2C交互,所以它看起來像是在試圖同時進行兩個i2c通信,因此減慢了過程。我刪除了ISR中的函數,現在它的工作我將繼續調查。

我在使用IAR 5.40編程STM32F103微代碼時遇到了這個問題我有這個函數,如果我嘗試printf一個局部變量,它會導致代碼在另一個點的方式下凍結,然後它甚至到達那個函數。

什麼可能導致這?

這是功能

u8 GSM_Telit_ReadSms(u8 bSmsIndex) 
{ 
    char bTmpSms[3] = { 0 }; 

    itoa(bSmsIndex, bTmpSms, 10); // converts the smsindex into a string 

    printf("index = %s\n", bTmpSms); //this printf caused the code to get stuck in the RTC // byte read function !!!!!!! 

    GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0); 
    return 1; 
} 

我想這也和這不引起我經歷

u8 GSM_Telit_ReadSms(u8 bSmsIndex) 
{ 
    char bTmpSms[3] = { 0 }; 

    itoa(bSmsIndex, bTmpSms, 10); 
    printf("index = 2\n"); 


    GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0); 
    return 1; 
} 

鎖沒有任何啓用的優化,並試圖在代碼卡從我的I2C RTC讀取一個字節,但只要我刪除這個printf("index = %s\n", bTmpSms);或使用這個而不是printf("index = 2\n");那麼一切都很開心任何想法?

編輯:bSmsIndex實際上永遠不會超過30個,即使如此,在調用此函數之前,鎖定會發生在wayyyy上。

+0

你是說即使這個函數還沒執行一次,鎖定會發生嗎? – 2010-10-12 19:04:26

+0

是的,就是這樣! – jramirez 2010-10-12 19:24:58

+0

哦 - 這是一個非常有趣的方面,直到現在我才意識到。當您停留在讀取I2C RTC時,堆棧是否會顯示任何有趣的內容?你在使用多任務嗎? – 2010-10-12 19:46:49

回答

1

好的,謝謝大家,你給了我一些很棒的指針,它幫助我弄明白了。

看來,如果我不初始化變量bTmpSms的問題發生,我也意識到,是不是printf是問題是itoa函數。再次感謝大家不斷提及它。它讓我檢查,即使我不認爲這是問題。當我評論itoa函數,然後整個代碼工作。

所以我落得這樣做是這樣的:

u8 GSM_Telit_ReadSms(u8 bSmsIndex) 
{ 
    char bTmpSms[4] = "aaa"; // I still need to find out why this is !!! 

    itoa(bSmsIndex, bTmpSms, 10); // converts the smsindex into a string 

    printf("index = %s\n", bTmpSms); //this printf caused the code to get stuck in the RTC // byte read function !!!!!!! 

    GSM_Telit_RequestModem("AT+CMGR=""1", 10, "CMGR", 5, 0); 
    return 1; 
} 

這是itoa功能我得到了我不記得在那裏我得到它,我會檢查它後面看到,如果有什麼我錯過了。

char itoa(int value, char* result, int base) 
{ 
    // check that the base if valid 
    if (base < 2 || base > 36) { *result = '\0'; return 0; } 

    char* ptr = result, *ptr1 = result, tmp_char; 
    int tmp_value; 

    do 
    { 
    tmp_value = value; 
    value /= base; 
    *ptr++ = "zyxwvutsrqponmlkjihgfedcba987654321abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)]; 
    } while (value); 

    // Apply negative sign 
    if (tmp_value < 0) *ptr++ = '-'; 
    *ptr-- = '\0'; 
    while(ptr1 < ptr) 
    { 
    tmp_char = *ptr; 
    *ptr--= *ptr1; 
    *ptr1++ = tmp_char; 
    } 
    return 1; 
} 
+0

看到我的答案。我不認爲你解決了這個問題,我認爲你掩蓋了它。它會在稍後回來咬你。 – 2010-10-12 21:21:30

+0

我同意你的意見。那就是爲什麼我說我稍後會檢查這個功能。但至少我知道大部分問題在哪裏。 – jramirez 2010-10-12 21:28:39

+0

我希望我不會誤解你 - 聽起來好像在調用'atoi'函數之前就會出現問題,所以錯誤也不存在。你不知道問題出在哪裏。 – 2010-10-12 21:34:06

2

char bTmpSms[3]只有「99」的空間。如果您的bSmsIndex爲100或更大,您將嘗試寫入不屬於您的內存。更新


編輯我沒有我的本地機器上的一個參考itoa,但我發現這個(http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/)。根據該參考文獻,對於任何可能的價值,目標排列必須足夠長。檢查您的文檔:您的具體itoa可能會有所不同。

或使用sprintf,snprintf或本標準描述的某些功能。

+0

正確,但這不是導致問題的寫入(因爲第二個代碼有效)。這是printf讀取殺死東西的字符串。然而,寫也可能導致在某個時候的問題,所以肯定也是一個問題 – 2010-10-12 18:39:26

+0

@Paul - 但誰知道錯誤的寫可能會被搗毀? – 2010-10-12 18:43:09

+0

就我而言,寫入不屬於你的內存,可以使你的程序從你的銀行賬戶轉移到我的錢:-) – pmg 2010-10-12 18:48:07

0

bSmsIndex的價值是什麼?

如果超過99個,則轉換爲字符串時將爲3位數字。當零終止時,它將只有四個字符,但你只分配了三個給bTmpSms,所以null可能會被覆蓋,並且printf會嘗試在bTmpSms之後打印任何uis,直到下一個空值。這可以訪問任何東西,真的。

0

您試圖打印的bSmsIndex的價值是多少?

如果它大於99那麼你超出了bTmpSms陣列。

如果這沒有幫助,那麼使用IAR相當不錯的調試器 - 我會在調用printf()的位置放入裝配窗口,直到事情進入雜草爲止。這可能會明確說明問題所在。

或者作爲一個快速n-dirty的疑難解答,嘗試調整數組大小(可能是8),看看會發生什麼。

+0

我確實嘗試使陣列更大但同樣的問題發生 – jramirez 2010-10-12 19:03:46

+0

@jramirez:我認爲你可能需要捲起袖子,開始踏入運行時的深淵... – 2010-10-12 19:34:42

1

一些想法:

如果itoa()沒有正確NUL終止的字符串,然後調用的printf可能導致機器尋找NUL永遠。

pmg有一個很好的觀點。

另外,請考慮itoa()的第一個參數是什麼類型。如果它已簽名並且傳入的是無符號整數,那麼您可能會在bTmpSms中收到一個意外的減號。請嘗試使用sprintf()

+0

itoa是null終止我檢查 – jramirez 2010-10-12 19:04:16

0

有你拆解這個領域具有指數= 2比指數=%s的

1

代碼的改變在內存中移動你的代碼的其餘部分。我的猜測是,這裏沒有列出的其他代碼部分正在抨擊一些隨機位置;在第一種情況下,該位置包含重要的事物,而在第二種情況下則不重要。

這些是追蹤*最嚴重的問題。祝你好運。

*也許不是最糟糕的 - 如果它是一個星期內只出現一次的多個線程之間的競爭條件,情況可能會更糟。仍然不是我最喜歡的一種錯誤。