заливка прошивки (hex файл) в ардуино через UART с SD карты другой ардуинки

gonzales
Offline
Зарегистрирован: 13.07.2015

Доброго времени суток!

Интересует тема, как можно залить прошивку в ардуино не через ISP, а через UART, по типу как это делается с помощью программатора USB-TTL, но используя не Arduino IDE, а другую Ардуино.

Суть задачки следующая. Есть несколько ПроМини, объединенных модифицированной RS-485 шиной. Модификация заключается в дополнительной линии, обеспечивающей аппаратный ребут ПроМини. Среди объединенных МК есть мастер с SD картой, на которой лежит прошивка (hex файл). Идея в следующем, чтобы мастер послал команду, какую ПроМини он сейчас будет прошивать, на ней выставился флаг прошивки, далее мастер дергает линию аппаратного ребута, все ПроМини перегружаются и та, на которой выставлен флаг прошивки входит в "режим прошивки". Далее мастер считывает прошивку с SD и льет ее по UART, соответственно она занимает свое место в памяти нужной ПроМини. После этого мастер еще раз дергает линию ребута, все ПроМини ребутятся еще раз и начинается выполнение программы.

Но это я так "красиво" написал, как я себе это представляю в общем, но при реализации возникает гора вопросов, пока основным является алгоритм взаимодействия мастера с ПроМини после ребута - как войти в "режим прошивки", если я правильно понял, чтобы ПроМини стала ожидать заливки прошивки нужно что-то послать заргузчику. По обрывочным сведениям должно быть что-то типа "бутлоадер по идее должен подхватить команду DTR (тройное сочетание не помню каких символов) и перепрошиться. И да, все модули должны быть настроены так: по умолчанию (подтяжкой,безо всяких действий со стороны МК) должны быть в режиме Rx."

 Интернет мне не смог помочь, либо я пока не знаю, как правильно спросить), может уважаемое сообщество располагает какими-либо сведениями в этом вопросе.

Всем заранее спасибо за ответы!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А не жестоко все сразу перегружать ради того, чтобы прошить одну? Если той одной сказали, что ей надо ребутиться, она могла бы и сама перегрузиться, нет?

gonzales
Offline
Зарегистрирован: 13.07.2015

ЕвгенийП пишет:

А не жестоко все сразу перегружать ради того, чтобы прошить одну? Если той одной сказали, что ей надо ребутиться, она могла бы и сама перегрузиться, нет?

Это пока нюансы, понятно как сделать, для упрощения допустим, что она вообще одна))) Как заставить ее принять прошивку

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

gonzales пишет:

ЕвгенийП пишет:

А не жестоко все сразу перегружать ради того, чтобы прошить одну? Если той одной сказали, что ей надо ребутиться, она могла бы и сама перегрузиться, нет?

Это пока нюансы, понятно как сделать, для упрощения допустим, что она вообще одна))) Как заставить ее принять прошивку

Наверное так же, как IDE заставляет...

sadman41
Онлайн
Зарегистрирован: 19.10.2016
gonzales
Offline
Зарегистрирован: 13.07.2015

Да, это я читал, но если я правильно понял это история не для ардуино

gonzales
Offline
Зарегистрирован: 13.07.2015

Я использую optiboot загрузчик https://github.com/Optiboot/optiboot Вроде как там открытый код, но я не понимаю его структуры, если не затруднит, ткните, где можно почитать об этом, или в двух словах как он устроен.

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

/* STK500 constants list, from AVRDUDE */
#define STK_OK              0x10
#define STK_FAILED          0x11  // Not used
#define STK_UNKNOWN         0x12  // Not used
#define STK_NODEVICE        0x13  // Not used
#define STK_INSYNC          0x14  // ' '
#define STK_NOSYNC          0x15  // Not used
#define ADC_CHANNEL_ERROR   0x16  // Not used
#define ADC_MEASURE_OK      0x17  // Not used
#define PWM_CHANNEL_ERROR   0x18  // Not used
#define PWM_ADJUST_OK       0x19  // Not used
#define CRC_EOP             0x20  // 'SPACE'
#define STK_GET_SYNC        0x30  // '0'
#define STK_GET_SIGN_ON     0x31  // '1'
#define STK_SET_PARAMETER   0x40  // '@'
#define STK_GET_PARAMETER   0x41  // 'A'
#define STK_SET_DEVICE      0x42  // 'B'
#define STK_SET_DEVICE_EXT  0x45  // 'E'
#define STK_ENTER_PROGMODE  0x50  // 'P'
#define STK_LEAVE_PROGMODE  0x51  // 'Q'
#define STK_CHIP_ERASE      0x52  // 'R'
#define STK_CHECK_AUTOINC   0x53  // 'S'
#define STK_LOAD_ADDRESS    0x55  // 'U'
#define STK_UNIVERSAL       0x56  // 'V'
#define STK_PROG_FLASH      0x60  // '`'
#define STK_PROG_DATA       0x61  // 'a'
#define STK_PROG_FUSE       0x62  // 'b'
#define STK_PROG_LOCK       0x63  // 'c'
#define STK_PROG_PAGE       0x64  // 'd'
#define STK_PROG_FUSE_EXT   0x65  // 'e'
#define STK_READ_FLASH      0x70  // 'p'
#define STK_READ_DATA       0x71  // 'q'
#define STK_READ_FUSE       0x72  // 'r'
#define STK_READ_LOCK       0x73  // 's'
#define STK_READ_PAGE       0x74  // 't'
#define STK_READ_SIGN       0x75  // 'u'
#define STK_READ_OSCCAL     0x76  // 'v'
#define STK_READ_FUSE_EXT   0x77  // 'w'
#define STK_READ_OSCCAL_EXT 0x78  // 'x'

 

b707
Offline
Зарегистрирован: 26.05.2017

gonzales пишет:

Да, это я читал, но если я правильно понял это история не для ардуино

так вся ваша задача - это "история не про ардуино". В ардуино нет наработок для написания загрузчиков. если вы не в курсе.

Придется "голый Си" изучать.

gonzales
Offline
Зарегистрирован: 13.07.2015

b707 пишет:

Придется "голый Си" изучать.

