реклама на сайте
подробности

 
 
5 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> LPC11xx не стартует код из своего бутлоадера
zuy
сообщение Oct 21 2010, 10:42
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Использую LPC1114. По доке вроде все понятно.
Свой бутлоадер код во флеш прописал.
для старта делаю следующее:
1. копирую 48 векторов прерывания основной программы в ОЗУ с адреса 0x10000000
2. Делаю ремап LPC_SYSCON->SYSMEMREMAP = 0x01; т.е. отобрашаем вектора из ОЗУ в начало адресного простанства
3. инициализирую SP и PC данными из первых 8-ми байт моей проги.

Все это выглядит так:
Код
__asm void boot_jump( uint32_t address )
{
   LDR R1, [R0]    ;Load new stack pointer address
   MOV R13, R1
   LDR R1, [R0, #4];Load new program counter address
   BX  R1
}

void run(unsigned long address)
{
  unsigned long          *dst, size;
  const unsigned long    *src;
  
  // Copy vectors table
  src = (unsigned long *)address;
  dst = (unsigned long *)0x10000000;
  size = VECTORS_TABLE_SIZE >> 2;
  do  { *dst++ = *src++; } while (--size);

  LPC_SYSCON->SYSMEMREMAP = 0x01;        /* remap to SRAM */

  boot_jump(address);
}


В результате поведение непредсказуемое. то висит, то попадает куда-то в середину бутлоадера.
Если убрать ремап, то целевая прога запускается, но естественно с векторами из флеша.

Что я забываю в этой схеме?
Go to the top of the page
 
+Quote Post
Alekseeey
сообщение Oct 21 2010, 12:12
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626



У меня та же проблема.

Пробую на отладке LPCXpresso, среда CodeRed. Процессор LPC1114.

Я взял проект blinky из примеров и попытался просто скопировать вектора в ОЗУ и сделать ремап.
(соотв. область озу зарезервирована в скрипте линкера).

Программа вылетает в HardFault exception.

Написал вопрос в LPCXpresso forum.

Жду ответа... У меня самого идеи кончились.

В дебаг режиме, при пошаговом выполнении, вылетает на команде bl.

Вот код функции Reset_Handler из примера с моими изменениями:

Код
void Reset_Handler(void)
{
    unsigned char *pulSrc, *pulDest;

    //
    // Copy the data segment initializers from flash to SRAM.
    //
    pulSrc = &_etext;
    for(pulDest = &_data; pulDest < &_edata; )
    {
        *pulDest++ = *pulSrc++;
    }

    //
    // Zero fill the bss segment.
    //
    for(pulDest = &_bss; pulDest < &_ebss; pulDest++)
      *pulDest = 0;

    // Copying the vector table to sram
    unsigned char i;
    unsigned char * vectDest;
    unsigned char * vectSrc;

    vectDest = (unsigned char *)(0x10000000);
    vectSrc  = (unsigned char *)(0x00000000);
    for (i = 0; i < 0xC0; i++)
    {
        *vectDest++ = *vectSrc++;
    };

    // Remap
    LPC_SYSCON->SYSMEMREMAP = 1;
    __DMB();

#ifdef __USE_CMSIS
    SystemInit();
#endif


    //
    // Call the application's entry point.
    // __main() is the entry point for redlib based applications (which calls main())
    // main() is the entry point for newlib based applications
    //
    if (__main)
        __main();
    else
        main();

    //
    // main() shouldn't return, but if it does, we'll just enter an infinite loop
    //
    while (1) {
    ;
    }
}



Go to the top of the page
 
+Quote Post
DpInRock
сообщение Oct 21 2010, 12:38
Сообщение #3


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Вообще-то так и должно быть.

Как правильно (это мое имхо, но которое работает).

0. Компилируем программу и линковщику показываем реальные адреса.
1. Грузим программу с нужного адреса.
2. Копируем вектора, только если ремаповая область не совпадает с расположением программы (к примеру код находится SDRAM или FLASH). Т.е в этом случае копируем из области своей программы в область которая может содержать вектора и ремапится.
3. Далее запрещаем прерывания и JMP на начало своей программы: либо на реальное начало, либо на начальный адрес зоны векторов, которые ремапили (там одно и тоже будет - goto Startup).

Что характерно, не надо трогать стеки. Ибо стартап их настроит как вы в линкере укажите.



--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 21 2010, 12:52
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Цитата(Alekseeey @ Oct 21 2010, 15:12) *
Вот код функции Reset_Handler из примера с моими изменениями:


Если честно не совсем понял зачем это все в Reset_Handler.
Он от бутлоадера или от прошиваемой проги?
Какая у вас логика работы бутлоадера?

Цитата(DpInRock @ Oct 21 2010, 15:38) *
Вообще-то так и должно быть.

Как правильно (это мое имхо, но которое работает).

0. Компилируем программу и линковщику показываем реальные адреса.
1. Грузим программу с нужного адреса.
2. Копируем вектора, только если ремаповая область не совпадает с расположением программы (к примеру код находится SDRAM или FLASH). Т.е в этом случае копируем из области своей программы в область которая может содержать вектора и ремапится.
3. Далее запрещаем прерывания и JMP на начало своей программы: либо на реальное начало, либо на начальный адрес зоны векторов, которые ремапили (там одно и тоже будет - goto Startup).

Что характерно, не надо трогать стеки. Ибо стартап их настроит как вы в линкере укажите.


А почему оно так должно быть и как починить?

0. Основная прога собрана с адреса 0x2000. RAM использует с 0x100000C0.
1. Верно, бутлоадер прощивает основную прогу во флеш по адресу 0x2000.
2. Копируем таблицу векторов. Т.е. 0xC0 байт c адреса 0x2000 в 0x10000000.
3. Ну перед джампом надо же сделать ремап, чтобы вектора из ОЗУ появились с адреса 0x0. И вот тут у меня сразу улетает куда-то в середину бутлоадера.

А как это стеки трогать не надо? У Cortex M0 вершина стека хранится в самом начале векторов и проц после ресета сам ее оттуда берет. А т.к. мы скачем в основную прогу без ресета, а из своего бутлоадера, то надо самому правильно стек настроить. Стартап у кортексов стеки не настраивает.

Go to the top of the page
 
+Quote Post
DpInRock
сообщение Oct 21 2010, 12:58
Сообщение #5


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Reset - это место откуда программа стартует. Как бы по сигналу сброса. Как бы независимо.
Но в реальности по сигналу сброса проц идет на собственный загрузчик и передает управление программе после ремапа. И тут якобы она стартует с 0. Делает вид,что после сброса как бы.

Разумеется, можно написать даже процедуру, которая будет располагаться с 0. Токо следущими идут вектора прерываний. И если прерывания не используются - да ради бога. Можно.

Против кортекса не попрешь. Извиняюсь.
Но логика все равно остается.
Не забывать прерывания убить.
Ну и правильно джамп сделать.
С переключением в режим супервизора. Я делаю
Код
void  JMP(unsigned int addr)
{

//asm ("mov r0, addr \n");
asm ("SWI 0 \n");
}

Вот так примерно.

В том плане, что я стартую с нуля всегда после ремапа. Ибо так универсальнее, разумеется.
(У меня все остальное - типа переключателя задач работает в супервизоре - выбрал за красивое название)
НУ, еще контроллр внешней памяти не забыть настроить... У меня-то вектора в локальной памяти...

Сообщение отредактировал DpInRock - Oct 21 2010, 13:05


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
Alekseeey
сообщение Oct 21 2010, 13:01
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626



Цитата(zuy @ Oct 21 2010, 16:52) *
Если честно не совсем понял зачем это все в Reset_Handler.
Он от бутлоадера или от прошиваемой проги?
Какая у вас логика работы бутлоадера?


Логику работы бутлоадера я пока оставил в стороне - у меня не работает именно ремап.
Я попытался взять работающий пример и сделать ремап векторов не трогая ничего другого.
По идее все долно было работать без изменений. Но не работает. smile.gif Что-то делаю не правильно, но не знаю что.

А вообще логика бутлоадера будет такой: лоадер в 0-й странице флеш, грузит программу в страницы 1..7,
копирует ее вектора прерываний в ОЗУ и передает управление ей.

Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 21 2010, 13:01
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Цитата(DpInRock @ Oct 21 2010, 15:54) *
Reset - это место откуда программа стартует. Как бы по сигналу сброса. Как бы независимо.
Но в реальности по сигналу сброса проц идет на собственный загрузчик и передает управление программе после ремапа. И тут якобы она стартует с 0. Делает вид,что после сброса как бы.


Да, это понятно. Мой бут делает в общем тоже самое, что и встроенный, только ремапит вектора не из флеша, а из ОЗУ.

Вроде нашел косяк. Забыл прерывания отключить до ремапа!

Тогда еще вопрос. А барьеры синхронизации или памяти нужно после ремапа ставить или нет?
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Oct 21 2010, 13:13
Сообщение #8


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



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

Сообщение отредактировал DpInRock - Oct 21 2010, 13:14


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
Alekseeey
сообщение Oct 21 2010, 13:41
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626



Цитата(zuy @ Oct 21 2010, 17:01) *
Да, это понятно. Мой бут делает в общем тоже самое, что и встроенный, только ремапит вектора не из флеша, а из ОЗУ.

Вроде нашел косяк. Забыл прерывания отключить до ремапа!

Тогда еще вопрос. А барьеры синхронизации или памяти нужно после ремапа ставить или нет?


Пожалуйста, опубликуйте работающий вариант процедуры ремапа.

В usermanual lpc1114 написано на стр. 317:
Vector table — If the program changes an entry in the vector table, and then enables the
corresponding exception, use a DMB instruction between the operations. This ensures that
if the exception is taken immediately after being enabled the processor uses the new
exception vector.

Судя по всему - надо.
Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 21 2010, 17:28
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Цитата(Alekseeey @ Oct 21 2010, 16:41) *
Пожалуйста, опубликуйте работающий вариант процедуры ремапа.

Да вот что-то еще не прокатило, разбираюсь.
Как будет рабочий вариант, отпишу
Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 21 2010, 19:14
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Нет, все равно решительно не понимаю, что делает ремап в LPC1114.
Вот простой код, который просто включает светодиод, и через некоторое время выключает:
Код
int main(void )
{
  unsigned long *dst, size, i;
  const unsigned long    *src;

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16) | (1<<6);  // Enable IOCON GPIO
  LPC_GPIO1->DIR  |= ( 1 << 8 );                  // LED pin direction out
  LPC_GPIO1->DATA &= ~( 1 << 8 );                 // LED ON

  // Copy vectors table from 0x0 to RAM
  src = (unsigned long *)0;
  dst = (unsigned long *)0x10000000;
  size = 0xC0 >> 2;
  do  { *dst++ = *src++; } while (--size);

  // Pause, just to mention the LED state.
  i= 10000000;
  while( --i );

  __disable_irq();
  LPC_SYSCON->SYSMEMREMAP = 0x01;        // remap to SRAM
  __ISB();

  LPC_GPIO1->DATA |= ( 1 << 8 );    // LED OFF

  while( 1 );
}


