У меня есть некоторые функции для чтения и записи в память внутренней памяти STM32F103.Эти функции работают на gcc и стандартном скрипте компоновщика.Когда я хочу использовать внутреннюю вспышку с stm32 и freertos.FreeRtos не дает мне доступа, когда я хочу записать данные во внутреннюю флэш-память.Вот стандартный файл сценария компоновщика freertos.
Файл сценария компоновщика по умолчанию для freertos для stm32.
/*************************************************
* linker script for ST32F103 & MPU REV 1.02
************************************************/
GROUP(libgcc.a libc.a)
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
/* Higher address of the user mode stack */
_estack = ORIGIN(SRAM)+LENGTH(SRAM);
/*
*There will be a link error if there is not this amount of RAM free at the end.
*/
_Minimum_Stack_Size = 1K;
_Minimum_Heap_Size = 1K;
/* Variables used by FreeRTOS-MPU. */
_Privileged_Functions_Region_Size = 16K;
_Privileged_Data_Region_Size = 512;
__FLASH_segment_start__ = ORIGIN( FLASH );
__FLASH_segment_end__ = __FLASH_segment_start__ + LENGTH( FLASH );
__privileged_functions_start__ = ORIGIN( FLASH );
__privileged_functions_end__ = __privileged_functions_start__ + _Privileged_Functions_Region_Size;
__SRAM_segment_start__ = ORIGIN( SRAM );
__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( SRAM );
__privileged_data_start__ = ORIGIN( SRAM );
__privileged_data_end__ = ORIGIN( SRAM ) + _Privileged_Data_Region_Size;
ENTRY(Reset_Handler)
SECTIONS
{
/*
Privileged section at the start of the flash.
Vectors must be first whatever.
*/
.isr_vectors :
{
. = ALIGN(4);
_isr_vectors_offs = . - __FLASH_segment_start__;
KEEP(*(.isr_vectors)) /* Startup code */
} >FLASH
privileged_functions :
{
. = ALIGN(4);
*(privileged_functions)
} > FLASH
/* Non privileged code starts here. */
.text_offset :
{
. = ALIGN(4);
. = . + _Privileged_Functions_Region_Size;
} > FLASH
.text :
{
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
} > FLASH
/*
.ARM.exidx is sorted, so has to go in its own output section.
*/
. = ALIGN(4);
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} >FLASH
__exidx_end = .;
/* -- */
.data.align :
{
. = ALIGN(4);
_etext = .;
_sipdata = _etext; /* Used by the startup in order to initialize privileged variables */
} >FLASH
/* -- */
.pdata.align :
{
. = ALIGN(4);
. = . + _Privileged_Data_Region_Size;
_sidata = .; /* Used by the startup in order to initialize variables */
} >FLASH
/*
* This is the Privileged data section. It is stored in RAM but the initial values
* are held in flash and copied to RAM by the startup code
*/
privileged_data : AT ( _sipdata ) /* AT makes the LMA follow on in the binary image */
{
. = ALIGN(4);
_bss = .;
_spdata = . ;
*(privileged_data)
_epdata = . ;
} > SRAM
/*
* This is the initialized data section. It is stored in RAM but the initial values
* are held in flash and copied to RAM by the startup code
*/
.data_offset :
{
. = ALIGN(4);
. = . + _Privileged_Data_Region_Size;
} > SRAM
.data : AT ( _sidata ) /* AT makes the LMA follow on in the binary image */
{
_sdata = . ; /* Used by the startup in order to initialize the .data section */
KEEP(*(vtable))
KEEP( *(.data) )
KEEP( *(.data.*) )
. = ALIGN(4);
_edata = . ; /* Used by the startup in order to initialize the .data section */
} >SRAM
/*
* This is the uninitialized data section. Date here is stored in RAM and will be
* set to zero by the startup code.
*/
.bss :
{
. = ALIGN(4);
_sbss = .; /* Used by the startup in order to initialize the .bss section */
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ; /* Used by the startup in order to initialize the .bss section */
} >SRAM
/*
* This is the heap section
* This is just to check that there is enough RAM left for the heap
* It should generate an error if it's full.
*/
._sheap :
{
. = ALIGN(4);
_heap_begin = . ;
. = . + _Minimum_Heap_Size ;
. = ALIGN(4);
_heap_end = . ;
} >SRAM
/*
* This is the user stack section
* This is just to check that there is enough RAM left for the User mode stack
* It should generate an error if it's full.
*/
._usrstack :
{
. = ALIGN(4);
_susrstack = . ;
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
_eusrstack = . ;
} >SRAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE( _heap = _heap_begin );
PROVIDE ( _eheap = _heap_end );
}
и вот мой новый файл сценария компоновщика здесь для доступа к последней страницеstm32f103, который является страницей 255. Когда я хочу изменить страницу 255.Это не позволяет мне.У вас есть предложение, как можно использовать внутреннюю вспышку stm32 с freertos?Мне просто нужно использовать одну страницу во флэш-памяти, когда свободны в использовании.Все работает, если я не использую freertos
/*************************************************
* linker script for ST32F103 & MPU REV 1.02
************************************************/
GROUP(libgcc.a libc.a)
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1022K
FLASH_STORAGE (rwx) : ORIGIN = 0x08000000+1022K, LENGTH = 2K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
/* Higher address of the user mode stack */
_estack = ORIGIN(SRAM)+LENGTH(SRAM);
/*
*There will be a link error if there is not this amount of RAM free at the end.
*/
_Minimum_Stack_Size = 1K;
_Minimum_Heap_Size = 1K;
/* Variables used by FreeRTOS-MPU. */
_Privileged_Functions_Region_Size = 16K;
_Privileged_Data_Region_Size = 512;
__FLASH_segment_start__ = ORIGIN( FLASH );
__FLASH_segment_end__ = __FLASH_segment_start__ + LENGTH( FLASH );
__privileged_functions_start__ = ORIGIN( FLASH );
__privileged_functions_end__ = __privileged_functions_start__ + _Privileged_Functions_Region_Size;
__SRAM_segment_start__ = ORIGIN( SRAM );
__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( SRAM );
__privileged_data_start__ = ORIGIN( SRAM );
__privileged_data_end__ = ORIGIN( SRAM ) + _Privileged_Data_Region_Size;
ENTRY(Reset_Handler)
SECTIONS
{
/*
Privileged section at the start of the flash.
Vectors must be first whatever.
*/
.isr_vectors :
{
. = ALIGN(4);
_isr_vectors_offs = . - __FLASH_segment_start__;
KEEP(*(.isr_vectors)) /* Startup code */
} >FLASH
privileged_functions :
{
. = ALIGN(4);
*(privileged_functions)
} > FLASH
/* Non privileged code starts here. */
.text_offset :
{
. = ALIGN(4);
. = . + _Privileged_Functions_Region_Size;
} > FLASH
.text :
{
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
} > FLASH
/*
.ARM.exidx is sorted, so has to go in its own output section.
*/
. = ALIGN(4);
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} >FLASH
__exidx_end = .;
/* -- */
.data.align :
{
. = ALIGN(4);
_etext = .;
_sipdata = _etext; /* Used by the startup in order to initialize privileged variables */
} >FLASH
/* -- */
.pdata.align :
{
. = ALIGN(4);
. = . + _Privileged_Data_Region_Size;
_sidata = .; /* Used by the startup in order to initialize variables */
} >FLASH
/*
* This is the Privileged data section. It is stored in RAM but the initial values
* are held in flash and copied to RAM by the startup code
*/
privileged_data : AT ( _sipdata ) /* AT makes the LMA follow on in the binary image */
{
. = ALIGN(4);
_bss = .;
_spdata = . ;
*(privileged_data)
_epdata = . ;
} > SRAM
/*
* This is the initialized data section. It is stored in RAM but the initial values
* are held in flash and copied to RAM by the startup code
*/
.data_offset :
{
. = ALIGN(4);
. = . + _Privileged_Data_Region_Size;
} > SRAM
.data : AT ( _sidata ) /* AT makes the LMA follow on in the binary image */
{
_sdata = . ; /* Used by the startup in order to initialize the .data section */
KEEP(*(vtable))
KEEP( *(.data) )
KEEP( *(.data.*) )
. = ALIGN(4);
_edata = . ; /* Used by the startup in order to initialize the .data section */
} >SRAM
/*
* This is the uninitialized data section. Date here is stored in RAM and will be
* set to zero by the startup code.
*/
.bss :
{
. = ALIGN(4);
_sbss = .; /* Used by the startup in order to initialize the .bss section */
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ; /* Used by the startup in order to initialize the .bss section */
} >SRAM
/*
* This is the heap section
* This is just to check that there is enough RAM left for the heap
* It should generate an error if it's full.
*/
._sheap :
{
. = ALIGN(4);
_heap_begin = . ;
. = . + _Minimum_Heap_Size ;
. = ALIGN(4);
_heap_end = . ;
} >SRAM
/*
* This is the user stack section
* This is just to check that there is enough RAM left for the User mode stack
* It should generate an error if it's full.
*/
._usrstack :
{
. = ALIGN(4);
_susrstack = . ;
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
_eusrstack = . ;
} >SRAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE( _heap = _heap_begin );
PROVIDE ( _eheap = _heap_end );
}
Изменения в сценарии компоновщика
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
в сценарии компоновщика:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1022K
FLASH_STORAGE (rwx) : ORIGIN = 0x08000000+1022K, LENGTH = 2K
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
Вотмои коды, чтобы написать флеш с FreeRtos.файл flash.c.
#include <FreeRTOS.h>
#include <queue.h>
#include <task.h>
/* -- */
#include "FlashMemoryDataStorage_FreeRtos.h"
/* -- */
/********************************************************************************
; Function: FlashMemoryDataStorage_UnLock
;
; Description: unlocks the flash memory
;
; Inputs: nothing
;
; Returns: Nothing
*********************************************************************************/
void FlashMemoryDataStorage_UnLock(void)
{
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
/********************************************************************************
; Function: FlashMemoryDataStorage_Lock
;
; Description: locks the flash memory
;
; Inputs: nothing
;
; Returns: Nothing
*********************************************************************************/
void FlashMemoryDataStorage_Lock(void)
{
FLASH->CR = FLASH_CR_LOCK;
}
/*********************************************************************************
; Function: FlashMemoryDataStorage_SectorErase
;
; Description: erases a sector
;
; Inputs: uint32_t address of erase operation
;
; Returns: Nothing
*********************************************************************************/
void FlashMemoryDataStorage_SectorErase(uint32_t addr)
{
FlashMemoryDataStorage_UnLock();
/* -- */
FLASH->CR |= FLASH_CR_PER;
FLASH->CR &= ~FLASH_CR_PG;
FLASH->CR |= FLASH_CR_OPTER;
FLASH->AR = addr;
FLASH->CR |= FLASH_CR_STRT;
/* wait until the operation finish */
while(FLASH->SR & (uint32_t)FLASH_SR_BSY);
FLASH->CR &= ~(FLASH_CR_PER | FLASH_CR_OPTER);
/* -- */
FlashMemoryDataStorage_Lock();
}
/*********************************************************************************
; Function: FlashMemoryDataStorage_SectorWrite
;
; Description: writes a sector
;
; Inputs: uint32_t address of write operation
;
; Inputs: uint32_t address of write buffer
;
; Returns: Nothing
*********************************************************************************/
ERRCODE FlashMemoryDataStorage_SectorWrite(uint32_t addr,void * pBuff)
{
ERRCODE ec = SUCCESS;
uint16_t size=0, *pAddr=NULL, *pBuffTemp=NULL;
/* -- */
size = FLASH_SECTOR_SIZE;
pAddr = (uint16_t *)addr;
pBuffTemp =(uint16_t *)pBuff;
size = size / 2; /* incoming values are in bytes (It should be 16-bit) */
/* -- */
while(size) {
FlashMemoryDataStorage_UnLock();
/* -- */
FLASH->CR &= ~FLASH_CR_PER;
FLASH->CR |= FLASH_CR_PG;
*(pAddr) = *(pBuffTemp);
tprintf("\r\nPage Erased22: \r\n");
while(1);
/* wait until the operation finish */
while(FLASH->SR & FLASH_SR_BSY);
if (FLASH->SR & FLASH_SR_PGERR) {
ec = FLASH_WRITE_PAGE_ERR;
tprintf("PAGE ERR");
while(1);
goto func_end;
}
/* -- */
if (FLASH->SR & FLASH_SR_WRPRTERR) {
ec = FLASH_WRITE_PROTECTION_ERR;
tprintf("WRTIE PROTEC");
while(1);
goto func_end;
}
pAddr++;
pBuffTemp++;
size--;
}
/* -- */
func_end:
FlashMemoryDataStorage_Lock();
return ec;
}
/*********************************************************************************************
; Function: FlashMemoryDataStorage_SectorDump
;
; Description: dumps a sector
;
; Inputs: uint32_t starting address of dump operation
;
; Returns: Nothing
***********************************************************************************************/
void FlashMemoryDataStorage_SectorDump(uint32_t addr)
{
uint16_t ndx=0, size=0;
size = FLASH_SECTOR_SIZE;
for( ndx=0; ndx < size; ndx++){
if(!(ndx % 16)) tprintf("\n\r0x%04x",ndx);
tprintf(" %02x",*(char *)addr);
addr++;
}
}
/*********************************************************************************************
; Function: FlashMemoryDataStorage_SectorRead
;
; Description: reads a sector
;
; Inputs: uint32_t starting address of read operation
;
; Inputs: char * read buffer pointer
;
; Returns: Nothing
;
***********************************************************************************************/
void FlashMemoryDataStorage_SectorRead(uint32_t addr, char *pBuff)
{
uint16_t index=0, size=0;
size = FLASH_SECTOR_SIZE;
for( index=0; index < size; index++){
pBuff[index] = *(char *)addr;
addr++;
}
}
/*********************************************************************************************
; Function: FlashMemoryDataStorage_SectorFillBuffer
;
; Description: fills the memory with a character
;
; Inputs: char * buffer pointer
;
; Inputs: char chacacter to fill
;
; Returns: Nothing
;
***********************************************************************************************/
void FlashMemoryDataStorage_SectorFillBuffer(char *pBuff, char ch)
{
uint16_t ndx=0, size=0;
size = FLASH_SECTOR_SIZE;
for( ndx=0; ndx < size; ndx++){
pBuff[ndx] = ch;
}
}
/* -- */
static void vTest_Flash( void *pvParameters )
{
/* The parameters are not used in this function. */
(void) pvParameters;
char buffw[FLASH_SECTOR_SIZE];
char buffr[FLASH_SECTOR_SIZE];
while(1) {
/* Erase Memory */
tprintf("\r\nPage Erased: \r\n");
FlashMemoryDataStorage_SectorErase(PAGE_255_ADDR);
/* sector 1 write operation */
FlashMemoryDataStorage_SectorFillBuffer(buffw,'a');
FlashMemoryDataStorage_SectorWrite(PAGE_255_TEST_SECTOR1,buffw);
FlashMemoryDataStorage_SectorRead(PAGE_255_TEST_SECTOR1,buffr);
if(0 != memcmp(buffw,buffr,FLASH_SECTOR_SIZE)) {
tprintf("\r\n flash read/error %d",PAGE_255_TEST_SECTOR1);
}
/* sector dump operations */
/* sector1 dump */
tprintf("\r\nSector 1 Dump: \r\n");
FlashMemoryDataStorage_SectorDump(PAGE_255_TEST_SECTOR1);
vTaskDelay(30000);;
}
}
/* -- */
int main()
{
portBASE_TYPE xReturn;
/* -- */
xReturn = xTaskCreate ( vTest_Flash, ( const signed portCHAR * const )"Test_Flash", configMINIMAL_STACK_SIZE<<5, NULL, tskIDLE_PRIORITY, NULL );
if( xReturn != pdPASS ) {
tprintf("\n\rTest_Flash initilisation problem.\n\r");
}
/* Now all the tasks have been started - start the scheduler. */
vTaskStartScheduler();
return 0;
}
файл flash.h
/* -- */
#define FLASH_KEY1 0x45670123 /* These Values Come From PM0075(Programming Manual Section 2.3.1) */
#define FLASH_KEY2 0xCDEF89AB /* We Need To Set The Keys Sequentialy As Described In PM0075 */
/* -- */
#define FLASH_SECTOR_SIZE 128
/* -- */
#define FLASH_WRITE_PAGE_ERR 0x40
#define FLASH_WRITE_PROTECTION_ERR 0x41
/* -- */
#define PAGE_255_ADDR 0x0807F800
#define PAGE_255_TEST_SECTOR1 PAGE_255_ADDR
#define PAGE_255_TEST_SECTOR2 (PAGE_255_TEST_SECTOR1 + 0x200)
#define PAGE_255_TEST_SECTOR3 (PAGE_255_TEST_SECTOR2 + 0x200)
#define PAGE_255_TEST_SECTOR4 (PAGE_255_TEST_SECTOR3 + 0x200)
/* -- */
void FlashMemoryDataStorage_UnLock(void);
void FlashMemoryDataStorage_Lock(void);
void FlashMemoryDataStorage_SectorErase(uint32_t addr);
void FlashMemoryDataStorage_SectorRead(uint32_t addr, char *pBuff);
ERRCODE FlashMemoryDataStorage_SectorWrite(uint32_t addr,void * pBuff);
/* -- */