2025-10-10 16:07:00 +08:00

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;
}