Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Запись данных во Flash Sam7s256
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Spoofing
Доброго времени суток.
Помогите решить такую проблему. Не могу разобраться как записать данные во флеш. Функционал - прием данных с USART запись в постоянную память, выдача по требованию. Все прекрасно работает с RAM - данные получаются и выдаются, но естественно сброс по питанию все обнуляет. С помошью SAM-BA залил прошивку, все работает из флеши и выполняется в RAM но как записывать пользовательские данные?
Судя по даташиту необходимо поместить данные в буфер-защелку, после чего запись команд в регистр EFC для операции со страницей №такой то. Где этот буфер определяется? по регистрам не нашел.

Второй вопрос как определить где закончится программа - с какого момента можно будет записать данные (флеш с 0х00100000 без ремапа начинается)
Не бейте сильно в электронике почти полный нуб) пока освоил инициализацию, прерывания и com
singlskv
Цитата(Spoofing @ Jun 21 2009, 21:55) *
Судя по даташиту необходимо поместить данные в буфер-защелку, после чего запись команд в регистр EFC для операции со страницей №такой то. Где этот буфер определяется? по регистрам не нашел.
просто пишите в флеш на те места куда хотели записать,
буфер там кольцевой, поэтому старшие разряды просто обрежет,
ну или обрезайте сами по границе страницы, регистры здесь не задействованны...
Цитата
Второй вопрос как определить где закончится программа - с какого момента можно будет записать данные (флеш с 0х00100000 без ремапа начинается)
Это уже зависит от применяемого компилятора,
нужно редактировать какой-нить файл отвечающий за распределение памяти.
Spoofing
Возможности проверить на железке дома нет. Но вроде бы компилится без ошибок. Есть замечания по коду?
Код
AT91PS_MC     f_pMC     = AT91C_BASE_MC;

int flash_write_page(int* addr, int* data, unsigned int size_data)    
{
    int page;
    unsigned int i = 0, count=0;
    int * Flash;
      
    Flash = (int*)addr;
    page =  ((int)addr >> 8);
  
    for (i=0;(i<size_data)&&(i<255); Flash++,count++,i += 4)  
        {
         *Flash= data[count];
        }
    
    f_pMC->MC_FCR = (0x5a << 24) | (page << 8) | AT91C_MC_FCMD_START_PROG;

    while(!( f_pMC->MC_FSR) & AT91C_MC_FRDY);

    if((f_pMC->MC_FSR & AT91C_MC_LOCKE) || (f_pMC->MC_FSR & AT91C_MC_PROGE))
    {
       return -1;
    }
    return 0;
}

вызов функции
Код
    //Write Flash
    s_pAIC->AIC_IDCR = NU1;
    flash_write_page (data_real,buff_ssc,32);
    s_pAIC->AIC_IECR = iMask;


data_real - начальный адрес области данных (пока фиксированный вручную)
aaarrr
Не забудьте в MC_FMR записать корректные значения.

Цитата(Spoofing @ Jun 23 2009, 19:44) *
Код
    while(!( f_pMC->MC_FSR) & AT91C_MC_FRDY);

    if((f_pMC->MC_FSR & AT91C_MC_LOCKE) || (f_pMC->MC_FSR & AT91C_MC_PROGE))
    {
       return -1;
    }
    return 0;

Здесь потеряете биты ошибок в MC_FSR.

Цитата(Spoofing @ Jun 23 2009, 19:44) *
Код
    while(!( f_pMC->MC_FSR) & AT91C_MC_FRDY);

Здесь скобки стоят неправильно.
Spoofing
Код
p_pMC->MC_FMR = 0x24<<16;
во время начальной инициализации

Цитата
Здесь скобки стоят неправильно.
спасибо, пропустил)

Цитата
Здесь потеряете биты ошибок в MC_FSR.
точно) вот так будет лучше
Код
int temp;
  while(!((temp=f_pMC->MC_FSR) & AT91C_MC_FRDY));
    
    if((temp & AT91C_MC_LOCKE) || (temp & AT91C_MC_PROGE))
    {
       return -1;
    }


По вопросу размещения кода \данных - размещение можно только жестко задать областями или как то динамически? Скорее всего в конце проекта можно будет сказать какого размера код и писать данные дальше, но как то не красиво
aaarrr
Цитата(Spoofing @ Jun 23 2009, 21:40) *
Код
p_pMC->MC_FMR = 0x24<<16;
во время начальной инициализации

