Stm32 FreeRtos Внутренний Flash Linker-скрипт - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть некоторые функции для чтения и записи в память внутренней памяти 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);
/* -- */ 
...