225 lines
6.6 KiB
C
225 lines
6.6 KiB
C
|
// Copyright 2020-2021 Beken
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
#include "driver/flash.h"
|
||
|
#include "flash_driver.h"
|
||
|
#include "iot_flash.h"
|
||
|
#include "os/mem.h"
|
||
|
|
||
|
#define SPI_FLASH_BLOCK_SIZE 0x10000 //64KB
|
||
|
|
||
|
static IotFlashInfo_t s_flash_info;
|
||
|
static bool s_flash_drv_open;
|
||
|
static uint32_t s_flash_write_size;
|
||
|
static uint32_t s_flash_read_size;
|
||
|
extern int hal_flash_lock();
|
||
|
extern int hal_flash_unlock();
|
||
|
|
||
|
static inline bool prv_is_alligned_4k( uint32_t dw_address)
|
||
|
{
|
||
|
return (dw_address & FLASH_SECTOR_SIZE_MASK) == 0;
|
||
|
}
|
||
|
|
||
|
IotFlashHandle_t iot_flash_open(int32_t lFlashInstance)
|
||
|
{
|
||
|
if ((lFlashInstance == -1) || (s_flash_drv_open == true)) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// Since architecture is based on common driver, flash has already initialized
|
||
|
if((bk_flash_is_driver_inited() == true)) {
|
||
|
s_flash_drv_open = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if CONFIG_FLASH
|
||
|
bk_flash_driver_init();
|
||
|
extern int hal_flash_init();
|
||
|
hal_flash_init();
|
||
|
s_flash_drv_open = true;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return (IotFlashHandle_t) 1;
|
||
|
}
|
||
|
|
||
|
IotFlashInfo_t *iot_flash_getinfo(IotFlashHandle_t const pxFlashHandle)
|
||
|
{
|
||
|
if (pxFlashHandle == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
s_flash_info.ulFlashSize = bk_flash_get_current_total_size();
|
||
|
s_flash_info.ulBlockSize = SPI_FLASH_BLOCK_SIZE;
|
||
|
s_flash_info.ulSectorSize = FLASH_SECTOR_SIZE;
|
||
|
s_flash_info.ulPageSize = FLASH_PAGE_SIZE;
|
||
|
s_flash_info.ulLockSupportSize = FLASH_SECTOR_SIZE;
|
||
|
s_flash_info.ucAsyncSupported = false;
|
||
|
|
||
|
return &s_flash_info;
|
||
|
}
|
||
|
|
||
|
void iot_flash_set_callback(IotFlashHandle_t const pxFlashHandle, IotFlashCallback_t xCallback, void *pvUserContext)
|
||
|
{
|
||
|
// Not supported for BK7235
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int32_t iot_flash_ioctl(IotFlashHandle_t const pxFlashHandle, IotFlashIoctlRequest_t xRequest, void *const pvBuffer)
|
||
|
{
|
||
|
int32_t dw_rtn = IOT_FLASH_INVALID_VALUE;
|
||
|
|
||
|
if (pxFlashHandle == NULL || (int) xRequest < 0) {
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
switch (xRequest){
|
||
|
|
||
|
case eGetFlashStatus:
|
||
|
if(pvBuffer == NULL){
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
hal_flash_lock();
|
||
|
uint16_t status_value = bk_flash_read_status_reg();
|
||
|
hal_flash_unlock();
|
||
|
|
||
|
os_memcpy(pvBuffer,&status_value,sizeof(status_value));
|
||
|
dw_rtn = IOT_FLASH_SUCCESS;
|
||
|
break;
|
||
|
case eGetFlashTxNoOfbytes:
|
||
|
if(pvBuffer == NULL){
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
os_memcpy(pvBuffer,&s_flash_write_size,sizeof(s_flash_write_size));
|
||
|
dw_rtn = IOT_FLASH_SUCCESS;
|
||
|
break;
|
||
|
case eGetFlashRxNoOfbytes:
|
||
|
if(pvBuffer == NULL){
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
os_memcpy(pvBuffer,&s_flash_read_size,sizeof(s_flash_read_size));
|
||
|
dw_rtn = IOT_FLASH_SUCCESS;
|
||
|
break;
|
||
|
case eSetFlashBlockProtection:
|
||
|
case eGetFlashBlockProtection:
|
||
|
case eSuspendFlashProgramErase:
|
||
|
case eResumeFlashProgramErase:
|
||
|
default:
|
||
|
dw_rtn = IOT_FLASH_FUNCTION_NOT_SUPPORTED;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return dw_rtn;
|
||
|
}
|
||
|
|
||
|
int32_t iot_flash_erase_sectors(IotFlashHandle_t const pxFlashHandle, uint32_t ulAddress, size_t lSize)
|
||
|
{
|
||
|
uint32_t erase_times = 0;
|
||
|
uint32_t dw_loop = 0;
|
||
|
uint32_t dw_rtn = 0;
|
||
|
flash_protect_type_t project_type;
|
||
|
|
||
|
if ((pxFlashHandle == NULL) || !(prv_is_alligned_4k(ulAddress)) || (lSize % FLASH_SECTOR_SIZE)) {
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
erase_times = lSize / FLASH_SECTOR_SIZE;
|
||
|
hal_flash_lock();
|
||
|
bk_flash_write_enable();
|
||
|
|
||
|
project_type = bk_flash_get_protect_type();
|
||
|
bk_flash_set_protect_type(FLASH_PROTECT_NONE);
|
||
|
for(dw_loop = 0; dw_loop < erase_times; dw_loop++){
|
||
|
dw_rtn = bk_flash_erase_sector(ulAddress + dw_loop * FLASH_SECTOR_SIZE);
|
||
|
|
||
|
if(dw_rtn != BK_OK){
|
||
|
bk_flash_set_protect_type(project_type);
|
||
|
bk_flash_write_disable();
|
||
|
hal_flash_unlock();
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
}
|
||
|
bk_flash_set_protect_type(project_type);
|
||
|
|
||
|
bk_flash_write_disable();
|
||
|
hal_flash_unlock();
|
||
|
return IOT_FLASH_SUCCESS;
|
||
|
}
|
||
|
|
||
|
int32_t iot_flash_erase_chip(IotFlashHandle_t const pxFlashHandle)
|
||
|
{
|
||
|
if (pxFlashHandle == NULL) {
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
return IOT_FLASH_FUNCTION_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
int32_t iot_flash_write_sync(IotFlashHandle_t const pxFlashHandle, uint32_t ulAddress, uint8_t *const pvBuffer, size_t xBytes)
|
||
|
{
|
||
|
flash_protect_type_t project_type;
|
||
|
if (pxFlashHandle == NULL || (int) ulAddress < 0 || pvBuffer == NULL) {
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
s_flash_write_size = xBytes;
|
||
|
hal_flash_lock();
|
||
|
bk_flash_write_enable();
|
||
|
|
||
|
project_type = bk_flash_get_protect_type();
|
||
|
bk_flash_set_protect_type(FLASH_PROTECT_NONE);
|
||
|
bk_err_t dw_rtn = bk_flash_write_bytes(ulAddress, (const uint8_t *)pvBuffer, xBytes);
|
||
|
bk_flash_set_protect_type(project_type);
|
||
|
|
||
|
bk_flash_write_disable();
|
||
|
hal_flash_unlock();
|
||
|
|
||
|
return (dw_rtn == BK_OK) ? IOT_FLASH_SUCCESS : IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
int32_t iot_flash_read_sync(IotFlashHandle_t const pxFlashHandle, uint32_t ulAddress, uint8_t *const pvBuffer, size_t xBytes)
|
||
|
{
|
||
|
if (pxFlashHandle == NULL || (int) ulAddress < 0 || pvBuffer == NULL) {
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
s_flash_read_size = xBytes;
|
||
|
hal_flash_lock();
|
||
|
bk_err_t dw_rtn = bk_flash_read_bytes(ulAddress, (uint8_t *)pvBuffer, xBytes);
|
||
|
hal_flash_unlock();
|
||
|
|
||
|
return (dw_rtn == BK_OK) ? IOT_FLASH_SUCCESS : IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
|
||
|
int32_t iot_flash_write_async(IotFlashHandle_t const pxFlashHandle, uint32_t ulAddress, uint8_t *const pvBuffer, size_t xBytes)
|
||
|
{
|
||
|
return IOT_FLASH_FUNCTION_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
int32_t iot_flash_read_async(IotFlashHandle_t const pxFlashHandle, uint32_t ulAddress, uint8_t *const pvBuffer, size_t xBytes)
|
||
|
{
|
||
|
return IOT_FLASH_FUNCTION_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
|
||
|
int32_t iot_flash_close(IotFlashHandle_t const pxFlashHandle)
|
||
|
{
|
||
|
if (s_flash_drv_open != true) {
|
||
|
return IOT_FLASH_INVALID_VALUE;
|
||
|
}
|
||
|
s_flash_drv_open = false;
|
||
|
return IOT_FLASH_SUCCESS;
|
||
|
}
|