Пока проблема в понимании, как устроен загрузчик и как с ним работать

b707
Offline
Зарегистрирован: 26.05.2017

gonzales пишет:

Пока проблема в понимании, как устроен загрузчик и как с ним работать

Вкратце, что где в исходниках оптибута - я вам ответил на Амперке.

Но судя по вопросу, корень ваших проблем, а том числе и с "пониманием оптибута" - в низком уровне владения предметом "программирование МК".

Обучайтесь. другого пути нет.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

А мне нравится! Люди ставят себе задачи в сложности реализации которых понятия не имеют ))) Ну а чё )))
 

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Через тернии к звёздам.

Ставить-то пусть ставят. Это полезно. Но вот когда после начинается катание ваты по форумам, а не втыкание в даташиты - это абзац, я считаю.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:

А мне нравится! Люди ставят себе задачи в сложности реализации которых понятия не имеют ))) Ну а чё )))

Ну, в общем-то, да. Задача-то идеально решается написанием собственного бутлоадера. Тогда можно всё сделать аккуратно и без костылей.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Зачем писать свой загрузчик? То, что человеку надо это стандартная функция существующего бутлоадера - прошивать данные поступающие из сериал порта, если сразу после ресета была получена соответствующая команда.

Вот логика работы оптибута:

1. При ресете Optiboot запускается и считывает причину ресета из MCUSR. По любой причине, кроме «внешнего ресета», ардуино запускается немедленно. В противном случае optiboot пытается загрузить новое программное обеспечение:

2 optiboot мигает «Start LED» , показывая, что работает. (какой пин используется и сколько раз он мигает, настраивается.)
3 Настраивает UART, и WDT  с тайм-аутом в 1 с.
4 Optiboot пытается прочитать команды с  последовательного порта. При получение правильной команды сбросывает WDT и начинает прошивку.
5. При отсутствии команды от UART или после программирования WDT срабатывает, что приводит к ресету.
6. Так как ресет WDT НЕ является «внешним ресетом», ардуино запускается как в п.1 -  все регистры AVR при этом сохраняют свои значения как после внешнего ресета за исключеним  MCUSR и SP.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Там много чего вылезет, что придётся решать костылями, а свой загрузчик был бы специально под эту задачу заточен.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

ЕвгенийП пишет:

Там много чего вылезет, что придётся решать костылями, а свой загрузчик был бы специально под эту задачу заточен.

Зачем же свой писать? Добавить одну команду в Оптибут и все. А если использовать не общий ресет для всех, а развести индивидуально (можно по кольцу, что бы кол-во проводов не увеличивать, одна ардуина управляет ресетом следующей), то тогда вообще ничего в бутлоадере менять не надо.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Дело за малым перевести RS-485 в хардовый rs232

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Это два пина  RX и TX.
Вопрос в другом - как обеспечивается доступ к пину DTR???

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

ua6em пишет:

 

Это два пина  RX и TX.
Вопрос в другом - как обеспечивается доступ к пину DTR???

А зачем доступ к DTR если ресет будет отдельной линией?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

asam пишет:

ua6em пишет:

 

Это два пина  RX и TX.
Вопрос в другом - как обеспечивается доступ к пину DTR???

А зачем доступ к DTR если ресет будет отдельной линией?

ТС написал - Есть несколько ПроМини, объединенных модифицированной RS-485 шиной. Модификация заключается в дополнительной линии, обеспечивающей аппаратный ребут ПроМини
но не написал как это сделано, думаю это важно, если ребут обеспечивается стандарными средствами управления (аналогично DTR) то видимо реализуемо

gonzales
Offline
Зарегистрирован: 13.07.2015

Ого тут понаписали)))

Во первых спасибо asam за поддержку, я тоже не понимаю, зачем писать свой загрузчик, если есть готовый, и какие там будут мифические костыли о которых мне так упорно рассказывают сразу на двух форумах, но не говорят какие, я не знаю. В общем то, загрузчик - такая же программа, которая специально создана для загрузки прошивки, я покопался в нем, благо дело код открытый, там все достаточно просто.