Понятно, на 24МГц работаете?

Цитата(Spoofing @ Jun 23 2009, 21:40) *
По вопросу размещения кода \данных - размещение можно только жестко задать областями или как то динамически? Скорее всего в конце проекта можно будет сказать какого размера код и писать данные дальше, но как то не красиво

Обычно можно выпытать у линкера, где кончается программа.
Spoofing
Цитата
Понятно, на 24МГц работаете?

пока на отладочной плате, а потом кварц на 18.462
Spoofing
При прогоне на плате возникли такие проблемы:
Если функцию записи проходить по шагам то все прекрасно, обычном запуске вешается на ожидании
Код
while(!((temp=f_pMC->MC_FSR) & AT91C_MC_FRDY));
бит не устанавливается, при остановке вываливаюсь на строку
Код
PAbt_Handler    B       PAbt_Handler
в SAM.s
В регистре отложенный прерываний висит 01 - fiq хотя я их не использую и перед вызовом функции записи все прерывания запрещены. Хз если бы проблемы были в отсутсвии обработчика то выкидывало бы на
Код
FIQ_Handler     B       FIQ_Handler


Код
#include "board.h"
AT91PS_MC     f_pMC     = AT91C_BASE_MC;
int flash_write_page(int addr, char *data, int size_data)
{
    int i = 0,  page, temp;
    int *Flash, *data_temp;
    Flash = (int*)addr;
    data_temp= (int*) data;
    page = (int)((addr - (int)AT91C_IFLASH)>> 8);

    for (i=0;(i<size_data)&&(i<255); Flash++,data_temp++,i += 4)
        {
        *Flash =*data_temp;
        }
    f_pMC->MC_FCR = (0x5a << 24) | (page << 8) | AT91C_MC_FCMD_START_PROG;
    while(!((temp=f_pMC->MC_FSR) & AT91C_MC_FRDY));
    if((temp & AT91C_MC_LOCKE) || (temp & AT91C_MC_PROGE))
    {
       return -1;
    }
    return 0;
}
aaarrr
Писать флеш можно только выполняя программу из RAM. Т.е. по крайней мере этот кусок -
Код
    f_pMC->MC_FCR = (0x5a << 24) | (page << 8) | AT91C_MC_FCMD_START_PROG;
    while(!((temp=f_pMC->MC_FSR) & AT91C_MC_FRDY));

должен быть в RAM.
Spoofing
Для выполнения функции из RAM достаточно добавить
Код
__ramfunc  int flash_write_page(int addr, char *data, int size_data)
или необходимо еще что то править?
aaarrr
А это смотрите в хелпе на конкретный компилятор. У какого-то древнего IAR'а было так.
Sanya_kv
Не мучийся вот:
CODE
//*----------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name : Flash.c
//* Object : Flash routine
//* Creation : JPP 30/Jun/2004
//* Modif : JPM 16/Nov/2004 Flash write status
//*----------------------------------------------------------------------------

// Include Standard files
#include <hardware.h>
#include <flash.h>

#define false 0
#define true 1

