Обсуждаем контроллеры компании Atmel.
Ответить

Ретранслятор UART в boot область

Сб ноя 13, 2021 16:39:41

Здравствуйте. Есть устройство из двух МК которые общаются между собой по UART (на первый МК Atmega324pa есть исходники но не мой, на второй Atmega328p пишу сам). Нужно предусмотреть возможность подключения к первому com порта вместо МК. Возникла идея сделать со второго МК программный ретранслятор. Почему программный т.к. аппаратный UART порт один, на Atmega324pa оба порта заняты. Смотрел на SoftwareSerial но с ним ругается на мой код с прерываниями. Написать простой свой - нужно долго вникать. Собственно вопрос: можно ли запихнуть этот ретранслятор в boot область. Т.е. при старте нажата кнопка - ретранслятор, не нажата - работает в обычном режиме и какие есть нюансы с прерываниями. В поиске гуглится только bootloader. Нашел исходники http://easyelectronics.ru/avr-uchebnyj- ... adera.html но не пойму что можно удалить и где добавить свое чтобы влезть в 4к.

Re: Ретранслятор UART в boot область

Сб ноя 13, 2021 18:33:58

Вроде как, в Atmega324pa и так 2 шт. USART на борту.
Ничего не понятно.

Re: Ретранслятор UART в boot область

Сб ноя 13, 2021 18:44:46

Карбофос писал(а):Вроде как, в Atmega324pa и так 2 шт. USART на борту.

Alexeytm писал(а):на Atmega324pa оба порта заняты

Alexeytm писал(а):на втором Atmega328p пишу сам

Карбофос писал(а):Ничего не понятно.

Я описал в общих чертах.
Нужно запихнуть ретранслятор USART в boot область. Т.е. при старте нажата кнопка - ретранслятор.
Что не понятно?

Re: Ретранслятор UART в boot область

Сб ноя 13, 2021 19:12:23

https://www.fischl.de/avrusbboot/

makefile
BOOTLOADER_ADDRESS = 1800

LDFLAGS += -Wl,--section-start=.text=$(BOOTLOADER_ADDRESS)

main.c
Код:
#define BOOTLOADER_INIT \
    PORTB = 0xff;       \
    DDRB  = 0;          \
    PORTC = 0xff;       \
    DDRC  = 0;          \
    PORTD = 0xfa;       \
    DDRD  = 0x02;

#define BOOTLOADER_CONDITION ((PINC & (1 << PC2)) == 0)

void (*jump_to_app)(void) = 0x0000;

void leaveBootloader() {
      cli();
      boot_rww_enable();
      GICR = (1 << IVCE);  /* enable change of interrupt vectors */
      GICR = (0 << IVSEL); /* move interrupts to application flash section */
      jump_to_app();
}

int main(void)
{
    /* initialize hardware */
    BOOTLOADER_INIT;

    /* jump to application if jumper is set */
    if (!BOOTLOADER_CONDITION) {
      leaveBootloader();
    }

    // сюда пихать

    return 0;
}


Конечно, встает вопрос, как с основной программой скомпоновать.
Здесь https://radiokot.ru/forum/viewtopic.php ... 3#p4097463 писал по мотивам интернетов.

И, мне совершенно не понятно, почему вся эта шняга должна находиться в области бутлодера???

Re: Ретранслятор UART в boot область

Сб ноя 13, 2021 20:14:33

Это вреде бы как перейти на boot из программы.
Конечно, встает вопрос, как с основной программой скомпоновать.

Я встречал как их склеить.
СпойлерЯ думаю, что самый простой способ объединить шестнадцатеричные файлы с помощью командной строки srec_cat. Этот инструмент входит в набор инструментов srecord. Он поставляется с WinAVR и очень легко устанавливается на Unix-подобных ОС. Вот команда, которую вы должны при этом использовать:

srec_cat app.hex -I boot.hex -I -o combined.hex -I
Также вы можете вручную объединить файлы app.hex и boot.hex файлов с небольшими правками: Каждый шестнадцатеричный файл имеет одну последнюю запись, в которой говорится, что «файл заканчивается». Таким образом, после ручного объединения нужно отредактировать объединенный шестнадцатеричный файл — найти в нем запись окончания файла, расположенную в конце app.hex (после объединения где-то в середине файла) и удалить ее. Запись имеет тип 01. Байт типа записи в шестнадцатеричном формате Intel по порядку является 4-м байтом, поэтому запись на самом деле будет выглядеть примерно так: «:00000001FF». Вся линия (та что в середине, а не в конце файла) должна быть удалена.