/* Forever loop: exits by causing WDT reset */
  for (;;) {
    /* get character from UART */
    ch = getch();

 программа ожидает по UART прихода символа.

вот список команд

/* STK500 constants list, from AVRDUDE */
#define STK_OK              0x10
#define STK_FAILED          0x11  // Not used
#define STK_UNKNOWN         0x12  // Not used
#define STK_NODEVICE        0x13  // Not used
#define STK_INSYNC          0x14  // ' '
#define STK_NOSYNC          0x15  // Not used
#define ADC_CHANNEL_ERROR   0x16  // Not used
#define ADC_MEASURE_OK      0x17  // Not used
#define PWM_CHANNEL_ERROR   0x18  // Not used
#define PWM_ADJUST_OK       0x19  // Not used
#define CRC_EOP             0x20  // 'SPACE'
#define STK_GET_SYNC        0x30  // '0'
#define STK_GET_SIGN_ON     0x31  // '1'
#define STK_SET_PARAMETER   0x40  // '@'
#define STK_GET_PARAMETER   0x41  // 'A'
#define STK_SET_DEVICE      0x42  // 'B'
#define STK_SET_DEVICE_EXT  0x45  // 'E'
#define STK_ENTER_PROGMODE  0x50  // 'P'
#define STK_LEAVE_PROGMODE  0x51  // 'Q'
#define STK_CHIP_ERASE      0x52  // 'R'
#define STK_CHECK_AUTOINC   0x53  // 'S'
#define STK_LOAD_ADDRESS    0x55  // 'U'
#define STK_UNIVERSAL       0x56  // 'V'
#define STK_PROG_FLASH      0x60  // '`'
#define STK_PROG_DATA       0x61  // 'a'
#define STK_PROG_FUSE       0x62  // 'b'
#define STK_PROG_LOCK       0x63  // 'c'
#define STK_PROG_PAGE       0x64  // 'd'
#define STK_PROG_FUSE_EXT   0x65  // 'e'
#define STK_READ_FLASH      0x70  // 'p'
#define STK_READ_DATA       0x71  // 'q'
#define STK_READ_FUSE       0x72  // 'r'
#define STK_READ_LOCK       0x73  // 's'
#define STK_READ_PAGE       0x74  // 't'
#define STK_READ_SIGN       0x75  // 'u'
#define STK_READ_OSCCAL     0x76  // 'v'
#define STK_READ_FUSE_EXT   0x77  // 'w'
#define STK_READ_OSCCAL_EXT 0x78  // 'x'

далее идет обработка

if(ch == STK_GET_PARAMETER) {
......
}
else if(ch == STK_SET_DEVICE) {
......
}

это тот фронт, через который и будет общение.

Будет всего два допила, во первых нужно будет перед передачей от бутлоадера дернуть ногу RE DE на MAX485 трансмитторе. То есть исправить вот эту функцию

void putch(char ch) {
#ifndef SOFT_UART
  #ifndef LIN_UART
    while (!(UART_SRA & _BV(UDRE0))) {  /* Spin */ }
  #else
    while (!(LINSIR & _BV(LTXOK)))   {  /* Spin */ }
  #endif

  UART_UDR = ch;

#else
  __asm__ __volatile__ (
    "   com %[ch]\n" // ones complement, carry set
    "   sec\n"
    "1: brcc 2f\n"
    "   cbi %[uartPort],%[uartBit]\n"
    "   rjmp 3f\n"
    "2: sbi %[uartPort],%[uartBit]\n"
    "   nop\n"
    "3: rcall uartDelay\n"
    "   rcall uartDelay\n"
    "   lsr %[ch]\n"
    "   dec %[bitcnt]\n"
    "   brne 1b\n"
    :
    :
      [bitcnt] "d" (10),
      [ch] "r" (ch),
      [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
      [uartBit] "I" (UART_TX_BIT)
    :
      "r25"
  );
#endif
}

Во вторых, более сложная задача, решить вопрос, чтобы отвечала только одна ПроМини на линии, пока не знаю, как ее решать оптимально, отложил ее решение на второй этап. Сейчас отлажу процесс с одной ПроМини и одним мастером. Asam предложил перегружать П индивидуально, но бось так не получится, так как топология сети - елочная гирлянда, на которую нанизываются ПроМини. Есть лини питания, А,В, служебные, одна из них "DTR", то есть подключена через кондер к ресету. Соответственно, как только на ней появляется 0, все ПроМини перегружаются. 

Сейчас буду делать эксперимент, подключу между ПроМини и програматором Мегу с двумя Serial интерфейсами, хочу перехватывать и выводить в монитор порта, что шлют друг другу программатор и бутлоадер, чтобы удостовериться, что алгоритм, описанный в статье действительно так работает.

 

gonzales
Offline
Зарегистрирован: 13.07.2015

А вот собственно решение первой проблемы. За меня уже все умные люди придумали. В коде еще не копался, но на вскидку - это то, что нужно

void putch(char ch) {
#ifndef SOFT_UART
#ifdef RS485
  uint8_t x;
  do {
    x = UART_SRA;
  } while (!(x & _BV(UDRE0)));
  // clear transmitted flag
  x |= _BV(TXC0);
  UART_SRA = x;
  // put transceiver to output mode
  RS485_PORT |= _BV(RS485);
  // put char
  UART_UDR = ch;
  // wait for char transmitted
  while (!(UART_SRA & _BV(TXC0)));
  // put transceiver to input mode
  RS485_PORT &= ~_BV(RS485);
#else
  while (!(UART_SRA & _BV(UDRE0)));
  UART_UDR = ch;
#endif
#else
#ifdef RS485
  // put transceiver to output mode
  RS485_PORT |= _BV(RS485);
#endif
  __asm__ __volatile__ (
    "   com %[ch]\n" // ones complement, carry set
    "   sec\n"
    "1: brcc 2f\n"
    "   cbi %[uartPort],%[uartBit]\n"
    "   rjmp 3f\n"
    "2: sbi %[uartPort],%[uartBit]\n"
    "   nop\n"
    "3: rcall uartDelay\n"
    "   rcall uartDelay\n"
    "   lsr %[ch]\n"
    "   dec %[bitcnt]\n"
    "   brne 1b\n"
    :
    :
      [bitcnt] "d" (10),
      [ch] "r" (ch),
      [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
      [uartBit] "I" (UART_TX_BIT)
    :
      "r25"
  );
#ifdef RS485
  // put transceiver to input mode
  RS485_PORT &= ~_BV(RS485);
#endif
#endif
}

 

sadman41
Онлайн
Зарегистрирован: 19.10.2016

gonzales пишет:

 Соответственно, как только на ней появляется 0, все ПроМини перегружаются. 

И все перешиваются разом - я правильно понимаю?

gonzales
Offline
Зарегистрирован: 13.07.2015

sadman41 пишет:

gonzales пишет:

 Соответственно, как только на ней появляется 0, все ПроМини перегружаются. 

И все перешиваются разом - я правильно понимаю?

Нет, и это как раз вторая проблема, разом прошивать нельзя, так как прошивка - это результат двустороннего общения мастера и пациента. Посмотрите ссылку, что я привел, там это как раз описано.

gonzales
Offline
Зарегистрирован: 13.07.2015

Ой, а ссылочка то пропала)))

Форум заглючил, пришлось переписывать пост и забыл.

Вот ссылка https://switch-case.ru/52426629

Там расписан протокол общения optiboot с МК

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Ну... шить прямо через сеть - это, конечно, по-ковбойски... А сли глючить будет - дергать всю сеть будете постоянно за reset? Может проще сначала спокойно сгрузить прошивку в I2C EEPROM, а потом дернуть за ногу? Под I2C не находили Optiboot mod?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

gonzales пишет:
костыли о которых мне так упорно рассказывают сразу на двух форумах, но не говорят какие, я не знаю

То, что ты не знаешь - это понятно, но я что-то не заметил, чтобы ты хоть раз спросил. Тебе проще так людей послать, что мол чушь несут. Хотя, и там и здесь тебе это не "последние чайники" говорят. Ну, смотри, тебе жить. Хочешь делать через жопу, - делай. :)))

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

gonzales пишет:

 

вот список команд

