Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Некорректная работа загрузчика
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
AlfaStar
Всем привет!

Камень: AT91SAM7S256

Проблема в следующем: написал загрузчик, который принимает bin файл и записывает его во флеш по нужному адресу ( к примеру 0x00108000). После записи выполняется прыжок на начальный адрес записи. Соответственно у программы которую я записываю через этот загрузчик я подправляю линкер, что бы функция main записывалась на нужный адрес (к примеру на 0x00108000). Перед прыжком включаю/отключаю подтягивающий резисор - все как надо. Если записывать программы работающие только с ЮЗБ (к примеру программа, которая по нажатию кнопки выводит слово hallo в терминал) то никаких проблем нет, все работает как надо. Но если записывать программу, работающую не только с ЮЗБ, но и с флешем (например считывает и записывает что то во флеш память), то прыжка никакого не происходит. Вместо этого загрузчик начинает свою программу загрузки заново ( выводит меню интерфейса, которое появляется в самом начале при запуске загрузчика). Мои подозрения падают на функцию, которая используется в записываемой программе(хотя я могу и ошибаться):
Код
extern unsigned int edata,etext,__bss_start,__bss_end__,_data;
void copy_rom_ram(void)
{
    unsigned int* p_rom, *p_ram;
    //--------------------
    p_rom=&etext;
    p_ram=(unsigned int*)0x200000;
    while(p_ram<&edata)
    {
        *p_ram=*p_rom;
        p_ram++;
        p_rom++;
    }
    //---------------------------
    p_ram=&__bss_start;
    while(p_ram<&__bss_end__)
    {
        *p_ram=0;
        p_ram++;
    }
}

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

P.S. Для написание загрузчика использовал стандартный IAR проект.
AlfaStar
Ну неужели никто не встречался с такой проблемой? Загрузчик после записи просто сбрасывается на начало, то есть как будто ничего и не записал. Тут дело именно в загрузчике, ибо программы, которые я прошиваю им, на других загрузчиках работают нормально!
aaarrr
Цитата(AlfaStar @ Apr 12 2011, 19:08) *
Тут дело именно в загрузчике, ибо программы, которые я прошиваю им, на других загрузчиках работают нормально!

Если дело в загрузчике, то опишите, как передается управление. Не забываете ли переключить режим процессора, сбросить контроллер прерываний, нет ли конфликта при повторной инициализации PLL и т.п. Много нюансов присутствует.
AlfaStar
Скорее всего дело именно в загрузчике. После записи принятой программы во флеш у меня выполняется прыжок

((void (*)(void))(0x108001))();

Соответственно в ликере программы, которую я записываю я ставлю:
Код
...

MEMORY
{
  FLASH (r) : ORIGIN = 0x00108000, LENGTH = 0x00038000
  DATA (rw)  : ORIGIN = 0x00200000, LENGTH = 0x00010000
  STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000
}


/* Section Definitions */

