Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: работа с внутренней флэш
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Annuta
Привет! У меня плата на AT91SAM7x256 - первый раз в жизни пытаюсь работать с внутреней флэш ... 07.gif
вот пишу что-то в память
Код
__ramfunc u32 EFC_WritePage(u32 adr, u32 *pbuf)
{
    unsigned int *pflash;
    unsigned int page;
    unsigned int region;
    unsigned int i;
  
  pflash = (unsigned int *)adr;
  page = (0x00310000)/EFC_PAGE_SIZE;
  region = (page/EFC_PagesInTheLockRegion);

  EFC_Init();

    if (AT91C_BASE_MC->MC_FSR & (region << 16)) {
    // lock set, clear it
    AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(50 <<16)) | AT91C_MC_FWS_2FWS;
    AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (region << 8 ) |AT91C_MC_FCMD_UNLOCK;
    }
    while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
    
    for (i = 0; i < EFC_PAGE_SIZE_UINT; i++)
    *(pflash + i ) = *(pbuf + i);
    
    AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (page << 8 ) |AT91C_MC_FCMD_START_PROG;
    while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));

  return 1;
}


__ramfunc void EFCWrite(u32 adr, u8 *pbuf, u32 Len, u32 NeedReset)
{
    u32 l;
    l=0;
    while (l<Len) {
    EFC_WritePage(adr, (u32*)&(pbuf[l]));
    l+=EFC_PAGE_SIZE;
    adr+=EFC_PAGE_SIZE;
    }
}


и кусочек xcl файла

Код
//*************************************************************************
// Read-only segments mapped to Flash 256K.
//*************************************************************************
-DROMSTART=00000040
-DROMEND=00030000
//*************************************************************************
// Read/write segments mapped to RAM.
//*************************************************************************
-DRAMSTART=00200000
-DRAMEND=0020FFFF

При попытке что-то записать из памяти стирается прошивка... то стириется то ли затирается - не мгу понять!... Хотя адреса не перекрещеваются... Не понимаю... ЧЕМ это вызвано! smile3046.gif ... и в xcl написано
"Read-Only" ...это значит что я могу только читать -- что надо прописать чтоб можно было и писать ?
Спасибо!
Timofey
Цитата(Annuta @ Jul 6 2007, 17:16) *


По собственному опыту не советую использовать внутреннюю флэш. При записи очень часто возникал глюк: страница стирается, а записывать не записывается. При проверке выяснилось что бит готовности не всегда вставал в положение "флэш занята". Лучше всего использовать внешнюю spi-ную например.

А по теме: что передаете в эту функцию EFCWrite(u32 adr, u8 *pbuf, u32 Len, u32 NeedReset)? Чему равна переменная EFC_PAGE_SIZE?
IV_K
в xcl из области ROM исключите страницы, которые пользуете при сохранении данных, чтоб линкер программу туда не пихал, скорее всего затираете нужный кусок кода, а так с внктренней влеш в самах вроде все нормально, я ни разу с глюками не сталкивался..
при записи запретите все прерывания! то что в комментах в xcl написано это ерунда.. страницы можно писать
Timofey
Цитата(IV_K @ Jul 6 2007, 22:04) *
в xcl из области ROM исключите страницы, которые пользуете при сохранении данных, чтоб линкер программу туда не пихал, скорее всего затираете нужный кусок кода, а так с внктренней влеш в самах вроде все нормально, я ни разу с глюками не сталкивался..
при записи запретите все прерывания! то что в комментах в xcl написано это ерунда.. страницы можно писать


Увы, но факт, есть факт. Когда устройство лежало у меня на столе, у меня тоже все было впорядке. Ни единого глюка. Но когда спустили десять таких устройств в шахту. Там то они и появились. Хотя дело выбора smile.gif . А так я тоже брал эту программу с форума этого. Зная конечный размер программы, я в xcl файле (как вы и советуете) ограничилч объем памяти (хотя было видно и без ограничения, что линкер туда программу не пихал, но это не важно). Потом долго разбирался: на столе нормально, в шахте - глюк. Пока с ноутом не залез в шахту, не подключился и не увидел лично.
Annuta
Моя переменная
#define EFC_PAGE_SIZE 128
Я просто не совсем может правильно чего понимаю, народ ? Но у меня ж никак не должна затираться прошивка данными...
При попытке поменять в xcl файле адреса на такие /скопировала в аналогичной проге/
Код
//*************************************************************************
// Read-only segments mapped to Flash 256K.
//*************************************************************************
-DROMSTART=00000000
-DROMEND=0003FFFF
//*************************************************************************
// Read/write segments mapped to 64K RAM.
//*************************************************************************
-DRAMSTART=00000000
-DRAMEND=0000FFFF