/* STK500 constants list, from AVRDUDE */
#define STK_OK              0x10
#define STK_FAILED          0x11  // Not used
#define STK_UNKNOWN         0x12  // Not used
#define STK_NODEVICE        0x13  // Not used
#define STK_INSYNC          0x14  // ' '
#define STK_NOSYNC          0x15  // Not used
#define ADC_CHANNEL_ERROR   0x16  // Not used
#define ADC_MEASURE_OK      0x17  // Not used
#define PWM_CHANNEL_ERROR   0x18  // Not used
#define PWM_ADJUST_OK       0x19  // Not used
#define CRC_EOP             0x20  // 'SPACE'
#define STK_GET_SYNC        0x30  // '0'
#define STK_GET_SIGN_ON     0x31  // '1'
#define STK_SET_PARAMETER   0x40  // '@'
#define STK_GET_PARAMETER   0x41  // 'A'
#define STK_SET_DEVICE      0x42  // 'B'
#define STK_SET_DEVICE_EXT  0x45  // 'E'
#define STK_ENTER_PROGMODE  0x50  // 'P'
#define STK_LEAVE_PROGMODE  0x51  // 'Q'
#define STK_CHIP_ERASE      0x52  // 'R'
#define STK_CHECK_AUTOINC   0x53  // 'S'
#define STK_LOAD_ADDRESS    0x55  // 'U'
#define STK_UNIVERSAL       0x56  // 'V'
#define STK_PROG_FLASH      0x60  // '`'
#define STK_PROG_DATA       0x61  // 'a'
#define STK_PROG_FUSE       0x62  // 'b'
#define STK_PROG_LOCK       0x63  // 'c'
#define STK_PROG_PAGE       0x64  // 'd'
#define STK_PROG_FUSE_EXT   0x65  // 'e'
#define STK_READ_FLASH      0x70  // 'p'
#define STK_READ_DATA       0x71  // 'q'
#define STK_READ_FUSE       0x72  // 'r'
#define STK_READ_LOCK       0x73  // 's'
#define STK_READ_PAGE       0x74  // 't'
#define STK_READ_SIGN       0x75  // 'u'
#define STK_READ_OSCCAL     0x76  // 'v'
#define STK_READ_FUSE_EXT   0x77  // 'w'
#define STK_READ_OSCCAL_EXT 0x78  // 'x'

 

Я в исходники опитбута не смотрел, но, согласно их документации они поддерживают очень маленький набор команд

Cmd Name Value Description
STK_LOAD_ADDRESS 0x55,'U' Note: 16bit word address, 128kb flash max.
STK_PROG_PAGE 0x64,'d' Flash only
STK_READ_PAGE 0x74,'t' Flash only
STK_READ_SIGN 0x75,'u' Reads compiled-in signature.
STK_LEAVE_PROGMODE 0x51,'Q' Starts application code via WDT reset.
STK_GET_PARAMETER 0x41,'A' Supports "minor SW version" and "major SW version" Returns 3 for all other parameters.

Остальные или просто игнорируются или посылается ответ об успешном завершении, но ничего другого не делается.

Главный вопрос здесь - как будете с Half-Duplex разбираться? Или у вас будет 2 пары 485 для Full-Duplex? 

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

gonzales пишет:

Во вторых, более сложная задача, решить вопрос, чтобы отвечала только одна ПроМини на линии, пока не знаю, как ее решать оптимально, отложил ее решение на второй этап.

Ну, это как раз просто.

- Присваиваете каждой ардуине уникальный номер, который хранится или в EEPROM или во Flash.

- Добавляете одну команду в бутлоадер - уходить в беспробудный сон (ну или бесконечный цикл) всем кроме особи с переданным номером. 

Тогда алгоритм прошивки выглядит так

- Дергайте ресет

- Передаете вышеописанную команду. В результате все ардуины кроме одной отваливаются и вы остаетесь с ней один на один.

- Программируете

- Дергаете ресет еще раз, но команд больше не передаете. 

- Через секунду все счастливо бутятся.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А почему не ресетить только одну, которую прошивать надо? Зачем всю сеть ресетить ради одной засранки?

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

ЕвгенийП пишет:

А почему не ресетить только одну, которую прошивать надо? Зачем всю сеть ресетить ради одной засранки?

Ну, ТС так не хочет, я уже предлагал. А еще, если не ресетить, то работающая основная программа может сойти с ума от непонятного трафика на RS-485 если она им пользуется.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

так нехрен чужой трафик подслушивать :)

gonzales
Offline
Зарегистрирован: 13.07.2015

>Я в исходники опитбута не смотрел, но, согласно их документации они поддерживают очень маленький набор команд

Вообще этот список я выдрал как раз из исходников оптибута. В любом случае набор команд достаточный для прошивки)))

>Главный вопрос здесь - как будете с Half-Duplex разбираться? Или у вас будет 2 пары 485 для Full-Duplex?

Так работа как раз в half-duplex идет, запрос - ответ. Тут ничего придумывать не придется, послал - слушай ответ - получил ответ - послал следующую.

>А почему не ресетить только одну, которую прошивать надо? Зачем всю сеть ресетить ради одной засранки?

А как это сделать если линия ресета общая, и линии данных общие, все сразу ребутятся, все сразу читают данные из линии. Если есть идеи, с удовольствием их выслушаю, но переделывать топологию сети нет возможности. Скорее всего делать буду так, как предложил asam, и собственно об этом писал выше, у меня каждая проМини имеет уникальный ID, пакет команды содержит этот ID, поэтому все понимают кому идет пакет, и если не ему, то просто его игнорирует, поэтому проблем с непонятным трафиком не будет.

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Ввести команду "reset" и дергать... ребут по вачдогу, вроде, не пропускает бутлоадер?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

gonzales пишет:

А как это сделать если линия ресета общая, и линии данных общие, все сразу ребутятся, 

Ребутить всю сеть (нарушать работоспособность) из-за одного контроллера - ну, я даже не знаю, как это инженерно назвать.

Делать очень просто, линия ресета вообще не нужна. Даёте команду контроллеру (одному, а не всей толпе) "ресетнись", он спокойно подаёт "LOW" на свою ногу reset и перегружается.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ЕвгенийП пишет:

gonzales пишет:

