|
|
  |
Внутренний flash для хранения пользовательских данных, как правильно? |
|
|
|
Jul 6 2010, 03:18
|

Частый гость
 
Группа: Свой
Сообщений: 156
Регистрация: 10-03-10
Из: Уфа
Пользователь №: 55 882

|
В процессоре at91sam7x512 нужно отдать последние 128Кб для хранения настроек устройства (конфигурационного файла). Запись и чтение у меня сделано и работает, но начиная с определённого размера конфигурации, запись повреждает основную программу. В icf-файле уменьшил адрес конца ROM __ICFEDIT_region_ROM_end__ со стандартных 0x17FFFF до 0x15FFFF, чтобы линкер не помещал программу выше 384Кб флеша. Но, видимо, этого недостаточно. Как правильно настроить линкер?
--------------------
Руслан
|
|
|
|
|
Jul 6 2010, 05:59
|

Частый гость
 
Группа: Свой
Сообщений: 156
Регистрация: 10-03-10
Из: Уфа
Пользователь №: 55 882

|
Цитата(cornflyer @ Jul 6 2010, 11:42)  проверь содержимое Flash Mode Register: AT91C_BASE_MC->MC_FMR Warning: In order to guarantee valid operations on the flash memory, the field Flash Microsecond Cycle Number (FMCN) must be correctly programmed.
у меня например MCK = 10MHz соответственно в LowLevelInit() у меня есть такая строчка: AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(10<<16)) | AT91C_MC_FWS_0FWS; // 1us =< 10 MCK ticks
если у тебя MCK = 48 MHz тогда должно быть так: AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(50<<16)) | AT91C_MC_FWS_0FWS; // 1us =< 50 MCK tick У меня в LowLevelInit(): Код AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS; AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS; А AT91C_MC_FWS равно: Код #define AT91C_MC_FWS_0FWS (0x0 << 8) // (EFC) 1 cycle for Read, 2 for Write operations #define AT91C_MC_FWS_1FWS (0x1 << 8) // (EFC) 2 cycles for Read, 3 for Write operations #define AT91C_MC_FWS_2FWS (0x2 << 8) // (EFC) 3 cycles for Read, 4 for Write operations #define AT91C_MC_FWS_3FWS (0x3 << 8) // (EFC) 4 cycles for Read, 4 for Write operations Пробовал AT91C_MC_FWS_2FWS, AT91C_MC_FWS_3FWS - ничего не меняет. При AT91C_MC_FWS_0FWS проц вообще не стартует
--------------------
Руслан
|
|
|
|
|
Jul 6 2010, 06:37
|

Частый гость
 
Группа: Свой
Сообщений: 156
Регистрация: 10-03-10
Из: Уфа
Пользователь №: 55 882

|
Цитата(cornflyer @ Jul 6 2010, 12:14)  пропиши строчку: AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(50<<16)) | AT91C_MC_FWS_1FWS; // 1us =< 50 MCK tick
где вместо 50 укажи свое значение, т.е. >=MCK[MHz] например если MCK = 48MHz, тогда округляешь до большего числа, т.е. до 50
в мануале на AT91SAM7 так написано, иначе флэш будет работать с глюками У sam7x512 два EFC, поэтому вписал: Код AT91C_BASE_EFC0->EFC_FMR = ((AT91C_MC_FMCN)&(50<<16)) | AT91C_MC_FWS_1FWS; // 1us =< 50 MCK tick AT91C_BASE_EFC1->EFC_FMR = ((AT91C_MC_FMCN)&(50<<16)) | AT91C_MC_FWS_1FWS; // 1us =< 50 MCK tick К сожалению, не помогло
--------------------
Руслан
|
|
|
|
|
Jul 6 2010, 08:04
|

Частый гость
 
Группа: Свой
Сообщений: 156
Регистрация: 10-03-10
Из: Уфа
Пользователь №: 55 882