Чтобы ремап не мешал работать, я копирую таблицу векторов из флеш в RAM.
Если строка с ремапом присутствует то код не работает,
если ее комментирую то все нормально.
Но я же скопировал таблицу в RAM. Т.е. после ремапа для процессора вообще ничего не поменялось в начале адресного пространства!

Кто-нибудь может объяснить что тут происходит?

Go to the top of the page
 
+Quote Post
Alekseeey
сообщение Oct 21 2010, 20:30
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626



Цитата(zuy @ Oct 21 2010, 23:14) *
Нет, все равно решительно не понимаю, что делает ремап в LPC1114.

Кто-нибудь может объяснить что тут происходит?


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

Причем, в тестовой программе blinky это исключение возникает при попытке
перехода на main();, но не происходит при переходе на SystemInit();
В памяти SystemInit расположена вверх по адресам от точки вызова, а main - вниз,
не знаю, важно это или нет...



Вот только что увеличил размер зарез. области до 0x1000 и скопировал туда 0x1000 байт флеш. Программа blinky дошла до main и попыталась начать работать. Прогресс.

Да, проект blinky заработал. При включенном ремапе. После копирования в ОЗУ 0x1000 байт флеша. У меня нехорошие предчувствия по поводу ремапа...



Интересная опечатка (?) есть в старых версиях user manual на lpc1114: на картинке карты памяти размер области векторов указан 0x0200 байт. И если я копирую 0x0200 байт, то программа работает...

Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 21 2010, 20:43
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Цитата(Alekseeey @ Oct 21 2010, 23:09) *
Обьяснить, к сожалению не могу, но могу от себя добавить, что когда я
выполняю программу в отладчике по шагам, по ассемблерным коммандам,
то при включенном ремапе происходит HardFault на инструкциях ветвления.

Отладчик Keil ?
Он для LPC1114 не совсем корректно работает. Тот пример что я привел в случае если ремап убрать, то вылетает в отладчике в HardFault, но работает отлично в железе.

Цитата(Alekseeey @ Oct 21 2010, 23:30) *
Интересная опечатка (?) есть в старых версиях user manual на lpc1114: на картинке карты памяти размер области векторов указан 0x0200 байт. И если я копирую 0x0200 байт, то программа работает...

