无法从 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);
    }
}