А как это сделать если линия ресета общая, и линии данных общие, все сразу ребутятся, 

Ребутить всю сеть (нарушать работоспособность) из-за одного контроллера - ну, я даже не знаю, как это инженерно назвать.

Делать очень просто, линия ресета вообще не нужна. Даёте команду контроллеру (одному, а не всей толпе) "ресетнись", он спокойно подаёт "LOW" на свою ногу reset и перегружается.

Ну да, только остальные при этом должны понимать, что следующий за этим делом пакет данных предназначен не для них, и, при том, имеет "нестандартный" для них протокол. А они - те, которые не перезагружаются, должны уметь определять конец пакета, чтобы в дальнейшем возобновить реакцию на "стандарнтные" пакеты.

Может, для индикации прохождения "нестандартно" пакета использовать линию, что освободилась от reset'а?

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

ЕвгенийП пишет:

Ребутить всю сеть (нарушать работоспособность) из-за одного контроллера - ну, я даже не знаю, как это инженерно назвать.

Делать очень просто, линия ресета вообще не нужна. Даёте команду контроллеру (одному, а не всей толпе) "ресетнись", он спокойно подаёт "LOW" на свою ногу reset и перегружается.

[/quote]

Ну если апдейт проводится не часто, а простой сети в течении минуты допустим, то почему нет?

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

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

ЕвгенийП пишет:

Делать очень просто, линия ресета вообще не нужна. Даёте команду контроллеру (одному, а не всей толпе) "ресетнись", он спокойно подаёт "LOW" на свою ногу reset и перегружается.

Тогда придется обучать штатное приложение основам STK. Вариант реализуемый, но на вопрос, что лучше, может ответить только ТС. 

gonzales
Offline
Зарегистрирован: 13.07.2015

>Делать очень просто, линия ресета вообще не нужна. Даёте команду контроллеру (одному, а не всей толпе) "ресетнись", он спокойно подаёт "LOW" на свою ногу reset и перегружается.

Класс!! Спасибо, изящное решение! И в бутлоадере не придется ничего прописывать, только плату немного переделать. Вопрос попутно, а при старте МК не будет на этой ноге, которая к reset подключена все время LOW, что будет вызывать boot-loop и до setup дело не дойдет?

>Вопрос, что нам выгоднее - допустить редкослучамый кратковременный простой сети или потратить N человеко-месяцев, для разработки софта позволяющего этого избежать.

простой сети допустим (в моем случае), а переписывать практически ничего не придется, так как протокол общения плат уже написан, нужно только внедрить обработку еще одной команды - это не проблема.

>Тогда придется обучать штатное приложение основам STK

Не понял эту фразу, что Вы имеете в виду?

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

gonzales пишет:
а при старте МК не будет на этой ноге, которая к reset подключена все время LOW, что будет вызывать boot-loop и до setup дело не дойдет?

Не, ну, это как сделать. По уму, нога "ресет" должна быть притянута к питанию резистором килоом в 10 и соединена с какой-нибудь цифровой ногой МК (управляющей ногой). Управляющую ногу надо постоянно держать в состоянии INPUT (она уже в нём при включении питания, вот и не трогать). А когда нужно ребутнуться, перевести в OUTPUT и подать LOW. При таком подходе, при включении питания никаких фокусов не будет.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

gonzales пишет:

>Тогда придется обучать штатное приложение основам STK

Не понял эту фразу, что Вы имеете в виду?

Я не знаю деталей того что ваши ардуины делают в штатном режиме. Если они не работают при этом с RS-485, то проблем нет. А вот если работают...

Представте, что одна ардуино каким-то образом переключилась в режим прошивания и вы шлете в нее новую прошивку. При этом все остальные будут видеть поток данных на их UART и может случиться, что в прошивке найдется комбинация выглядящая как команда для них. Реакция будет мало предсказуемая. Что бы этого избежать придется в них встраивать распазнование комманд программатора, что бы они на них не реагировали.

sadman41
Онлайн
Зарегистрирован: 19.10.2016

То есть решение с вачдогом, при котором переделывать плату вообще не требуется - не подходит. Ну, ОКчё.

gonzales
Offline
Зарегистрирован: 13.07.2015

> То есть решение с вачдогом, при котором переделывать плату вообще не требуется - не подходит.

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

> По уму, нога "ресет" должна быть притянута к питанию резистором килоом в 10 и соединена с какой-нибудь цифровой ногой МК

То, что должна быть притянута - это само собой. 

> Управляющую ногу надо постоянно держать в состоянии INPUT (она уже в нём при включении питания, вот и не трогать). А когда нужно ребутнуться, перевести в OUTPUT и подать LOW. При таком подходе, при включении питания никаких фокусов не будет.

Да, все логично. Нужно ли ставить кондер между управляющей ногой и резетом как в случае с ногой DTR у ПроМини?

>Представте, что одна ардуино каким-то образом переключилась в режим прошивания и вы шлете в нее новую прошивку. При этом все остальные будут видеть поток данных на их UART и может случиться, что в прошивке найдется комбинация выглядящая как команда для них. Реакция будет мало предсказуемая. Что бы этого избежать придется в них встраивать распазнование комманд программатора, что бы они на них не реагировали.

Пакет команды расчитан на это, в пакете есть СтартБайт, Стопбайт, ID получателя, Подпись пакета, и определенная длина пакета. В теории конечно может случиться, что все условия совпадут и выполнится какая-то команда, но это маловероятно, да и ничего криминального не должно произойти.

 

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Разве в ситуации с дёрганьем себя за ногу синхронизация не нужна? Как удаленный прошивальщик узнает, что принимающий МК уже ждет посылку? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, Вы то чего ... :) Вы ж отлично понимаете, что есть 100500 способов сделать какую-никакую (а более точная и не нужна) синхронизацию.

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Да я так, интересуюсь модными тенденциями - может интересного чего узнаю.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Тогда поинтересуйтесь языком Idris :)

gonzales
Offline
Зарегистрирован: 13.07.2015

> Разве в ситуации с дёрганьем себя за ногу синхронизация не нужна? Как удаленный прошивальщик узнает, что принимающий МК уже ждет посылку? 