//*----------------------------------------------------------------------------
//* \fn AT91F_Flash_Init
//* \brief Flash init
//*----------------------------------------------------------------------------
void AT91F_Flash_Init (void)
{
//* Set number of Flash Waite sate
// SAM7S64 features Single Cycle Access at Up to 30 MHz
// if MCK = 47923200, 50 Cycles for 1 µseconde ( field MC_FMR->FMCN)
AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(50 <<16)) | AT91C_MC_FWS_1FWS;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_Flash_Ready
//* \brief Wait the flash ready
//*----------------------------------------------------------------------------
__ramfunc int AT91F_Flash_Ready (void)
{
unsigned int status;
status = 0;

//* Wait the end of command
while ((status & AT91C_MC_FRDY) != AT91C_MC_FRDY )
{
status = AT91C_BASE_MC->MC_FSR;
}
return status;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_Flash_Lock_Status
//* \brief Get the Lock bits field status
//*----------------------------------------------------------------------------
__ramfunc int AT91F_Flash_Lock_Status(void)
{
return (AT91C_BASE_MC->MC_FSR & AT91C_MC_FSR_LOCK);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_Flash_Lock
//* \brief Write the lock bit and set at 0 FSR Bit = 1
//* \input page number (0-1023)
//* \output Region
//*----------------------------------------------------------------------------
__ramfunc int AT91F_Flash_Lock (unsigned int Flash_Lock_Page)
{
//* set the Flash controller base address
AT91PS_MC ptMC = AT91C_BASE_MC;

//* write the flash
//* Write the Set Lock Bit command
ptMC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_LOCK | (AT91C_MC_PAGEN & (Flash_Lock_Page << 8) );

//* Wait the end of command
AT91F_Flash_Ready();

return (AT91F_Flash_Lock_Status());
}
//*----------------------------------------------------------------------------
//* \fn AT91F_Flash_Unlock
//* \brief Clear the lock bit and set at 1 FSR bit=0
//* \input page number (0-1023)
//* \output Region
//*----------------------------------------------------------------------------
__ramfunc int AT91F_Flash_Unlock(unsigned int Flash_Lock_Page)
{
//* Write the Clear Lock Bit command
AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_UNLOCK | (AT91C_MC_PAGEN &
(Flash_Lock_Page << 8) );

//* Wait the end of command
AT91F_Flash_Ready();

return (AT91F_Flash_Lock_Status());
}

//*----------------------------------------------------------------------------
//* \fn AT91F_Flash_Check_Erase
//* \brief Check the memory at 0xFF in 32 bits access
//*----------------------------------------------------------------------------
__ramfunc int AT91F_Flash_Check_Erase (unsigned int * start, unsigned int size)
{
unsigned int i;
//* Check if flash is erased
for (i=0; i < (size/4); i++ )
{
if ( start[i] != ERASE_VALUE ) return false;
}
return true;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_Flash_Erase_All
//* \brief Send command erase all flash
//*----------------------------------------------------------------------------
__ramfunc int AT91F_Flash_Erase_All(void)
{
//* set the Flash controller base address
AT91PS_MC ptMC = AT91C_BASE_MC;
//* Write the Erase All command
ptMC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_ERASE_ALL;
//* Wait the end of command
AT91F_Flash_Ready();
//* Check the result
return ( (ptMC->MC_FSR & ( AT91C_MC_PROGE | AT91C_MC_LOCKE ))==0);
}

//*----------------------------------------------------------------------------
//* \fn AT91F_Flash_Write
//* \brief Write in one Flash page located in AT91C_IFLASH, size in 32 bits
//* \input Flash_Address: start at 0x0010 0000 size: in byte
//*----------------------------------------------------------------------------
__ramfunc int AT91F_Flash_Write( unsigned int Flash_Address ,int size ,unsigned int * buff)
{
//* set the Flash controller base address
AT91PS_MC ptMC = AT91C_BASE_MC;
unsigned int i, page, status;
unsigned int * Flash;
//* init flash pointer
Flash = (unsigned int *) Flash_Address;
//* Get the Flash page number
page = ((Flash_Address - (unsigned int)AT91C_IFLASH ) /FLASH_PAGE_SIZE_BYTE);
//* copy the new value
for (i=0; (i < FLASH_PAGE_SIZE_BYTE) & (size > 0);i++, Flash++,buff++,size-=4 ){
//* copy the flash to the write buffer ensuring code generation
*Flash=*buff;
}
//* Write the write page command
ptMC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG | (AT91C_MC_PAGEN & (page <<8));
//* Wait the end of command
status = AT91F_Flash_Ready();
//* Check the result
if ( (status & ( AT91C_MC_PROGE | AT91C_MC_LOCKE ))!=0) return false;
return true;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_Flash_Write
//* \brief Write in one Flash page located in AT91C_IFLASH, size in byte
//* \input Start address (base=AT91C_IFLASH) size (in byte ) and buff address
//*----------------------------------------------------------------------------
__ramfunc int AT91F_Flash_Write_all( unsigned int Flash_Address ,int size ,unsigned int * buff)
{

int next, status;
unsigned int dest;
unsigned int * src;

dest = Flash_Address;
src = buff;
status = true;

while( (status == true) & (size > 0) )
{
//* Check the size
if (size <= FLASH_PAGE_SIZE_BYTE) next = size;
else next = FLASH_PAGE_SIZE_BYTE;

//* Unlock current sector base address - current address by sector size
AT91F_Flash_Unlock((dest - (unsigned int)AT91C_IFLASH ) /FLASH_PAGE_SIZE_BYTE);

//* Write page and get status
status = AT91F_Flash_Write( dest ,next ,src);
// * get next page param
size -= next;
src += FLASH_PAGE_SIZE_BYTE/4;
dest += FLASH_PAGE_SIZE_BYTE;
}
return status;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_NVM_Status
//* \brief Get the NVM field status
//*----------------------------------------------------------------------------
__ramfunc int AT91F_NVM_Status(void)
{
return (AT91C_BASE_MC->MC_FSR & AT91C_MC_FSR_MVM);
}

//*----------------------------------------------------------------------------
//* \fn AT91F_NVM_Set
//* \brief Write the Non Volatile Memory Bits and set at 0 FSR Bit = 1
//*----------------------------------------------------------------------------
__ramfunc int AT91F_NVM_Set (unsigned char NVM_Number)
{
//* set the Flash controller base address
AT91PS_MC ptMC = AT91C_BASE_MC;

//* write the flash
//* Write the Set NVM Bit command
ptMC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_SET_GP_NVM | (AT91C_MC_PAGEN & (NVM_Number << 8)
);

//* Wait the end of command
AT91F_Flash_Ready();
return (AT91F_NVM_Status());
}
//*----------------------------------------------------------------------------
//* \fn AT91F_NVM_Clear
//* \brief Clear the Non Volatile Memory Bits and set at 1 FSR bit=0
//*----------------------------------------------------------------------------
__ramfunc int AT91F_NVM_Clear(unsigned char NVM_Number)
{
//* set the Flash controller base address
AT91PS_MC ptMC = AT91C_BASE_MC;

//* write the flash
//* Write the Clear NVM Bit command
ptMC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_CLR_GP_NVM | (AT91C_MC_PAGEN & (NVM_Number << 8)
);

//* Wait the end of command
AT91F_Flash_Ready();

return (AT91F_NVM_Status());
}

//*----------------------------------------------------------------------------
//* \fn AT91F_SET_Security_Status
//* \brief Get Flash Security Bit Status
//*----------------------------------------------------------------------------
int AT91F_SET_Security_Status (void)
{
return (AT91C_BASE_MC->MC_FSR & AT91C_MC_SECURITY);
}

//*----------------------------------------------------------------------------
//* \fn AT91F_SET_Security
//* \brief Set Flash Security Bit
//*----------------------------------------------------------------------------
int AT91F_SET_Security (void)
{
//* write the flash
//* Write the Set Security Bit command
AT91C_BASE_MC->MC_FCR = ( AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_SET_SECURITY );

//* Wait the end of command
AT91F_Flash_Ready();

return (AT91F_SET_Security_Status());
}


//*----------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name : Flash.h
//* Object : Flash constan description
//* Creation : JPP 30/Jun/2004
//*
//*----------------------------------------------------------------------------

#ifndef Flash_h
#define Flash_h

/*-------------------------------*/
/* Flash Status Field Definition */
/*-------------------------------*/

#define AT91C_MC_FSR_MVM ((unsigned int) 0xFF << 8) // (MC) Status Register GPNVMx: General-purpose NVM
Bit Status
#define AT91C_MC_FSR_LOCK ((unsigned int) 0xFFFF << 16) // (MC) Status Register LOCKSx: Lock Region x
Lock Status

#define ERASE_VALUE 0xFFFFFFFF

/*-----------------------*/
/* Flash size Definition */
/*-----------------------*/
/* 64 Kbytes of Internal High-speed Flash, Organized in 512 Pages of 128 Bytes */

#define FLASH_PAGE_SIZE_BYTE 256
#define FLASH_PAGE_SIZE_LONG 32

#define FLASH_LOCK_BITS_SECTOR 16
#define FLASH_SECTOR_PAGE 32
#define FLASH_LOCK_BITS 16 /* 16 lock bits, each protecting 16 sectors of 32 pages*/
#define FLASH_BASE_ADDRESS 0x00100000
/*------------------------------*/
/* External function Definition */
/*------------------------------*/

/* Flash function */
extern void AT91F_Flash_Init(void);
extern int AT91F_Flash_Check_Erase(unsigned int * start, unsigned int size);
extern int AT91F_Flash_Erase_All(void);
extern int AT91F_Flash_Write( unsigned int Flash_Address ,int size ,unsigned int * buff);
extern int AT91F_Flash_Write_all( unsigned int Flash_Address ,int size ,unsigned int * buff);

/* Lock Bits functions */
extern int AT91F_Flash_Lock_Status(void);
extern int AT91F_Flash_Lock (unsigned int Flash_Lock);
extern int AT91F_Flash_Unlock(unsigned int Flash_Lock);

/* NVM bits functions */
extern int AT91F_NVM_Status(void);
extern int AT91F_NVM_Set (unsigned char NVM_Number);
extern int AT91F_NVM_Clear(unsigned char NVM_Number);

/* Security bit function */
extern int AT91F_SET_Security_Status (void);
extern int AT91F_SET_Security (void);

#endif /* Flash_h */
aaarrr
Цитата(Sanya_kv @ Jun 24 2009, 22:04) *
Не мучийся вот:

Да-да, и думать тоже не надо sad.gif
Сергей Борщ
Цитата(Sanya_kv @ Jun 24 2009, 21:04) *
Не мучийся вот:
krapula.gif А самому сравнить, сколько этот "писанный левой ногой" код отъедает ОЗУ по сравнению с кодом, приведенном aaarrr в сообщении №9? Тут не мучаться, тут прослезиться нужно.
Spoofing
А смысл от этого монумента если большая часть не нужна?) Лучше сделать подпрограмму записи команды и ожидания флага и вызывать его из функции записи.
Sanya_kv
Цитата(aaarrr @ Jun 24 2009, 22:14) *
Да-да, и думать тоже не надо sad.gif

Не разделяю, да ты и сам это понимаешь.

Цитата(Сергей Борщ @ Jun 24 2009, 22:46) *
krapula.gif А самому сравнить, сколько этот "писанный левой ногой" код отъедает ОЗУ по сравнению с кодом, приведенном aaarrr в сообщении №9? Тут не мучаться, тут прослезиться нужно.

Внимательней посмотри. Было бы пользы больше, если б ошибки искал в исподниках а не комментариях.

Цитата(Spoofing @ Jun 25 2009, 00:04) *
А смысл от этого монумента если большая часть не нужна?) Лучше сделать подпрограмму записи команды и ожидания флага и вызывать его из функции записи.

Конечно не нужна, каждый использует по потребностям. Если тебе нужно только писать, то скопируй 2-3 функции:
Код
AT91F_Flash_Init;
AT91F_Flash_Ready;
AT91F_Flash_Write;

И поменяй константы в соответствии со своим АРМом.
А то что визуальный объем большой, так это из-за комментариев, для Вашего же удобства.
Использую от сюда функции. Вполне доволен. Врятли кому-либо удастся написать компактней, а если учитывать, что это все от производителя, думаю не скривлю, если добавлю что лучше.
Цитата
Причина редактирования: Нарушение п.3.4 Правил форума.
Спасибо, учту в будущем.
Сергей Борщ
Цитата(Sanya_kv @ Jun 25 2009, 11:09) *
Внимательней посмотри. Было бы пользы больше, если б ошибки искал в исподниках а не комментариях.
Смотрел. Каждая функция этого кода размещается в ОЗУ. Прибита туда гвоздями ключевым словом __ramfunc. В то время как небходимо и достатночно иметь в ОЗУ один-единственный кусочек кода из сообщения №9. Один на все функции. Это 7 ARM-команд. Является такое вольное расходование ОЗУ ошибкой или "писанием левой ногой" - не берусь судить, скорее всего первое вытекающее из второго.
Цитата(Sanya_kv @ Jun 25 2009, 11:09) *
Конечно не нужна, каждый использует по потребностям. Если тебе нужно только писать, то скопируй 2-3 функции:
Вообще-то это забота линкера - подцепить к выходному файлу только используемые функции.
Цитата(Sanya_kv @ Jun 25 2009, 11:09) *
Врятли кому-либо удастся написать компактней, а если учитывать, что это все от производителя, думаю не скривлю, если добавлю что лучше.
Это классический пример "индийского" кода. Написано по принципу "работает - и ладно". Авторитет производителя скорее страдает от таких примеров.
Код
at91_flash.h:
#ifndef AT91_FLASH_H__
#define AT91_FLASH_H__
#include    <stdint.h>
#include    <ioAT91SAM77S64.h>

#define MCK_CYCLES          ((15ULL * MCK + 5000000) / 10000000)
#define FLASH_WAITSTATES    MCK_CYCLES < 30000000ULL ? AT91C_MC_FWS_0FWS : AT91C_MC_FWS_1FWS

inline void 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) | (FLASH_WAITSTATES) | (MCK_CYCLES * AT91C_MC_FMCN / 0xFF));
}