Для меня это пока не проблема - запишу программатором.
Alexeytm писал(а):И, мне совершенно не понятно, почему вся эта шняга должна находиться в области бутлодера???

чтобы не пересекались прерывания при работе с USART. Ругается при попытке добавить либу SoftwareSerial. Хочу сделать типа как две отдельные проги. Может кто поможет как добавить в ISR(USART_RX_vect) чтобы после приема байта он автоматом дублировался на другой ноге, и так же при передаче, я откажусь от boot.

Re: Ретранслятор UART в boot область

Сб ноя 13, 2021 20:38:07

При загрузке определили, что кнопка нажата - идем в отдельный цикл.
В цикле, изменился пин приема1 - изменить пин передачи 2.
В цикле, изменился пин приема2 - изменить пин передачи 1.

Только, это на асме надо писать, не силен.
Надеюсь, вам помогут.
Что-то вроде
Код:
Cycle:
BST PIND,0  ;Rx0
BLD PORTB,1 ;Tx1
BST PINB,0  ;Rx1
BLD PORTD,1 ;Tx0
rjmp Cycle

Re: Ретранслятор UART в boot область

Вс ноя 14, 2021 10:15:55

Это вреде бы как перейти на boot из программы....Ругается при попытке добавить либу SoftwareSerial....

Это случаем не игрушки с адуринкой имеют место?
(вместо чистого Си в соответствующей IDE)
:tea:

Re: Ретранслятор UART в boot область

Вс ноя 14, 2021 19:45:47

Написал такой повторитель
Спойлер#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIMER1_COMPA_vect)
{
if (PIND & (1 << PIND4))PORTD &= ~(1 << 4);//светодиод
else PORTD |= 1 << 4;
}
static void (*jump_to_app)(void) = 0x0000;
int main (void) {
DDRD |= 1 << 3;
PORTD |= 1<<3;
cli();
TCCR1A = 0;
TCCR1B = 0;
OCR1A = 9999;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
TIMSK1 |= (1 << OCIE1A);
sei();

if (!(PIND & (1 << PIND3))){//нажата кнопка
DDRD |= 1 << 4;//светодиод
PORTD |= 1 << 4; //установить "1" на линии 4 порта D

//Tx Uart
DDRD |= 1 << 1;//сконфигурировать линию 1 порта D как выход
PORTD |= 1 << 1;//установить "1" на линии 1 порта D
//Tx
DDRB |= 1 << 3;//сконфигурировать линию 3 порта В как выход
PORTB |= 1 << 3;//установить "1" на линии 3 порта B
//Rx Uart
DDRD |= 1 << 0;//сконфигурировать линию 0 порта D как выход
PORTD |= 1 << 0;//установить 1 на линии 0 потра D
//Rx
DDRB |= 1 << 4;//сконфигурировать линию 4 порта В как выход
PORTB |= 1 << 4;//установить 1 на линии 4 потра В

while(1){
if (!(PIND & (1 << PIND0)))//проверить "0" на линии 0 порта D
PORTB &= ~(1 << 3);//установить 0 на линии 3 потра В
else PORTB |= 1 << 3;//установить 1 на линии 3 потра В
//Tx
if (!(PINB & (1 << PINB4)))//проверить "0" на линии 4 порта B
PORTD &= ~(1 << 1);//установить 0 на линии 1 потра D
else PORTD |= 1 << 1;//установить 1 на линии 1 потра D
}
}
else jump_to_app();

}

"кнопку" повторяет, а сигнал - нет.
Заипался пробовать в железе, собрал в протэусе.
Если верить ослику протэуса то сигнал не дотягивает до 0 и по этому программа не может определить что пришел лог 0.
Или делать на аналоговых пинах или както дотягивать до 0 самому. И то и то не айс. :facepalm:

Re: Ретранслятор UART в boot область

Вс ноя 14, 2021 20:50:24

Код:
//Rx Uart
DDRD |= 1 << 0;//сконфигурировать линию 0 порта D как выход
PORTD |= 1 << 0;//установить 1 на линии 0 потра D
//Rx
DDRB |= 1 << 4;//сконфигурировать линию 4 порта В как выход
PORTB |= 1 << 4;//установить 1 на линии 4 потра В

У вас там битва титанов? Кто кого пересилит?