Стандартный протокол отпибут посылает 3 посылки с некоторым интервалом времени STK_GET_SYNC + CRC_EOP и ждет ответ STK_INSYNC + STK_OK. Если ответ пришел - все ок, можно начинать прошивку. То есть дернул себя за ногу, шлешь посылки и ждешь ответа, если ответа нет - ребут по вачдогу.

gonzales
Offline
Зарегистрирован: 13.07.2015

Всех с прошедшими!!!

На досуге поковырялся немного по теме, удалось подключить Мегу между программатором и ПроМини, посмотрел, кто что куда передает. Если кому интересно, вот результаты:

Вот содержимое blink.hex

:10000000 0C945C000C946E000C946E000C946E00 CA
:10001000 0C946E000C946E000C946E000C946E00 A8
:10002000 0C946E000C946E000C946E000C946E00 98
:10003000 0C946E000C946E000C946E000C946E00 88
:10004000 0C9419010C946E000C946E000C946E00 CC
:10005000 0C946E000C946E000C946E000C946E00 68
:10006000 0C946E000C946E000000000800020100 69
:10007000 00030407000000000000000000000000 72

:10008000 250028002B0000000000240027002A00 83
:10009000 04040404040404040202020202020303 2E
:1000A000 03030303010204081020408001020408 36
:1000B000 102001020408102011241FBECFEFD8E0 49
:1000C000 DEBFCDBF21E0A0E0B1E001C01D92A930 AC
:1000D000 B207E1F70E9463010C94D4010C940000 74
:1000E000 90E0FC01E859FF4F3491FC01EC55FF4F C3
:1000F000 2491FC01E057FF4FE491EE2309F43BC0 4B

:10010000 332339F1333091F038F43130A9F03230 03
:10011000 01F584B58F7D12C0373091F03830A1F0 F1
:10012000 3430B9F4809180008F7D03C080918000 CD
:10013000 8F77809380000DC084B58F7784BD09C0 10
:10014000 8091B0008F7703C08091B0008F7D8093 45
:10015000 B000F0E0EE0FFF1FE458FF4FA591B491 FF
:10016000 8FB7F894EC91611103C020952E2301C0 44
:10017000 2E2B2C938FBF08953FB7F89480910501 E3

:10018000 90910601A0910701B091080126B5A89B A6
:10019000 05C02F3F19F00196A11DB11D3FBFBA2F 19
:1001A000 A92F982F8827820F911DA11DB11DBC01 79
:1001B000 CD0142E0660F771F881F991F4A95D1F7 3E
:1001C000 08958F929F92AF92BF92CF92DF92EF92 5B
:1001D000 FF920E94BC004B015C0184EFC82EDD24 1D
:1001E000 D394E12CF12C0E94BC00DC01CB018819 D6
:1001F000 9909AA09BB09883E9340A105B10558F0 A9

:10020000 21E0C21AD108E108F10888EE880E83E0 E7
:10021000 981EA11CB11CC114D104E104F10419F7 0A
:10022000 FF90EF90DF90CF90BF90AF909F908F90 16
:10023000 08951F920F920FB60F9211242F933F93 A0
:10024000 8F939F93AF93BF938091010190910201 8F
:10025000 A0910301B09104013091000123E0230F 2C
:10026000 2D3720F40196A11DB11D05C026E8230F EE
:10027000 0296A11DB11D20930001809301019093 6E

:10028000 0201A0930301B0930401809105019091 B4
:10029000 0601A0910701B09108010196A11DB11D B1
:1002A000 8093050190930601A0930701B0930801 84
:1002B000 BF91AF919F918F913F912F910F900FBE 62
:1002C000 0F901F901895789484B5826084BD84B5 92
:1002D000 816084BD85B5826085BD85B5816085BD 41
:1002E000 80916E00816080936E00109281008091 F9
:1002F000 81008260809381008091810081608093 81

:10030000 8100809180008160809380008091B100 A5
:10031000 84608093B1008091B00081608093B000 D0
:10032000 80917A00846080937A0080917A008260 64
:10033000 80937A0080917A00816080937A008091 26
:10034000 7A00806880937A001092C100E1EBF0E0 BF
:10035000 2491EDE9F0E08491882399F090E0880F F2
:10036000 991FFC01EA57FF4FA591B491FC01E458 95
:10037000 FF4F859194918FB7F894EC91E22BEC93 19

:10038000 8FBFC0E0D0E061E08DE00E9470000E94 6D
:10039000 E10060E08DE00E9470000E94E1002097 83
:0C03A000 91F30E940000EFCFF894FFCF         13
:00000001 FF

Если кто не знает, вот выдержка структуры hex файла

Если у нас есть строка 

: NN AAAA CC DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD SS

: - маркер начала строки

NN - определяет количество байтов данных в строке

AAAA - начальный адрес, с которого данные будут записаны в память микроконтроллера

CC - поле команды CC. Программатор, ориентируясь на поле CC, распознает функциональное назначения строки. Ассемблер и другие компиляторы языков высокого уровня для AVR могут установить следующие значения данного параметра:

00 – в строке находятся данные для записи в память,

01 – последняя строка в файле,

02 – строка содержит начальный адрес сегмента памяти,

04 – строка содержит адрес в пределах сегмента памяти.

DDDDD... - собственно данные

SS - контрольная сумма. Сумма всех байтов в неповрежденной строке без учета переполнения всегда нулевая, то есть DD + DD +... + DD + SS = 0

 

Вот лог arduino ide при загрузке скетча

avrdude: Version 6.3, compiled on Jan 17 2017 at 12:00:53
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM3
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 8.0
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "C:\Users\User\AppData\Local\Temp\arduino_build_735206/Blink.ino.hex"
avrdude: writing flash (940 bytes):

Writing | ################################################## | 100% 0.18s

avrdude: 940 bytes of flash written
avrdude: verifying flash memory against C:\Users\User\AppData\Local\Temp\arduino_build_735206/Blink.ino.hex:
avrdude: load data flash data from input file C:\Users\User\AppData\Local\Temp\arduino_build_735206/Blink.ino.hex:
avrdude: input file C:\Users\User\AppData\Local\Temp\arduino_build_735206/Blink.ino.hex contains 940 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.12s

