Как правильно активировать контакт сброса ATMega328 с помощью ПО, чтобы загрузчик работал, а прошивка могла обновляться через контакты RX/TX?

Я программирую свой чип Atmega328P через преобразователь USB в TTL (https://www.amazon.com/ gp/product/B075N82CDL/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1)

Я могу загружать шестнадцатеричные файлы через командную строку и Arduino IDE, когда у меня есть контакт RTS адаптера и конденсатор, подключенный к контакту !RESET Atmega. (http://www.electronics-lab.com /wp-content/uploads/2018/09/programming-Uno-on-breadboard.png)

Я также могу выполнить загрузку через командную строку, когда у меня есть кнопка, прикрепленная к контакту !RESET, и я вручную опускаю ее, а затем начинаю загружать прошивку в течение нескольких секунд. (https://cdn.instructables.com/F0L/2F6U/J7AQSHD1/F0L2F6UJ7AQSHD1.LARGE.jpg )

Моя проблема заключается в том, что для моего приложения у меня будут доступны только контакты TX/RX/Vcc/GND (без RTS или кнопки), и мне нужно сбросить микроконтроллер, чтобы загрузчик работал и прослушивал программирование с обновленной прошивкой. .

На данный момент я написал пакетный файл, который отправляет команду на перезапуск Arduino, а затем вызывает avrdude для загрузки шестнадцатеричного файла. Я пробовал два метода перезапуска микроконтроллера. Я сказал ему перейти в нулевую ячейку памяти, и я подключил вывод ввода-вывода к сбросу и понизил его (хотя он остается низким до сброса, поэтому сброс на самом деле не работает, пока я вручную не отключу провод между вводом-выводом). контакт и контакт !RESET)

Моя последовательность такова:

  1. Имейте работающий код Arduino:
    int recvByte;
    int delayS = 400;
    int resetPin = 9; //правый нижний контакт uC

    void setup() {
      // поместите сюда код установки для однократного запуска:
    pinMode(txPin, OUTPUT);
    pinMode(rxPin, INPUT);
    pinMode(resetPin, OUTPUT);
    digitalWrite(resetPin, HIGH);
    Serial.begin(57600);
    Serial.write("Booted/reset");
    Serial.write("This setup was uploaded with batch");    
    }

    void(* resetFunc) (void) = 0;

    void loop() {

    if (Serial.available() )
    {    // получаем входящий байт:
        recvByte = Serial.read();
        if (recvByte==int('r'))
        {
        Serial.write("resetting");
        delay(10); // ждем отправки последнего сообщения
        // цифровая запись (resetPin, LOW); // закомментирован, потому что этот метод остается низким, пока провод не будет удален
        resetFunc();
        Serial.write("should not see if reset properly");
        }

    }

    delay(100);
    }

2. Затем я запускаю пакетный файл.

echo Running upload bat, sending reset command then calling avrdude
cd "C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\"
python "path\sendR.py"
.\avrdude.exe -C"C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:"path\Atmega328code.hex":i 

SendR.py Python должен отправлять символ «r», который Arduino рассматривает как команду сброса.

import serial
ser = serial.Serial("COM6", baudrate=57600)  # открыть последовательный порт
bytes = "r".encode()
ser.write(bytes)
ser.close()
print("End python script")

Когда я отправляю "r" через Tera Term или python, код установки запускается снова, но я не смог загрузить его с помощью .\avrdude.exe -C"C:\Program Files (x86)\ Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:"path\Atmega328code.hex":i внутри пакетного файла. Если я использую кнопку для аппаратного сброса, эта команда работает без проблем.

Как я могу загрузить новую прошивку через контакты RX и TX, используя программное обеспечение для сброса микроконтроллера и прослушивания нового кода во время работы загрузчика?

Испробованы новые идеи: Используйте единую скорость передачи 57600 в последовательной настройке python и atmega. Я выбрал это значение, потому что IDE Arduino выводит эту скорость передачи данных в avrdude.exe -C"C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:"path\Atmega328code.hex":i

, 👍2

Обсуждение

wdt_enable(WDTO_15MS); сбрасывает MCU через 15 миллисекунд после вызова. это полный сброс, как с булавкой сброса., @Juraj


1 ответ


Лучший ответ:

0

Вы писали:

void(* resetFunc) (void) = 0;

Мне кажется, что этот подход стоит попробовать, за исключением того, что функция адрес неверный. По нулевому адресу флэш-памяти у вас есть начало код пользователя. Загрузчик, если вы его используете, живет в конце вспышка. Начальный адрес загрузчика зависит от его размера и настраивается установкой некоторых предохранителей на микросхеме. Если вы используете популярный optiboot (загрузчик Uno), вы должны перейти к ровно за 512 байт до конца флэш-памяти, т. е.:

void (*resetFunc)(void) = 0x7e00;

Ой, подождите... флэш-память организована как 16-битные слова, так что вам, возможно, придется вместо этого используйте пословный адрес:

void (*resetFunc)(void) = 0x3f00;

Но обратите внимание, что, в отличие от реального аппаратного сброса, этот подход не сбросьте периферийные устройства в нормальное исходное состояние. Вы можете сделать перед переходом к загрузчику.


Правка: я разобрал тестовую программу, которая выполняет подобные действия. вызов по указателю, затем дважды проверил документацию язык инструкция. Похоже, что указанный вами адрес функции действительно интерпретируется как пословный адрес, поэтому вы должны написать половину побайтовый адрес. Если вы напишете что-то большее, чем размер flash (0x4000 = 16 килослов), получаются старшие биты теряется, и адрес сокращается до правильного диапазона по модулю флэш-памяти. размер.

То есть, если у вас сработал 0x7800, то предположительно правильный адрес равно 0x3800, то есть за 2 килослова (4 КБ) до конца вспышка. Это довольно большой загрузчик, и самый большой поддерживаемый размер на ATmega328P. Вы уверены, что это правильно? Разве ты не скользишь какая-то неинициализированная прошивка перед попаданием в загрузчик? Вот таблица который дает начальный адрес загрузчика в зависимости от количества память, зарезервированная для него:

reserved size  start address
    512 B         0x3f00
     1 KB         0x3e00
     2 KB         0x3c00
     4 KB         0x3800

Обратите внимание, что Arduino Uno использует optiboot, что соответствует наименьший размер, который может быть выделен загрузчику (512 байт).

,

Спасибо! Батник работает с чипом после изменения кода чипа на void(*resetFunc)(void)=0x7e00;, @Jalconvolvon2

Место, которое я должен был использовать, было «0x7800», но теперь оно отлично работает для меня. Еще раз спасибо!, @Jalconvolvon2

Я думаю, что это съедает вашу память после нескольких циклов перезагрузки, поскольку вы вызываете их как функцию, которая требует некоторого места в стеке. Разве не будет использовать wdt для правильной перезагрузки?, @Kwasmich

@Kwasmich: загрузчик может сбросить указатель стека. Если это не так, программа пользователя, безусловно, делает: это одна из первых вещей, которые делает среда выполнения C. Тем не менее трюк с WDT может быть полезен, потому что он сбрасывает все порты ввода-вывода в их начальные значения., @Edgar Bonet