手头有个固件, 使用了arduino Mega2560 开发板来做控制.
但是我是arduino新手, Mega2560并不能做单步调试. 光看代码不管用啊, 要单步调试才能深入理解代码实现逻辑.
整了一块arduino zero开发板, 可以在 Arduino IDE 单步调试, 这就好多了.
单步调试后, 通过实验, 就可以理解很多arduino编程的细节问题了.
Arduino IDE 2.0.3 + arduino zero
每块开发板都包含了特定的库, 可能这个库由于MCU的原因(e.g. AVR MCU vs ARM M0 MCU), 并没有包含进开发板的库, 导致编译不过.
e.g. _delay_loop_2 声明在 util/delay_basic.h 中, 头文件路径为 C:\Users\me\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\util
在mega2560开发板的工程上, 可以看到为了延时, 调用_delay_loop_2()
但是arduino zero是ARM M0的MCU, 所以就没有这个函数. 需要看官方例子, 找到延时函数, 进行替代.
打开官方例子工程, 将板子选为arduino zero, 打开有延时操作的例子, e.g. Blink工程, 单步delay()函数, 在实验里面, 可以看到微妙延时的函数. delayMicroseconds(), 替换掉就好.
还有些寄存器定义, 是和MCU相关的. e.g. SREG 这个在avr MCU中才有, 在ARM MCU中是没有的, 这就移植不了, 只能在mega2560或arduino nano every上运行. 因为这2款开发板不能单步, 只能用arduino zero模拟运行(将编译不过的实现注释掉), 将实现逻辑理清楚. 然后在avr mcu 的板子上实际测试.
这个单步一下就知道, 先在setup()和loop()入口下断点, 跑起来, 单步出了这2个函数就看到了.
/*
Copyright (c) 2015 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define ARDUINO_MAIN
#include "Arduino.h"
// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }
extern USBDeviceClass USBDevice;
// Initialize C library
extern "C" void __libc_init_array(void);
/*
* \brief Main entry point of Arduino application
*/
int main( void )
{
init();
__libc_init_array();
initVariant();
delay(1);
#if defined(USBCON)
USBDevice.init();
USBDevice.attach();
#endif
setup();
for (;;)
{
loop();
if (arduino::serialEventRun) arduino::serialEventRun();
}
return 0;
}
可以看到arduino IDE自己实现的main(), 系统初始化init()之后, 调用用户自己的初始化函数setup(), 然后在一个循环中调用用户自己的循环处理函数loop().
arduino这么搞, 对于用户来说, 方便倒是方便, 但是不灵活. 只能处理一些实时性不强, 没有并行处理, 只有顺序处理的任务.
对于产品来说, 还是不能用arduino IDE的这种编程方式, 还是要用没有封装的, 传统的MCU编程流程.