首页 > 解决方案 > 不能从 C 中断 Arduino Uno 的引导加载程序

问题描述

我正在尝试让 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);
    }
}

标签: arduinobootloader

解决方案


知道了。我获取了 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);
    }
}

推荐阅读