Рано я обрадовался. в 0х200 байт у меня вся тестовая прога. Получается я ее скопировал всю в ОЗУ.
В реальном бутлоадере это не помогло :-(
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 21 2010, 20:55
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Возникло предположение, что ремапу подвергается Flash кратно одному полному сектору размером 512 байт. Посмотрел в других кристаллах Cortex-M0 и Cortex-M3 - аналогично: либо 512 байт, либо 256 слов. Видимо бангалорские писатели даташитов что-то перемудрили laughing.gif
К сожалению, под рукой у меня нету ни LPC1114, ни отладчика, чтобы чем-то помочь в исследовании проблемы sad.gif
Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 21 2010, 21:09
Сообщение #15


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Цитата(rezident @ Oct 21 2010, 23:55) *
Возникло предположение, что ремапу подвергается Flash кратно одному полному сектору размером 512 байт. Посмотрел в других кристаллах Cortex-M0 и Cortex-M3 - аналогично: либо 512 байт, либо 256 слов. Видимо бангалорские писатели даташитов что-то перемудрили laughing.gif
К сожалению, под рукой у меня нету ни LPC1114, ни отладчика, чтобы чем-то помочь в исследовании проблемы sad.gif


Абсолютно верно. Я точно не проверял 512байт или какое другое значение,
но факт в том, что действительно ремап отображает не таблицу векторов в 0хС0 байт, а больше.

Я решил просто. Разместил код запуска основной проги в начале. Глянул какой максимальный адрес он занимает и
копирую в ОЗУ все до этого адреса. После ремапа, получается этот же код и отображается из ОЗУ и проц продолжает работать.
Далее я уже переписываю первые 0xc0 байт векторов из основной проги, и передаю ей управление через загрузку SP и PC.
Все работает.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 21 2010, 21:48
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Встречный вопрос. А сколько памяти у вас отведено под стек? Не может ли быть так, что переписывая вектора вы затираете стек?
В тестовом проекте Blinky стек начинается с 0x10000800. Но в конфигурации RAM Debug, когда ремап используется-таки, в icf-файле в начале ОЗУ резервируются 0x124 байта, а не 0x200. Такой же диапазон, но уже во Flash резервируется в конфигурации FLASH Debug.

Сообщение отредактировал rezident - Oct 21 2010, 22:23
Эскизы прикрепленных изображений
Прикрепленное изображение
Прикрепленное изображение
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 22 2010, 05:17
Сообщение #17


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Цитата(rezident @ Oct 22 2010, 00:48) *
Встречный вопрос. А сколько памяти у вас отведено под стек? Не может ли быть так, что переписывая вектора вы затираете стек?
В тестовом проекте Blinky стек начинается с 0x10000800. Но в конфигурации RAM Debug, когда ремап используется-таки, в icf-файле в начале ОЗУ резервируются 0x124 байта, а не 0x200. Такой же диапазон, но уже во Flash резервируется в конфигурации FLASH Debug.


У меня стек 0х200 и находится в самом конце используемого ОЗУ.
А чтобы вектора ничего не затерли, я в проекте бутлоадера и основной проги разрешаю использовать ОЗУ с отступом на длину векторов.
Go to the top of the page
 
+Quote Post
Alekseeey
сообщение Oct 22 2010, 07:00
Сообщение #18


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626



Цитата(zuy @ Oct 22 2010, 00:43) *
Отладчик Keil ?
Он для LPC1114 не совсем корректно работает. Тот пример что я привел в случае если ремап убрать, то вылетает в отладчике в HardFault, но работает отлично в железе.


Рано я обрадовался. в 0х200 байт у меня вся тестовая прога. Получается я ее скопировал всю в ОЗУ.
В реальном бутлоадере это не помогло :-(


Отладчик у меня LPCXpresso. Плата + ide.

Вообще, я думаю, именно в данном случае отладчик мешает.

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

Пока я для себя решил делать так: первые 512 (0x200) байт загрузчика заняты его векторами и просто нулями. Т. е. код загрузчика будет начинаться, например, с 0x204.
В основной программе будет запрещено использование ОЗУ меньше адреса 0xC0.


Цитата(rezident @ Oct 22 2010, 01:48) *
Встречный вопрос. А сколько памяти у вас отведено под стек? Не может ли быть так, что переписывая вектора вы затираете стек?
В тестовом проекте Blinky стек начинается с 0x10000800. Но в конфигурации RAM Debug, когда ремап используется-таки, в icf-файле в начале ОЗУ резервируются 0x124 байта, а не 0x200. Такой же диапазон, но уже во Flash резервируется в конфигурации FLASH Debug.


По моим сведениям, в LPCXpresso стек начинается с самого старшего адреса ОЗУ и растет в сторону уменьшения адресов. Переменные же располагаются с самого младшего адреса ОЗУ и заполняют память в сторону увеличения адресов.

У lpc1114, соответственно, в lpcxpresso, стек начинается с адреса 0x10002000.

А у вас, я так понял, Keil?

И он резервирует 0x124? (рит) Обдумаю эту информацию на досуге.

Сообщение отредактировал Alekseeey - Oct 22 2010, 07:03
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 22 2010, 13:28
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Alekseeey @ Oct 22 2010, 13:00) *
По моим сведениям, в LPCXpresso стек начинается с самого старшего адреса ОЗУ и растет в сторону уменьшения адресов. Переменные же располагаются с самого младшего адреса ОЗУ и заполняют память в сторону увеличения адресов.
Направление изменения стека не зависит от вида/типа платы, а только от архитектуры самого МК.
Цитата(Alekseeey @ Oct 22 2010, 13:00) *
А у вас, я так понял, Keil?
IAR EWARM 5.50. Пример проекта Blinky из него же.
Цитата(Alekseeey @ Oct 22 2010, 13:00) *
И он резервирует 0x124? (рит) Обдумаю эту информацию на досуге.
Это установки конкретного проекта, приводимого в примерах. Ни IDE, ни компилятор сами ничего не резервируют. Все настройки можно поменять так, как захочется. В худшем случае компилятор даст предупреждение или ошибку. Но своевольничать он не имеет права.
Использую самодельную плату с LPC1114FBD48,301 и LCD-модулем (TIC234). Отладчик - MT-Link. Так что никаких ограничений, накладываемых LPCXpresso, у меня нет.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 22 2010, 20:51
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Сегодня проэкспериментировал со своей платой и исходником из сообщения #11. Все работает корректно. Ничего не виснет и не вылетает. Через 9 секунд после ресета светодиод гаснет. Единственное, что я скорректировал, это обращение к порту, т.к. у меня из индикации только подсветка LCD и ее управление к другому пину МК подключено. Настройки icf-файла я взял из проекта Blinky, т.е. настройки стека как на скриншотах выше. Компилятор IAR EWARM 5.50.5. Отладчик MT-Link. Драйвер отладчика J-Link V4.14e. Что я не так делаю? laughing.gif
Go to the top of the page
 
+Quote Post
Alekseeey
сообщение Oct 23 2010, 05:02
Сообщение #21


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 21-09-10
Пользователь №: 59 626



Цитата(rezident @ Oct 23 2010, 00:51) *
Что я не так делаю? laughing.gif


Все так. Пожалуйста, укажи в каких адресах расположена функция main. (я думаю, в отладчике это будет видно).

Мне кажется, что IAR учитывает возможность ремапа и кладет исполняемый код в более старшие адреса. И поэтому все работает. В отличие от lpcxpresso, который размещает исполняемый код сразу после таблицы векторов прерываний (адрес 0xC0), и при ремапе эта область памяти начинает ссылаться на ОЗУ, где лежит мусор. Мне интересно узнать, куда кладет исполняемый код IAR, чтобы подправить у себя линкерный скрипт.
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Oct 23 2010, 08:47
Сообщение #22


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



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

Что-то типа того.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 23 2010, 09:18
Сообщение #23


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Цитата(rezident @ Oct 22 2010, 23:51) *
Сегодня проэкспериментировал со своей платой и исходником из сообщения #11. Все работает корректно. Ничего не виснет и не вылетает. Через 9 секунд после ресета светодиод гаснет. Единственное, что я скорректировал, это обращение к порту, т.к. у меня из индикации только подсветка LCD и ее управление к другому пину МК подключено. Настройки icf-файла я взял из проекта Blinky, т.е. настройки стека как на скриншотах выше. Компилятор IAR EWARM 5.50.5. Отладчик MT-Link. Драйвер отладчика J-Link V4.14e. Что я не так делаю? laughing.gif

Конфигурацию FLASH запускали? Поставьте начало ROM с 0х0, зачем кусок флеша размером 0х124 резервировать?
А то получается, собранный код располагается после 0х124 во флеш. А длина куска который ремапится вполне может быть и до 0х124.
У меня ф-ция main того примера до 0x124 заканчивается.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 23 2010, 20:00
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(zuy @ Oct 23 2010, 15:18) *
Поставьте начало ROM с 0х0, зачем кусок флеша размером 0х124 резервировать?
Поставил. Все равно работает. Вот проект. Специально включил генерацию всевозможных листингов и map-файла.
Только не знаю, зачем вам это (в смысле начало программы с нуля)? Ведь вся эта программа умещается в сегмент, который копируется и потом маппируется. Я попробовал то же самое (разместить с нуля во Flash) сделать с другой своей программой, которая обслуживает 4 кнопки, LCD и по нажатию на кнопку выводит одну из несколько картинок на него. В ней используются прерывания от timer16_b0 и i2c-модуля. В качестве "рыбы" для этой программы я использовал пример проекта I2C из экзамплов IAR. Программа вместе с битмаповскими картинками занимает чуть меньше 12кБ во Flash. Скомпилировал, загрузил. Работает laughing.gif Опять я что-то не так делаю? Или в IAR не кошерный компилятор? cranky.gif

Update. Я установил Keil 4.12. Но с ним я не знаком и не знаю как создать проект и работать с ним. Если вы выложите свой простейший тестовый проект, который у вас не работает с LPCExpresso, то я попробую проверить его работу на своей плате.

Сообщение отредактировал rezident - Oct 23 2010, 20:58
Прикрепленные файлы
Прикрепленный файл  Test.zip ( 29.47 килобайт ) Кол-во скачиваний: 36
 
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 24 2010, 01:05
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Любопытство победило smile.gif Со второй попытки создал в Keil работоспособный проект с исходником из сообщения #11. Не мудрствуя лукаво, вывел в окно watch значение регистра SYSMEMREMAP. Изменяя его значение с 0x02 на 0x01, наблюдаю, что содержимое памяти меняется. Вместо кода исполняемой из Flash программы появляются значения 0x00000000 вплоть до границы адреса 0x00000200. То бишь подтверждается версия о маппировании всего сегмента Flash размером 512 байт. Как этот глюк обходится в IAR, мне пока непонятно. laughing.gif Тестовый проект (для Keil 4.12) прикладываю.
Прикрепленные файлы
Прикрепленный файл  Test.zip ( 72.68 килобайт ) Кол-во скачиваний: 38
 
Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 24 2010, 15:20
Сообщение #26


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Цитата(rezident @ Oct 24 2010, 04:05) *
Любопытство победило smile.gif Со второй попытки создал в Keil работоспособный проект с исходником из сообщения #11. Не мудрствуя лукаво, вывел в окно watch значение регистра SYSMEMREMAP. Изменяя его значение с 0x02 на 0x01, наблюдаю, что содержимое памяти меняется. Вместо кода исполняемой из Flash программы появляются значения 0x00000000 вплоть до границы адреса 0x00000200. То бишь подтверждается версия о маппировании всего сегмента Flash размером 512 байт. Как этот глюк обходится в IAR, мне пока непонятно. laughing.gif Тестовый проект (для Keil 4.12) прикладываю.

Да, похоже в ИАР это дело автоматически обходится.
В общем понятно что произошло. В Rev 0_0 мануала, они ошибочно указали размер таблицы векторов в 0х200 байт и тогда в описании регистра SYSMEMREMAP написали, что он ремапит таблицу векторов. И все вроде сходилось. Но потом видимо заметили косяк, что таблица то длиной 0хС0 байт и исправили это дело, а в описании регистра SYSMEMREMAP забыли указать, что он теперь ремапит не таблицу векторов, но область 0х200.
Т.о. на данный момент в последней версии мануала мы имеем некорректное описание регистра SYSMEMREMAP. Нигде по мануалу не написано, что он ремапит 0х200 байт.

А зачем мне надо настройки ROM ставить с 0-го адреса. Так я считаю, что это не мое дело раскладывать программу по адресам памяти.
Я линкеру указываю только где находятся области куда он может результат ложить, пусть сам и складывает. Мне то зачем над этим думать.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 24 2010, 16:17
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(zuy @ Oct 24 2010, 21:20) *
Т.о. на данный момент в последней версии мануала мы имеем некорректное описание регистра SYSMEMREMAP. Нигде по мануалу не написано, что он ремапит 0х200 байт.
Угу. В NXP-ной документации косяков немало sad.gif
Цитата(zuy @ Oct 24 2010, 21:20) *
А зачем мне надо настройки ROM ставить с 0-го адреса. Так я считаю, что это не мое дело раскладывать программу по адресам памяти.
Любая программа не умнее программиста, написавшего ее wink.gif Если вы знаете чуток побольше компилятора, то почему бы это знание не применить для облегчения ему работы? Ведь вас наверняка интересует результат, а не заморочки, которые испытывает компилятор? Да и результат его работы будет вашим общим, не так ли?
Go to the top of the page
 
+Quote Post
zuy
сообщение Oct 24 2010, 16:56
Сообщение #28


Частый гость
**

Группа: Свой
Сообщений: 173
Регистрация: 30-11-05
Из: San Francisco
Пользователь №: 11 593



Цитата(rezident @ Oct 24 2010, 19:17) *
Любая программа не умнее программиста, написавшего ее wink.gif Если вы знаете чуток побольше компилятора, то почему бы это знание не применить для облегчения ему работы? Ведь вас наверняка интересует результат, а не заморочки, которые испытывает компилятор? Да и результат его работы будет вашим общим, не так ли?

Не, тут немного другое. Определив ROM с адреса отличного от 0х0 я должен иметь некоторое основание. Иначе, как я это обосную коллегам по работе.
У нас по бутлоадеру жесткие ограничения, каждый байт нужно знать чем занят.
А то, что ремап захватывает больше байт чем таблица векторов лечится 5-ю строками кода, и не нужно линкеру ничего об этом говорить.
Go to the top of the page
 
+Quote Post
KRS
сообщение Jun 16 2011, 14:20
Сообщение #29


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Тоже столкнулся с проблемой. Но при обычной отладке в памяти.
В какой то момент, после загрузки программы, но до любых шагов портится слово по адресу
0x100000C0 = 0xFFFFFFFF
Может быть проблема в Jlink, я так и не разобрался просто сделал дырку на этом месте.

Память мапится скриптом до загрузки проги, все ок! кроме порчи байта.


К ремапу не имеет отношения вообще, JLINK портит слово 0x100000C0 каждый раз если нажать кнопку reset (я в IAR смотрю).
Т.е. заполняю 0, нажимаю reset и слово по этому адресу портится...
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Sep 24 2012, 08:46
Сообщение #30


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Вот код бутлоадера:
CODE
#include "LPC11xx.h"
#include "rom_drivers.h"
#include "gpio.h"
#include "string.h"
#include "type.h"
#include "core_cm0.h"
#include "system_LPC11xx.h"
#include "application_Flash.h"


__ASM void __copy_MSP_( )
{
ldr r0, =0x10000000
ldr r0, [r0]
mov sp, r0
}

__ASM void __copy_reset_handler_( )
{
ldr r0, =0x10000004
ldr r0, [r0]
bx r0
}

/********************************************************** Main function ********************************/
int main(void)
{
SystemInit();

LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);

uint32_t const * pSrc = (uint32_t const *)0x00001000; //копируем первые 200 байт флеша, начиная с адреса 0х1000 в ОЗУ
uint32_t * pDst = (uint32_t *)0x10000000;
#define VECTORS_COUNT 128
for(uint_fast8_t i = 0; i < VECTORS_COUNT; ++i)
*pDst++ = *pSrc++;

__copy_MSP_( ); //загружаем в стек

__disable_irq(); //запрещаем прерывания
LPC_SYSCON->SYSMEMREMAP = 0x01; // remap to ram

__copy_reset_handler_(); //прыгаем на Resrt_handler

while(1);
}

