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

 
 
> Пишу AT91SAM7A3 UART bootloader, есть проблемы и вопросы :)
Aaron
сообщение Aug 24 2011, 12:02
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



Доброго времени суток. Так сложилось, что до сих пор я ни разу не работал с загрузчиками - хватало разъёма JTAG. Но времена меняются, - надо делать загрузчик для своих железок (под UART). Естественно, под gcc (раз уж я начал его изучать) - бутлоадер выступает в роли подопытного кролика wink.gif
Накопал кучу бутлоадеров, выбрал наиболее понравившийся - USB-бутлоадер, и на его основе начал параллельно изучать gcc и особенности работы с flash памятью.
Внёс в проект кучу своего "мусора", в частности из проекта at91sam7a3-getting-started с сайта Atmel взял startup код. Как-то из разных мест ещё интересные моменты подглядывал-вставлял, разобрался с makefile и в итоге сейчас проект выглядит вот так: Прикрепленный файл  AT91_Bootloader.7z ( 233.2 килобайт ) Кол-во скачиваний: 102

Файлы компилируются, проект собирается - но я ничего не вижу ни в терминале, ни в осциллографе (контролирую ножку LED, которая на PA20 находится) - при включении порт встаёт в "1" и ничего не делает. Отладчиком в eclipse ещё не учился пользоваться, чую скоро придётся засесть изучать wink.gif Для прошивки использую MT-Link, при работе через консоль j-link показывает, что PC крутится в районе адресов 0x0 - 0x300, после jtag-reset выдаёт сообщение:
Цитата
WARNING: PC of target system has unexpected value of 0x0000023C after reset.

Адрес в warning тоже постоянно меняется в этом же диапазоне.
Чую себя новичком sm.gif Прошиваю at91sam7a3-getting-started - всё работает, прошиваю свой проект - ничего не работает sm.gif Кто поможет разобраться? Исходники рабочего бутлоадера (если и когда он появится) обязательно выложу.

Что происходит (в теории)?
1. инициализируем стеки прерываний (flash-reset.s: Reset_Handler)
2. инициализируем раздел bss (flash-reset.s: _init_data, _init_bss)
3. переходим в наш сишный код бутлоадера (bootrom.c: Bootrom)
4. обрабатываем пакеты, пишем во флэш.

Я так понимаю, что затык идёт на 2м этапе скорее всего, чую - перемудрил с секциями. Поэтому кто решится помочь - в первую очередь прошу поглядеть, как я объявил секции (AT91-Bootloader\bootrom\prj\ldscript-flash.lds)!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Aaron
сообщение Feb 13 2012, 10:32
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



Потихоньку доделываю проект, интересные вещи узнал. Сейчас застрял на таком моменте: передаю данные для записи во флэш (одну страницу), отрабатываю запись, а дальше код зависает. Перезапускаюсь, считываю участок памяти, который записывал - записалось то, что я хотел. Вопрос - почему зависает код? Если моё понимание кода ошибочно в комментариях, прошу поправить.
Код
#define BL_DATA_UINT32_LENGTH    64
typedef struct {
    unsigned int        cmd;    // основная команда (служебное слово)
    unsigned int        param;    // дополнительные параметры команды
    unsigned int        addr;    // адрес страницы памяти
    union {
        uint8_t     asBytes[BL_DATA_UINT32_LENGTH*4];
        unsigned int    asDwords[BL_DATA_UINT32_LENGTH];
    } data;                // данные для записи в страницу памяти
    unsigned int    crc;    // контрольная сумма
} BootloaderPacket;

BootloaderPacket inPckt;
volatile AT91PS_MC mc = AT91C_BASE_MC;
volatile uint32_t *p;
...
p = (volatile uint32_t *)(inPckt.addr);
// при записи по адресу памяти FLASH данные записываются сначала в буфер записи памяти, и писать
// в него надо по 32 бита за 1 раз! поэтому используем asDwords
printf("Setup data to write @ flash addr 0x%08X:", inPckt.addr);
for (i = 0; i < BL_DATA_UINT32_LENGTH; i++) {
    p[i] = inPckt.data.asDwords[i];
    printf(" 0x%04X", inPckt.data.asDwords[i]);
};
printf("\r\n");
interrupt_mask = *AT91C_AIC_IMR;    // сохраняем набор включенных прерываний
*AT91C_AIC_IDCR = AT91C_ALL_INT;    // выключаем все прерывания
// буфер для записи в память уже заполнился, и можно писать страницу FLASH памяти
mc->MC_FCR = AT91C_MC_WRITE_KEY | AT91C_MC_FCMD_START_PROG | AT91C_MC_PAGEN(inPckt.addr/AT91C_IFLASH_PAGE_SIZE);
while (0 == (mc->MC_FSR & AT91C_MC_EOP)) {};        // ждём когда взведётся статус EndOfProgramming
// FIXME: запись происходит, но до сюда код не доходит, зависает в цикле

