Jump to content

    
Sign in to follow this  
jenya7

Запись во FLASH.

Recommended Posts

Я сохраняю системные параметры во внутреннюю память микроконтролера. (STM32F303CB)

 

Собственно функции для записи.

FLASH_Status WriteFlash(void* src, void* dst, int len)
{
        uint32_t timeout = 0;  
        uint16_t* srcw = (uint16_t*)src;
        volatile uint16_t* dstw = (uint16_t*)dst;

        FLASH_Status status = FLASH_COMPLETE;
        
        FLASH->CR |= FLASH_CR_PG; /* Programm the flash */
        
	while (len)
	{
		*dstw = *srcw;
		while ((FLASH->SR & FLASH_SR_BSY) != 0 ) 
                {
                    timeout++;
                    if (timeout > 100000)
                    {
                        status = FLASH_ERROR_PROGRAM;
                        break;
                    }
                }
             
		if (*dstw != *srcw )
		{
                    status = FLASH_ERROR_PROGRAM;
                     break;
		}
               
		dstw++;
		srcw++;
		len = len - sizeof(uint16_t);
	}
        
	FLASH->CR &= ~FLASH_CR_PG; /* Reset the flag back !!!! */
        
        return status;
}

FLASH_Status WriteToFlash(uint32_t flash_page)
{
    uint32_t *addr;
    uint32_t size;
    uint32_t offset;
    //uint32_t space_left;

    FLASH_Status status = FLASH_COMPLETE;

    //flash unlock
    if((FLASH->CR & FLASH_CR_LOCK) != RESET)
    {
	 /* Authorize the FLASH Registers access */
	    FLASH->KEYR = FLASH_KEY1;
	    FLASH->KEYR = FLASH_KEY2;
    }

    status = FLASH_ErasePage(flash_page);

    if (status == FLASH_COMPLETE)
    {   
        size = sizeof(MOTOR_SYS_PARAMS);
        offset = 0;
        addr = (uint32_t *)(flash_page + offset);
        flash_status = WriteFlash(&motor_sys_params, addr, size);
        
        size = sizeof(GLOB_MOTOR_DATA);
        offset += (size + SEPARATOR);	
        addr = (uint32_t *)(flash_page + offset);
        flash_status = WriteFlash(&glob_mot_data, addr, size);
            
        size = sizeof(IR_DATA);
        offset += (size + SEPARATOR);
        addr = (uint32_t *)(flash_page + offset);
        flash_status = WriteFlash(&ir_data, addr, size);
            
        size = sizeof(MOTOR_TASK) * MAX_TASKS;
        offset += (size + SEPARATOR);
        addr = (uint32_t *)(flash_page + offset);
        flash_status = WriteFlash(&mot_task, addr, size);
	    
    }
  
    //flash lock
    FLASH->CR |= FLASH_CR_LOCK;
    
    return status;
}

И потом вызываю команду

uint32_t COM_Save(uint32_t argc, char** args)
{
    FLASH_Status status;
     
     __disable_interrupt();
     
      status = WriteToFlash(FLASH_PAGE_62);
 
    __enable_interrupt(); 
    
    if (status == FLASH_COMPLETE)
        Parser_SendString(COM_USART, "Save OK\r", 0);
    else
        Parser_SendString(COM_USART, "Save failed\r", 0);
    
    return MSG_OK;
}

Первая проблема – вызвал команду save – получил свой Save OK – рисет – вижу все прописалось.

Но если я хочу прописать повторно я падаю на  status = FLASH_ErasePage(flash_page);

Не удается стереть страницу. Если сделать рисет – все нормально – страница перезаписалась.

 

Первая проблема геморойна, неудобна, но можно жить.

 

Вторая проблема – когда я сказал все прописалось я покривил душой – все кроме

WriteFlash(&ir_data, addr, size);

Падает на валидации данных
 

if (*dstw != *srcw )
{

     status = FLASH_ERROR_PROGRAM;

     break;
}

ir_data ничем не страшнее других прописываемых структур

