Ретранслятор UART в boot область
Здравствуйте. Есть устройство из двух МК которые общаются между собой по UART (на первый МК Atmega324pa есть исходники но не мой, на второй Atmega328p пишу сам). Нужно предусмотреть возможность подключения к первому com порта вместо МК. Возникла идея сделать со второго МК программный ретранслятор. Почему программный т.к. аппаратный UART порт один, на Atmega324pa оба порта заняты. Смотрел на SoftwareSerial но с ним ругается на мой код с прерываниями. Написать простой свой - нужно долго вникать. Собственно вопрос: можно ли запихнуть этот ретранслятор в boot область. Т.е. при старте нажата кнопка - ретранслятор, не нажата - работает в обычном режиме и какие есть нюансы с прерываниями. В поиске гуглится только bootloader. Нашел исходники http://easyelectronics.ru/avr-uchebnyj- ... adera.html но не пойму что можно удалить и где добавить свое чтобы влезть в 4к.
- Реклама
Вроде как, в Atmega324pa и так 2 шт. USART на борту.
Ничего не понятно.
Ничего не понятно.
Карбофос писал(а):Вроде как, в Atmega324pa и так 2 шт. USART на борту.
Alexeytm писал(а):на Atmega324pa оба порта заняты
Alexeytm писал(а):на втором Atmega328p пишу сам
Я описал в общих чертах.Карбофос писал(а):Ничего не понятно.
Нужно запихнуть ретранслятор USART в boot область. Т.е. при старте нажата кнопка - ретранслятор.
Что не понятно?
https://www.fischl.de/avrusbboot/
makefile
Конечно, встает вопрос, как с основной программой скомпоновать.
Здесь https://radiokot.ru/forum/viewtopic.php ... 3#p4097463 писал по мотивам интернетов.
И, мне совершенно не понятно, почему вся эта шняга должна находиться в области бутлодера???
makefile
main.cBOOTLOADER_ADDRESS = 1800
LDFLAGS += -Wl,--section-start=.text=$(BOOTLOADER_ADDRESS)
Код: Выделить всё
#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 писал по мотивам интернетов.
И, мне совершенно не понятно, почему вся эта шняга должна находиться в области бутлодера???
Это вреде бы как перейти на boot из программы.
[uquote="Карбофос",url="/forum/viewtopic.php?p=4121441#p4121441"]Конечно, встает вопрос, как с основной программой скомпоновать.[/uquote]
Я встречал как их склеить.
srec_cat app.hex -I boot.hex -I -o combined.hex -I
Также вы можете вручную объединить файлы app.hex и boot.hex файлов с небольшими правками: Каждый шестнадцатеричный файл имеет одну последнюю запись, в которой говорится, что «файл заканчивается». Таким образом, после ручного объединения нужно отредактировать объединенный шестнадцатеричный файл — найти в нем запись окончания файла, расположенную в конце app.hex (после объединения где-то в середине файла) и удалить ее. Запись имеет тип 01. Байт типа записи в шестнадцатеричном формате Intel по порядку является 4-м байтом, поэтому запись на самом деле будет выглядеть примерно так: «:00000001FF». Вся линия (та что в середине, а не в конце файла) должна быть удалена.
Для меня это пока не проблема - запишу программатором.
[uquote="Карбофос",url="/forum/viewtopic.php?p=4121441#p4121441"]Конечно, встает вопрос, как с основной программой скомпоновать.[/uquote]
Я встречал как их склеить.
Спойлер
Я думаю, что самый простой способ объединить шестнадцатеричные файлы с помощью командной строки 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». Вся линия (та что в середине, а не в конце файла) должна быть удалена.
чтобы не пересекались прерывания при работе с USART. Ругается при попытке добавить либу SoftwareSerial. Хочу сделать типа как две отдельные проги. Может кто поможет как добавить в ISR(USART_RX_vect) чтобы после приема байта он автоматом дублировался на другой ноге, и так же при передаче, я откажусь от boot.Alexeytm писал(а):И, мне совершенно не понятно, почему вся эта шняга должна находиться в области бутлодера???
- Реклама
При загрузке определили, что кнопка нажата - идем в отдельный цикл.
В цикле, изменился пин приема1 - изменить пин передачи 2.
В цикле, изменился пин приема2 - изменить пин передачи 1.
Только, это на асме надо писать, не силен.
Надеюсь, вам помогут.
Что-то вроде
В цикле, изменился пин приема1 - изменить пин передачи 2.
В цикле, изменился пин приема2 - изменить пин передачи 1.
Только, это на асме надо писать, не силен.
Надеюсь, вам помогут.
Что-то вроде
Код: Выделить всё
Cycle:
BST PIND,0 ;Rx0
BLD PORTB,1 ;Tx1
BST PINB,0 ;Rx1
BLD PORTD,1 ;Tx0
rjmp Cycle[uquote="Alexeytm",url="/forum/viewtopic.php?p=4121530#p4121530"]Это вреде бы как перейти на boot из программы....Ругается при попытке добавить либу SoftwareSerial....[/uquote]
Это случаем не игрушки с адуринкой имеют место?
(вместо чистого Си в соответствующей IDE)