получаю ошибку...
Fatal Error[e72]: Segment SVC_STACK must be defined in a segment definition option (-Z,
-b or -P)

Чего он ругается !????
AlexBoy
Цитата(Annuta @ Jul 9 2007, 08:27) *
Моя переменная
#define EFC_PAGE_SIZE 128

Странно, у меня другой размер страницы именно для X256.
#define AT91C_IFLASH_PAGE_SIZE ((unsigned int) 256)
учтите что вы пишете по 4 байта, так что делите еще на 4.

А функция записи страницы такая:
Код
// Write in one Flash page located in AT91C_IFLASH
BOOL AT91F_Flash_Write(int page, DWORD *buff)
  {
    unsigned int i;
    DWORD *flash;

    // init flash pointer
    flash = (DWORD *)AT91C_IFLASH;

    // copy the new value
    i = (AT91C_IFLASH_PAGE_SIZE>>2);
    do { *flash++ = *buff++; } while(--i);
    // Write the write page command
    AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG | (AT91C_MC_PAGEN & (page << 8));
    // Wait the end of command
    AT91F_Flash_Ready();
    // Check the result
    if ((AT91C_BASE_MC->MC_FSR & (AT91C_MC_PROGE | AT91C_MC_LOCKE)) != 0) return FALSE;
    return TRUE;
  }
Dron_Gus
Цитата(Annuta @ Jul 9 2007, 09:27) *
Код
//*************************************************************************
// Read-only segments mapped to Flash 256K.
//*************************************************************************
-DROMSTART=00000000
-DROMEND=0003FFFF
//*************************************************************************
// Read/write segments mapped to 64K RAM.
//*************************************************************************
-DRAMSTART=00000000
-DRAMEND=0000FFFF

получаю ошибку...
Fatal Error[e72]: Segment SVC_STACK must be defined in a segment definition option (-Z,
-b or -P)

Чего он ругается !????


Ругается т.к. Вы ему РАМ урезали до 64 Кб. А стек обычно лежит в конце РАМы, а теперь там неопределенная память... Надеюсь понятно выразил. smile.gif



Вот кусов моего бутлоадера под at91sam7x256 может поможет



Код
/*
********************************************************************************
*************************
*                                               AT91_PageWrite
********************************************************************************
*************************
*                         Writers len page to flash
*                           Addr - start sector num
*                           pBuff - data to write
*                           len - page count to write
*                         Return:
*                           >0 - bytes flashed
*                           -1 - outside flash adr.
********************************************************************************
*************************
*/

__ramfunc int AT91_PageWrite(unsigned int Addr, const char *pBuff, unsigned int len)
  {
  unsigned int *pSource;
  unsigned int *pDest;
  unsigned int i;
  unsigned int Page;

  pSource = (unsigned int*) pBuff;
  pDest = (unsigned int*) (AT91C_IFLASH_PAGE_SIZE * Addr + AT91C_IFLASH);
  Page = Addr;
  while (Page < Addr + len)
    {
    i = 0;
    while (i < AT91C_IFLASH_PAGE_SIZE)
      {
      *pDest = *pSource;
      pDest++;
      pSource++;
      i += 4;
      }
    AT91C_BASE_MC->MC_FCR |= AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG | ((Page << 8) & AT91C_MC_PAGEN);
    while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
    Page++;
    }
  return (len * AT91C_IFLASH_PAGE_SIZE);
  }




/*
********************************************************************************
*************************
*                                     flash init
********************************************************************************
*************************
*/