inline void 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) | (FLASH_WAITSTATES) | (MCK_CYCLES * AT91C_MC_FMCN / 0xFF));
}

inline void RewritePage(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) | (FLASH_WAITSTATES) | (MCK_CYCLES * AT91C_MC_FMCN / 0xFF));
}
#endif  // AT91_FLASH_H__

at91_flash.c:
__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)
{
    uint32_t Status = __get_CPSR();
    do
    {
        __set_CPSR(Status | (1 << CPSR_IRQ_EN));    // disable IRQ
    }
    while(! (__get_CPSR() & (1 << CPSR_IRQ_EN)));
    
    AT91C_BASE_MC->MC_FMR = mode;
    FlashCommand_RAM(command);
    __set_CPSR(Status);             // restore IRQ
}
Sanya_kv
Вы абсолютно правы, хочу лишь немного Вас поправить.
Цитата(Сергей Борщ)
Смотрел. Каждая функция этого кода размещается в ОЗУ. Прибита туда гвоздями ключевым словом __ramfunc. В то время как небходимо и достатночно иметь в ОЗУ один-единственный кусочек кода из сообщения №9. Один на все функции. Это 7 ARM-команд. Является такое вольное расходование ОЗУ ошибкой или "писанием левой ногой" - не берусь судить, скорее всего первое вытекающее из второго.
Привильно. Но я с помощью этих функций обновляю прошивку. Ваш вариант для этого не подходит.
Цитата
Вообще-то это забота линкера - подцепить к выходному файлу только используемые функции.
"Захламление" кода делает его менее читаемым. Хотя это на любителя, о вкусах не спорят.

