Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: bootloader
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
dimka76
Пишу 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 и прохождении программы по шагам все работает нормально.


Подскажите пожалуйста в чем может быть причина.
Сергей Борщ
Цитата
Код
        *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();
}
dimka76
Цитата(Сергей Борщ @ Jul 21 2009, 13:11) *
При записи в MC_FCR и ожидании MC_FRDY код должен исполняться из ОЗУ


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

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


какой ЭТОТ ?

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

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

откуда эта формула?
Код
#define    MCK_CYCLES ((15ULL * MCK + 5000000) / 10000000)
Сергей Борщ
Цитата(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)
dimka76
Цитата(Сергей Борщ @ Jul 21 2009, 15:22) *
Код
    __disable_interrupt();

    __enable_interrupt();
Из THUMB нет доступа к регистру CPSR, поэтому для разрешения/запрещения прерываний придется переключаться в ARM. А между ними - опять в THUMB.


Я то подумал, что речь идет обо всей программе.
А это же лишь небольшой процент от всей программы.
А я имел весь бутлоадер в тумбе делать. А в указанном вами фрагменте пусть себе переключается. Потеря в объеме программы несущественная.
А вот если весь бутлоадер делать в АРМ режиме, то и размер почти в два раза возрастает. А это на мой взгляд расточительство для бутлоадера. Проигрыш в производительности значения не имеет.

Цитата
Количество тактов в полутора микросекундах с округлением.


почему в полуторах, ведь в datasheet написано

Цитата
FMCN:Flash Microsecond Cycle Number
This field defines the number of Master Clock cycles in 1 microsecond.


В одной микросекунде получается.
Dron_Gus
• FMCN: Flash Microsecond Cycle Number
Before writing Non Volatile Memory bits (Lock bits, General Purpose NVM bit and Security bits), this field must be set to the
number of Master Clock cycles in one microsecond.
When writing the rest of the Flash, this field defines the number of Master Clock cycles in 1.5 microseconds. This number
must be rounded up.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.