*AT91C_AIC_IECR = interrupt_mask;   // восстанавливаем прерывания
printf("\r\nWrote page #%04u at address 0x%08X.\r\n", inPckt.addr/AT91C_IFLASH_PAGE_SIZE, inPckt.addr);
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 13 2012, 10:46
Сообщение #3


Гуру
******

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



QUOTE (Aaron @ Feb 13 2012, 12:32) *
CODE
mc->MC_FCR = AT91C_MC_WRITE_KEY | AT91C_MC_FCMD_START_PROG | AT91C_MC_PAGEN(inPckt.addr/AT91C_IFLASH_PAGE_SIZE);
while (0 == (mc->MC_FSR & AT91C_MC_EOP)) {};        // ждём когда взведётся статус EndOfProgramming

Этот участок кода должен выполняться из ОЗУ. Флешка блокируется на время записи и читать из нее команды проц не может.

CODE
class flash_t
{
public:
    INLINE static void clear_buffer();
    INLINE static void fill(uint32_t const *addr, uint32_t data) { *(uint32_t *)addr = data; }
    INLINE static void fill(uint32_t const *dst, uint32_t const *src, uint32_t size);
    INLINE static uint32_t read(uint32_t const *addr) { return *addr; }
    INLINE static void read(uint32_t *dst, uint32_t const *src, uint32_t size);
    INLINE static void erase(void const *page_addr);
    INLINE static void program(void const *page_addr);

    static uint32_t const PAGE_SIZE = 128;
private:
    static void command(uint32_t command, uint32_t mode);
    NOINLINE static void command_RAM(uint32_t command) __attribute__((section(".ramfunc")));
    
    static uint32_t const MCK_CYCLES = ((15ULL * MCK + 5000000ULL) / 10000000ULL);
public:
    static uint32_t const FLASH_WAITSTATES = MCK < 30000000ULL ? AT91C_MC_FWS_0FWS : AT91C_MC_FWS_1FWS;
} static Flash __attribute__((__unused__));


void flash_t::erase(void const *page_addr)
{
    command( ((AT91C_MC_KEY / 0xFFU) * 0x5A) | (((uint32_t)page_addr >> 7) << 8) | AT91C_MC_FCMD_START_PROG,
                (0 * AT91C_MC_FRDY) | (0 * AT91C_MC_LOCKE) | ( 0 * AT91C_MC_PROGE) |
                (0 * AT91C_MC_NEBP) | (FLASH_WAITSTATES) | (AT91C_MC_FMCN / 0xFFU * MCK_CYCLES)
           );
}

void flash_t::program(void const *page_addr)
{
    command( ((AT91C_MC_KEY / 0xFFU) * 0x5A) | (((uint32_t)page_addr >> 7) << 8) | AT91C_MC_FCMD_START_PROG,
                (0 * AT91C_MC_FRDY) | (0 * AT91C_MC_LOCKE) | ( 0 * AT91C_MC_PROGE) |
                (1 * AT91C_MC_NEBP) | (FLASH_WAITSTATES) | (AT91C_MC_FMCN / 0xFFU * MCK_CYCLES)
           );
}

void flash_t::command_RAM(uint32_t command)
{
    AT91C_BASE_MC->MC_FCR = command;
    while(!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY))
       ;
}

void flash_t::command(uint32_t command, uint32_t mode)
{
    TCritSect cs;
    AT91C_BASE_MC->MC_FMR = mode;
    command_RAM(command);
}

CODE
  /* .data section which is used for initialized data */
  .data : /* place init values immediatly after .text section */
  {
    _data = .;
    *(.ramfunc*)
    
    *(.data*)

    _edata = .;
    _data_image = LOADADDR(.data);

    PROVIDE (edata = .);
  } > RAM  AT > ROM


--------------------
На любой вопрос даю любой ответ
"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



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

 


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


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