Спасибо за тептые слова блогодарности smile.gif .
Цитата(Сергей Борщ)
"писанный левой ногой"

Цитата(Сергей Борщ)
"Это классический пример "индийского" кода. Написано по принципу "работает - и ладно". Авторитет производителя скорее страдает от таких примеров."


Обидно лишь то, что свой вариант Вы не показали ранее sad.gif , в этом случае я со своим примером даже и не высовывался.
Сергей Борщ
Цитата(Sanya_kv @ Jun 25 2009, 13:32) *
Но я с помощью этих функций обновляю прошивку. Ваш вариант для этого не подходит.
Хм. А как же мне это удается? Что, по-вашему, мешает ему обновлять прошивку?
Цитата(Sanya_kv @ Jun 25 2009, 13:32) *
"Захламление" кода делает его менее читаемым.
Частично согласен. Но в этом случае мы можем считать этот файл "библиотекой".
Цитата(Sanya_kv @ Jun 25 2009, 13:32) *
Обидно лишь то, что свой вариант Вы не показали ранее sad.gif
Я уже выкладывал его здесь в разных вариациях: 1, 2, 3.
Sanya_kv
Цитата(Сергей Борщ @ Jun 25 2009, 16:42) *
Хм. А как же мне это удается? Что, по-вашему, мешает ему обновлять прошивку?

