Files
zTC1/mico-os/platform/MCU/MX1101/peripherals/platform_flash.c

574 lines
15 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 "platform.h"
#include "Platform_config.h"
#include "platform_peripheral.h"
#include "stdio.h"
//#define DEBUG_FLASH
#ifdef DEBUG_FLASH
#define APP_DBG printf
#endif
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
#ifdef DEBUG_FLASH
SPI_FLASH_INFO FlashInfo;
void GetFlashGD(int32_t protect)
{
uint8_t str[20];
int32_t FlashCapacity = 0;
switch(FlashInfo.Did)
{
case 0x1340:
strcpy((char *)str,"GD25Q40(GD25Q40B)");
FlashCapacity = 0x00080000;
break;
case 0x1240:
strcpy((char *)str,"GD25Q20(GD25Q20B)");
FlashCapacity = 0x00040000;
break;
case 0x1540:
strcpy((char *)str,"GD25Q16(GD25Q16B)");
FlashCapacity = 0x00200000;
break;
case 0x1640:
strcpy((char *)str,"GD25Q32(GD25Q32B)");
FlashCapacity = 0x00400000;
break;
case 0x1740:
strcpy((char *)str,"GD25Q64B");
FlashCapacity = 0x00800000;
break;
case 0x1440:
strcpy((char *)str,"GD25Q80(GD25Q80B)");
FlashCapacity = 0x00100000;
break;
case 0x1840:
strcpy((char *)str,"GD25Q128B");
FlashCapacity = 0x01000000;
break;
default:
break;
}
if(FlashCapacity > 0)
{
APP_DBG("Module: ");
APP_DBG("%s\r\n",str);
APP_DBG("Capacity: ");
APP_DBG("0x%08X\r\n", FlashCapacity);
}
else
{
APP_DBG("Found failed\r\n");
}
}
void GetFlashWinBound(int32_t protect)
{
uint8_t str[20];
int32_t FlashCapacity = 0;
switch(FlashInfo.Did)
{
case 0x1440:
strcpy((char *)str,"W25Q80BV");
FlashCapacity = 0x00100000;
break;
case 0x1760:
strcpy((char *)str,"W25Q64DW");
FlashCapacity = 0x00800000;
break;
case 0x1740:
strcpy((char *)str,"W25Q64CV");
FlashCapacity = 0x00800000;
break;
default:
break;
}
if(FlashCapacity > 0)
{
APP_DBG("Module: ");
APP_DBG("%s\r\n",str);
APP_DBG("Capacity: ");
APP_DBG("0x%08X\r\n", FlashCapacity);
}
else
{
APP_DBG("Found failed\r\n");
}
}
void GetFlashPct(void)
{
uint8_t str[20];
int32_t FlashCapacity = 0;
switch(FlashInfo.Did)
{
case 0x0126:
strcpy((char *)str,"PCT26VF016");
FlashCapacity = 0x00200000;
break;
case 0x0226:
strcpy((char *)str,"PCT26VF032");
FlashCapacity = 0x00400000;
break;
default:
break;
}
if(FlashCapacity > 0)
{
APP_DBG("Module: ");
APP_DBG("%s\r\n",str);
APP_DBG("Capacity: ");
APP_DBG("0x%08X\r\n", FlashCapacity);
}
else
{
APP_DBG("Found failed\r\n");
}
}
void GetFlashEon(int32_t protect)
{
uint8_t str[20];
int32_t FlashCapacity = 0;
switch(FlashInfo.Did)
{
case 0x1430:
strcpy((char *)str,"EN25Q80A");
FlashCapacity = 0x00100000;
break;
case 0x1530:
strcpy((char *)str,"EN25Q16A");
FlashCapacity = 0x00200000;
break;
case 0x1830:
strcpy((char *)str,"EN25Q128");
FlashCapacity = 0x01000000;
break;
case 0x1630:
strcpy((char *)str,"EN25Q32A");
FlashCapacity = 0x00400000;
break;
case 0x1330:
strcpy((char *)str,"EN25Q40");
FlashCapacity = 0x00080000;
break;
case 0x1730:
strcpy((char *)str,"EN25Q64");
FlashCapacity = 0x00800000;
break;
case 0x1570:
strcpy((char *)str,"EN25QH16");
FlashCapacity = 0x00200000;
break;
case 0x1670:
strcpy((char *)str,"EN25QH32");
FlashCapacity = 0x00400000;
break;
default:
break;
}
if(FlashCapacity > 0)
{
APP_DBG("Module: ");
APP_DBG("%s\r\n",str);
APP_DBG("Capacity: ");
APP_DBG("0x%08X\r\n", FlashCapacity);
}
else
{
APP_DBG("Found failed\r\n");
}
}
void GetFlashBg(int32_t protect)
{
uint8_t str[20];
int32_t FlashCapacity = 0;
switch(FlashInfo.Did)
{
case 0x1540:
strcpy((char *)str,"BG25Q16A");
FlashCapacity = 0x00200000;
break;
case 0x1340:
strcpy((char *)str,"BG25Q40A");
FlashCapacity = 0x00080000;
break;
case 0x1440:
strcpy((char *)str,"BG25Q80A");
FlashCapacity = 0x00100000;
break;
default:
break;
}
if(FlashCapacity > 0)
{
APP_DBG("Module: ");
APP_DBG("%s\r\n",str);
APP_DBG("Capacity: ");
APP_DBG("0x%08X\r\n", FlashCapacity);
}
else
{
APP_DBG("Found failed\r\n");
}
}
void GetFlashEsmt(int32_t protect)
{
uint8_t str[20];
int32_t FlashCapacity = 0;
switch(FlashInfo.Did)
{
case 0x1440:
strcpy((char *)str,"F25L08QA");
FlashCapacity = 0x00100000;
break;
case 0x1540:
strcpy((char *)str,"F25L16QA");
FlashCapacity = 0x00200000;
break;
case 0x1641:
strcpy((char *)str,"F25L32QA");
FlashCapacity = 0x00400000;
break;
case 0x1741:
strcpy((char *)str,"F25L64QA");
FlashCapacity = 0x00800000;
break;
default:
break;
}
if(FlashCapacity > 0)
{
APP_DBG("Module: ");
APP_DBG("%s\r\n",str);
APP_DBG("Capacity: ");
APP_DBG("0x%08X\r\n", FlashCapacity);
}
else
{
APP_DBG("Found failed\r\n");
}
}
void GetDidInfo(int32_t protect)
{
APP_DBG("%-30s","Did:");
APP_DBG("0x%08X\r\n",FlashInfo.Did);
APP_DBG("%-30s","Lock Area(BP4~BP0:Bit4~Bit0):");
APP_DBG("0x%08X\r\n",protect);
}
void GetFlashInfo(void)
{
int32_t protect = 0;
APP_DBG("\r\n\r\n****************************************************************\n");
APP_DBG("%-30s\r\n","Flash information");
if(FlashInfo.Mid != FLASH_PCT)
{
protect = SpiFlashIOCtl(3,0);
protect = (protect >> 2) & 0x1F;
}
switch(FlashInfo.Mid)
{
case FLASH_GD:
APP_DBG("Manufacture: GD\r\n");
GetDidInfo(protect);
GetFlashGD(protect);
break;
case FLASH_WINBOUND:
APP_DBG("Manufacture: WINBOUND\r\n");
GetDidInfo(protect);
GetFlashWinBound(protect);
break;
case FLASH_PCT:
APP_DBG("Manufacture: PCT\r\n");
GetFlashPct();
break;
case FLASH_EON:
APP_DBG("Manufacture: EN\r\n");
GetDidInfo(protect);
GetFlashEon(protect);
break;
case FLASH_BG:
APP_DBG("Manufacture: BG\r\n");
GetDidInfo(protect);
GetFlashBg(protect);
break;
case FLASH_ESMT:
APP_DBG("Manufacture: ESMT\r\n");
GetDidInfo(protect);
GetFlashEsmt(protect);
break;
default:
APP_DBG("Manufacture: not found\r\n");
break;
}
APP_DBG("\r\n");
APP_DBG("****************************************************************\n");
}
#endif /* DEBUG_FLASH */
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_SPI ){
SpiFlashInfoInit();
#ifdef DEBUG_FLASH
SpiFlashGetInfo(&FlashInfo);
GetFlashInfo();
#endif
//require_action(FlashUnlock(), exit, err = kUnknownErr);
}
else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
#define MAX_OPERATE_LEN (16*1024)
OSStatus platform_flash_erase( const platform_flash_t *peripheral, uint32_t StartAddress, uint32_t EndAddress )
{
OSStatus err = kNoErr;
int erase_len = MAX_OPERATE_LEN, total_len = EndAddress - StartAddress +1;
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
require_action( StartAddress >= peripheral->flash_start_addr
&& EndAddress < peripheral->flash_start_addr + peripheral->flash_length, exit, err = kParamErr);
if( peripheral->flash_type == FLASH_TYPE_SPI ){
while(total_len > 0) {
if (total_len > MAX_OPERATE_LEN) {
erase_len = MAX_OPERATE_LEN;
total_len -= MAX_OPERATE_LEN;
} else {
erase_len = total_len;
total_len = 0;
}
err = SpiFlashErase( StartAddress, erase_len );
#ifndef MICO_DISABLE_WATCHDOG
WdgFeed();
#endif
require_noerr(err, exit);
StartAddress += erase_len;
}
}else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
OSStatus platform_flash_write( const platform_flash_t *peripheral, volatile uint32_t* FlashAddress, uint8_t* Data ,uint32_t DataLength )
{
OSStatus err = kNoErr;
int write_len = MAX_OPERATE_LEN, total_len = DataLength;
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
require_action( *FlashAddress >= peripheral->flash_start_addr
&& *FlashAddress + DataLength <= peripheral->flash_start_addr + peripheral->flash_length, exit, err = kParamErr);
if( peripheral->flash_type == FLASH_TYPE_SPI ){
while(total_len > 0) {
if (total_len > MAX_OPERATE_LEN) {
write_len = MAX_OPERATE_LEN;
total_len -= MAX_OPERATE_LEN;
} else {
write_len = total_len;
total_len = 0;
}
err = SpiFlashWrite( *FlashAddress, Data, write_len );
#ifndef MICO_DISABLE_WATCHDOG
WdgFeed();
#endif
require_noerr(err, exit);
*FlashAddress += write_len;
Data += write_len;
}
}else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
OSStatus platform_flash_read( const platform_flash_t *peripheral, volatile uint32_t* FlashAddress, uint8_t* Data ,uint32_t DataLength )
{
OSStatus err = kNoErr;
int read_len = MAX_OPERATE_LEN, total_len = DataLength;
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
require_action_quiet( DataLength != 0, exit, err = kNoErr);
require_action( *FlashAddress >= peripheral->flash_start_addr
&& *FlashAddress + DataLength <= peripheral->flash_start_addr + peripheral->flash_length, exit, err = kParamErr);
if( peripheral->flash_type == FLASH_TYPE_SPI ){
while(total_len > 0) {
if (total_len > MAX_OPERATE_LEN) {
read_len = MAX_OPERATE_LEN;
total_len -= MAX_OPERATE_LEN;
} else {
read_len = total_len;
total_len = 0;
}
err = SpiFlashRead( *FlashAddress, Data, read_len );
#ifndef MICO_DISABLE_WATCHDOG
WdgFeed();
#endif
require_noerr(err, exit);
*FlashAddress += read_len;
Data += read_len;
}
}else{
err = kTypeErr;
goto exit;
}
exit:
return err;
}
#define BP_Pos 2
#define BP_Msk (0x1Fu << BP_Pos)
#define CMP_Pos 14
#define CMP_Msk (0x1u << BP_Pos)
OSStatus platform_flash_enable_protect( const platform_flash_t *peripheral, uint32_t start_address, uint32_t end_address )
{
OSStatus err = kNoErr;
int32_t spi_err = 0;
int32_t status = SpiFlashIOCtl( IOCTL_STATUS_REGISTER );
UNUSED_PARAMETER( end_address );
//platform_log("protect %d, %x, %x", peripheral->flash_type, start_address, end_address);
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
if( ( 0x5 == ( status & BP_Msk ) >> BP_Pos ) && ( status&CMP_Msk ) )
return kNoErr;
spi_err = SpiFlashIOCtl(IOCTL_FLASH_PROTECT, FLASH_HALF_PROTECT);
//platform_log("status %x", ( SpiFlashIOCtl( IOCTL_STATUS_REGISTER ) & BP_Msk ) >> BP_Pos );
require_action_quiet(spi_err == 0, exit, err = kUnexpectedErr);
exit:
return err;
}
OSStatus platform_flash_disable_protect( const platform_flash_t *peripheral, uint32_t start_address, uint32_t end_address )
{
OSStatus err = kNoErr;
char cmd[3] = "\x35\xBA\x69";
int32_t spi_err = 0;
int32_t status = SpiFlashIOCtl( IOCTL_STATUS_REGISTER );
UNUSED_PARAMETER( end_address );
require_action_quiet( peripheral != NULL, exit, err = kParamErr);
if( ( 0x0 == ( status & BP_Msk ) >> BP_Pos ) && !( status&CMP_Msk ) )
return kNoErr;
spi_err = SpiFlashIOCtl(IOCTL_FLASH_UNPROTECT, cmd, sizeof(cmd));
require_action_quiet(spi_err == 0, exit, err = kUnexpectedErr);
exit:
return err;
}