void AT91_FlashInit()
  {
  AT91C_BASE_MC->MC_FMR = (((MCK*2/1000000)<< 16) & AT91C_MC_FMCN) | AT91C_MC_FWS_1FWS;
  AT91C_BASE_MC->MC_FMR = ((100 <<16)&(AT91C_MC_FMCN)) | AT91C_MC_FWS_1FWS;
  while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
  }




Тут главное правильно проинициализировать регистры MC, особенно задержки.
Timofey
Цитата(Annuta @ Jul 9 2007, 11:27) *
Моя переменная
#define EFC_PAGE_SIZE 128

Размер страницы что у SAM7X128 что у SAM7X256 равен 256 байт (согласно даташиту)
Цитата(Annuta @ Jul 9 2007, 11:27) *
При попытке поменять в xcl файле адреса на такие /скопировала в аналогичной проге/

верните прежние значения, просто смотрите куда вы пишете, то есть какой начальный адрес вы передаете в функцию void EFCWrite(u32 adr, u8 *pbuf, u32 Len, u32 NeedReset)
Если вы передадите туда допустим адрес 0х00001000 а размер программы у вас более 4 кб, то собственно все что свыше этих 4 кб будет затерто вашими данными ... Поэтому просто ограничиваете размер флэшки в xlc файле (как тут советовали) и пишете в ту область. Допустим пишете тут
-DROMSTART=00000000
-DROMEND=0002FFFF
(размер программы при этом не может быть более 196607 байт)
и уже в функцию записи передаете адрес 00030000.
И еще: вместо page = (0x00310000)/EFC_PAGE_SIZE;
напишите page = (adr & 0x3FFFF)/EFC_PAGE_SIZE;
Annuta
Спасибо!! Вроде пишет - не могу провериить -- так как не работает чтение .... wacko.gif
вот функция
Код
__ramfunc u32 EFC_ReadPage(u32 adr, u32 *pbuf)
{
    unsigned int *pflash = (unsigned int *)(adr & 0x00000040);
    unsigned int i;
    
    EFC_Init();
    
    for (i = 0; i < EFC_PAGE_SIZE_UINT; i++)
    *(pbuf + i) = *(pflash + i );
    
    return 1;
}

// вот массив пусто!
помогите уж до конца разобраться...
Timofey
Код
__ramfunc u32 EFC_ReadPage(u32 adr, u32 *pbuf)
{
    unsigned int *pflash = (unsigned int *) adr;
    unsigned int i;
    
    EFC_Init();
    
    for (i = 0; i < EFC_PAGE_SIZE_UINT; i++)
    *(pbuf + i) = *(pflash + i );
    
    return 1;
}

в переменную adr передавайте тот же начальный адрес который указывали для записи.
Annuta
Происходят странные вещи!.. моя прога на этой строке сбрасывается... перегружается...
AT91C_BASE_MC->MC_FCR = (0x5A << 24) | AT91C_MC_FCMD_ERASE_ALL;
Это я пытаюсь сделть очистку....
как правильно - очистку сделать!... стереть стр?
и ещё где можно скачать - самы простой - работающий проект для работы с внутренней флэш... демку какую-нить... ?
Timofey
Цитата(Annuta @ Jul 11 2007, 17:37) *
Происходят странные вещи!.. моя прога на этой строке сбрасывается... перегружается...
AT91C_BASE_MC->MC_FCR = (0x5A << 24) | AT91C_MC_FCMD_ERASE_ALL;
Это я пытаюсь сделть очистку....
как правильно - очистку сделать!... стереть стр?

Это вы указываете стереть ВСЮ флэш память!!
"Запускает процесс стирания всей реализованной на кристалле области флэш-памяти. Если защищена хотя бы одна страница с помощью бита защиты, то эта команда выполнена не будет."
Если вы используете программу взятую с форума, то там есть строка в программе
Код
AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (page << 8 ) | AT91C_MC_FCMD_START_PROG;

вот она собственно и записывает
"Команда программирования страницы (WP):
Запускает процесс программирования одной страницы, номер которой указан в поле PAGEN."
Цитата(Annuta @ Jul 11 2007, 17:37) *
и ещё где можно скачать - самы простой - работающий проект для работы с внутренней флэш... демку какую-нить... ?