Имел в виду обновление всей Flash памяти. Скорей всего моя вина, нужно было попроще объяснить.
Цитата(Сергей Борщ)
Я уже выкладывал его здесь в разных вариациях: 1, 2, 3.

Считал, что наши рассуждения актуальны в данной ветви, ссылки на исходники в ней ранее я не нашел.
Но, во сём есть плюсы. Думаю Spoofing получил исчерпывающие ответы.
Spoofing
Спасибо всем за развернутые листинги. Использую Keil 3.72 - иаровскому __ramfunc соотвествует __ram. Но при попытке использования транслятор начал либо ругаться на тип функции (int) как на no storadge если ставить перед функцией, либо не находил ее тело если после. В итоге пришлось прибегать к Scatter
Код
  FLASH_LOAD 0x100000
  {
  EXE +0 0x40000
    {
    *.o (RESET, +FIRST)
    * (+RO)
    }
  DATA 0x200000 0x7fff
    {
    * (+RW +ZI)
    }
  ISR_EXE 0x208000 0x2000
    {
    flash.o (+RO)
    }
  }
aaarrr
ИМХО, лучше функцию записи обрамить:
Код
#pragma arm section CODE = "CODE_RAM"
...
#pragma arm section CODE

А в scatter'е написать:
Код
FLASH_LOAD 0x100000
  {
  EXE +0 0x40000
    {
    *.o (RESET, +FIRST)
    * (+RO)
    }
  DATA 0x200000 0x8000
    {
    * (+RW +ZI)
    }
  ISR_EXE 0x208000 0x2000
    {
    * (CODE_RAM)
    }
  }
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.