I have an Arduino project where I read data from a webserver.
我有一个Arduino项目,在这个项目中我从web服务器读取数据。
I have an EthernetClient
that reads the data character by character in a callback function.
我有一个EthernetClient,它按回调函数中的字符读取数据字符。
My working code looks like (only the relevant parts):
我的工作代码是这样的(只有相关的部分):
void setup() {
Serial.begin(9600);
...
}
void loop() {
char* processedData = processData(callback); // this is in a external lib
}
boolean callback(char* buffer, int& i) {
...
if (Client.available()) {
char c = client.read();
buffer[i++] = c;
Serial.print(c);
}
...
}
This works without any problems (reading and processing the data), but when I remove Serial.begin(9600);
and Serial.print(c);
it stops working and I don't know why? The only thing changed is that the char c
is not printed. What could be the problem?
这个操作没有任何问题(读取和处理数据),但是当我删除Serial.begin(9600);和并(c);它停止工作了,我不知道为什么?唯一改变的是char c没有打印出来。有什么问题呢?
2 个解决方案
#1
2
A common reason why callback functions change their behavior when seemingly unrelated code is altered, is optimizer-related bugs.
当看似不相关的代码被修改时,回调函数改变其行为的一个常见原因是与优化器相关的bug。
Many embedded compilers fail to understand that a callback function (or an interrupt service routine) will ever be called in the program. They see no explicit call to that function and then assumes it is never called.
许多嵌入式编译器无法理解在程序中调用回调函数(或中断服务例程)。他们没有看到对该函数的明确调用,然后假设它从未被调用。
When the compiler has made such an assumption, it will optimize variables that are changed by the callback function, because it fails to see that the variable is changed by the program, between the point of initialization and the point of access.
当编译器做出这样的假设时,它将优化由回调函数更改的变量,因为它没有看到变量是由程序更改的,在初始化点和访问点之间。
// Bad practice example:
int x;
void main (void)
{
x=5;
...
if(x == 0) /* this whole if statement will get optimized away,
the compiler assumes that x has never been changed. */
{
do_stuff();
}
}
void callback (void)
{
x = 0;
}
When this bug strikes, it is nearly impossible to find, it can cause any kind of weird symptoms.
当这个bug发生时,几乎不可能找到,它会导致任何奇怪的症状。
The solution is to always declare all file scope ("global") variables shared between main() and an interrupt/callback/thread as volatile
. This makes it impossible for the compiler to make incorrect optimizer assumptions.
解决方案是始终将main()和中断/回调/线程之间共享的所有文件范围(“全局”)变量声明为volatile。这使得编译器不可能做出不正确的优化器假设。
(Please note that the volatile
keyword cannot be used to achieve synchronization nor does it guarantee any memory barriers. This answer is not in the slightest related to such issues!)
(请注意,volatile关键字不能用于实现同步,也不能保证任何内存障碍。这个答案与这些问题一点关系也没有!
#2
0
A guess: Because without the serial driver started, there is no data to process, and therefore your callback is not hit.
猜测:因为没有启动串行驱动程序,就没有数据要处理,因此不会击中回调。
What were you hoping the serial callback to be doing in the absence of data?
在没有数据的情况下,您希望串行回调做什么?
Providing more information about Client
and processData
may help.
提供更多关于客户端和过程数据的信息可能会有所帮助。
#1
2
A common reason why callback functions change their behavior when seemingly unrelated code is altered, is optimizer-related bugs.
当看似不相关的代码被修改时,回调函数改变其行为的一个常见原因是与优化器相关的bug。
Many embedded compilers fail to understand that a callback function (or an interrupt service routine) will ever be called in the program. They see no explicit call to that function and then assumes it is never called.
许多嵌入式编译器无法理解在程序中调用回调函数(或中断服务例程)。他们没有看到对该函数的明确调用,然后假设它从未被调用。
When the compiler has made such an assumption, it will optimize variables that are changed by the callback function, because it fails to see that the variable is changed by the program, between the point of initialization and the point of access.
当编译器做出这样的假设时,它将优化由回调函数更改的变量,因为它没有看到变量是由程序更改的,在初始化点和访问点之间。
// Bad practice example:
int x;
void main (void)
{
x=5;
...
if(x == 0) /* this whole if statement will get optimized away,
the compiler assumes that x has never been changed. */
{
do_stuff();
}
}
void callback (void)
{
x = 0;
}
When this bug strikes, it is nearly impossible to find, it can cause any kind of weird symptoms.
当这个bug发生时,几乎不可能找到,它会导致任何奇怪的症状。
The solution is to always declare all file scope ("global") variables shared between main() and an interrupt/callback/thread as volatile
. This makes it impossible for the compiler to make incorrect optimizer assumptions.
解决方案是始终将main()和中断/回调/线程之间共享的所有文件范围(“全局”)变量声明为volatile。这使得编译器不可能做出不正确的优化器假设。
(Please note that the volatile
keyword cannot be used to achieve synchronization nor does it guarantee any memory barriers. This answer is not in the slightest related to such issues!)
(请注意,volatile关键字不能用于实现同步,也不能保证任何内存障碍。这个答案与这些问题一点关系也没有!
#2
0
A guess: Because without the serial driver started, there is no data to process, and therefore your callback is not hit.
猜测:因为没有启动串行驱动程序,就没有数据要处理,因此不会击中回调。
What were you hoping the serial callback to be doing in the absence of data?
在没有数据的情况下,您希望串行回调做什么?
Providing more information about Client
and processData
may help.
提供更多关于客户端和过程数据的信息可能会有所帮助。