Программа, которую выложили вначале, вполне работоспособная. Я для SAM7S64 пишу нормально. И считываю данные тоже. Просто сделайте все заново, учитывая коментарии.
Annuta
вот написала по вашему совету прогу сначала. Эх... ну не работает!. crying.gif .. Не пинайте ногами если - что упускаю... програмимирую первый раз в жизни микроконтроллер!...
вот мой код
Код
#include <os_cpu.h>
#define TestAddr 0x0030000
#define EFC_PAGE_SIZE 256
#define EFC_PAGE_COUNT 256
#define EFC_PagesInTheLockRegion 32
#define EFC_PAGE_SIZE_UINT (EFC_PAGE_SIZE/4) //
#define u32 unsigned long
#define u8 unsigned char
#define DWORD unsigned long

__ramfunc void EFC_Init(void)
{
    while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
    AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(100 <<16)) | AT91C_MC_FWS_1FWS;
    while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
}

__ramfunc u32 EFC_WritePage(u32 adr, u32 *pbuf)
{
      unsigned int *pflash;
      unsigned int page;
      unsigned int region;
      unsigned int i;
    
        pflash = (unsigned int *)adr;
        page = (adr & 0x3FFFF)/EFC_PAGE_SIZE;
        region = (page/EFC_PagesInTheLockRegion);
    
    EFC_Init();
    
    if (AT91C_BASE_MC->MC_FSR & (region << 16)) {
    // lock set, clear it
    AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(50 <<16)) | AT91C_MC_FWS_2FWS;
    AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (region << 8 ) |AT91C_MC_FCMD_UNLOCK;
    }
    while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
    
    for (i = 0; i < EFC_PAGE_SIZE_UINT; i++)
    *(pflash + i ) = *(pbuf + i);
    
    AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (page << 8 ) |AT91C_MC_FCMD_START_PROG;
    while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));

return 1;
}

__ramfunc void EFCWrite(u32 adr, u8 *pbuf, u32 Len, u32 NeedReset)
{
u32 l;
  if (NeedReset) {
     l=0;
  }
     l=0;
while (l<Len) {
    EFC_WritePage(adr, (u32*)&(pbuf[l]));
    l+=EFC_PAGE_SIZE;
    adr+=EFC_PAGE_SIZE;
}
  if (NeedReset) {
      __asm("sub r0, r0,r0;");
      __asm("bx r0;");
  }
}

__ramfunc u32 EFC_ReadPage(u32 adr, u32 *pbuf)
{
unsigned int *pflash = (unsigned int *)adr;
unsigned int i;

EFC_Init();

for (i = 0; i < EFC_PAGE_SIZE_UINT; i++)
*(pbuf + i) = *(pflash + i );

return 1;
}

void TestEFC(void)
{
  unsigned int buf1[8192/4];
  int i;
  unsigned int *pbuf3=(unsigned int *)TestAddr;
  
  //AT91C_BASE_MC->MC_FCR = (0x5A << 24) | AT91C_MC_FCMD_ERASE_ALL;
  //while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
  
    for(i=0;i<8192/4;i++)
        buf1[i]=i+9;
    
  OS_CPU_SR  cpu_sr = 0;
  OS_ENTER_CRITICAL(); //Запретили прерывания
       EFCWrite( TestAddr ,(u8*)buf1,8192,0);
  OS_EXIT_CRITICAL();  //Разрешили прерывания
    
    for( i=0;i<8192/4;i++)
     if (buf1[i]!=pbuf3[i])
         buf1[i]=0;
}