Работает только если в "рабочей программе" не используются прерывания. Если прерывания используются, то "Рабоча программа" нивкакую не стартует.
Какие есть догадки, в чем ошибка?

Сообщение отредактировал IgorKossak - Sep 24 2012, 13:31
Причина редактирования: [codebox] для длинного кода!!!
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Sep 24 2012, 11:18
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Almaz1988 @ Sep 24 2012, 11:46) *
Работает только если в "рабочей программе" не используются прерывания. Если прерывания используются, то "Рабоча программа" нивкакую не стартует.
Какие есть догадки, в чем ошибка?

Попробуйте по-другому.
Например так:
Код
typedef void (*ISRPtr) (void);
    uint32_t *ram_vector_table, *flash_vector_table;
    ram_vector_table=(uint32_t *)0x10000000;
    flash_vector_table=(uint32_t *)0x1000;
    for (uint_fast32_t i=0; i<48; i++)
        *ram_vector_table++=*flash_vector_table++;
    LPC_SYSCON->SYSMEMREMAP=1;
    __set_MSP(*(uint32_t *)0x1000);
    ISRPtr application_reset_handler=(ISRPtr)(*(uint32_t *)0x1004);
    application_reset_handler();
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 24 2012, 11:41
Сообщение #32


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Т.к. у Cortex-M0 нет VTOR и переместить таблицу прерываний нельзя, а все таки понадобился вторичный бутлоадер, я сделал так:
в бутлоадере прерывания не используются! И все указатели из таблицы прерываний (кроме ресета) указывают на такую функцию:
Код
void handler(void)
{
        asm (
             "mrs r0,IPSR\n"
             "movs r1,#0x1\n"
             "lsls r1,#10\n"
             "add r0, r1\n"
             "lsls r0,#2\n"
             "ldr r0,[r0]\n"
             "mov r15, r0");
        while(1);
}


