mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-17 23:48:13 +08:00
350 lines
10 KiB
C
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
|