avrdude: verifying ...
avrdude: 940 bytes of flash verified

avrdude done.  Thank you.

А вот собственно лог, снятый с Меги при работе программатора

START

DTR Signal 

>30>20 //STK_GET_SYNC CRC_EOP
<14<10 //STK_INSYNC STK_OK

>30>20
<14<10

>30>20
<14<10

>41>80>20 //STK_GET_PARAMETER STK_HW_VER
<14<03<10

>41>81>20 //STK_GET_PARAMETER STK_SW_MAJOR 
<14<08<10

>41>82>20 //STK_GET_PARAMETER STK_SW_MINOR 
<14<00<10

>41>98>20 //STK_GET_PARAMETER STK500_TOPCARD_DETECT
<14<03<10

>41>84>20 //STK_GET_PARAMETER STK_VTARGET
<14<03<10

>41>85>20 //STK_GET_PARAMETER STK_VADJUST 
<14<03<10

>41>86>20 //STK_GET_PARAMETER STK_OSC_PSCALE 
<14<03<10

>41>87>20 //STK_GET_PARAMETER STK_OSC_CMATCH
<14<03<10

>41>89>20 //STK_GET_PARAMETER STK_SCK_DURATION
<14<03<10

>41>81>20 //STK_GET_PARAMETER STK_SW_MAJOR 
<14<08<10

>41>82>20 //STK_GET_PARAMETER STK_SW_MINOR 
<14<00<10

>42>86>00>00>01>01>01>01>03>FF>FF>FF>FF>00>80>04>00>00>00>80>00>20 //STK_SET_DEVICE 
<14<10

>45>05>04>D7>C2>00>20 //STK_SET_DEVICE_EXT
<14<10

>50>20 //STK_ENTER_PROGMODE
<14<10

>75>20 //STK_READ_SIGN
<14<1E<95<F<10

>55>00>00>20 //STK_LOAD_ADDRESS
<14<10

>64>00>80>46 //STK_PROG_PAGE
>0C945C000C946E000C946E000C946E00
 0C946E000C946E000C946E000C946E00
 0C946E000C946E000C946E000C946E00
 0C946E000C946E000C946E000C946E00
 0C9419010C946E000C946E000C946E00
 0C946E000C946E000C946E000C946E00
 0C946E000C946E000000000800020100
 00030407000000000000000000000000
>20
<14<10

>55>40>00>20 //STK_LOAD_ADDRESS
<14<10

>64>00>80>46 //STK_PROG_PAGE
>250028002B0000000000240027002A00
 04040404040404040202020202020303
 03030303010204081020408001020408
 102001020408102011241FBECFEFD8E0
 DEBFCDBF21E0A0E0B1E001C01D92A930
 B207E1F70E9463010C94D4010C940000
 90E0FC01E859FF4F3491FC01EC55FF4F
 2491FC01E057FF4FE491EE2309F43BC0
>20
<14<10

>55>80>00>20 //STK_LOAD_ADDRESS
<14<10

>64>00>80>46 //STK_PROG_PAGE
>332339F1333091F038F43130A9F03230
 01F584B58F7D12C0373091F03830A1F0
 3430B9F4809180008F7D03C080918000
 8F77809380000DC084B58F7784BD09C0
 8091B0008F7703C08091B0008F7D8093
 B000F0E0EE0FFF1FE458FF4FA591B491
 8FB7F894EC91611103C020952E2301C0
 2E2B2C938FBF08953FB7F89480910501
>20
<14<10

>55>C0>00>20  //STK_LOAD_ADDRESS
<14<10

>64>00>80>46 //STK_PROG_PAGE
>90910601A0910701B091080126B5A89B
 05C02F3F19F00196A11DB11D3FBFBA2F
 A92F982F8827820F911DA11DB11DBC01
 CD0142E0660F771F881F991F4A95D1F7
 08958F929F92AF92BF92CF92DF92EF92
 FF920E94BC004B015C0184EFC82EDD24
 D394E12CF12C0E94BC00DC01CB018819
 9909AA09BB09883E9340A105B10558F0
>20
<14<10

>55>00>01>20 //STK_LOAD_ADDRESS
<14<10

>64>00>80>46 //STK_PROG_PAGE
>21E0C21AD108E108F10888EE880E83E0
 981EA11CB11CC114D104E104F10419F7
 FF90EF90DF90CF90BF90AF909F908F90
 08951F920F920FB60F9211242F933F93
 8F939F93AF93BF938091010190910201
 A0910301B09104013091000123E0230F
 2D3720F40196A11DB11D05C026E8230F
 0296A11DB11D20930001809301019093
>20
<14<10

>55>40>01>20  //STK_LOAD_ADDRESS
<14<10

>64>00>80>46  //STK_PROG_PAGE
>0201A0930301B0930401809105019091
 0601A0910701B09108010196A11DB11D
 8093050190930601A0930701B0930801
 BF91AF919F918F913F912F910F900FBE
 0F901F901895789484B5826084BD84B5
 816084BD85B5826085BD85B5816085BD
 80916E00816080936E00109281008091
 81008260809381008091810081608093
>20
<14<10

>55>80>01>20  //STK_LOAD_ADDRESS
<14<10

>64>00>80>46  //STK_PROG_PAGE
>8100809180008160809380008091B100
 84608093B1008091B00081608093B000
 80917A00846080937A0080917A008260
 80937A0080917A00816080937A008091
 7A00806880937A001092C100E1EBF0E0
 2491EDE9F0E08491882399F090E0880F
 991FFC01EA57FF4FA591B491FC01E458
 FF4F859194918FB7F894EC91E22BEC93
>20
<14<10

>55>C0>01>20 //STK_LOAD_ADDRESS
<14<10

>64>00>80>46  //STK_PROG_PAGE
>8FBFC0E0D0E061E08DE00E9470000E94
 E10060E08DE00E9470000E94E1002097
 91F30E940000EFCFF894FFCFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
>20
<14<10

>55>00>00>20 //STK_LOAD_ADDRESS
<14<10