А старт приложения такой последовательностью:
Код
        asm ("movs r1,#0x1\n"
             "lsls r1,#12\n"
             "ldm r1, {r0,r1}\n"
             "mov r13, r0\n"
             "mov r15, r1");
        while(1);


Все работает!
Приложение ничем не отличается от обычного, только начинается с адреса 0x1000 по которому лежит обычная таблица прерываний.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 24 2012, 12:45
Сообщение #33


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Almaz1988 @ Sep 24 2012, 11:46) *
Вот код бутлоадера:
Для вставки кода в сообщения есть кнопочка на форме ввода. Используйте ее, пожалуйста. Здесь так принято.
QUOTE (Almaz1988 @ Sep 24 2012, 11:46) *
uint32_t const * pSrc = (uint32_t const *)0x00001000; //копируем первые 200 байт флеша, начиная с адреса 0х1000 в ОЗУ
uint32_t * pDst = (uint32_t *)0x10000000;
#define VECTORS_COUNT 128
for(uint_fast8_t i = 0; i < VECTORS_COUNT; ++i)
*pDst++ = *pSrc++;
А теперь смотрите внимательно: 1) Вы в комментариях пишете, что копируете 200 байт, а на самом деле копируете 128*sizeof(uint32_t), т.е. 512 байт.
2) Та часть ОЗУ, куда вы пишете, у вас зарезервирована? Т.е. не получается ли так, что вы копируя разрушаете данные или стек загрузчика?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Sep 24 2012, 15:09
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Almaz1988 @ Sep 24 2012, 11:46) *
Работает только если в "рабочей программе" не используются прерывания. Если прерывания используются, то "Рабоча программа" нивкакую не стартует.
Какие есть догадки, в чем ошибка?

Такая догадка: в рабочей программе происходит очистка памяти, в которой находятся адреса обработчиков прерываний.
Проверьте на входе в main рабочей программы что у вас по адресам ОЗУ 0x10000000-0x100000C0? Заполнена эта область нулями или там адреса обработчиков?
Эту область нужно как-то выделить в скрипте линкера или указать в скрипте область ОЗУ рабочей программы не 0x10000000-0x100001FF, а от 0x100000C0 до 0x100001FFF.

Цитата(Almaz1988 @ Sep 24 2012, 11:46) *
нивкакую не стартует.
Какие есть догадки, в чем ошибка?

Не стартует - это что значит? А что она делает?
В HardFault не попадает?

P.S. Выложили бы проекты целиком - программа это не только текст.
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Sep 28 2012, 06:22
Сообщение #35


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Наметился небольшой прогресс))
В "загрузчике" копирую из флеша ячейки 0х0000-0х0200 в ОЗУ по адресам 0х1000 0000 - 0х1000 0200, делаю ремап и затем прыгаю по адресу Reset_handler(0х1000 0004). "Загрузчик" успешно перезапускается.
Если же я копирую в ОЗУ из адресов флеша 0х2000-0х2200. То после ремапа и прыжка "Рабочая программа", которая залита по адресу 0х2000 не запускается.
В том что у меня залита корректная рабочая программа я могу убедиться если не делая ремапа прыгаю:
Код
    void (*fptr)(void);
    fptr = (void (*)(void))0x000002675;
    fptr();

Тогда рабочая программа запускается.
Прикладываю проекты "Загрузчика" и "Рабочей программы".



Еще один вопрос:
Используемый МК - lpc11c24 с "железным" протоколом CAN. В рабочей программе он используется.
В мануале на МК написано:
Цитата
On-chip
RAM from address 0x1000 0050 to 0x1000 00B8 is used by the CAN API. This address
range should not be used by the application. For applications using the on-chip CAN API,
the linker control file should be modified appropriately to prevent usage of this area for
application’s variable storage.

Выходит, что ремап векторов в ОЗУ будет приводить к затиранию CAN функций?
Значит ремап не решение.
Какие есть другие способы решения проблемы, если и загрузчик и рабочая программа активно будут пользоваться прерываниями?
Прикрепленные файлы
Прикрепленный файл  bootloader.rar ( 197.97 килобайт ) Кол-во скачиваний: 17
 
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 28 2012, 07:15
Сообщение #36


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Almaz1988 @ Sep 28 2012, 10:22) *
Еще один вопрос:
Используемый МК - lpc11c24 с "железным" протоколом CAN. В рабочей программе он используется.
В мануале на МК написано:

Выходит, что ремап векторов в ОЗУ будет приводить к затиранию CAN функций?



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

Если вы используете функции CAN, которые в ПЗУ лежат, то они могут перетереть ваши вектора - т.к. используют эту область памяти под свои данные (сами функции стереть нельзя они в ПЗУ)

