无法从 C 中断 Arduino Uno 的引导加载程序
Can't interrupt Arduino Uno's bootloader from C
我正在尝试让 Arduino 进入编程模式。我想检查闪存以查看我的软件是否已经安装,然后根据需要上传几个二进制文件之一。为了测试,我有一个简单的草图,它在循环中什么都不做,但在设置时通过串行端口发送“在常规模式下”。
切换 DTR/RTS 确实重置了 Arduino,但发送同步请求没有任何作用,引导加载程序超时并将控制权传递给草图。
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/io.h>
#include <sys/ioctl.h>
#include <termios.h>
int main()
{
static const uint8_t bSyncString [] = {0x30, 0x20}; // {CMD_STK_GET_SYNC, SYNC_CRC_EOP};
uint8_t bBuffer [256];
unsigned int ctl;
struct termios tty;
int iFd = open ("/dev/ttyACM0", O_RDWR | O_NOCTTY);
if (iFd >= 0)
{
// From STK500 spec: 115.2kbps, 8 data bits, 1stop bits, no parity
if (tcgetattr (iFd, &tty) == 0)
{
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
tty.c_cflag |= CS8|CSTOPB;
tty.c_cflag &= ~(PARENB|PARODD);
if (tcsetattr(iFd, TCSANOW|TCSADRAIN, &tty) == 0)
printf ("Attributes set\n");
}
if (ioctl (iFd, TIOCMGET, &ctl) >= 0) // Get current line states
{
ctl &= ~(TIOCM_DTR|TIOCM_RTS);
if (ioctl(iFd, TIOCMSET, &ctl) >= 0) // DTR and RTS low
{
usleep (50 * 1000);
ctl |= TIOCM_DTR|TIOCM_RTS;
if (ioctl(iFd, TIOCMSET, &ctl) >= 0) // DTR and RTS high
{
usleep (50 * 1000);
if (write (iFd, bSyncString, 2) == 2)
if (read (iFd, bBuffer, sizeof (bBuffer)) > 0)
printf ("Received %s\n", bBuffer);
}
}
}
close (iFd);
}
}
知道了。我获取了 avrdude 的源代码,提取了相关位,然后将它们精简,来回粘贴功能,直到它起作用。
我的一些串行设置已关闭,发送写入之前的延迟太短,因此最小设置如下:
int main()
{
static const uint8_t bSyncString [] = {0x30, 0x20}; // {CMD_STK_GET_SYNC, SYNC_CRC_EOP};
uint8_t bBuffer [256];
unsigned int ctl;
struct termios tty;
int iFd = open ("/dev/ttyACM0", O_RDWR | O_NOCTTY);
if (iFd >= 0)
{
// From STK500 spec: 115.2kbps, 8 data bits, 1stop bits, no parity
if (tcgetattr (iFd, &tty) == 0)
{
tty.c_iflag = IGNBRK;
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_cflag = (CS8 | CREAD | CLOCAL);
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
if (tcsetattr(iFd, TCSANOW, &tty) == 0)
printf ("Attributes set\n");
}
if (ioctl (iFd, TIOCMGET, &ctl) >= 0) // Get current line states
{
ctl &= ~(TIOCM_DTR|TIOCM_RTS);
if (ioctl(iFd, TIOCMSET, &ctl) >= 0) // DTR and RTS low
{
usleep (50 * 1000);
ctl |= TIOCM_DTR|TIOCM_RTS;
if (ioctl(iFd, TIOCMSET, &ctl) >= 0) // DTR and RTS high
usleep (250 * 1000);
}
}
if (write (iFd, bSyncString, 2) == 2)
{
int iRead = read (iFd, bBuffer, sizeof (bBuffer));
if (iRead > 0)
{
printf ("Received %s\n", bBuffer);
for (int i = 0; i < iRead; i++)
printf ("%02x ", bBuffer [i]);
printf ("\n");
}
}
close (iFd);
}
}
我正在尝试让 Arduino 进入编程模式。我想检查闪存以查看我的软件是否已经安装,然后根据需要上传几个二进制文件之一。为了测试,我有一个简单的草图,它在循环中什么都不做,但在设置时通过串行端口发送“在常规模式下”。
切换 DTR/RTS 确实重置了 Arduino,但发送同步请求没有任何作用,引导加载程序超时并将控制权传递给草图。
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/io.h>
#include <sys/ioctl.h>
#include <termios.h>
int main()
{
static const uint8_t bSyncString [] = {0x30, 0x20}; // {CMD_STK_GET_SYNC, SYNC_CRC_EOP};
uint8_t bBuffer [256];
unsigned int ctl;
struct termios tty;
int iFd = open ("/dev/ttyACM0", O_RDWR | O_NOCTTY);
if (iFd >= 0)
{
// From STK500 spec: 115.2kbps, 8 data bits, 1stop bits, no parity
if (tcgetattr (iFd, &tty) == 0)
{
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
tty.c_cflag |= CS8|CSTOPB;
tty.c_cflag &= ~(PARENB|PARODD);
if (tcsetattr(iFd, TCSANOW|TCSADRAIN, &tty) == 0)
printf ("Attributes set\n");
}
if (ioctl (iFd, TIOCMGET, &ctl) >= 0) // Get current line states
{
ctl &= ~(TIOCM_DTR|TIOCM_RTS);
if (ioctl(iFd, TIOCMSET, &ctl) >= 0) // DTR and RTS low
{
usleep (50 * 1000);
ctl |= TIOCM_DTR|TIOCM_RTS;
if (ioctl(iFd, TIOCMSET, &ctl) >= 0) // DTR and RTS high
{
usleep (50 * 1000);
if (write (iFd, bSyncString, 2) == 2)
if (read (iFd, bBuffer, sizeof (bBuffer)) > 0)
printf ("Received %s\n", bBuffer);
}
}
}
close (iFd);
}
}
知道了。我获取了 avrdude 的源代码,提取了相关位,然后将它们精简,来回粘贴功能,直到它起作用。
我的一些串行设置已关闭,发送写入之前的延迟太短,因此最小设置如下:
int main()
{
static const uint8_t bSyncString [] = {0x30, 0x20}; // {CMD_STK_GET_SYNC, SYNC_CRC_EOP};
uint8_t bBuffer [256];
unsigned int ctl;
struct termios tty;
int iFd = open ("/dev/ttyACM0", O_RDWR | O_NOCTTY);
if (iFd >= 0)
{
// From STK500 spec: 115.2kbps, 8 data bits, 1stop bits, no parity
if (tcgetattr (iFd, &tty) == 0)
{
tty.c_iflag = IGNBRK;
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_cflag = (CS8 | CREAD | CLOCAL);
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
if (tcsetattr(iFd, TCSANOW, &tty) == 0)
printf ("Attributes set\n");
}
if (ioctl (iFd, TIOCMGET, &ctl) >= 0) // Get current line states
{
ctl &= ~(TIOCM_DTR|TIOCM_RTS);
if (ioctl(iFd, TIOCMSET, &ctl) >= 0) // DTR and RTS low
{
usleep (50 * 1000);
ctl |= TIOCM_DTR|TIOCM_RTS;
if (ioctl(iFd, TIOCMSET, &ctl) >= 0) // DTR and RTS high
usleep (250 * 1000);
}
}
if (write (iFd, bSyncString, 2) == 2)
{
int iRead = read (iFd, bBuffer, sizeof (bBuffer));
if (iRead > 0)
{
printf ("Received %s\n", bBuffer);
for (int i = 0; i < iRead; i++)
printf ("%02x ", bBuffer [i]);
printf ("\n");
}
}
close (iFd);
}
}