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

 
 
> bootloader, возникает исключительная ситуация
dimka76
сообщение Jul 21 2009, 08:37
Сообщение #1


developer
****

Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032



Пишу bootloader.
Контроллер AT91SAM7S64.
Компилятор IAR.
Вот код самой процедуры самопрограммирования

Код
void flash_init (void)
{
    *AT91C_MC_FMR = ((AT91C_MC_FMCN)&(72 <<16)) | AT91C_MC_FWS_1FWS;
}


void flash_write(unsigned int page, unsigned int* flash_buf)
{
    unsigned int* flash;
    unsigned int i;

        *AT91C_MC_FCR = (0x5A<<24) | (page<<8 & AT91C_MC_PAGEN) | AT91C_MC_FCMD_UNLOCK;    //Unlock Region
        while((*AT91C_MC_FSR & AT91C_MC_FRDY) != AT91C_MC_FRDY );

    flash = (unsigned int *) 0x00100000 + 4*page*FLASH_PAGE_SIZE_WORDS;
    
    for(i=0; i < FLASH_PAGE_SIZE_WORDS; i++) flash[i] = flash_buf[i];
    __disable_interrupt();
    *AT91C_MC_FCR = (0x5A<<24) | (page<<8 & AT91C_MC_PAGEN) | AT91C_MC_FCMD_START_PROG; // | (1 << 8); //0x5A000001; //
    while((*AT91C_MC_FSR & AT91C_MC_FRDY) == 0);
        while((*AT91C_MC_FSR & AT91C_MC_FRDY) != AT91C_MC_FRDY );
        __enable_interrupt();
}


Где-то внутри функции flash_write(...) вылетает в Prefetch Abort.
Точное место определить не могу, т.е. при использовании JTAG и прохождении программы по шагам все работает нормально.


Подскажите пожалуйста в чем может быть причина.


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Сергей Борщ
сообщение Jul 21 2009, 09:11
Сообщение #2


Гуру
******

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



Цитата
Код
        *AT91C_MC_FCR = (0x5A<<24) | (page<<8 & AT91C_MC_PAGEN) | AT91C_MC_FCMD_UNLOCK;    //Unlock Region
        while((*AT91C_MC_FSR & AT91C_MC_FRDY) != AT91C_MC_FRDY );
При записи в MC_FCR и ожидании MC_FRDY код должен исполняться из ОЗУ:
Код
flash.h:
#ifndef FLASH_H__
#define FLASH_H__
#include <at91SAM7s64.h>

#define    MCK_CYCLES ((15ULL * MCK + 5000000) / 10000000)
#if MCK > 30000000
#define WAITSTATES  AT91C_MC_FWS_1FWS
#else
#define WAITSTATES  AT91C_MC_FWS_0FWS
#endif

extern __arm void FlashCommand(uint32_t command, uint32_t mode);
inline void Flash_ErasePage(uint32_t const *addr)
{
    FlashCommand( (0x5AULL *  AT91C_MC_KEY / 0xFF) | (((uint32_t)addr >> 7) << 8) | AT91C_MC_FCMD_START_PROG,
                (0 * AT91C_MC_FRDY) | (0 * AT91C_MC_LOCKE) | ( 0 * AT91C_MC_PROGE) |
                (0 * AT91C_MC_NEBP) | (WAITSTATES) | (MCK_CYCLES * AT91C_MC_FMCN / 0xFF));
}
inline void Flash_ProgramPage(uint32_t const *addr)
{
    FlashCommand( (0x5AULL *  AT91C_MC_KEY / 0xFF) | (((uint32_t)addr >> 7) << 8) | AT91C_MC_FCMD_START_PROG,
                (0 * AT91C_MC_FRDY) | (0 * AT91C_MC_LOCKE) | ( 0 * AT91C_MC_PROGE) |
                (1 * AT91C_MC_NEBP) | (WAITSTATES) | (MCK_CYCLES * AT91C_MC_FMCN / 0xFF));
}
#endif  // FLASH_H__

flash.cpp:
#include <at91SAM7s64.h>
#include "Flash.h"
__ramfunc __arm void FlashCommand_RAM(uint32_t command)
{
    AT91C_BASE_MC->MC_FCR = command;
    while(!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
}

__arm void FlashCommand(uint32_t command, uint32_t mode)
{
    __disable_interrupt();
    AT91C_BASE_MC->MC_FMR = mode;
    FlashCommand_RAM(command);
    __enable_interrupt();
}


--------------------
На любой вопрос даю любой ответ
"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
dimka76
сообщение Jul 21 2009, 09:33
Сообщение #3


developer
****

Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032



Цитата(Сергей Борщ @ Jul 21 2009, 13:11) *
При записи в MC_FCR и ожидании MC_FRDY код должен исполняться из ОЗУ


Спасибо. Помогло.

А обязательно в режиме ARM ?
Нельзя ли в режиме THUMB ?


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 21 2009, 10:12
Сообщение #4


Гуру
******

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



Цитата(dimka76 @ Jul 21 2009, 12:33) *
А обязательно в режиме ARM ?
Нельзя ли в режиме THUMB ?
Можно, но в ARM этот код получается короче.


--------------------
На любой вопрос даю любой ответ
"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
dimka76
сообщение Jul 21 2009, 10:18
Сообщение #5


developer
****

Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032



Цитата(Сергей Борщ @ Jul 21 2009, 14:12) *
Можно, но в ARM этот код получается короче.


какой ЭТОТ ?

У меня в THUMB режиме почти в два раза меньше код во FLASH, в RAM такой же.
я не стал использовать ваш код просто учел ваши рекомендации в своем.

И еще вопросик.

откуда эта формула?
Код
#define    MCK_CYCLES ((15ULL * MCK + 5000000) / 10000000)


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 21 2009, 11:22
Сообщение #6


Гуру
******

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



Цитата(dimka76 @ Jul 21 2009, 13:18) *
какой ЭТОТ ?
Код
    __disable_interrupt();

    __enable_interrupt();
Из THUMB нет доступа к регистру CPSR, поэтому для разрешения/запрещения прерываний придется переключаться в ARM. А между ними - опять в THUMB. Делая код чуть длинее за счет ARM-команд экономим место и время на выкидывании переключения в THUMB между ними. Мне так казалось. Давно это писалось.
Цитата(dimka76 @ Jul 21 2009, 13:18) *
откуда эта формула?
Код
#define    MCK_CYCLES ((15ULL * MCK + 5000000) / 10000000)
Из головы. Количество тактов в полутора микросекундах с округлением.
И наверное красивее было бы заменить
Код
#if MCK > 30000000
#define WAITSTATES  AT91C_MC_FWS_1FWS
#else
#define WAITSTATES  AT91C_MC_FWS_0FWS
#endif
на
Код
#define WAITSTATES  ((MCK) > 30000000 ? AT91C_MC_FWS_1FWS : AT91C_MC_FWS_0FWS)


--------------------
На любой вопрос даю любой ответ
"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 Текстовая версия Сейчас: 23rd July 2025 - 21:49
Рейтинг@Mail.ru


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