В любом случае хранить вектора прерываний в ОЗУ для данного контроллера не очень хорошее решение!
Я уже привел метод - он прекрасно работает! http://electronix.ru/forum/index.php?s=&am...t&p=1095595
Можно использовать метод еще тупее - в бутлоадере создать обработчик на каждое прерывание (для M0 их не так много) который просто берет указатель из таблицы прерываний приложения и переходит по нему. (собственно говоря приведенный исходник это и делает, но что бы не плодить функции он узнает номер из регистра).

При этом приложения с бутлоадером и без бутлоадера отличаются только icf файлом! (началом флеша) и никаких ограничений на использования памяти нет.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 28 2012, 07:56
Сообщение #37


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Almaz1988 @ Sep 28 2012, 09:22) *
и затем прыгаю по адресу Reset_handler(0х1000 0004).
А вот неверно - вы прыгаете на вектор сброса. А надо прыгать на адрес, которых хранится в этом векторе:
CODE
    void (**fptr)(void);
    fptr = (void (**)(void))0x10000004;
    (*fptr)();


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Sep 28 2012, 08:10
Сообщение #38


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Цитата(KRS @ Sep 28 2012, 11:15) *
Если вы используете функции CAN, которые в ПЗУ лежат, то они могут перетереть ваши вектора - т.к. используют эту область памяти под свои данные (сами функции стереть нельзя они в ПЗУ)

В любом случае хранить вектора прерываний в ОЗУ для данного контроллера не очень хорошее решение!
Я уже привел метод - он прекрасно работает! http://electronix.ru/forum/index.php?s=&am...t&p=1095595
Можно использовать метод еще тупее - в бутлоадере создать обработчик на каждое прерывание (для M0 их не так много) который просто берет указатель из таблицы прерываний приложения и переходит по нему. (собственно говоря приведенный исходник это и делает, но что бы не плодить функции он узнает номер из регистра).

При этом приложения с бутлоадером и без бутлоадера отличаются только icf файлом! (началом флеша) и никаких ограничений на использования памяти нет.


Ваш пример подойдет в случае, если в загрузчике не используются прерывания. В моем же случае, я планирую это делать.
Я думаю написать обработчики для каждого прерывания с двумя вариантами выбора:
Код
__ASM void CAN_IRQapplication(void)
{
    ldr r0, =0x2074
    ldr r0, [r0]
    mov pc, r0
}
__ASM void CAN_IRQbootloader(void)
{
    ldr r0, =0x0074
    ldr r0, [r0]
    mov pc, r0
}
void CAN_IRQ(void)
{
              if ( main < 2000 )
              {
                          CAN_IRQapplication();
              }
              else
              {
                          CAN_IRQbootloader();
              }
}

Такое решение приведено в примере NXP secondary bootloader (без варианта выбора). Сейчас пытаюсь вкрутить их стартап-файл (LPCXpresso) в свой Keil-овский проект.


Сработает?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 28 2012, 08:44
Сообщение #39


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Almaz1988 @ Sep 28 2012, 11:10) *
Сработает?
Нет. для этой программы main будет константой, она понятия не имеет, что в другой программе есть свой main и никаким образом не может получить его адрес. Можно взводить и анализировать какой-то флаг.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Sep 28 2012, 09:06
Сообщение #40


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Цитата(Сергей Борщ @ Sep 28 2012, 12:44) *
Нет. для этой программы main будет константой, она понятия не имеет, что в другой программе есть свой main и никаким образом не может получить его адрес. Можно взводить и анализировать какой-то флаг.

Так нам и не нужен main другой программы.
Запускается загрузчик.
Начинает работать.
При прерываниях прыгает в свою табл векторов ( т.к. адрес его функции main < 0x2000).
Закончил работу, передал управление рабочей программе.
Та начинает работу и при прерываниях прыгает по своим адресам ( т.к. адрес его функции main > 0x2000).

что в keil'e, что в LPCXpresso startup-файлы полны загадочных extern и импорт, например:
в Keil:
Цитата
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
LDR R0, =__main
BX R0
ENDP


в LPCXpresso:
Цитата
extern unsigned long _etext;
extern unsigned long _data;
extern unsigned long _edata;
extern unsigned long _bss;
extern unsigned long _ebss;

void ResetISR(void)
{
unsigned char *pulSrc, *pulDest;
pulSrc = (unsigned char *)&_etext;
for(pulDest = (unsigned char *)&_data; pulDest < (unsigned char *)&_edata; )
{
*pulDest++ = *pulSrc++;
}
.........


Откуда в Кейловском варианте берется __main, а в LPC-шном _etext, _data, _edata....?
Их тупо проэкстернили, но они нигде не инициализируются


Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 28 2012, 09:26
Сообщение #41


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Almaz1988 @ Sep 28 2012, 12:06) *
Та начинает работу и при прерываниях прыгает по своим адресам ( т.к. адрес его функции main > 0x2000).
Прыгает в каком месте? В тех функциях, которые принадлежат загрузчику и знают только о существовании своего main. Либо приложению надо переписать эти функции поверх функций загрузчика, тогда зачем в них ветвление?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Sep 28 2012, 09:43
Сообщение #42


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Цитата(Сергей Борщ @ Sep 28 2012, 13:26) *
Прыгает в каком месте? В тех функциях, которые принадлежат загрузчику и знают только о существовании своего main. Либо приложению надо переписать эти функции поверх функций загрузчика, тогда зачем в них ветвление?

В каждый проект(загрузчик и рабочая программа) добавляет один и тот же файл (Handlers.h), в котором написаны обработчики прерываний которые отправляют по адресам 0х0000 - 0х00С0, если они вызваны из загрузчика и по адресам 0х2000 - 0х20С), если они вызваны из рабочей программы. По идее нужно просто переделать стартап файл, чтобы из него при всех прерываниях прыгать в мои самописные обработчики прерываний.
Но он меня пока вводит в тупик - своими экстернами и импортами нигде не объявленных переменных
Go to the top of the page
 
+Quote Post
KRS
сообщение Sep 28 2012, 10:45
Сообщение #43


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Almaz1988 @ Sep 28 2012, 12:10) *
Я думаю написать обработчики для каждого прерывания с двумя вариантами выбора:

там функции на асме не нужны! Проще сразу из С вызвать нужную функцию из таблиц указателей!

тут весь вопрос в условии - как определить что бутлоадер еще работает!

А можно и один код для всех обработчиков оставить - только базовый адрес таблицы вычислять в зависимости от условия

Код
void handler(void)
{
        asm (
             // вычислить адрес таблицы в R1

             "mrs r0,IPSR\n"
             "add r0, r1\n"
             "lsls r0,#2\n"
             "ldr r0,[r0]\n"
             "mov r15, r0");
        while(1);
}

Go to the top of the page
 
+Quote Post
_Артём_
сообщение Sep 28 2012, 18:55
Сообщение #44


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Almaz1988 @ Sep 28 2012, 09:22) *
Используемый МК - lpc11c24 с "железным" протоколом CAN. В рабочей программе он используется.
В мануале на МК написано:

Выходит, что ремап векторов в ОЗУ будет приводить к затиранию CAN функций?
Значит ремап не решение.
Какие есть другие способы решения проблемы, если и загрузчик и рабочая программа активно будут пользоваться прерываниями?

