2010-10-12 84 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

代码的改变在内存中移动你的代码的其余部分。我的猜测是,这里没有列出的其他代码部分正在抨击一些随机位置;在第一种情况下,该位置包含重要的事物,而在第二种情况下则不重要。

这些是追踪*最严重的问题。祝你好运。

*也许不是最糟糕的 - 如果它是一个星期内只出现一次的多个线程之间的竞争条件,情况可能会更糟。仍然不是我最喜欢的一种错误。