STM32 printf 和 RTC
*更新*
这是我发现的。每当我在那里有这个函数时,它实际上不会使代码锁定。它实际上会使读取 RTC I²C 函数的执行速度非常慢,但代码仍然可以正常运行,但每次读取 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;
}
没有启用任何优化,并且在尝试从 I²C RTC 中读取字节时代码会卡住,但是一旦我删除它printf("index = %s\n", bTmpSms);
或使用这个 printf("index = 2\n");
那么一切都会很高兴。有什么想法吗?
bSmsIndex 实际上永远不会超过 30,即使如此,锁定也会在调用此函数之前发生。
* UPDATE *
Here is what I found. Whenever I had that function in there it wouldn't actually make the code lock up. It would actually make the read RTC I²C function very slow to execute, but the code would still run properly, but I had to wait a really long time to get past every time I read the RTC.
So there is an alarm interrupt for the RTC and this was triggering other I²C interactions inside the ISR, so it looks like it was trying to do two I²C communications at the same time, therefore slowing down the process. I removed the functions in the ISR and it's working now. I will keep investigating.
I am having this problem when programming an STM32F103 microcontroller using IAR 5.40. I have this function that if I try to printf a local variable it causes the code to freeze at another point way before it even gets to that function in question.
What could possibly be causing this?
This is the function:
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;
}
I tried this as well and this does not cause the lock I experienced:
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;
}
There is no optimization enabled whatsoever and the code gets stuck when trying to read a byte out of my I²C RTC, but as soon as I remove this printf("index = %s\n", bTmpSms);
or use this one instead printf("index = 2\n");
then everything is happy. Any ideas?
The bSmsIndex will never be more than 30 actually and even then the lock up happens wayyyy before this function gets called.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
char bTmpSms[3]
只有“99”的空间。如果您的 bSmsIndex 为 100 或更大,您将尝试写入不属于您的内存。更新后编辑
我的本地计算机上没有对
itoa
的引用,但我找到了这个( http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/ )。根据该参考文献,目标数组必须足够长以容纳任何可能的值。检查您的文档:您的特定itoa
可能有所不同。或者使用
sprintf
、snprintf
或标准描述的某些函数。char bTmpSms[3]
only has space for "99". If your bSmsIndex is 100 or greater, you will be trying to write to memory that doesn't belong to you.Edit after the update
I don't have a reference to
itoa
on my local machine, but I found this one ( http://www.cplusplus.com/reference/clibrary/cstdlib/itoa/ ). According to that reference, the destination array MUST BE LONG ENOUGH FOR ANY POSSIBLE VALUE. Check your documentation: your specificitoa
might be different.Or use
sprintf
,snprintf
, or some function described by the Standard.一些想法:
如果
itoa()
没有正确地以 NUL 终止字符串,那么对 printf 的调用可能会导致机器永远寻找 NUL。pmg 有一个很好的观点。
另外,请考虑 itoa() 的第一个参数是什么类型。如果它是有符号的并且您传递的是无符号整数,那么您可能会在 bTmpSms 中得到意外的减号。尝试使用
sprintf()
代替。Some ideas:
If
itoa()
is not properly NUL-terminating the string, then the call to printf may result in the machine looking for the NUL forever.pmg has a very good point.
Also, consider what type the first argument to
itoa()
is. If it's signed and you're passing in an unsigned integer, then you may be getting an unexpected minus sign in bTmpSms. Try usingsprintf()
instead.代码的更改正在内存中移动其余代码。我的猜测是,代码的其他部分(此处未列出)正在攻击某个随机位置;在第一种情况下,该位置包含关键内容,在第二种情况下则不包含。
这些是最难追踪的问题*。祝你好运。
*也许不是最糟糕的 - 如果是每周只出现一次的多个线程之间的竞争条件,情况可能会更糟。仍然不是我最喜欢的错误。
The change in code is moving the rest of your code around in memory. My guess is that some other part of the code, not listed here, is bashing some random location; in the first case that location contains something critical, in the second case it does not.
These are the worst kinds of problems to track down*. Good luck.
*Maybe not the worst - it could be worse if it were a race condition between multiple threads that only manifested itself once a week. Still not my favorite kind of bug.
似乎如果我不将变量 bTmpSms 初始化为某个值,就会出现问题。
我还意识到问题不是 printf 。这是 itoa 函数。它让我检查,即使我不认为这是问题所在,但当我评论 itoa 函数时,整个代码都可以工作。
所以我最终这样做了:
这是我得到的 itoa 函数:
qponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
while(值);
It seems that if I don't initialize the variable bTmpSms to something the problem occurs.
I also realized that it is not the printf that is the problem. It is the itoa function. It got me to check that even though I didn't think that was the problem, when I commented the itoa function then the whole code worked.
So I ended up doing this:
This is the itoa function I got:
qponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
} while (value);
您尝试打印的
bSmsIndex
的值是多少?如果它大于 99,那么您就会超出
bTmpSms
数组。如果这没有帮助,那么使用 IAR 相当好的调试器 - 我会在调用
printf()
的地方进入汇编窗口并单步执行,直到事情变得混乱为止。这可能会清楚问题所在。或者作为一种快速的故障排除,尝试将数组大小调整为较大的值(可能是 8),然后看看会发生什么。
What's the value of
bSmsIndex
you're trying to print?If it's greater than 99 then you're overrunning the
bTmpSms
array.If that doesn't help, then use IAR's pretty good debugger - I'd drop into the assembly window at the point where
printf()
is being called and single step until things went into the weeds. That'll probably make clear what the problem is.Or as a quick-n-dirty troubleshoot, try sizing the array to something large (maybe 8) and see what happens.
bSmsIndex 的值是多少?
如果大于99,转换为字符串时将是三位数字。当零终止时,它将是四个字符,但您只为 bTmpSms 分配了三个字符,因此 null 可能会被覆盖,并且 printf 将尝试打印 bTmpSms 之后的任何内容,直到下一个 null。真的可以访问任何东西。
What's the value of bSmsIndex?
If more than 99 it will be three digits when converted to a string. When zero terminated, it will be four characters, but you've allocated only three to bTmpSms so the null may get overwritten and the printf will try to print whatever is after bTmpSms until the next null. That could access anything, really.
尝试使用index =
2
与index =%s
反汇编该区域。Try to disassemble this area with index =
2
vs. index =%s
.