вот прога делает такой финт ушами... как только я вызываю функцию записи в основном цикле
LED_On(2);
TestEFC();
LED_On(3);
Она зажигает второй лед, потом плата перегружается... !... все огоньки гаснут /как будто жму кнопочку на плате ресет/ ...и она снова работает... только сначала!... Третий лед не зажигается...
Dron_Gus
Какой у Вас MCK?
Далее EFC_WritePage: зачем Вы вызываете EFC_Init() и тут же по-новой настраиваете MC другими значениями. При этом учтите:
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.
Для флеша должно быть в 1.5 раза больше. Проще выразить это через MCK чем использовать прямое значение.
Сергей Борщ
Цитата(Annuta @ Jul 12 2007, 13:51) *
Она зажигает второй лед, потом плата перегружается... !... все огоньки гаснут /как будто жму кнопочку на плате ресет/ ...и она снова работает... только сначала!... Третий лед не зажигается...
Я извиняюсь, три вопроса -
1) у вас Watchdog Timer остановлен? Если нет, возможно как раз в этот момент истекает его тайм-аут.
2) вы пользуетесь внутрисхемным отладчиком? Если да, то можно пошагово дойти до точки "падения" и узнать какое именно действие вызывает перезагрузку.
3)У вас стоят "заглушки" на исключениях Prefetch Abort, DataAbort, Undefined Instruction? Если нет - поставьте пустые циклы с какой-то индикацией, уже будет больше информации.
Dron_Gus
Отладчик в таких ситуациях может только мешать. Советую попробовать без него.
Annuta
Спасибо, Dron_Gus!... да именно из-за этого плата и перегружалась... Теперь не перегружаеься... но и не работает.... sad.gif
Код
__ramfunc int EFCWrite(u32 adr, u8 *pbuf, u32 Len, u32 NeedReset)
{
    u32 l;
    unsigned int *pflash;
    unsigned int page;
    unsigned int region;
    unsigned int i;  

    l=0;    
    while (l<Len)
    {    
          pflash = (unsigned int *)adr;
          page = (adr & 0x3FFFF)/EFC_PAGE_SIZE;
          region = (page/EFC_PagesInTheLockRegion);      
      
      if (AT91C_BASE_MC->MC_FSR & (region << 16))
      {
          // lock set, clear it
          AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(50 <<16)) | AT91C_MC_FWS_2FWS;
          AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (region << 8 ) |AT91C_MC_FCMD_UNLOCK;
      }
      while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
      
      for (i = 0; i < EFC_PAGE_SIZE_UINT; i++)
           *(pflash + i ) = *(pbuf + i);      
      
      AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (page << 8 ) |AT91C_MC_FCMD_START_PROG;
      while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
      
        l+=EFC_PAGE_SIZE;
        adr+=EFC_PAGE_SIZE;
    }
    
    if (NeedReset)
    {
      __asm("sub r0, r0,r0;");
      __asm("bx r0;");
    }
    
    return (Len * AT91C_IFLASH_PAGE_SIZE);
}

вот - делаю как... Прошивка доходит до волшебной строчки
AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (page << 8 ) |AT91C_MC_FCMD_START_PROG;
... и всё... дальше... тормоз!... Возвращает "0" .. естевтсвенно...
AlexBoy
Цитата(Annuta @ Jul 12 2007, 16:33) *
вот - делаю как... Прошивка доходит до волшебной строчки
AT91C_BASE_MC->MC_FCR = (0x5A << 24) | (page << 8 ) |AT91C_MC_FCMD_START_PROG;
... и всё... дальше... тормоз!... Возвращает "0" .. естевтсвенно...


в это фрагменте ошибочка, pbuf у вас объявлен как "u8 *pbuf" соответственно читается по 1 байту а пишется по 4. pbuf должен быть "unsigned int *" или заведите локальную переменную и сделайте преобразование к этому типу.
Код
for (i = 0; i < EFC_PAGE_SIZE_UINT; i++)
           *(pflash + i ) = *(pbuf + i);
Timofey
В функцию EFCWrite(); передается адрес 0x0030000 - область ОЗУ после ремапа, причем получается 196 608 байт, хотя у этого контроллера 64 кб ОЗУхи

или я не прав?
AlexBoy
Цитата(Timofey @ Jul 12 2007, 21:21) *
В функцию EFCWrite(); передается адрес 0x0030000 - область ОЗУ после ремапа, причем получается 196 608 байт, хотя у этого контроллера 64 кб ОЗУхи

или я не прав?