typedef struct 
{
    uint8_t show; 
    uint8_t bits;
    uint8_t protocol;
    uint8_t res;
    
    uint8_t action[4];  
    uint32_t code [4];
    
    uint32_t debounce_time;
}IR_DATA;

IR_DATA ir_data;

Думал битая страница (62). Поменял (63) – то же самое, обе проблемы присутствуют.

Share this post


Link to post
Share on other sites

Вы пилите сук на котором сидите: функции для изменения содержимого Flash должны размещаться в другой памяти (ОЗУ, внешней памяти, другом банке Flash, если банков хотя бы два).

 

Share this post


Link to post
Share on other sites
33 minutes ago, Forger said:

Вы пилите сук на котором сидите: функции для изменения содержимого Flash должны размещаться в другой памяти (ОЗУ, внешней памяти, другом банке Flash, если банков хотя бы два).

 

достаточно поставить перед функцией __ramfunc ?

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

Edited by jenya7

Share this post


Link to post
Share on other sites
44 minutes ago, jenya7 said:

достаточно поставить перед функцией __ramfunc ?

Не достаточно, подробности читайте в мануале на ваш компилятор/линкер.

 

 

Quote

И все же я не думаю что это причина проблемы.

Профи опирается только факты, а всякие "думаю", "раньше работало" и т. п. - это все домыслы ;)

Share this post


Link to post
Share on other sites
2 часа назад, jenya7 сказал:

достаточно поставить перед функцией __ramfunc ?

Есть такой Application note AN4296 Overview and tips for using STM32F303/328/334/358xx CCM RAM with IAR EWARM, Keil MDK-ARM and GNU-based toolchains

Share this post


Link to post
Share on other sites
23 minutes ago, HardEgor said:

Есть такой Application note AN4296 Overview and tips for using STM32F303/328/334/358xx CCM RAM with IAR EWARM, Keil MDK-ARM and GNU-based toolchains

спасибо. документ объясняет как положить функции в РАМ. но не решает мою проблему.

Share this post


Link to post
Share on other sites
2 hours ago, jenya7 said:

достаточно поставить перед функцией __ramfunc ?

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

 

Я бы посмотрел для начала на карту памяти. Коллега Forger прав.

Заморочки с размещением функций работы с флэш именно в ОЗУ для STM32 не обязательны (EFM32 - другое дело). До сих пор мои проекты работали с функциями во флэше, сами находясь, конечно же, не в странице, которая перезаписывается.

Share this post


Link to post
Share on other sites
24 minutes ago, KnightIgor said:

Я бы посмотрел для начала на карту памяти. Коллега Forger прав.

Заморочки с размещением функций работы с флэш именно в ОЗУ для STM32 не обязательны (EFM32 - другое дело). До сих пор мои проекты работали с функциями во флэше, сами находясь, конечно же, не в странице, которая перезаписывается.

так

Quote

Коллега Forger прав.

или

Quote

Заморочки с размещением функций работы с флэш именно в ОЗУ для STM32 не обязательны

До сих пор мои проекты работали с функциями во флэше

давайте уже определимся.

Конструктивный разбор полетов будет?

Память смотрю. Все структуры прописаны кроме той которая не прописана. И почему нужно делать рисет чтоб прописать страницу заново?

Edited by jenya7

Share this post


Link to post
Share on other sites

Функции записи во flash можно размещать в самой flash и даже на той же странице, куда пишем (только смысл?).

Однако, стирание и, например, перевод flash в спячку требуют запуска этих функций уже из другой памяти. 

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

Короче, хоть это и банально прозвучит, но все же RTFM ;)

8 minutes ago, jenya7 said:

И почему нужно делать рисет чтоб прописать страницу заново?

Походу, вы - первый кто так делает :)

Share this post


Link to post
Share on other sites
10 minutes ago, Forger said:

Однако, стирание и, например, перевод flash в спячку требуют запуска этих функций уже из другой памяти.  

У меня бутлодер сидит в той же памяти которую стирает.

Share this post


Link to post
Share on other sites
26 minutes ago, jenya7 said:

