|
работа с внутренней флэш, AT91SAM7X256 |
|
|
|
Jul 6 2007, 11:16
|

Участник

Группа: Новичок
Сообщений: 42
Регистрация: 26-04-07
Из: Смоленск
Пользователь №: 27 333

|
Привет! У меня плата на AT91SAM7x256 - первый раз в жизни пытаюсь работать с внутреней флэш ... вот пишу что-то в память Код __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 При попытке что-то записать из памяти стирается прошивка... то стириется то ли затирается - не мгу понять!... Хотя адреса не перекрещеваются... Не понимаю... ЧЕМ это вызвано!  ... и в xcl написано "Read-Only" ...это значит что я могу только читать -- что надо прописать чтоб можно было и писать ? Спасибо!
Сообщение отредактировал Annuta - Jul 6 2007, 11:21
--------------------
Из комбинации лени и логики - получается программист! /народная мудрость/
|
|
|
|
|
Jul 6 2007, 13:40
|
Частый гость
 
Группа: Участник
Сообщений: 119
Регистрация: 3-07-06
Пользователь №: 18 528

|
Цитата(Annuta @ Jul 6 2007, 17:16)  По собственному опыту не советую использовать внутреннюю флэш. При записи очень часто возникал глюк: страница стирается, а записывать не записывается. При проверке выяснилось что бит готовности не всегда вставал в положение "флэш занята". Лучше всего использовать внешнюю spi-ную например. А по теме: что передаете в эту функцию EFCWrite(u32 adr, u8 *pbuf, u32 Len, u32 NeedReset)? Чему равна переменная EFC_PAGE_SIZE?
Сообщение отредактировал Timofey - Jul 6 2007, 13:45
|
|
|
|
|
Jul 7 2007, 06:19
|
Частый гость
 
Группа: Участник
Сообщений: 119
Регистрация: 3-07-06
Пользователь №: 18 528

|
Цитата(IV_K @ Jul 6 2007, 22:04)  в xcl из области ROM исключите страницы, которые пользуете при сохранении данных, чтоб линкер программу туда не пихал, скорее всего затираете нужный кусок кода, а так с внктренней влеш в самах вроде все нормально, я ни разу с глюками не сталкивался.. при записи запретите все прерывания! то что в комментах в xcl написано это ерунда.. страницы можно писать Увы, но факт, есть факт. Когда устройство лежало у меня на столе, у меня тоже все было впорядке. Ни единого глюка. Но когда спустили десять таких устройств в шахту. Там то они и появились. Хотя дело выбора  . А так я тоже брал эту программу с форума этого. Зная конечный размер программы, я в xcl файле (как вы и советуете) ограничилч объем памяти (хотя было видно и без ограничения, что линкер туда программу не пихал, но это не важно). Потом долго разбирался: на столе нормально, в шахте - глюк. Пока с ноутом не залез в шахту, не подключился и не увидел лично.
Сообщение отредактировал Timofey - Jul 7 2007, 06:19
|
|
|
|
|
Jul 9 2007, 05:27
|

Участник

Группа: Новичок
Сообщений: 42
Регистрация: 26-04-07
Из: Смоленск
Пользователь №: 27 333

|
Моя переменная #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 - Jul 9 2007, 05:28
--------------------
Из комбинации лени и логики - получается программист! /народная мудрость/
|
|
|
|
|
Jul 9 2007, 09:30
|

Местный
  
Группа: Свой
Сообщений: 205
Регистрация: 19-12-05
Из: Kiev
Пользователь №: 12 394

|
Цитата(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; }
|
|
|
|
|
Jul 9 2007, 09:34
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861

|
Цитата(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 Кб. А стек обычно лежит в конце РАМы, а теперь там неопределенная память... Надеюсь понятно выразил. Вот кусов моего бутлоадера под 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, особенно задержки.
--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
|
|
|
|
|
Jul 9 2007, 09:59
|
Частый гость
 
Группа: Участник
Сообщений: 119
Регистрация: 3-07-06
Пользователь №: 18 528

|
Цитата(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;
Сообщение отредактировал Timofey - Jul 9 2007, 10:11
|
|
|
|
|
Jul 9 2007, 13:42
|

Участник

Группа: Новичок
Сообщений: 42
Регистрация: 26-04-07
Из: Смоленск
Пользователь №: 27 333

|
Спасибо!! Вроде пишет - не могу провериить -- так как не работает чтение .... вот функция Код __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; } // вот массив пусто! помогите уж до конца разобраться...
--------------------
Из комбинации лени и логики - получается программист! /народная мудрость/
|
|
|
|
|
Jul 9 2007, 16:07
|
Частый гость
 
Группа: Участник
Сообщений: 119
Регистрация: 3-07-06
Пользователь №: 18 528

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

Участник

Группа: Новичок
Сообщений: 42
Регистрация: 26-04-07
Из: Смоленск
Пользователь №: 27 333

|
Происходят странные вещи!.. моя прога на этой строке сбрасывается... перегружается... AT91C_BASE_MC->MC_FCR = (0x5A << 24) | AT91C_MC_FCMD_ERASE_ALL; Это я пытаюсь сделть очистку.... как правильно - очистку сделать!... стереть стр? и ещё где можно скачать - самы простой - работающий проект для работы с внутренней флэш... демку какую-нить... ?
Сообщение отредактировал Annuta - Jul 11 2007, 11:38
--------------------
Из комбинации лени и логики - получается программист! /народная мудрость/
|
|
|
|
|
Jul 12 2007, 08:27
|
Частый гость
 
Группа: Участник
Сообщений: 119
Регистрация: 3-07-06
Пользователь №: 18 528

|
Цитата(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 пишу нормально. И считываю данные тоже. Просто сделайте все заново, учитывая коментарии.
|
|
|
|
|
Jul 12 2007, 10:51
|

Участник

Группа: Новичок
Сообщений: 42
Регистрация: 26-04-07
Из: Смоленск
Пользователь №: 27 333

|
вот написала по вашему совету прогу сначала. Эх... ну не работает!.  .. Не пинайте ногами если - что упускаю... програмимирую первый раз в жизни микроконтроллер!... вот мой код Код #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); Она зажигает второй лед, потом плата перегружается... !... все огоньки гаснут /как будто жму кнопочку на плате ресет/ ...и она снова работает... только сначала!... Третий лед не зажигается...
--------------------
Из комбинации лени и логики - получается программист! /народная мудрость/
|
|
|
|
|
Jul 12 2007, 12:01
|

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

|
Цитата(Annuta @ Jul 12 2007, 13:51)  Она зажигает второй лед, потом плата перегружается... !... все огоньки гаснут /как будто жму кнопочку на плате ресет/ ...и она снова работает... только сначала!... Третий лед не зажигается... Я извиняюсь, три вопроса - 1) у вас Watchdog Timer остановлен? Если нет, возможно как раз в этот момент истекает его тайм-аут. 2) вы пользуетесь внутрисхемным отладчиком? Если да, то можно пошагово дойти до точки "падения" и узнать какое именно действие вызывает перезагрузку. 3)У вас стоят "заглушки" на исключениях Prefetch Abort, DataAbort, Undefined Instruction? Если нет - поставьте пустые циклы с какой-то индикацией, уже будет больше информации.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|