Almaz1988, а в буте CAN используется?
Если не используется, то может можно сделать наоборот:
бут располагается где нибудь в конце памяти, и при старте ремапит вектора в ОЗУ, а основная программа работает с векторами расположенными во flash.
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 1 2012, 11:34
Сообщение #45


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Продолжаю штурм))
и в загрузчике и в рабочей программе будут использоваться прерывания: 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();//иначе обработчик прерывания вызван из загрузчика
}
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 1 2012, 11:36
Сообщение #46


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Продолжаю штурм))
и в загрузчике и в рабочей программе будут использоваться прерывания: 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();//иначе обработчик прерывания вызван из загрузчика
}
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 1 2012, 11:36
Сообщение #47


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Продолжаю штурм))
и в загрузчике и в рабочей программе будут использоваться прерывания: 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();//иначе обработчик прерывания вызван из загрузчика
}
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 1 2012, 11:36
Сообщение #48


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Продолжаю штурм))
и в загрузчике и в рабочей программе будут использоваться прерывания: 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();//иначе обработчик прерывания вызван из загрузчика
}
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 1 2012, 11:38
Сообщение #49


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Продолжаю штурм))
и в загрузчике и в рабочей программе будут использоваться прерывания: 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();//иначе обработчик прерывания вызван из загрузчика
}
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 2 2012, 06:09
Сообщение #50


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Добил бутлоадер)))
В бутлоадере использую только 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;


Как оказалось ничего сложного, если разобраться)))
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 2 2012, 06:31
Сообщение #51


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Almaz1988 @ Oct 2 2012, 09:09) *
Как оказалось ничего сложного, если разобраться)))

Еще чуть-чуть и можно избавиться от тяжелого наследия (ассемблера) совсем:

CODE
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 все же не получилось? wink.gif


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
alx2
сообщение Oct 2 2012, 10:16
Сообщение #52


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Кажется, без ответа остался этот вопрос:
Цитата(Almaz1988 @ Sep 28 2012, 14:06) *
Откуда в Кейловском варианте берется __main, а в LPC-шном _etext, _data, _edata....?
Их тупо проэкстернили, но они нигде не инициализируются

Судя по названиям, символы _etext, _data, _edata и т.п. определены в скрипте линкера и обозначают:
_etext - конец секции .text;
_data - начало секции .data;
_edata - конец секции .data;
_bss - начало секции .bss;
_ebss - конец секции .bss.


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 5 2012, 10:07
Сообщение #53


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Дело близится к завершению))

"Программный загрузчик" при запуске слушает сеть, определяет есть ли устройства которые требуют обновления прошивки. Если таких нет передает управление "Рабочей программе". Если есть, то переводит это устройство в режим аппаратного загрузчика (заводской бутлоадер) и прошивает его.
Дальше по идее нужно перезапустить прошитое устройство. Для этого у аппаратного загрузчика предусмотрена команда "GO". Но, она позволяет прыгать только по адресам кратным 0х10! А Reset_handler у меня находится по адресу, не кратному 0х10. Т.е. сейчас он у меня по адресу 0x01ad. Прыгнуть в него командой аппаратного загрузчика "GO" я смогу, только если он будет по адресу, например, 0x1b0.

Keil позволяет использовать атрибут __attribute__((at(0x10000))) расположения переменных по конкретному адресу, но, к сожалению на функции этот атрибут не распростаняется. Откусывать память в линкере могу только кусками кратными 4 байтам, что не выручает.

Есть ли другой способ "подвинуть" Reset_handler в памяти МК?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Oct 5 2012, 13:23
Сообщение #54


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Almaz1988 @ Oct 5 2012, 13:07) *
"Программный загрузчик" при запуске слушает сеть, определяет есть ли устройства которые требуют обновления прошивки. Если таких нет передает управление "Рабочей программе". Если есть, то переводит это устройство в режим аппаратного загрузчика (заводской бутлоадер) и прошивает его.

Не понимаю, зачем переводить устройство в режим заводского загрузчика, если есть свой?

Цитата(Almaz1988 @ Oct 5 2012, 13:07) *
Дальше по идее нужно перезапустить прошитое устройство. Для этого у аппаратного загрузчика предусмотрена команда "GO". Но, она позволяет прыгать только по адресам кратным 0х10! А Reset_handler у меня находится по адресу, не кратному 0х10. Т.е. сейчас он у меня по адресу 0x01ad. Прыгнуть в него командой аппаратного загрузчика "GO" я смогу, только если он будет по адресу, например, 0x1b0.

Опять же зачем использовать Go и тп. Не проще ли подать буту команду reset и он запустит Reset_Handler по какому надо адресу, не глядя на выравнивание.

Цитата(Almaz1988 @ Oct 5 2012, 13:07) *
А Reset_handler у меня находится по адресу, не кратному 0х10. Т.е. сейчас он у меня по адресу 0x01ad.

Это Reset_Handler бута или приложения?

Цитата(Almaz1988 @ Oct 5 2012, 13:07) *
Keil позволяет использовать атрибут __attribute__((at(0x10000))) расположения переменных по конкретному адресу, но, к сожалению на функции этот атрибут не распростаняется. Откусывать память в линкере могу только кусками кратными 4 байтам, что не выручает.

Раз можно кратными по 4 байта, то можно и кратно 16 байтам откусывуть.
Go to the top of the page
 
+Quote Post
igor_mmm
сообщение Oct 6 2012, 19:07
Сообщение #55





Группа: Новичок
Сообщений: 7
Регистрация: 3-10-12
Пользователь №: 73 792



Добрый День!
Использую 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);

Что нужно добавить?

Go to the top of the page
 
+Quote Post
KRS
сообщение Oct 6 2012, 20:13
Сообщение #56


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(igor_mmm @ Oct 6 2012, 23:07) *
Необходимо организовать выдачу без подтверждения приема. То есть на приемной стороне может отсутствовать приемник.

Если в сети только одно устройство (ACK выставить некому) то передатчик будет отправлять сообщение заново и увеличивать счетчик ошибок (пока не дойдет до ERROR PASSIVE), потом просто будет передавать пока не остановишь принудительно или не появится второе устройство.

Если реально надо выдавать разные фреймы (хотя принимать их все равно не кому) Надо сделать Disable Automatic Retransmission, тогда попытка отправки будет тольо одна! Или надо отменять посылку потом.
Go to the top of the page
 
+Quote Post
igor_mmm
сообщение Oct 7 2012, 07:29
Сообщение #57





Группа: Новичок
Сообщений: 7
Регистрация: 3-10-12
Пользователь №: 73 792



Цитата(KRS @ Oct 7 2012, 00:13) *
Если в сети только одно устройство (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);
   }
}

стало посылать с некой периодичностью.
не понял почему но повторная посылка заработала
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 8 2012, 04:11
Сообщение #58


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Цитата(igor_mmm @ Oct 6 2012, 22:07) *
Добрый День!
Использую 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);