прав на 100%
#define TestAddr 0x0030000
при вызове EFCWrite(adr, pbuf, Len, NeedReset) adr должен показывать на адрес внутри флеша
#define AT91C_IFLASH ((char *)0x00100000) // Internal FLASH base address
#define AT91C_IFLASH_SIZE ((unsigned int) 0x00040000) // Internal FLASH size in byte (256 Kbytes)
причем не на начало, чтобы не стереть программу, можно так:
Код
#define TestAddr (AT91C_IFLASH+AT91C_IFLASH_SIZE-sizeof(buf1))


To Annuta: Полезно иногда заглядывать в файл AT91SAM7X256.h, там все константы описаны, чтоб не делать таких ошибок с размещением.
Timofey
Цитата(AlexBoy @ Jul 13 2007, 15:27) *
To Annuta: Полезно иногда заглядывать в файл AT91SAM7X256.h, там все константы описаны, чтоб не делать таких ошибок с размещением.
Она просто учится smile.gif Про ремап я просто забыл сообщить smile.gif
Annuta
Получилось!!! Спасибо БОЛЬШОЕ всем за помощь!!! smile.gif
Waso
Мне в AT91 нужно менять только одно слово во флеше. Обязательно ли для этого читать всю страницу, содержащую слово, менять его и записывать всю страницу обратно? Или можно канибудь проще? Мне не ради простоты а ради удлинения срока службы флеша... (реализую файловую систему. файлы будут больше читаться, писАться - редко, но тем не менее...)
Сергей Борщ
Цитата(Waso @ Oct 24 2007, 14:00) *
Мне в AT91 нужно менять только одно слово во флеше. Обязательно ли для этого читать всю страницу, содержащую слово, менять его и записывать всю страницу обратно?
Если менять с единиц на нолики - не обязательно. Если с ноликов на единицы - да, обязательно. Причем не обязательно читать-менять-писать. Достаточно прочитать и записать в теневой буфер всю страницу, а потом сверху в буфер дописать изменяемые данные:
Код
    volatile uint32_t* pTmp = (uint32_t*)((uint32_t)&Config_flash & ~0x7F);
    uint32_t* pSegmentEnd = (uint32_t*)(((uint32_t)&Config_flash & ~0x7F) + 128);
    while(pTmp < pSegmentEnd) // copy to shadow buffer
    {
        uint32_t Data = *pTmp;
        *pTmp++ = Data;
    }
    uint32_t *pSrc = (uint32_t*)&TmpConfig;
    uint32_t *pDst = (uint32_t*)&Config_flash;
    while(pDst < (uint32_t*)((config_t*)&Config_flash + 1))
    {
        *pDst++ = *pSrc++;
    }

    Flash::RewritePage((uint32_t const*)&Config_flash);
_dem
сколько же у вас памяти жрет проект, если вы пишете на CPP ?
Сергей Борщ
Цитата(_dem @ Oct 24 2007, 15:20) *
сколько же у вас памяти жрет проект, если вы пишете на CPP ?
Примерно столько же. А удобства неравненно больше. Обсуждалось неоднократно, хотя бы тут.
Waso
2 Сергей Борщ. Смысл понятен, но реализация в примере темновата.
Цитата(Сергей Борщ @ Oct 24 2007, 19:02) *
[code] volatile uint32_t* pTmp = (uint32_t*)((uint32_t)&Config_flash & ~0x7F);
uint32_t* pSegmentEnd = (uint32_t*)(((uint32_t)&Config_flash & ~0x7F) + 128);
while(pTmp < pSegmentEnd) // copy to shadow buffer
{
uint32_t Data = *pTmp;
*pTmp++ = Data;
}
Разве ~0x7F не равно 0x80 ? Каков смысл такой записи как у Вас?
Тело цикла while тоже кажется избыточным моему неопытному глазу: Сначала присваиваем переменной Data то, на что указывает pTmp, затем, если я правильно понимаю работу постинкремента, сначала присваиваем тому на что указывает pTmp значение Data и после этого увеличиваем сам адрес указателя. Зачем кидать туда-сюда значение *pTmp ?? wacko.gif
Сергей Борщ
Цитата(Waso @ Oct 25 2007, 06:14) *
Разве ~0x7F не равно 0x80 ? Каков смысл такой записи как у Вас?
Нет, не равно. ~0x7F для ARM равно 0xFFFFFF80. Вот и вы попались. Вообще-то совсем правильно было бы ~0x7FULL, тогда такая запись обнуляла бы 5 младших бит в любой целочисленной переменной. Но я пока не выработал в себе такую привычку, наверное пора начинать.
Цитата(Waso @ Oct 25 2007, 06:14) *
Зачем кидать туда-сюда значение *pTmp ?
Tmp объявлен как volatile *. Без временной переменной получили бы warning компилятора о непредсказуемом порядке доступа к volatile (IAR выдает его всегда, если в выражении встречается более одной volatile-переменной). Без volatile компилятор имел бы полное право выкинуть весь цикл.
Angle
У меня такая проблема не могу записать во внутреннюю флэш.
Контроллер AT91SAM7A3, компилятор Keil.
В настройках проекта Оptions->Target ограничил размер ROM с 0x40000 до 0x30000

