реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Внутренний flash для хранения пользовательских данных, как правильно?
athlon64
сообщение Jul 6 2010, 03:18
Сообщение #1


Частый гость
**

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



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


--------------------
Руслан
Go to the top of the page
 
+Quote Post
athlon64
сообщение Jul 6 2010, 04:48
Сообщение #2


Частый гость
**

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



Посмотрел map-файл, линкер действительно не помещает ничего выше адреса 0x0015FFFF, так что видимо дело не в том что область основной программы пересекается с областью конфигурации, а в том что во время записи конфигурации возникает прерывание от TWI и при этом каким то образом повреждается основная программа.
В связи с этим вопрос: как лучше всего корректно отключить прерывания от TWI на время записи во flash?


--------------------
Руслан
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Jul 6 2010, 05:42
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



проверь содержимое 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

Go to the top of the page
 
+Quote Post
athlon64
сообщение Jul 6 2010, 05:59
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 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 проц вообще не стартует


--------------------
Руслан
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Jul 6 2010, 06:14
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



пропиши строчку:
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 так написано, иначе флэш будет работать с глюками
Go to the top of the page
 
+Quote Post
athlon64
сообщение Jul 6 2010, 06:37
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 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

К сожалению, не помогло


--------------------
Руслан
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Jul 6 2010, 07:37
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



выкладывай код функций чтения/записи....
во время работы с флешью надо запрещать все прерывания:

__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}^
Go to the top of the page
 
+Quote Post
athlon64
сообщение Jul 6 2010, 08:04
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 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 запись и такой конфигурации проходит нормально


--------------------
Руслан
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Jul 6 2010, 08:14
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



добавь в main.c
#include <intrinsics.h>

тогда иар ругатся не будет
__enable_interrupt(); // это глобальное прерывание
Go to the top of the page
 
+Quote Post
athlon64
сообщение Jul 6 2010, 14:11
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 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 пачек

Во всех случаях после резета начинает выполнять программу и зависает

Вот такие вот дела sad.gif


--------------------
Руслан
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Jul 7 2010, 06:37
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



я к сожалению только сейчас получил возможность пощупать at91sam7
до этого момента работал c процами NXP
для хранения конфигов ставил внешнюю SPI EEPROM
как вариант AT24C1024BW-SH25-B - EEPROM SERIAL 2.7-5.5V
Memory Configuration:128K x 8bit
Interface:Serial, 2 Wire
Clock Frequency:1MHz
Go to the top of the page
 
+Quote Post
dimka76
сообщение Jul 7 2010, 07:05
Сообщение #12


developer
****

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



Функция
Код
FLASHD_Write(firstPageAddress+(PageNoStart*AT91C_IFLASH_PAGE_SIZE), pFlashBuffer, AT91C_IFLASH_PAGE_SIZE);


у вас откуда исполняется? Из FLASH или из RAM ?


--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
Go to the top of the page
 
+Quote Post
athlon64
сообщение Jul 7 2010, 07:18
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 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


--------------------
Руслан
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 7 2010, 16:03
Сообщение #14


кекс
******

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



Цитата(athlon64 @ Jul 6 2010, 17:11) *
Во всех случаях после резета начинает выполнять программу и зависает

Вот такие вот дела sad.gif

Для того чтобы функции __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.
Go to the top of the page
 
+Quote Post
athlon64
сообщение Jul 15 2010, 04:49
Сообщение #15


Частый гость
**

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



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


--------------------
Руслан
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 15:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.0148 секунд с 7
ELECTRONIX ©2004-2016