Если подтверждение не требуется
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 8 2012, 06:05
Сообщение #59


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Вопрос по примеру "NXP secondary bootloader" (документ AN10995).
Программный бутлоадер под конец загрузки новой прошивки во флеш в последнюю ячейку флеша записывает контрольную сумму.
В последующем при всяком запуске микронотроллера он вычисляет действительную контрольную сумму флеш-памяти и значение, которое записано в последней ячейке флеша. Если они совпадают, то рабочая программа корректна и программный загрузчик передает управление рабочей программе.
А как быть если рабочая программа заливается не с помощью программного бутлоадера, а программатором с компа. В этом случае контрольная сумма не записывается и программный бутлоадер посчитает, что рабочая программа битая. Как быть?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 8 2012, 06:34
Сообщение #60


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Almaz1988 @ Oct 8 2012, 09:05) *
Как быть?
Посчитать ее при помощи какой-либо внешней утилиты и добавить той же или другой утилитой в прошиваемый программатором файл. Но не совсем красиво хранить контрольную сумму в последней ячейке флеша. По двум причинам:
1) Вне зависимости от реального размера приложения загрузчик вынужден обсчитывать всю флеш, а это время.
2) При очередном обновлении может захотеться добавить эмуляцию eeprom в последнюю страницу флеша, а эта область уже защищена CRC.
Поэтому я делаю так: в первую же ячейку сразу за векторами линкер записывает размер приложения. CRC кладется сразу же следом за приложением. Загрузчик знает, в какой ячейке лежит размер и считает CRC только реально занятой области флеша.
Поскольку у LPC11 перед ремапом вектора копируются и им не обязательно начинаться с адреса, кратного 256 - можно размер хранить перед векторами.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 8 2012, 09:28
Сообщение #61


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Цитата(Сергей Борщ @ Oct 8 2012, 09:34) *
Посчитать ее при помощи какой-либо внешней утилиты и добавить той же или другой утилитой в прошиваемый программатором файл.

Так и сделал, тем более и Keil рекомендует такое решение.

Цитата
Поэтому я делаю так: в первую же ячейку сразу за векторами линкер записывает размер приложения. CRC кладется сразу же следом за приложением.

Как вы это проделываете? Скаттер файл изменяете?

Получается у вас контрольная сумма записывается не в последнюю очередь? Для максимальной надежности механизма логично писать ее в последнюю очередь.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 8 2012, 11:02
Сообщение #62


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Almaz1988 @ Oct 8 2012, 12:28) *
Как вы это проделываете? Скаттер файл изменяете?
Я использую gcc и делаю это через его скрипт линкера. В Кейле, насколько мне известно, такую функцию выполняет скаттер-файл. Значит менять надо его, да.
QUOTE (Almaz1988 @ Oct 8 2012, 12:28) *
Получается у вас контрольная сумма записывается не в последнюю очередь?
Почему вы так решили? В скрипте линкера под контрольную сумму выделается место после кода и данных, после линковки контрольная сумма вписывается в это зарезервированное место сторонней утилитой.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 8 2012, 11:45
Сообщение #63


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



В общем осталась последняя проблема.
Есть функция Х( ). В МАР-файле она расположена по адресам 0х00000175 - 0х00000189.
Когда я прыгаю в ячейку 0х00000175, вызывается эта функция:
Код
    void (*fptr)(void);
    fptr = (void (*)(void))0x00000175;
    fptr();



Копирую эти адреса в оперативку по адресу начиная с 0х10000300. Эта область "откушена" в настройках проекта и она не затирается при работе. Дебагером смотрю - скопирована точь-в-точь и не затирается.
Но когда прыгаю по адресу 0х10000300. Эта функция не вызывается.
Что я не учел?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 8 2012, 11:57
Сообщение #64


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Almaz1988 @ Oct 8 2012, 14:45) *
Что я не учел?
Надо пошагать в отладчике. Версии есть, но излагать их довольно долго (предполагаю, дело в способах адресации внутри функции). Попробуйте поискать в документации ключевое слово ramfunc или похожее на него - оно как раз для этих целей.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
igor_mmm
сообщение Oct 9 2012, 03:21
Сообщение #65





Группа: Новичок
Сообщений: 7
Регистрация: 3-10-12
Пользователь №: 73 792



Цитата(Almaz1988 @ Oct 8 2012, 08:11) *
Вот как выглядит моя функция отправки 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);

Если подтверждение не требуется


а где взять переменную "flagMessageTransmitte" и кто ее выставляет
я так понимаю кто то в прерывании эту переменную выставляет 1
покажите весь пример пожалуйста
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 9 2012, 04:24
Сообщение #66


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Цитата(igor_mmm @ Oct 9 2012, 06:21) *
а где взять переменную "flagMessageTransmitte" и кто ее выставляет
я так понимаю кто то в прерывании эту переменную выставляет 1
покажите весь пример пожалуйста


В прерывании CAN_TX, которое вызывается автоматически всякий раз при успешной отправке сообщения.
В примере устройство каждые 0.5 сек шлет хартбит.
Отправь SDO-запрос: 0х601 40 00 10 00 00 00 00 00, оно откликнется сообщением с ид-ром 0х581.
Отправь любое сообщение с ид-ром меньше - 0х600 загорится светодиод на выводе 2.1
Прикрепленные файлы
Прикрепленный файл  to_forum.rar ( 372.66 килобайт ) Кол-во скачиваний: 10
 
Go to the top of the page
 
+Quote Post
igor_mmm
сообщение Oct 9 2012, 05:53
Сообщение #67





Группа: Новичок
Сообщений: 7
Регистрация: 3-10-12
Пользователь №: 73 792



Цитата(Almaz1988 @ Oct 9 2012, 08:24) *
В прерывании CAN_TX, которое вызывается автоматически всякий раз при успешной отправке сообщения.
В примере устройство каждые 0.5 сек шлет хартбит.
Отправь SDO-запрос: 0х601 40 00 10 00 00 00 00 00, оно откликнется сообщением с ид-ром 0х581.
Отправь любое сообщение с ид-ром меньше - 0х600 загорится светодиод на выводе 2.1

добрый день!
я смотрю пример и вижу , что вы отправляете сообщение через промежутки времени. при "удачной" передаче заходите в прерывание и выставляете флаг - понятно.
Но как быть если передача тыла так сказать неудачная (датчик отвалился) (ведущим так сказать в моем случае будет контроллер lpc ). Он (контроллер) будет пытаться отослать посылку повторно.
Я сделал так перед передачей выставил флаг "DAR" - отключение повторной передачи и выдаю раз в секунду. контроллер зараза первый 16 секунд не выдает (либо выдает но прерывается но пол посылки потому что не видит датчика ) а потом начинает успешно выдавать раз в секунду.
бит DAR - это как я понял отключение повторной передачи. а мне нужно что бы при отсутствии датчика посылка отправилась и только один раз.
== как это сделать я не знаю ===.
в принципе прерывание может возникнуть и при неправильной передаче это можно распознать но как потом отключить передачу (те есть очистить буфер)
Go to the top of the page
 
+Quote Post
Almaz1988
сообщение Oct 9 2012, 08:34
Сообщение #68


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 19-09-12
Пользователь №: 73 602



Цитата(Сергей Борщ @ Oct 8 2012, 14:57) *
Надо пошагать в отладчике. Версии есть, но излагать их довольно долго (предполагаю, дело в способах адресации внутри функции). Попробуйте поискать в документации ключевое слово ramfunc или похожее на него - оно как раз для этих целей.

Разобрался в чем дело: Если копирую функцию из флеша в ОЗУ, она не запускается. Если изначально "говорю" линкеру расположить функцию в ОЗУ она старутет нормально. Видимо дело в использовании абсолютной адресации в ассемблерном коде функций
Go to the top of the page
 
+Quote Post

5 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 01:04
Рейтинг@Mail.ru


Страница сгенерированна за 0.02349 секунд с 7
ELECTRONIX ©2004-2016