Jump to content

    

Запись во FLASH.

Я сохраняю системные параметры во внутреннюю память микроконтролера. (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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now