Almaz1988 0 1 октября, 2012 Опубликовано 1 октября, 2012 · Жалоба Продолжаю штурм)) и в загрузчике и в рабочей программе будут использоваться прерывания: SysTick, SVC, PendSV, CAN. Пишу обработчики для этих прерываний. Если в обработчике для каждого прерывания делаю прыжок, например в SysTick_Handler: __ASM void SysTick_Handler(void) { ldr r0, =0x203C ldr r0, [r0] mov pc, r0 } То Загрузчик передает управление Рабочей программе, в которой все прерывания обрабатываются корректно. Но, стоит написать вот так (через функцию посредник): __ASM void SysTick_Handler_of_application(void) { ldr r0, =0x203C ldr r0, [r0] mov pc, r0 } void SysTick_Handler(void) { SysTick_Handler_of_application( ); } И три из четырех обработчика прерывания работать уже не хотят! Обрабатываются только CAN-прерывания! Функции посредники нужны мне для того, чтобы производить проверку, из какой программы вызвано прерывание: void SysTick_Handler(void) { if ( *(uint32_t *)0x100001F0 == 0x67 ) //сли обработчик прерывания вызван из рабочей программы, то прыгаем в таблицу векторов рабочей программы SysTick_Handler_of_application( ); else SysTick_Handler_of_bootloader();//иначе обработчик прерывания вызван из загрузчика } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Almaz1988 0 1 октября, 2012 Опубликовано 1 октября, 2012 · Жалоба Продолжаю штурм)) и в загрузчике и в рабочей программе будут использоваться прерывания: SysTick, SVC, PendSV, CAN. Пишу обработчики для этих прерываний. Если в обработчике для каждого прерывания делаю прыжок, например в SysTick_Handler: __ASM void SysTick_Handler(void) { ldr r0, =0x203C ldr r0, [r0] mov pc, r0 } То Загрузчик передает управление Рабочей программе, в которой все прерывания обрабатываются корректно. Но, стоит написать вот так (через функцию посредник): __ASM void SysTick_Handler_of_application(void) { ldr r0, =0x203C ldr r0, [r0] mov pc, r0 } void SysTick_Handler(void) { SysTick_Handler_of_application( ); } И три из четырех обработчика прерывания работать уже не хотят! Обрабатываются только CAN-прерывания! Функции посредники нужны мне для того, чтобы производить проверку, из какой программы вызвано прерывание: void SysTick_Handler(void) { if ( *(uint32_t *)0x100001F0 == 0x67 ) //сли обработчик прерывания вызван из рабочей программы, то прыгаем в таблицу векторов рабочей программы SysTick_Handler_of_application( ); else SysTick_Handler_of_bootloader();//иначе обработчик прерывания вызван из загрузчика } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Almaz1988 0 1 октября, 2012 Опубликовано 1 октября, 2012 · Жалоба Продолжаю штурм)) и в загрузчике и в рабочей программе будут использоваться прерывания: SysTick, SVC, PendSV, CAN. Пишу обработчики для этих прерываний. Если в обработчике для каждого прерывания делаю прыжок, например в SysTick_Handler: __ASM void SysTick_Handler(void) { ldr r0, =0x203C ldr r0, [r0] mov pc, r0 } То Загрузчик передает управление Рабочей программе, в которой все прерывания обрабатываются корректно. Но, стоит написать вот так (через функцию посредник): __ASM void SysTick_Handler_of_application(void) { ldr r0, =0x203C ldr r0, [r0] mov pc, r0 } void SysTick_Handler(void) { SysTick_Handler_of_application( ); } И три из четырех обработчика прерывания работать уже не хотят! Обрабатываются только CAN-прерывания! Функции посредники нужны мне для того, чтобы производить проверку, из какой программы вызвано прерывание: void SysTick_Handler(void) { if ( *(uint32_t *)0x100001F0 == 0x67 ) //сли обработчик прерывания вызван из рабочей программы, то прыгаем в таблицу векторов рабочей программы SysTick_Handler_of_application( ); else SysTick_Handler_of_bootloader();//иначе обработчик прерывания вызван из загрузчика } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Almaz1988 0 1 октября, 2012 Опубликовано 1 октября, 2012 · Жалоба Продолжаю штурм)) и в загрузчике и в рабочей программе будут использоваться прерывания: SysTick, SVC, PendSV, CAN. Пишу обработчики для этих прерываний. Если в обработчике для каждого прерывания делаю прыжок, например в SysTick_Handler: __ASM void SysTick_Handler(void) { ldr r0, =0x203C ldr r0, [r0] mov pc, r0 } То Загрузчик передает управление Рабочей программе, в которой все прерывания обрабатываются корректно. Но, стоит написать вот так (через функцию посредник): __ASM void SysTick_Handler_of_application(void) { ldr r0, =0x203C ldr r0, [r0] mov pc, r0 } void SysTick_Handler(void) { SysTick_Handler_of_application( ); } И три из четырех обработчика прерывания работать уже не хотят! Обрабатываются только CAN-прерывания! Функции посредники нужны мне для того, чтобы производить проверку, из какой программы вызвано прерывание: void SysTick_Handler(void) { if ( *(uint32_t *)0x100001F0 == 0x67 ) //сли обработчик прерывания вызван из рабочей программы, то прыгаем в таблицу векторов рабочей программы SysTick_Handler_of_application( ); else SysTick_Handler_of_bootloader();//иначе обработчик прерывания вызван из загрузчика } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Almaz1988 0 2 октября, 2012 Опубликовано 2 октября, 2012 · Жалоба Добил бутлоадер))) В бутлоадере использую только CAN-прерывания: __ASM void CAN_IRQHandler_of_application(void) { ldr r0, =0x2074 ldr r0, [r0] bx r0 } void CAN_IRQHandler(void) { if ( *(uint32_t *)0x100001F0 == 0x67 ) { CAN_IRQHandler_of_application( ); } else { (*rom)->pCAND->isr(); } } Значение 0х67 в ячейку 0x100001F0 записывает рабочая программа при запуске (в своем main()): uint32_t *ram_vector_table; ram_vector_table=(uint32_t *)0x100001F0; *ram_vector_table = 0x67; Как оказалось ничего сложного, если разобраться))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 2 октября, 2012 Опубликовано 2 октября, 2012 · Жалоба Как оказалось ничего сложного, если разобраться))) Еще чуть-чуть и можно избавиться от тяжелого наследия (ассемблера) совсем: void CAN_IRQHandler(void) { if ( *(uint32_t *)0x100001F0 == 0x67 ) { void(**CAN_IRQHandler_of_application)() = (void(**)())0x2074; (*CAN_IRQHandler_of_application)( ); } else { (*rom)->pCAND->isr(); } } P.S. c меткой main все же не получилось? ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alx2 0 2 октября, 2012 Опубликовано 2 октября, 2012 · Жалоба Кажется, без ответа остался этот вопрос: Откуда в Кейловском варианте берется __main, а в LPC-шном _etext, _data, _edata....? Их тупо проэкстернили, но они нигде не инициализируются Судя по названиям, символы _etext, _data, _edata и т.п. определены в скрипте линкера и обозначают: _etext - конец секции .text; _data - начало секции .data; _edata - конец секции .data; _bss - начало секции .bss; _ebss - конец секции .bss. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Almaz1988 0 5 октября, 2012 Опубликовано 5 октября, 2012 · Жалоба Дело близится к завершению)) "Программный загрузчик" при запуске слушает сеть, определяет есть ли устройства которые требуют обновления прошивки. Если таких нет передает управление "Рабочей программе". Если есть, то переводит это устройство в режим аппаратного загрузчика (заводской бутлоадер) и прошивает его. Дальше по идее нужно перезапустить прошитое устройство. Для этого у аппаратного загрузчика предусмотрена команда "GO". Но, она позволяет прыгать только по адресам кратным 0х10! А Reset_handler у меня находится по адресу, не кратному 0х10. Т.е. сейчас он у меня по адресу 0x01ad. Прыгнуть в него командой аппаратного загрузчика "GO" я смогу, только если он будет по адресу, например, 0x1b0. Keil позволяет использовать атрибут __attribute__((at(0x10000))) расположения переменных по конкретному адресу, но, к сожалению на функции этот атрибут не распростаняется. Откусывать память в линкере могу только кусками кратными 4 байтам, что не выручает. Есть ли другой способ "подвинуть" Reset_handler в памяти МК? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 5 октября, 2012 Опубликовано 5 октября, 2012 · Жалоба "Программный загрузчик" при запуске слушает сеть, определяет есть ли устройства которые требуют обновления прошивки. Если таких нет передает управление "Рабочей программе". Если есть, то переводит это устройство в режим аппаратного загрузчика (заводской бутлоадер) и прошивает его. Не понимаю, зачем переводить устройство в режим заводского загрузчика, если есть свой? Дальше по идее нужно перезапустить прошитое устройство. Для этого у аппаратного загрузчика предусмотрена команда "GO". Но, она позволяет прыгать только по адресам кратным 0х10! А Reset_handler у меня находится по адресу, не кратному 0х10. Т.е. сейчас он у меня по адресу 0x01ad. Прыгнуть в него командой аппаратного загрузчика "GO" я смогу, только если он будет по адресу, например, 0x1b0. Опять же зачем использовать Go и тп. Не проще ли подать буту команду reset и он запустит Reset_Handler по какому надо адресу, не глядя на выравнивание. А Reset_handler у меня находится по адресу, не кратному 0х10. Т.е. сейчас он у меня по адресу 0x01ad. Это Reset_Handler бута или приложения? Keil позволяет использовать атрибут __attribute__((at(0x10000))) расположения переменных по конкретному адресу, но, к сожалению на функции этот атрибут не распростаняется. Откусывать память в линкере могу только кусками кратными 4 байтам, что не выручает. Раз можно кратными по 4 байта, то можно и кратно 16 байтам откусывуть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
igor_mmm 0 6 октября, 2012 Опубликовано 6 октября, 2012 · Жалоба Добрый День! Использую 11с24 и работаю с CAN. Необходимо организовать выдачу без подтверждения приема. То есть на приемной стороне может отсутствовать приемник. Смотрю пример "CAN on_chip" из примеров KEIL. msg_obj.msgobj = 1; msg_obj.mode_id = 0x123 ; msg_obj.mask = 0xff; msg_obj.dlc = 5; msg_obj.data[0] = 'T'; msg_obj.data[1] = 'E'; msg_obj.data[2] = 'S'; //0x53 msg_obj.data[3] = 'T'; //0x54 (*rom)->pCAND->can_transmit(&msg_obj); Что нужно добавить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KRS 1 6 октября, 2012 Опубликовано 6 октября, 2012 · Жалоба Необходимо организовать выдачу без подтверждения приема. То есть на приемной стороне может отсутствовать приемник. Если в сети только одно устройство (ACK выставить некому) то передатчик будет отправлять сообщение заново и увеличивать счетчик ошибок (пока не дойдет до ERROR PASSIVE), потом просто будет передавать пока не остановишь принудительно или не появится второе устройство. Если реально надо выдавать разные фреймы (хотя принимать их все равно не кому) Надо сделать Disable Automatic Retransmission, тогда попытка отправки будет тольо одна! Или надо отменять посылку потом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
igor_mmm 0 7 октября, 2012 Опубликовано 7 октября, 2012 · Жалоба Если в сети только одно устройство (ACK выставить некому) то передатчик будет отправлять сообщение заново и увеличивать счетчик ошибок (пока не дойдет до ERROR PASSIVE), потом просто будет передавать пока не остановишь принудительно или не появится второе устройство. Если реально надо выдавать разные фреймы (хотя принимать их все равно не кому) Надо сделать Disable Automatic Retransmission, тогда попытка отправки будет тольо одна! Или надо отменять посылку потом. Сделал DAR. Сначала долго не работало, я засылал посылку один раз и после инициализации типа так (*rom)->pCAND->can_transmit(&msg_obj); //послать один раз while (1); // бесконечный цикл. а теперь сделал while(1) { i++; if(i>1000000) { i=0; /* Send a simple CAN message */ msg_obj.msgobj = 0; msg_obj.mode_id = 0x500; msg_obj.mask = 0x0; msg_obj.dlc = 5; msg_obj.data[0] = 'T'; //0x54 msg_obj.data[1] = 'E'; //0x45 msg_obj.data[2] = 'S'; //0x53 msg_obj.data[3] = 'T'; //0x54 msg_obj.data[4] = 1; (*rom)->pCAND->can_transmit(&msg_obj); } } стало посылать с некой периодичностью. не понял почему но повторная посылка заработала Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Almaz1988 0 8 октября, 2012 Опубликовано 8 октября, 2012 · Жалоба Добрый День! Использую 11с24 и работаю с CAN. Необходимо организовать выдачу без подтверждения приема. То есть на приемной стороне может отсутствовать приемник. Смотрю пример "CAN on_chip" из примеров KEIL. msg_obj.msgobj = 1; msg_obj.mode_id = 0x123 ; msg_obj.mask = 0xff; msg_obj.dlc = 5; msg_obj.data[0] = 'T'; msg_obj.data[1] = 'E'; msg_obj.data[2] = 'S'; //0x53 msg_obj.data[3] = 'T'; //0x54 (*rom)->pCAND->can_transmit(&msg_obj); Что нужно добавить? Вот как выглядит моя функция отправки 4-ехбайтового сообщения: void CANsend4byte(uint32_t ID, uint32_t DATA ) { CAN_MSG_OBJ msg_obj_transmit; msg_obj_transmit.msgobj = 0; msg_obj_transmit.mode_id = ID; msg_obj_transmit.mask = 0x0; msg_obj_transmit.dlc = 4; msg_obj_transmit.data[0] = DATA; msg_obj_transmit.data[1] = DATA>>8; msg_obj_transmit.data[2] = DATA>>16; msg_obj_transmit.data[3] = DATA>>24; while (flagMessageTransmitted != 1); (*rom)->pCAND->can_transmit(&msg_obj_transmit); flagMessageTransmitted = 0; } Она рабочая Убираешь строчку while (flagMessageTransmitted != 1); Если подтверждение не требуется Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Almaz1988 0 8 октября, 2012 Опубликовано 8 октября, 2012 · Жалоба Вопрос по примеру "NXP secondary bootloader" (документ AN10995). Программный бутлоадер под конец загрузки новой прошивки во флеш в последнюю ячейку флеша записывает контрольную сумму. В последующем при всяком запуске микронотроллера он вычисляет действительную контрольную сумму флеш-памяти и значение, которое записано в последней ячейке флеша. Если они совпадают, то рабочая программа корректна и программный загрузчик передает управление рабочей программе. А как быть если рабочая программа заливается не с помощью программного бутлоадера, а программатором с компа. В этом случае контрольная сумма не записывается и программный бутлоадер посчитает, что рабочая программа битая. Как быть? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 8 октября, 2012 Опубликовано 8 октября, 2012 · Жалоба Как быть?Посчитать ее при помощи какой-либо внешней утилиты и добавить той же или другой утилитой в прошиваемый программатором файл. Но не совсем красиво хранить контрольную сумму в последней ячейке флеша. По двум причинам: 1) Вне зависимости от реального размера приложения загрузчик вынужден обсчитывать всю флеш, а это время. 2) При очередном обновлении может захотеться добавить эмуляцию eeprom в последнюю страницу флеша, а эта область уже защищена CRC. Поэтому я делаю так: в первую же ячейку сразу за векторами линкер записывает размер приложения. CRC кладется сразу же следом за приложением. Загрузчик знает, в какой ячейке лежит размер и считает CRC только реально занятой области флеша. Поскольку у LPC11 перед ремапом вектора копируются и им не обязательно начинаться с адреса, кратного 256 - можно размер хранить перед векторами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться