Перейти к содержанию
    

работа с внутренней флэш

Привет! У меня плата на AT91SAM7x256 - первый раз в жизни пытаюсь работать с внутреней флэш ... :07:

вот пишу что-то в память

__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: ... и в xcl написано

"Read-Only" ...это значит что я могу только читать -- что надо прописать чтоб можно было и писать ?

Спасибо!

Изменено пользователем Annuta

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

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

 

А по теме: что передаете в эту функцию EFCWrite(u32 adr, u8 *pbuf, u32 Len, u32 NeedReset)? Чему равна переменная EFC_PAGE_SIZE?

Изменено пользователем Timofey

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в xcl из области ROM исключите страницы, которые пользуете при сохранении данных, чтоб линкер программу туда не пихал, скорее всего затираете нужный кусок кода, а так с внктренней влеш в самах вроде все нормально, я ни разу с глюками не сталкивался..

при записи запретите все прерывания! то что в комментах в xcl написано это ерунда.. страницы можно писать

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в xcl из области ROM исключите страницы, которые пользуете при сохранении данных, чтоб линкер программу туда не пихал, скорее всего затираете нужный кусок кода, а так с внктренней влеш в самах вроде все нормально, я ни разу с глюками не сталкивался..

при записи запретите все прерывания! то что в комментах в xcl написано это ерунда.. страницы можно писать

 

Увы, но факт, есть факт. Когда устройство лежало у меня на столе, у меня тоже все было впорядке. Ни единого глюка. Но когда спустили десять таких устройств в шахту. Там то они и появились. Хотя дело выбора :) . А так я тоже брал эту программу с форума этого. Зная конечный размер программы, я в xcl файле (как вы и советуете) ограничилч объем памяти (хотя было видно и без ограничения, что линкер туда программу не пихал, но это не важно). Потом долго разбирался: на столе нормально, в шахте - глюк. Пока с ноутом не залез в шахту, не подключился и не увидел лично.

Изменено пользователем Timofey

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Моя переменная

#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)

 

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

Изменено пользователем Annuta

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Моя переменная

#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;
  }

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

//*************************************************************************
// 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 Кб. А стек обычно лежит в конце РАМы, а теперь там неопределенная память... Надеюсь понятно выразил. :)

 

 

 

Вот кусов моего бутлоадера под 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, особенно задержки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Моя переменная

#define EFC_PAGE_SIZE 128

Размер страницы что у SAM7X128 что у SAM7X256 равен 256 байт (согласно даташиту)

При попытке поменять в 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;

Изменено пользователем Timofey

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо!! Вроде пишет - не могу провериить -- так как не работает чтение .... :wacko:

вот функция

__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;
}

// вот массив пусто!

помогите уж до конца разобраться...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

__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 передавайте тот же начальный адрес который указывали для записи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Происходят странные вещи!.. моя прога на этой строке сбрасывается... перегружается...

AT91C_BASE_MC->MC_FCR = (0x5A << 24) | AT91C_MC_FCMD_ERASE_ALL;

Это я пытаюсь сделть очистку....

как правильно - очистку сделать!... стереть стр?

и ещё где можно скачать - самы простой - работающий проект для работы с внутренней флэш... демку какую-нить... ?

Изменено пользователем Annuta

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Происходят странные вещи!.. моя прога на этой строке сбрасывается... перегружается...

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."

и ещё где можно скачать - самы простой - работающий проект для работы с внутренней флэш... демку какую-нить... ?

Программа, которую выложили вначале, вполне работоспособная. Я для SAM7S64 пишу нормально. И считываю данные тоже. Просто сделайте все заново, учитывая коментарии.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вот написала по вашему совету прогу сначала. Эх... ну не работает!. :crying: .. Не пинайте ногами если - что упускаю... програмимирую первый раз в жизни микроконтроллер!...

вот мой код

#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);

Она зажигает второй лед, потом плата перегружается... !... все огоньки гаснут /как будто жму кнопочку на плате ресет/ ...и она снова работает... только сначала!... Третий лед не зажигается...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какой у Вас 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 чем использовать прямое значение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Она зажигает второй лед, потом плата перегружается... !... все огоньки гаснут /как будто жму кнопочку на плате ресет/ ...и она снова работает... только сначала!... Третий лед не зажигается...
Я извиняюсь, три вопроса -

1) у вас Watchdog Timer остановлен? Если нет, возможно как раз в этот момент истекает его тайм-аут.

2) вы пользуетесь внутрисхемным отладчиком? Если да, то можно пошагово дойти до точки "падения" и узнать какое именно действие вызывает перезагрузку.

3)У вас стоят "заглушки" на исключениях Prefetch Abort, DataAbort, Undefined Instruction? Если нет - поставьте пустые циклы с какой-то индикацией, уже будет больше информации.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...