|
Цитата(cornflyer @ Jul 6 2010, 13:37)  во время работы с флешью надо запрещать все прерывания: __disable_interrupt(); // flash read/write __enable_interrupt(); причем надо еще добавить в startup.s: irqHandler: // spurious interrupts elimination MRS r14, SPSR ; Abort if IRQ disabled ANDS r14, r14, #I_BIT ; (IRQ_BIT = 1) LDMNEFD sp!, {pc}^ на __disable_interrupt(); и __enable_interrupt(); IAR ругается Я пробовал запрещать прерывания от TWI с помощью: AT91C_BASE_TWI->TWI_IDR = 0xFFFFFFFF; и IRQ_DisbleIT(AT91C_ID_TWI); не помогло. Если не инициализировать TWI - запись и чтение происходят без ошибок. Причём с включенным TWI запись конфигурационного файла до 256 байт тоже проходит без ошибок, больше 256 - виснет и после резета виснет снова, т.е. как будто повреждена основная программа. Вот код чтения: Код char EPR_Rd(unsigned int adr) { return((char) *(pfirstPageData+adr)); } Запись - функция реализующая запись в произвольное место произвольное кол-во байт: Код volatile unsigned int firstPageAddress; volatile unsigned int *pfirstPageData; // Указатель на начало пользовательского блока во FLASH unsigned int pFlashBuffer[AT91C_IFLASH_PAGE_SIZE / 4]; // Буфер записи страницы flash
void WriteBlokToFlash(unsigned int address_wr, char *data_array_p, unsigned char IndexStartWr, unsigned int CntByte_wr) { unsigned int BytesSaved, i; unsigned char PageNoStart, AddrInPage, i_end; unsigned char array_idx=0;
BytesSaved=0; // Пока не записали ни одного байта конфигурации while (BytesSaved!=CntByte_wr) // Сидим в цикле до тех пор пока всё запланированное не будет записано { PageNoStart = address_wr/64; // Номер страницы для записи AddrInPage = address_wr%64; // Адрес внутри страницы for (i=0;i<64;i++) pFlashBuffer[i] = *(pfirstPageData+(PageNoStart*64)+i); // Загоняем в буфер текущую страницу флеша if ((AddrInPage+CntByte_wr)>64) // Если блок не умещается в текущую страницу пишем до конца страницы (64*4байт) i_end=64; else // Если умещается - пишем до конца блока i_end = AddrInPage + CntByte_wr - BytesSaved; array_idx = IndexStartWr + BytesSaved; // Ставим указатель в массиве данных for (i=AddrInPage; i<i_end; i++) { pFlashBuffer[i]=*(data_array_p+(array_idx++)); // Вносим изменения в буфер записи BytesSaved++; } FLASHD_Write(firstPageAddress+(PageNoStart*AT91C_IFLASH_PAGE_SIZE), pFlashBuffer, AT91C_IFLASH_PAGE_SIZE); address_wr = address_wr + BytesSaved; // Увеличиваем адрес на кол-во записанных байт } } Щас появилась мысль: Конфигурация пишется пачками по 62 байта, обычно затык на 5 пакете, т.е. который попадает между 2х страниц, соответственно эта функция произведёт запись 2х страниц почти подряд. Возможно не хватает времени на запись первой страницы, как нужно писать уже вторую? Попробую сделать задержку. Но тогда не понятно почему с отключенным TWI запись и такой конфигурации проходит нормально
--------------------
Руслан
|
|
|
|
|
Jul 6 2010, 14:11
|

Частый гость
 
Группа: Свой
Сообщений: 156
Регистрация: 10-03-10
Из: Уфа
Пользователь №: 55 882

|
Цитата(cornflyer @ Jul 6 2010, 14:14)  добавь в main.c #include <intrinsics.h>
тогда иар ругатся не будет __enable_interrupt(); // это глобальное прерывание Конфигурация 272 байта: Теперь из 5 пачек по 62 байта пишет все Тут же при контрольном чтении читает 4 и виснет Конфигурация 968 байт: Пишет успешно 3 пачки по 62 байта и виснет Конфигурация 348 байт: Пишется 5 пачек по 62 байт и виснет При повторной записи виснет после 2 пачек Во всех случаях после резета начинает выполнять программу и зависает Вот такие вот дела
--------------------
Руслан
|
|
|
|
|
Jul 7 2010, 07:05
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
Функция Код FLASHD_Write(firstPageAddress+(PageNoStart*AT91C_IFLASH_PAGE_SIZE), pFlashBuffer, AT91C_IFLASH_PAGE_SIZE); у вас откуда исполняется? Из FLASH или из RAM ?
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Jul 7 2010, 07:18
|

Частый гость
 
Группа: Свой
Сообщений: 156
Регистрация: 10-03-10
Из: Уфа
Пользователь №: 55 882

|
Цитата(dimka76 @ Jul 7 2010, 13:05)  Функция Код FLASHD_Write(firstPageAddress+(PageNoStart*AT91C_IFLASH_PAGE_SIZE), pFlashBuffer, AT91C_IFLASH_PAGE_SIZE); у вас откуда исполняется? Из FLASH или из RAM ? Из flash
--------------------
Руслан
|
|
|
|
|
Jul 7 2010, 16:03
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(athlon64 @ Jul 6 2010, 17:11)  Во всех случаях после резета начинает выполнять программу и зависает Вот такие вот дела  Для того чтобы функции __enabled_interrupt() и __disable_interrupts() работали, необходимо чтобы проц был в SYS или SVC режиме. В USR mode эти фукнции работать не будут. В USR mode запретить прерывания можно так: Код U32 iMask = pAIC->AIC_IMR; pAIC->AIC_IDCR = 0xFFFFFFFF;
// execute function from SRAM ...
// restore interrupt sources pAIC->AIC_IECR = iMask; Цитата(athlon64 @ Jul 7 2010, 10:18)  Из flash А надо из RAM.
|
|
|
|
|
Jul 15 2010, 04:49
|

Частый гость
 
Группа: Свой
Сообщений: 156
Регистрация: 10-03-10
Из: Уфа
Пользователь №: 55 882

|
В общем разобрался в ситуации, дело было не в бобине как грится  Проблема была не с записью флеш. Процессор зависал при попытке выполнить конфигурационные команды в процессе записи конфигурации. Т.е. блокировки на время записи не было, точнее она была закомментирована и забыта. Отключение инициализации TWI помогало потому что в том же цикле, где лежит исполнение конфигурации, инициировался обмен по TWI, который занимал его флагом и никогда не освобождал (т.к. прерывания были отключены) и выполнение конфигурации было запрещено, соответственно флеш записывался корректно. Т.о. запись/чтение работали нормально  Тем не менее, было принято решение не хранить конфигурацию во внутреннем флеше. Теперь для этого используется AT45DB321. Всех благодарю за наводки и комментарии
--------------------
Руслан
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|