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

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

Отладчик в таких ситуациях может только мешать. Советую попробовать без него.

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


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

Спасибо, Dron_Gus!... да именно из-за этого плата и перегружалась... Теперь не перегружаеься... но и не работает.... :(

__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" .. естевтсвенно...

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


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

вот - делаю как... Прошивка доходит до волшебной строчки

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

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


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

В функцию EFCWrite(); передается адрес 0x0030000 - область ОЗУ после ремапа, причем получается 196 608 байт, хотя у этого контроллера 64 кб ОЗУхи

 

или я не прав?

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


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

В функцию 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, там все константы описаны, чтоб не делать таких ошибок с размещением.

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


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

To Annuta: Полезно иногда заглядывать в файл AT91SAM7X256.h, там все константы описаны, чтоб не делать таких ошибок с размещением.
Она просто учится :) Про ремап я просто забыл сообщить :)

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


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

Мне в AT91 нужно менять только одно слово во флеше. Обязательно ли для этого читать всю страницу, содержащую слово, менять его и записывать всю страницу обратно? Или можно канибудь проще? Мне не ради простоты а ради удлинения срока службы флеша... (реализую файловую систему. файлы будут больше читаться, писАться - редко, но тем не менее...)

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


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

Мне в 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);

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


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

сколько же у вас памяти жрет проект, если вы пишете на CPP ?
Примерно столько же. А удобства неравненно больше. Обсуждалось неоднократно, хотя бы тут.

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


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

2 Сергей Борщ. Смысл понятен, но реализация в примере темновата.

	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:

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


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

Разве ~0x7F не равно 0x80 ? Каков смысл такой записи как у Вас?
Нет, не равно. ~0x7F для ARM равно 0xFFFFFF80. Вот и вы попались. Вообще-то совсем правильно было бы ~0x7FULL, тогда такая запись обнуляла бы 5 младших бит в любой целочисленной переменной. Но я пока не выработал в себе такую привычку, наверное пора начинать.

Зачем кидать туда-сюда значение *pTmp ?
Tmp объявлен как volatile *. Без временной переменной получили бы warning компилятора о непредсказуемом порядке доступа к volatile (IAR выдает его всегда, если в выражении встречается более одной volatile-переменной). Без volatile компилятор имел бы полное право выкинуть весь цикл.

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


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

У меня такая проблема не могу записать во внутреннюю флэш.

Контроллер 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);

В чем может быть причина ?

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


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

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

В чем может быть причина ?

Кусочек, пишущий в FCR и ожидающий после этого готовности FSR должен исполняться из ОЗУ.

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


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

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

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

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

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

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

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

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

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

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