>74>00>80>46>20 //STK_READ_PAGE
<14
<0C945C000C946E000C946E000C946E00
 0C946E000C946E000C946E000C946E00
 0C946E000C946E000C946E000C946E00
 0C946E000C946E000C946E000C946E00
 0C9419010C946E000C946E000C946E00
 0C946E000C946E000C946E000C946E00
 0C946E000C946E000000000800020100
 00030407000000000000000000000000
<10

>55>40>00>20 //STK_LOAD_ADDRESS
<14<10

>74>00>80>46>20 //STK_READ_PAGE
<14
<250028002B0000000000240027002A00
 04040404040404040202020202020303
 03030303010204081020408001020408
 102001020408102011241FBECFEFD8E0
 DEBFCDBF21E0A0E0B1E001C01D92A930
 B207E1F70E9463010C94D4010C940000
 90E0FC01E859FF4F3491FC01EC55FF4F
 2491FC01E057FF4FE491EE2309F43BC0
<10

>55>80>00>20 //STK_LOAD_ADDRESS
<14<10

>74>00>80>46>20 //STK_READ_PAGE
<14
<332339F1333091F038F43130A9F03230
 01F584B58F7D12C0373091F03830A1F0
 3430B9F4809180008F7D03C080918000
 8F77809380000DC084B58F7784BD09C0
 8091B0008F7703C08091B0008F7D8093
 B000F0E0EE0FFF1FE458FF4FA591B491
 8FB7F894EC91611103C020952E2301C0
 2E2B2C938FBF08953FB7F89480910501
<10

>55>C0>00>20 //STK_LOAD_ADDRESS
<14<10

>74>00>80>46>20 //STK_READ_PAGE
<14
<90910601A0910701B091080126B5A89B
 05C02F3F19F00196A11DB11D3FBFBA2F
 A92F982F8827820F911DA11DB11DBC01
 CD0142E0660F771F881F991F4A95D1F7
 08958F929F92AF92BF92CF92DF92EF92
 FF920E94BC004B015C0184EFC82EDD24
 D394E12CF12C0E94BC00DC01CB018819
 9909AA09BB09883E9340A105B10558F0
<10

>55>00>01>20 //STK_LOAD_ADDRESS
<14<10

>74>00>80>46>20 //STK_READ_PAGE
<14
<21E0C21AD108E108F10888EE880E83E0
 981EA11CB11CC114D104E104F10419F7
 FF90EF90DF90CF90BF90AF909F908F90
 08951F920F920FB60F9211242F933F93
 8F939F93AF93BF938091010190910201
 A0910301B09104013091000123E0230F
 2D3720F40196A11DB11D05C026E8230F
 0296A11DB11D20930001809301019093
<10

>55>40>01>20 //STK_LOAD_ADDRESS
<14<10

>74>00>80>46>20 //STK_READ_PAGE
<14
<0201A0930301B0930401809105019091
 0601A0910701B09108010196A11DB11D
 8093050190930601A0930701B0930801
 BF91AF919F918F913F912F910F900FBE
 0F901F901895789484B5826084BD84B5
 816084BD85B5826085BD85B5816085BD
 80916E00816080936E00109281008091
 81008260809381008091810081608093
<10

>55>80>01>20 //STK_LOAD_ADDRESS
<14<10

>74>00>80>46>20 //STK_READ_PAGE
<14
<8100809180008160809380008091B100
 84608093B1008091B00081608093B000
 80917A00846080937A0080917A008260
 80937A0080917A00816080937A008091
 7A00806880937A001092C100E1EBF0E0
 2491EDE9F0E08491882399F090E0880F
 991FFC01EA57FF4FA591B491FC01E458
 FF4F859194918FB7F894EC91E22BEC93
<10

>55>C0>01>20 //STK_LOAD_ADDRESS
<14<10

>74>00>80>46>20 //STK_READ_PAGE
<14
<8FBFC0E0D0E061E08DE00E9470000E94
 E10060E08DE00E9470000E94E1002097
 91F30E940000EFCFF894FFCFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
<10

>51>20 STK_LEAVE_PROGMODE
<14<10

Соответственно знак > - это направление от программатора в МК, < - от МК к программатору

Из лога понятно, что программатор начинает общение командой, далее идут парамерты (если необходимо), заканчивается передача коммандой 20 (CRC_EOP). Соответственно МК отвечает обязательно вначале посылки командой 14 (STK_INSYNC) и заканчивает коммандо 10 (STK_OK).

Структура общения описана на страничке в приведенной мною ссылке выше и полностью ей соответствует, так что повторяться не буду. 

 

Теперь то, что вызвало у меня вопрос, ответ на который пока не ясен.

Размер страницы составляет 128 байт (Page Size), а адресация коммандой STK_LOAD_ADDRESS идет со смещением на 64 байта, то есть в половину, то есть

>55>00>00>20 //STK_LOAD_ADDRESS - установили адрес 00 00 (первый параметр addr_low второй addr_high)

>64>00>80>46 //STK_PROG_PAGE - записываем (64) 128 байт (00 80) типа Flash (46 = 'F')

далее данные 

>20 (CRC_EOP)

>55>40>00>20 //STK_LOAD_ADDRESS - установили адрес 40 00, вот тут не понятно, почему????

В протоколе STK500 (https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591659) ничего по этому поводу не нашел. Дальнейшие смещения адреса тоже происходят на 64 байта, а не на 128, что было бы логично.

Может кто подскажет, почему?

Дальше планирую написать скетч для прошивки по UART с SD-карты teensy 3.5. 

Результаты выложу в этой теме. 

 

 

 

b707
Offline
Зарегистрирован: 26.05.2017

gonzales пишет:

Теперь то, что вызвало у меня вопрос, ответ на который пока не ясен.

Размер страницы составляет 128 байт (Page Size), а адресация коммандой STK_LOAD_ADDRESS идет со смещением на 64 байта, то есть в половину,

невнимательно читаете документацию. Параметр STK_LOAD_ADDRESS указывается не в байтах, а в 16-битных словах:

STK_LOAD_ADDRESS 0x55,'U' Note: 16bit word address, 128kb flash max.

кстати, об этом сказано и в описании структуры общения оптибута и дудки, на которую вы сами ссылаетесь, вот цитата:

Load address (initially 0x0000). The address is in words (ie. a word is two bytes). This sets the address for where the next page of data will be written.