Кусок кода
Код
void EFC_Init(void)
{ unsigned long clkus;
    
// Calculate Flash Microsecond Cycle Number - Approximate (no Library Code)
//clkus = (1074*(clk >> 10)) >> 20;            // Master Clock Cycles in 1.0us
  clkus = (1611*(MCK >> 10)) >> 20;            // Master Clock Cycles in 1.5us
   // Set Flash Microsecond Cycle Number
  // Set Flash Waite State to max. (Single Cycle Access at Up to 30 MHz)
  AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN) & (clkus << 16)) | AT91C_MC_FWS_3FWS;
  AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
}


int EFC_WritePage(DWORD adr, DWORD *pbuf)
{
  
    unsigned int *pflash;
    unsigned int page;
    unsigned int i;  

            
pflash = (unsigned int *)adr;
page = (adr - 0x00100000)/AT91C_IFLASH_PAGE_SIZE;
          
AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_UNLOCK |AT91C_MC_PAGEN & (page << 8));
// Wait until the end of Command
while ((AT91C_BASE_MC->MC_FSR & AT91C_MC_EOL) != AT91C_MC_EOL);

for (i = 0; i <AT91C_IFLASH_PAGE_SIZE/4; i++)   *(pflash + i ) = *(pbuf + i);      

AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG |(AT91C_MC_PAGEN & (page << 8));

  // Wait until the end of Command
  while ((AT91C_BASE_MC->MC_FSR & AT91C_MC_EOP) != AT91C_MC_EOP);

// Check for Errors
  if (AT91C_BASE_MC->MC_FSR & (AT91C_MC_PROGE | AT91C_MC_LOCKE)) return (1);
  return (0);
    }

#define TestAddr AT91C_IFLASH+AT91C_IFLASH_SIZE-AT91C_IFLASH_PAGE_SIZE
BYTE TestEFC(void)
{
DWORD buf1[256];
  int i;
  BYTE result;
  for(i=1;i<=63;i++) buf1[i]=i;
  EFC_Init();  
  result=(BYTE)EFC_WritePage((DWORD)TestAddr,(DWORD*)buf1);
  return     result;
}

Прогамма зависает после выполнения строки кода
Код
while ((AT91C_BASE_MC->MC_FSR & AT91C_MC_EOL) != AT91C_MC_EOL);

В чем может быть причина ?
Сергей Борщ
Цитата(Angle @ Nov 21 2007, 11:10) *
Прогамма зависает после выполнения строки кода
Код
while ((AT91C_BASE_MC->MC_FSR & AT91C_MC_EOL) != AT91C_MC_EOL);

В чем может быть причина ?
Кусочек, пишущий в FCR и ожидающий после этого готовности FSR должен исполняться из ОЗУ.
Angle
Цитата(Сергей Борщ @ Nov 21 2007, 16:20) *
Кусочек, пишущий в FCR и ожидающий после этого готовности FSR должен исполняться из ОЗУ.

А как это реализовать в Keil?
Сергей Борщ
Цитата(Angle @ Nov 21 2007, 13:36) *
А как это реализовать в Keil?
А я не знаю. Поищите по форуму. ключевые слова ramfunc, scatter.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.