Files
zTC1/mico-os/platform/MCU/ATSAMG55/peripherals/platform_flash.c
2025-03-11 15:54:45 +08:00

350 lines
10 KiB
C

/**
******************************************************************************
* @file platform_flash.c
* @author William Xu
* @version V1.0.0
* @date 05-May-2014
* @brief This file provides flash operation functions.
******************************************************************************
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "platform_logging.h"
#include "mico_platform.h"
#include "platform.h"
#include "stdio.h"
#ifdef USE_MICO_SPI_FLASH
#include "spi_flash.h"
#endif
#include "flash_efc.h"
/* Private constants --------------------------------------------------------*/
#define ADDR_FLASH_SECTOR_00 ((uint32_t)0x00400000) /* base @ of sector 0, 8 kbyte */
#define ADDR_FLASH_SECTOR_01 ((uint32_t)0x00402000) /* base @ of sector 1, 8 kbyte */
#define ADDR_FLASH_SECTOR_02 ((uint32_t)0x00404000) /* base @ of sector 2, 112 kbyte */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x00420000) /* base @ of sector 1, 128 kbyte */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x00440000) /* base @ of sector 2, 128 kbyte */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x00480000) /* base @ of sector 3, 128 kbyte */
/* End of the Flash address */
#define FLASH_START_ADDRESS IFLASH_ADDR //internal flash
#define FLASH_END_ADDRESS (IFLASH_ADDR + IFLASH_SIZE - 1)
#define FLASH_SIZE IFLASH_SIZE
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* critical disable irq */
#define mem_flash_op_enter() do {\
__DSB(); __ISB(); \
cpu_irq_disable(); \
__DMB(); \
} while (0)
/* critical enable irq */
#define mem_flash_op_exit() do { \
__DMB(); __DSB(); __ISB();\
cpu_irq_enable(); \
} while (0)
typedef enum
{
SAMG55_FLASH_ERASE_4_PAGES = 0x04,
SAMG55_FLASH_ERASE_8_PAGES = 0x08,
SAMG55_FLASH_ERASE_16_PAGES = 0x10,
SAMG55_FLASH_ERASE_32_PAGES = 0x20,
} samg55_flash_erase_page_amount_t;
/* Private variables ---------------------------------------------------------*/
#ifdef USE_MICO_SPI_FLASH
static sflash_handle_t sflash_handle = {0x0, 0x0, SFLASH_WRITE_NOT_ALLOWED};
#endif
/* Private function prototypes -----------------------------------------------*/
static OSStatus internalFlashInitialize( void );
static OSStatus internalFlashErase(uint32_t StartAddress, uint32_t EndAddress);
static OSStatus internalFlashWrite(volatile uint32_t* FlashAddress, uint32_t* Data ,uint32_t DataLength);
#ifdef MCU_EBANLE_FLASH_PROTECT
static OSStatus internalFlashProtect(uint32_t StartAddress, uint32_t EndAddress, bool enable);
#endif
#ifdef USE_MICO_SPI_FLASH
static OSStatus spiFlashErase(uint32_t StartAddress, uint32_t EndAddress);
#endif
OSStatus platform_flash_init( const platform_flash_t *peripheral )
{
OSStatus err = kNoErr;
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
if( peripheral->flash_type == FLASH_TYPE_EMBEDDED ){
err = internalFlashInitialize();
require_noerr(err, exit);
}
#ifdef USE_MICO_SPI_FLASH
else if( peripheral->flash_type == FLASH_TYPE_SPI ){
err = init_sflash( &sflash_handle, 0, SFLASH_WRITE_ALLOWED );
require_noerr(err, exit);
}
#endif
else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
OSStatus platform_flash_erase( const platform_flash_t *peripheral, uint32_t start_address, uint32_t end_address )
{
OSStatus err = kNoErr;
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
require_action( start_address >= peripheral->flash_start_addr
&& end_address <= peripheral->flash_start_addr + peripheral->flash_length - 1, exit, err = kParamErr);
if( peripheral->flash_type == FLASH_TYPE_EMBEDDED ){
err = internalFlashErase( start_address, end_address );
require_noerr(err, exit);
}
#ifdef USE_MICO_SPI_FLASH
else if( peripheral->flash_type == FLASH_TYPE_SPI ){
err = spiFlashErase( start_address, end_address );
require_noerr(err, exit);
}
#endif
else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
OSStatus platform_flash_write( const platform_flash_t *peripheral, volatile uint32_t* start_address, uint8_t* data ,uint32_t length )
{
OSStatus err = kNoErr;
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
require_action( *start_address >= peripheral->flash_start_addr
&& *start_address + length <= peripheral->flash_start_addr + peripheral->flash_length, exit, err = kParamErr);
if( peripheral->flash_type == FLASH_TYPE_EMBEDDED ){
err = internalFlashWrite( start_address, (uint32_t *)data, length);
require_noerr(err, exit);
}
#ifdef USE_MICO_SPI_FLASH
else if( peripheral->flash_type == FLASH_TYPE_SPI ){
err = sflash_write( &sflash_handle, *start_address, data, length );
require_noerr(err, exit);
*start_address += length;
}
#endif
else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
OSStatus platform_flash_read( const platform_flash_t *peripheral, volatile uint32_t* start_address, uint8_t* data ,uint32_t length )
{
OSStatus err = kNoErr;
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
require_action( (*start_address >= peripheral->flash_start_addr)
&& (*start_address + length) <= ( peripheral->flash_start_addr + peripheral->flash_length), exit, err = kParamErr);
if( peripheral->flash_type == FLASH_TYPE_EMBEDDED ){
memcpy(data, (void *)(*start_address), length);
*start_address += length;
}
#ifdef USE_MICO_SPI_FLASH
else if( peripheral->flash_type == FLASH_TYPE_SPI ){
err = sflash_read( &sflash_handle, *start_address, data, length );
require_noerr(err, exit);
*start_address += length;
}
#endif
else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
OSStatus platform_flash_enable_protect( const platform_flash_t *peripheral, uint32_t start_address, uint32_t end_address )
{
OSStatus err = kNoErr;
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
require_action( start_address >= peripheral->flash_start_addr
&& end_address <= peripheral->flash_start_addr + peripheral->flash_length - 1, exit, err = kParamErr);
if( peripheral->flash_type == FLASH_TYPE_EMBEDDED ){
#ifdef MCU_EBANLE_FLASH_PROTECT
err = internalFlashProtect( start_address, end_address, true );
#endif
require_noerr(err, exit);
}
#ifdef USE_MICO_SPI_FLASH
else if( peripheral->flash_type == FLASH_TYPE_SPI ){
err = kNoErr;
goto exit;
}
#endif
else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
OSStatus platform_flash_disable_protect( const platform_flash_t *peripheral, uint32_t start_address, uint32_t end_address )
{
OSStatus err = kNoErr;
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
require_action( start_address >= peripheral->flash_start_addr
&& end_address <= peripheral->flash_start_addr + peripheral->flash_length - 1, exit, err = kParamErr);
if( peripheral->flash_type == FLASH_TYPE_EMBEDDED ){
#ifdef MCU_EBANLE_FLASH_PROTECT
err = internalFlashProtect( start_address, end_address, false );
#endif
require_noerr(err, exit);
}
#ifdef USE_MICO_SPI_FLASH
else if( peripheral->flash_type == FLASH_TYPE_SPI ){
err = kNoErr;
goto exit;
}
#endif
else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
static OSStatus internalFlashInitialize( void )
{
platform_log_trace();
OSStatus err = kNoErr;
platform_mcu_powersave_disable();
require_action( flash_init(FLASH_ACCESS_MODE_128, 6) == FLASH_RC_OK, exit, err = kGeneralErr );
exit:
platform_mcu_powersave_enable();
return err;
}
OSStatus internalFlashErase(uint32_t start_address, uint32_t end_address)
{
platform_log_trace();
uint32_t i;
OSStatus err = kNoErr;
uint32_t page_start_address, page_end_address;
uint32_t page_start_number, page_end_number;
platform_mcu_powersave_disable();
require_action( flash_unlock( start_address, end_address, &page_start_address, &page_end_address ) == FLASH_RC_OK, exit, err = kGeneralErr );
page_start_number = page_start_address/512;
page_end_number = page_end_address/512;
require_action( page_end_number >= page_start_number + 16, exit, err = kUnsupportedErr);
for ( i = page_start_number; i <= page_end_number; i+=16 )
{
require_action( flash_erase_page( i * 512, IFLASH_ERASE_PAGES_16) == FLASH_RC_OK, exit, err = kGeneralErr );
}
require_action( flash_lock( start_address, end_address, NULL, NULL ) == FLASH_RC_OK, exit, err = kGeneralErr );
exit:
platform_mcu_powersave_enable();
return err;
}
OSStatus internalFlashWrite(volatile uint32_t* flash_address, uint32_t* data ,uint32_t data_length)
{
platform_log_trace();
OSStatus err = kNoErr;
uint32_t start_address = * flash_address;
platform_mcu_powersave_disable();
//mem_flash_op_enter();
require_action( flash_unlock( start_address, start_address + data_length - 1, NULL, NULL ) == FLASH_RC_OK, exit, err = kGeneralErr );
require_action( flash_write((*flash_address), data, data_length, false) == FLASH_RC_OK, exit, err = kGeneralErr );
*flash_address += data_length;
require_action( flash_lock( start_address, start_address + data_length - 1, NULL, NULL ) == FLASH_RC_OK, exit, err = kGeneralErr );
//mem_flash_op_exit();
exit:
platform_mcu_powersave_enable();
return err;
}
#ifdef MCU_EBANLE_FLASH_PROTECT
OSStatus internalFlashProtect(uint32_t StartAddress, uint32_t EndAddress, bool enable)
{
OSStatus err = kNoErr;
UNUSED_PARAMETER( StartAddress );
UNUSED_PARAMETER( EndAddress );
UNUSED_PARAMETER( enable );
return err;
}
#endif
#ifdef USE_MICO_SPI_FLASH
OSStatus spiFlashErase(uint32_t StartAddress, uint32_t EndAddress)
{
platform_log_trace();
OSStatus err = kNoErr;
uint32_t StartSector, EndSector, i = 0;
/* Get the sector where start the user flash area */
StartSector = StartAddress>>12;
EndSector = EndAddress>>12;
for(i = StartSector; i <= EndSector; i += 1)
{
require_action(sflash_sector_erase(&sflash_handle, i<<12) == kNoErr, exit, err = kWriteErr);
}
exit:
return err;
}
#endif