давайте уже определимся.

Я имел ввиду, что коллега прав по поводу сука. Далее он предложил НЕСКОЛЬКО вариантов, два из них: размещение функций в ОЗУ или в другом банке флэш. Я уточнил, что размещение в ОЗУ для STM32 (в отличие от EFM32) не является обязательным, можно оставить во флэш, просто в другой странице (даже не банке, если стирать постранично, что Вы и делаете, вроде). В желании Вам помочь и разобраться, я просматриваю мой нынешний рабочий код, которому уже много лет, и слабо вспоминаю, что вначале я тоже сталкивался с похожей проблемой.

 

P.S. Вот у меня нашел такое:
   

    FLASH_Unlock();
    FLASH_ClearFlag (FLASH_FLAG_BSY |
                     FLASH_FLAG_EOP |
                     FLASH_FLAG_PGERR |
                     FLASH_FLAG_WRPERR); // Clear All pending flags

Возможно, нужно сбросить флаги с предыдущей операции. Может это объясняет, почему первая запись после сброса у Вас работает, а последующие нет, хотя сам факт записи имел место.

Edited by KnightIgor

Share this post


Link to post
Share on other sites
12 minutes ago, KnightIgor said:

Я имел ввиду, что коллега прав по поводу сука. Далее он предложил НЕСКОЛЬКО вариантов, два из них: размещение функций в ОЗУ или в другом банке флэш. Я уточнил, что размещение в ОЗУ для STM32 (в отличие от EFM32) не является обязательным, можно оставить во флэш, просто в другой странице (даже не банке, если стирать постранично, что Вы и делаете, вроде). В желании Вам помочь и разобраться, я просматриваю мой нынешний рабочий код, которому уже много лет, и слабо вспоминаю, что вначале я тоже сталкивался с похожей проблемой.

 

P.S. Вот у меня нашел такое:
   


    FLASH_Unlock();
    FLASH_ClearFlag (FLASH_FLAG_BSY |
                     FLASH_FLAG_EOP |
                     FLASH_FLAG_PGERR |
                     FLASH_FLAG_WRPERR); // Clear All pending flags

Возможно, нужно сбросить флаги с предыдущей операции. Может это объясняет, почему первая запись после сброса у Вас работает, а последующие нет, хотя сам факт записи имел место.

 

О! Вот это слова не мальчика но мужа! Я почти уверен что в этом проблема. У меня забрали все переходники не могу проверить сейчас.

Я конечно учту замечания Forger и перенесу ф-ции в РАМ.

Share this post


Link to post
Share on other sites
30 minutes ago, jenya7 said:

У меня бутлодер сидит в той же памяти которую стирает.

Надо же и у меня тоже!

Но в моем случае все сразу заработало с полпинка и сразу так, как надо.

Наверно, просто повезло, а чтение даташитов и разбор чужих рабочих исходников (в частности на SPL от ST) тут вообще ни причем :)

Share this post


Link to post
Share on other sites

Вспомнил один важный момент - писать во флэш нужно целыми 32-битными словами, причем источник данных должен быть выровнен по границе этого слова! 

Share this post


Link to post
Share on other sites
12 minutes ago, Forger said:

Надо же и у меня тоже!

Но в моем случае все сразу заработало с полпинка и сразу так, как надо.

Наверно, просто повезло, а чтение даташитов и разбор чужих рабочих исходников (в частности на SPL от ST) тут вообще ни причем :)

Так я пользуюсь SPL-вскими ф-циями. Но они не прописаны в рам. Скажем, как правильно заметил KnightIgor, у EFM32 все библиотечные ф-ции использующие флеш имеют #pragma arm section code="ram_code".

 

 

7 minutes ago, Forger said:

Вспомнил один важный момент - писать во флэш нужно целыми 32-битными словами, причем источник данных должен быть выровнен по границе этого слова! 

32? а в примерах half-word - 16 бит.

WriteFlash я взял из их примера - там приводиться к (uint16_t*).

Edited by jenya7

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this