SECTIONS
{
  /* first section is .text which is used for code */
  . = 0x0000000;

  .text :
  {
    *(.start)
    *(.text)                   /* remaining code */

    *(.glue_7t) *(.glue_7)

  } /*>FLASH

  . = ALIGN(4);

  /* .rodata section which is used for read-only data (constants) */

  .rodata :
  {
    *(.rodata)
  } >FLASH

  . = ALIGN(4);

  _etext = .;
  PROVIDE (etext = .);

...


А в самой программе функцию main изменяю и сразу выполняю функцию copy_rom_ram, которая описана выше дабы потом использовать флеш память:
Код
int __attribute__ ((section (".start"))) main ( void )
{

    copy_rom_ram();


Именно использование этой функции и вызывает подозрения. Не работает именно тогда когда я ее добавляю. Но как я понимаю без нее никуда, с флешем если работать, то она нужна...
aaarrr
Цитата(AlfaStar @ Apr 12 2011, 21:27) *
Именно использование этой функции и вызывает подозрения. Не работает именно тогда когда я ее добавляю. Но как я понимаю без нее никуда, с флешем если работать, то она нужна...

Я не понимаю зачем вообще нужна эта функция. Почему нельзя воспользоваться средствами линкера для размещения нужных процедур в RAM?
AlfaStar
Загрузчик записывает принятую программу во флеш полностью (программа принимается по протоколу Ymodem). Затем выполняется прыжок. Получается что линкер тут не поможет и нам самим надо вручную (то есть такой функцией) прописывать перенос функций в RAM.
aaarrr
А "принятую программу" не линкер собирает что ли? Чем она принципиально отличается от того же загрузчика, кроме адреса?
AlfaStar
Сам загрузчик я записываю SAM-BA. Я тут не совсем понимаю конечно, но думаю что Самба сама выполняет запись функций в RAM. Линкер же просто обозначает что и по какому адресу должно лежать. Если при записи Самбой она сама помещает нужные функции в RAM, то когда загрузчик принимает файл bin он просто его записывает во флеш и ничего более. Ну по крайней мере, программа с функциями записи и чтения флеш памяти, при ее загрузке САмбой работает как надо... Если же эту программу прошить загрузчиком (ну с соответствующими изменениями в линкере), то ничего не работает. Андебаг (мигание светодиодом) показал что программа виснет именно на функции copy_rom_ram. Если ее просто исключить, то программа вообще не работает.
aaarrr
Цитата(AlfaStar @ Apr 13 2011, 18:23) *
Сам загрузчик я записываю SAM-BA. Я тут не совсем понимаю конечно, но думаю что Самба сама выполняет запись функций в RAM. Линкер же просто обозначает что и по какому адресу должно лежать.

Нет. Вот тут нужно достичь полного понимания путем изучения документации. Копированием функций и данных в RAM занимаются процедуры библиотечного стартапа в соответствии с созданными линкером таблицами. SAM-BA ничем в данном случае не отличается от вашего загрузчика.
В скрипте линкера, который вы привели, нет ни малейшего намека на выделение той памяти, которую в дальнейшем использует copy_rom_ram. Последняя в результате просто портит задействованную уже подо что-то память.
AlfaStar
Для полного понимая, привожу полный код линкера программы, которую я записываю с помощью загрузчика:
Код
MEMORY
{
  FLASH (r) : ORIGIN = 0x00108000, LENGTH = 0x00038000
  DATA (rw)  : ORIGIN = 0x00200000, LENGTH = 0x00010000
  STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000
}


/* Section Definitions */

SECTIONS
{
  /* first section is .text which is used for code */
  . = 0x0000000;
  /*.text : { *Cstartup.o (.text) }>FLASH =0*/
  .text :
  {
    *(.start)
    *(.text)                   /* remaining code */

    *(.glue_7t) *(.glue_7)

  } /*>FLASH

  . = ALIGN(4);

  /* .rodata section which is used for read-only data (constants) */

  .rodata :
  {
    *(.rodata)
  } >FLASH

  . = ALIGN(4);

  _etext = .;
  PROVIDE (etext = .);


    /* .data section which is used for initialized data */

  .data : AT (_etext)
  {
    _data = .;
    *(.data)
    SORT(CONSTRUCTORS)
    *(.ramfunc)
  } >DATA
  . = ALIGN(4);

  _edata = .;
   PROVIDE (edata = .);

    
  /* .bss section which is used for uninitialized data */

  .bss :
  {
    __bss_start = .;
    __bss_start__ = .;
    *(.bss)
    *(COMMON)
  }
  . = ALIGN(4);
  __bss_end__ = .;
  __bss_end__ = .;
  _end = .;
  PROVIDE (end = .);

    . = ALIGN(4);
   .int_data :  
   {
   *(.internal_ram_top)
   }> STACK

  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }
  

}


Дело в том что старт-ап в загружаемой программе я удалил, объясняя это тем, что вся инициализация железа прошла когда еще САм-ба прописывала загрузчик. А в загрузчике тоже присутствуют функции записи во флеш.
aaarrr
Цитата(AlfaStar @ Apr 13 2011, 19:09) *
Дело в том что старт-ап в загружаемой программе я удалил, объясняя это тем, что вся инициализация железа прошла когда еще САм-ба прописывала загрузчик. А в загрузчике тоже присутствуют функции записи во флеш.

Проще было бы убрать из него инициализацию железа, чем потом брать на себя его функции (которые помимо копирования включают инициализацию стандартного ввода-вывода, кучи и т.п).
В самой функции copy_rom_ram никакого криминала нет, все зависит от входных значений и их соответствию реальной жизни. Загоните свою программу в симулятор.
AlfaStar
Попробую поэкспериментировать со Стартапом. Посмотрим, что получиться...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.