Это случаем не игрушки с адуринкой имеют место?
(вместо чистого Си в соответствующей IDE)
Написал такой повторитель
#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 самому. И то и то не айс.
Спойлер
#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 самому. И то и то не айс.
Код: Выделить всё
//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.
Не нужно линии Rx настраивать на выход.
Это входные линии.
Этот код надо исключить.
Мне самому интересно, заработает-ли в таком виде ретранслятор.
Если да - можно и c векторами дальше разбираться будет. И, для ретранслятора, этот тик-так лучше отключить.
Хотя, и обработчик можно свести к:
Запись 1 в PINx инвертирует PORTx.
Это входные линии.
Этот код надо исключить.
Мне самому интересно, заработает-ли в таком виде ретранслятор.
Если да - можно и c векторами дальше разбираться будет. И, для ретранслятора, этот тик-так лучше отключить.
Хотя, и обработчик можно свести к:
Код: Выделить всё
PIND |= _BV(PIND4);Большое спасибо!!!Карбофос писал(а):Не нужно линии Rx настраивать на выход.
Это входные линии.
Этот код надо исключить.
Заработало в протэусе и в железе.
Тиктак нужен чтобы знать работает контроллер или нет, пока для отладки.
Попробую запихнуть в boot.
Код: Выделить всё
ISR(TIMER1_COMPA_vect, ISR_NAKED)
{
PIND |= _BV(PIND4);
reti();
}Добавил к прошивке по адресу 0x7E00 это кусок и с него не стартует.
поставил ардуиновские
low_fuses=0xFF
high_fuses=0xDE
extended_fuses=0xFD
Убираю бит чтобы стартовал с 0х0000 грузит основной код. Что не так с этим boot?
И протэус висит и не ругается.
поставил ардуиновские
low_fuses=0xFF
high_fuses=0xDE
extended_fuses=0xFD
Убираю бит чтобы стартовал с 0х0000 грузит основной код. Что не так с этим boot?
И протэус висит и не ругается.
Необходим повторитель UART с одним входом (Rx) и двумя выходами (Tx_1; Tx_2)?
Получилось: в буте моргает светодиод и работает основная программа.
Нужно было перенаправить прерывания в boot
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL);
Если перенаправить до работы в boot - не работала основная прога. Поставил после срабатывания кнопки.
Через Arduino IDE через USBasp пишу основную программу, а потом без стирания дописываю через ProgISP boot.hex. Пробовал склеить две прошивки в HEX редакторе и залить - тоже работает.
Исходники для AVR Studio 4.19. Makefile брать из архива и править под себя и может дописывать свой контроллер, тогда будет прошивка с адресами для boot.
Делал по AVR. Учебный Курс. Использование Bootloader’а В протэусе с boot не стартует. Что то там адреса не совпадают при выборе fuse boot.
Помогла статья
AVR BootLoader в вопросах и ответах. Часть 1
Спойлер
Код: Выделить всё
#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();
}
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL);
Если перенаправить до работы в boot - не работала основная прога. Поставил после срабатывания кнопки.
Через Arduino IDE через USBasp пишу основную программу, а потом без стирания дописываю через ProgISP boot.hex. Пробовал склеить две прошивки в HEX редакторе и залить - тоже работает.
Исходники для AVR Studio 4.19. Makefile брать из архива и править под себя и может дописывать свой контроллер, тогда будет прошивка с адресами для boot.
Делал по AVR. Учебный Курс. Использование Bootloader’а В протэусе с boot не стартует. Что то там адреса не совпадают при выборе fuse boot.
Помогла статья
AVR BootLoader в вопросах и ответах. Часть 1