Reset vector is affected by the BOOTRST fuse, and the interrupt vector start address is affected by the IVSEL bit in MCUCR.

Re: Ретранслятор UART в boot область

Вс ноя 14, 2021 21:17:09

Что не так? Как нужно?

Re: Ретранслятор UART в boot область

Вс ноя 14, 2021 21:26:48

Не нужно линии Rx настраивать на выход.
Это входные линии.
Этот код надо исключить.

Мне самому интересно, заработает-ли в таком виде ретранслятор.
Если да - можно и c векторами дальше разбираться будет. И, для ретранслятора, этот тик-так лучше отключить.

Хотя, и обработчик можно свести к:
Код:
PIND |= _BV(PIND4);

Запись 1 в PINx инвертирует PORTx.

Re: Ретранслятор UART в boot область

Вс ноя 14, 2021 22:06:56

Карбофос писал(а):Не нужно линии Rx настраивать на выход.
Это входные линии.
Этот код надо исключить.

Большое спасибо!!! :beer:
Заработало в протэусе и в железе.
Тиктак нужен чтобы знать работает контроллер или нет, пока для отладки.
Попробую запихнуть в boot.

Re: Ретранслятор UART в boot область

Вс ноя 14, 2021 22:12:59

Код:
ISR(TIMER1_COMPA_vect, ISR_NAKED)
{
  PIND |= _BV(PIND4);
  reti();
}

Re: Ретранслятор UART в boot область

Вс ноя 14, 2021 22:37:22

Добавил к прошивке по адресу 0x7E00 это кусок и с него не стартует.
поставил ардуиновские
low_fuses=0xFF
high_fuses=0xDE
extended_fuses=0xFD
Убираю бит чтобы стартовал с 0х0000 грузит основной код. Что не так с этим boot?
И протэус висит и не ругается. :facepalm:

Re: Ретранслятор UART в boot область

Пн ноя 15, 2021 01:04:40

Необходим повторитель UART с одним входом (Rx) и двумя выходами (Tx_1; Tx_2)?

Re: Ретранслятор UART в boot область

Пн ноя 15, 2021 16:53:57

Получилось: в буте моргает светодиод и работает основная программа.
Спойлер
Код:
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TIMER1_COMPA_vect, ISR_NAKED)//
{
  PIND |= _BV(PIND4);
  reti();
}
static void (*jump_to_app)(void) = 0x0000;
int main (void) {
DDRD |= 1 << 3;
PORTD |= 1<<3;
asm("NOP");
if (!(PIND & (1 << PIND3))){//нажата кнопка
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL);
cli();
TCCR1A = 0;
TCCR1B = 0;
OCR1A = 9999;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
TIMSK1 |= (1 << OCIE1A);
sei();

DDRD |= 1 << 4;//светодиод
PORTD |= 1 << 4; //установить "1" на линии 4 порта D

//Tx Uart
DDRD |= 1 << 1;//сконфигурировать линию 1 порта D как выход
//Tx
DDRB |= 1 << 3;//сконфигурировать линию 3 порта В как выход

while(1){
if (!(PIND & (1 << PIND0)))//проверить "0" на линии 0 порта D
PORTB &= ~(1 << 3);//установить 0 на линии 3 порта В
else PORTB |= 1 << 3;//установить 1 на линии 3 порта В
//Tx
if (!(PINB & (1 << PINB4)))//проверить "0" на линии 4 порта B
PORTD &= ~(1 << 1);//установить 0 на линии 1 порта D
else PORTD |= 1 << 1;//установить 1 на линии 1 порта D
}
}
else jump_to_app();

}

Нужно было перенаправить прерывания в boot
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL);
Если перенаправить до работы в boot - не работала основная прога. Поставил после срабатывания кнопки.
Через Arduino IDE через USBasp пишу основную программу, а потом без стирания дописываю через ProgISP boot.hex. Пробовал склеить две прошивки в HEX редакторе и залить - тоже работает.
Исходники для AVR Studio 4.19. Makefile брать из архива и править под себя и может дописывать свой контроллер, тогда будет прошивка с адресами для boot.
Делал по AVR. Учебный Курс. Использование Bootloader’а
boot.zip
Исходники
(19.56 KiB) Скачиваний: 251

В протэусе с boot не стартует. Что то там адреса не совпадают при выборе fuse boot.
Помогла статья
AVR BootLoader в вопросах и ответах. Часть 1
Ответить