Merge pull request #4565 from Archcady/flash

Add FlashIAP support for REALTEK_RTL8195AM
pull/4691/head
Anna Bridge 2017-07-03 11:07:21 +01:00 committed by GitHub
commit c826e2f8b7
5 changed files with 546 additions and 582 deletions

View File

@ -13,555 +13,58 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "flash_ext.h"
#define FLASH_START (SPI_FLASH_BASE + FLASH_OFS_START)
#define FLASH_END (SPI_FLASH_BASE + FLASH_OFS_END)
#define FLASH_OFS(addr) ((addr) - SPI_FLASH_BASE)
#include "objects.h" int32_t flash_init(flash_t *obj)
#include "PinNames.h"
#include "pinmap.h"
#include "rtl8195a.h"
#include "hal_spi_flash.h"
#include "hal_platform.h"
#include "rtl8195a_spi_flash.h"
#include "hal_api.h"
#include "flash_api.h"
extern u32 ConfigDebugInfo;
extern SPIC_INIT_PARA SpicInitParaAllClk[3][CPU_CLK_TYPE_NO];
_LONG_CALL_
extern VOID SpicWaitBusyDoneRtl8195A(VOID);
static int isinit = 0;
static flash_t flashobj;
static void flash_init(flash_t * obj);
static void flash_turnon();
/**
* global data structure
*/
//flash_t flash;
/**
* @brief Control the flash chip write protect enable/disable
* @param protect: 1/0: protect/unprotect
* @retval none
*/
void flash_write_protect(flash_t *obj, uint32_t protect)
{ {
flash_turnon(); __flash_ext_turnon();
if(isinit == 0) return 0;
flash_init(&flashobj);
SpicWriteProtectFlashRtl8195A(protect);
SpicDisableRtl8195A();
} }
/** int32_t flash_free(flash_t *obj)
* @brief Init Flash
* @param obj: address of the flash object
* @retval none
*/
void flash_init(flash_t *obj)
{ {
//SPIC_INIT_PARA spic_init_para; __flash_ext_turnoff();
// Init SPI Flash Controller return 0;
// DBG_8195A("Initial Spi Flash Controller\n");
//SPI_FLASH_PIN_FCTRL(ON);
if (!SpicFlashInitRtl8195A(SpicOneBitMode)){
DBG_8195A("SPI Init Fail!!!!!!\n");
HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO3, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO3)|0xf);
} else {
isinit = 1;
}
flashobj.SpicInitPara.flashtype = SpicInitParaAllClk[0][0].flashtype;
}
void flash_turnon()
{
SPI_FLASH_PIN_FCTRL(ON);
SpicWaitBusyDoneRtl8195A();
} }
/** int32_t flash_erase_sector(flash_t *obj, uint32_t address)
* @brief Erase flash sector
* @param address: Specifies the starting address to be erased.
* @retval none
*/
void flash_erase_sector(flash_t *obj, uint32_t address)
{ {
flash_turnon(); __flash_ext_erase_sector(obj, FLASH_OFS(address));
if(isinit == 0) return 0;
flash_init(&flashobj);
SpicSectorEraseFlashRtl8195A(SPI_FLASH_BASE + address);
SpicDisableRtl8195A();
} }
void flash_erase_block(flash_t *obj, uint32_t address) int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
{ {
flash_turnon(); return __flash_ext_stream_write(obj, FLASH_OFS(address), size, data);
if(isinit == 0)
flash_init(&flashobj);
SpicBlockEraseFlashRtl8195A(SPI_FLASH_BASE + address);
SpicDisableRtl8195A();
} }
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
/**
* @brief Read a word from specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be read.
* @param data: Specified the address to save the readback data.
* @retval status: Success:1 or Failure: Others.
*/
int flash_read_word(flash_t *obj, uint32_t address, uint32_t * data)
{ {
if (address < FLASH_START || address >= FLASH_END)
return 0;
flash_turnon(); return FLASH_SECTOR_SIZE;
if(isinit == 0)
flash_init(&flashobj);
// Wait flash busy done (wip=0)
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
* data = HAL_READ32(SPI_FLASH_BASE, address);
SpicDisableRtl8195A();
return 1;
} }
/** uint32_t flash_get_page_size(const flash_t *obj)
* @brief Write a word to specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be programmed.
* @param data: Specified the data to be programmed.
* @retval status: Success:1 or Failure: Others.
*/
int flash_write_word(flash_t *obj, uint32_t address, uint32_t data)
{ {
u8 flashtype = 0; return FLASH_PAGE_SIZE;
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
flashtype = flashobj.SpicInitPara.flashtype;
//Write word
HAL_WRITE32(SPI_FLASH_BASE, address, data);
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
SpicDisableRtl8195A();
return 1;
} }
uint32_t flash_get_start_address(const flash_t *obj)
/**
* @brief Read a stream of data from specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be read.
* @param len: Specifies the length of the data to read.
* @param data: Specified the address to save the readback data.
* @retval status: Success:1 or Failure: Others.
*/
int flash_stream_read(flash_t *obj, uint32_t address, uint32_t len, uint8_t * data)
{ {
u32 offset_to_align; return FLASH_START;
u32 i;
u32 read_word;
uint8_t *ptr;
uint8_t *pbuf;
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
// Wait flash busy done (wip=0)
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
offset_to_align = address & 0x03;
pbuf = data;
if (offset_to_align != 0) {
// the start address is not 4-bytes aligned
read_word = HAL_READ32(SPI_FLASH_BASE, (address - offset_to_align));
ptr = (uint8_t*)&read_word + offset_to_align;
offset_to_align = 4 - offset_to_align;
for (i=0;i<offset_to_align;i++) {
*pbuf = *(ptr+i);
pbuf++;
len--;
if (len == 0) {
break;
}
}
}
address = (((address-1) >> 2) + 1) << 2; // address = next 4-bytes aligned
ptr = (uint8_t*)&read_word;
if ((u32)pbuf & 0x03) {
while (len >= 4) {
read_word = HAL_READ32(SPI_FLASH_BASE, address);
for (i=0;i<4;i++) {
*pbuf = *(ptr+i);
pbuf++;
}
address += 4;
len -= 4;
}
} else {
while (len >= 4) {
*((u32 *)pbuf) = HAL_READ32(SPI_FLASH_BASE, address);
pbuf += 4;
address += 4;
len -= 4;
}
}
if (len > 0) {
read_word = HAL_READ32(SPI_FLASH_BASE, address);
for (i=0;i<len;i++) {
*pbuf = *(ptr+i);
pbuf++;
}
}
SpicDisableRtl8195A();
return 1;
} }
/** uint32_t flash_get_size(const flash_t *obj)
* @brief Write a stream of data to specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be read.
* @param len: Specifies the length of the data to write.
* @param data: Specified the pointer of the data to be written.
* @retval status: Success:1 or Failure: Others.
*/
int flash_stream_write(flash_t *obj, uint32_t address, uint32_t len, uint8_t * data)
{ {
u32 offset_to_align; return FLASH_SIZE;
u32 align_addr;
u32 i;
u32 write_word;
uint8_t *ptr;
uint8_t *pbuf;
u8 flashtype = 0;
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
flashtype = flashobj.SpicInitPara.flashtype;
offset_to_align = address & 0x03;
pbuf = data;
if (offset_to_align != 0) {
// the start address is not 4-bytes aligned
align_addr = (address - offset_to_align);
write_word = HAL_READ32(SPI_FLASH_BASE, align_addr);
ptr = (uint8_t*)&write_word + offset_to_align;
offset_to_align = 4 - offset_to_align;
for (i=0;i<offset_to_align;i++) {
*(ptr+i) = *pbuf;
pbuf++;
len--;
if (len == 0) {
break;
}
}
//Write word
HAL_WRITE32(SPI_FLASH_BASE, align_addr, write_word);
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
address = (((address-1) >> 2) + 1) << 2; // address = next 4-bytes aligned
if ((u32)pbuf & 0x03) {
while (len >= 4) {
write_word = (u32)(*pbuf) | ((u32)(*(pbuf+1)) << 8) | ((u32)(*(pbuf+2)) << 16) | ((u32)(*(pbuf+3)) << 24);
//Write word
HAL_WRITE32(SPI_FLASH_BASE, address, write_word);
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
pbuf += 4;
address += 4;
len -= 4;
}
} else {
while (len >= 4) {
//Write word
HAL_WRITE32(SPI_FLASH_BASE, address, (u32)*((u32 *)pbuf));
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
pbuf += 4;
address += 4;
len -= 4;
}
}
if (len > 0) {
write_word = HAL_READ32(SPI_FLASH_BASE, address);
ptr = (uint8_t*)&write_word;
for (i=0;i<len;i++) {
*(ptr+i) = *pbuf;
pbuf++;
}
//Write word
HAL_WRITE32(SPI_FLASH_BASE, address, write_word);
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
SpicDisableRtl8195A();
return 1;
} }
/*
Function Description:
This function performans the same functionality as the function flash_stream_write.
It enhances write performance by reducing overheads.
Users can use either of functions depending on their needs.
* @brief Write a stream of data to specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be read.
* @param Length: Specifies the length of the data to write.
* @param data: Specified the pointer of the data to be written.
* @retval status: Success:1 or Failure: Others.
*/
int flash_burst_write(flash_t *obj, uint32_t address ,uint32_t Length, uint8_t * data)
{
u32 OccuSize;
u32 ProgramSize;
u32 PageSize;
u8 flashtype = 0;
PageSize = 256;
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
flashtype = flashobj.SpicInitPara.flashtype;
OccuSize = address & 0xFF;
if((Length >= PageSize) ||((Length + OccuSize) >= PageSize)){
ProgramSize = PageSize - OccuSize;
} else {
ProgramSize = Length;
}
flashobj.Length = Length;
while(Length > 0){
if(OccuSize){
SpicUserProgramRtl8195A(data, flashobj.SpicInitPara, address, &(flashobj.Length));
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
address += ProgramSize;
data+= ProgramSize;
Length -= ProgramSize;
OccuSize = 0;
} else{
while((flashobj.Length) >= PageSize){
SpicUserProgramRtl8195A(data, flashobj.SpicInitPara, address, &(flashobj.Length));
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
address += PageSize;
data+=PageSize;
Length -= PageSize;
}
flashobj.Length = Length;
if((flashobj.Length) > 0){
SpicUserProgramRtl8195A(data, flashobj.SpicInitPara, address, &(flashobj.Length));
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
break;
}
}
flashobj.Length = Length;
}
SpicDisableRtl8195A();
return 1;
}
/**
* @brief Read a stream of data from specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be read.
* @param len: Specifies the length of the data to read.
* @param data: Specified the address to save the readback data.
* @retval status: Success:1 or Failure: Others.
*/
int flash_burst_read(flash_t *obj, uint32_t address, uint32_t Length, uint8_t * data)
{
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
// Wait flash busy done (wip=0)
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
SpicUserReadRtl8195A(Length, address, data, SpicOneBitMode);
SpicDisableRtl8195A();
return 1;
}
int flash_get_status(flash_t *obj)
{
u8 Status = 0;
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
Status = SpicGetFlashStatusRefinedRtl8195A(flashobj.SpicInitPara);
SpicDisableRtl8195A();
return Status;
}
/*
Function Description:
Please refer to the datatsheet of flash for more details of the content of status register.
The block protected area and the corresponding control bits are provided in the flash datasheet.
* @brief Set Status register to enable desired operation
* @param obj: Specifies the parameter of flash object.
* @param data: Specifies which bit users like to set
ex: if users want to set the third bit, data = 0x8.
*/
int flash_set_status(flash_t *obj, uint32_t data)
{
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
SpicSetFlashStatusRefinedRtl8195A(data, flashobj.SpicInitPara);
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
DBG_8195A("Status Register After Setting= %x\n", flash_get_status(&flashobj));
SpicDisableRtl8195A();
return 1;
}
/*
Function Description:
This function aims to reset the status register, please make sure the operation is appropriate.
*/
void flash_reset_status(flash_t *obj)
{
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
SpicSetFlashStatusRefinedRtl8195A(0, flashobj.SpicInitPara);
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
SpicDisableRtl8195A();
}
/*
Function Description:
This function is only for Micron 512Mbit flash to access beyond 128Mbit by switching between four 128 Mbit area.
Please refer to flash datasheet for more information about memory mapping.
*/
int flash_set_extend_addr(flash_t *obj, uint32_t data)
{
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
SpicSetExtendAddrRtl8195A(data, flashobj.SpicInitPara);
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
DBG_8195A("Extended Address Register After Setting= %x\n", flash_get_extend_addr(&flashobj));
SpicDisableRtl8195A();
return 1;
}
int flash_get_extend_addr(flash_t *obj)
{
u8 Status = 0;
flash_turnon();
if(isinit == 0)
flash_init(&flashobj);
Status = SpicGetExtendAddrRtl8195A(flashobj.SpicInitPara);
SpicDisableRtl8195A();
return Status;
}

View File

@ -1,59 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2016 Realtek Semiconductor Corp.
*
* 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.
*/
#ifndef MBED_EXT_FLASH_API_EXT_H
#define MBED_EXT_FLASH_API_EXT_H
#include "device.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct flash_s flash_t;
/**
* global data structure
*/
extern flash_t flash;
enum {
FLASH_COMPLETE = 0,
FLASH_ERROR_2 = 1,
};
//void flash_init (flash_t *obj);
void flash_erase_sector (flash_t *obj, uint32_t address);
void flash_erase_block(flash_t * obj, uint32_t address);
int flash_read_word (flash_t *obj, uint32_t address, uint32_t * data);
int flash_write_word (flash_t *obj, uint32_t address, uint32_t data);
int flash_stream_read (flash_t *obj, uint32_t address, uint32_t len, uint8_t * data);
int flash_stream_write (flash_t *obj, uint32_t address, uint32_t len, uint8_t * data);
void flash_write_protect (flash_t *obj, uint32_t protect);
int flash_get_status(flash_t * obj);
int flash_set_status(flash_t * obj, uint32_t data);
void flash_reset_status(flash_t * obj);
int flash_burst_write(flash_t * obj, uint32_t address, uint32_t Length, uint8_t * data);
int flash_burst_read(flash_t * obj, uint32_t address, uint32_t Length, uint8_t * data);
int flash_set_extend_addr(flash_t * obj, uint32_t data);
int flash_get_extend_addr(flash_t * obj);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,467 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2016 Realtek Semiconductor Corp.
*
* 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 "objects.h"
#include "PinNames.h"
#include "pinmap.h"
#include "rtl8195a.h"
#include "flash_ext.h"
extern u32 ConfigDebugInfo;
extern SPIC_INIT_PARA SpicInitParaAllClk[3][CPU_CLK_TYPE_NO];
static int flash_inited = 0;
static flash_t flashobj;
static void flash_ext_init(void)
{
if (!SpicFlashInitRtl8195A(SpicOneBitMode)){
HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO3, HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_DSTBY_INFO3)|0xf);
} else {
flash_inited = 1;
}
flashobj.SpicInitPara.flashtype = SpicInitParaAllClk[0][0].flashtype;
}
void __flash_ext_turnon(void)
{
SPI_FLASH_PIN_FCTRL(ON);
SpicWaitBusyDoneRtl8195A();
if (flash_inited == 0) {
flash_ext_init();
}
}
void __flash_ext_turnoff(void)
{
SpicDisableRtl8195A();
}
void flash_ext_write_protect(flash_t *obj, uint32_t protect)
{
__flash_ext_turnon();
SpicWriteProtectFlashRtl8195A(protect);
__flash_ext_turnoff();
}
void __flash_ext_erase_sector(flash_t *obj, uint32_t address)
{
SpicSectorEraseFlashRtl8195A(SPI_FLASH_BASE+address);
}
void flash_ext_erase_sector(flash_t *obj, uint32_t address)
{
__flash_ext_turnon();
__flash_ext_erase_sector(obj, address);
__flash_ext_turnoff();
}
void flash_ext_erase_block(flash_t *obj, uint32_t address)
{
__flash_ext_turnon();
SpicBlockEraseFlashRtl8195A(SPI_FLASH_BASE+address);
__flash_ext_turnoff();
}
int flash_ext_read_word(flash_t *obj, uint32_t address, uint32_t *data)
{
__flash_ext_turnon();
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
*data = HAL_READ32(SPI_FLASH_BASE, address);
__flash_ext_turnoff();
return 0;
}
/**
* @brief Write a word to specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be programmed.
* @param data: Specified the data to be programmed.
* @retval status: Success:1 or Failure: Others.
*/
int flash_ext_write_word(flash_t *obj, uint32_t address, uint32_t data)
{
u8 flashtype = 0;
__flash_ext_turnon();
flashtype = flashobj.SpicInitPara.flashtype;
HAL_WRITE32(SPI_FLASH_BASE, address, data);
SpicWaitBusyDoneRtl8195A();
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else {
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
__flash_ext_turnoff();
return 0;
}
/**
* @brief Read a stream of data from specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be read.
* @param len: Specifies the length of the data to read.
* @param data: Specified the address to save the readback data.
* @retval status: Success:1 or Failure: Others.
*/
int flash_ext_stream_read(flash_t *obj, uint32_t addr, uint32_t len, uint8_t *data)
{
uint32_t i, offset, word;
uint8_t *ptr, *pbuf;
__flash_ext_turnon();
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
offset = addr & 0x03;
addr = addr & ~0x03;
pbuf = data;
if (offset != 0) {
word = HAL_READ32(SPI_FLASH_BASE, addr);
ptr = (uint8_t *)&word + offset;
offset = 4 - offset;
for (i = 0; i < offset && len > 0; i++, len--) {
*pbuf = *ptr;
pbuf++;
ptr++;
}
addr += 4;
}
ptr = (uint8_t *)&word;
if ((uint32_t)pbuf & 0x03) {
while (len >= 4) {
word = HAL_READ32(SPI_FLASH_BASE, addr);
for (i = 0; i < 4; i++) {
*pbuf = *(ptr+i);
pbuf++;
}
addr += 4;
len -= 4;
}
} else {
while (len >= 4) {
*((uint32_t *)pbuf) = HAL_READ32(SPI_FLASH_BASE, addr);
pbuf += 4;
addr += 4;
len -= 4;
}
}
if (len > 0) {
word = HAL_READ32(SPI_FLASH_BASE, addr);
for (i = 0; i < len; i++) {
*pbuf = *(ptr+i);
pbuf++;
}
}
__flash_ext_turnoff();
return 0;
}
/**
* @brief Write a stream of data to specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be read.
* @param len: Specifies the length of the data to write.
* @param data: Specified the pointer of the data to be written.
* @retval status: Success:1 or Failure: Others.
*/
int __flash_ext_stream_write(flash_t *obj, uint32_t addr, uint32_t len, const uint8_t *data)
{
uint32_t i, offset, word;
const uint8_t*pbuf;
uint8_t *ptr;
u8 flashtype = 0;
offset = addr & 0x03;
addr = addr & ~0x03;
pbuf = data;
flashtype = flashobj.SpicInitPara.flashtype;
if (offset != 0) {
word = HAL_READ32(SPI_FLASH_BASE, addr);
ptr = (uint8_t *)&word + offset;
offset = 4 - offset;
for (i = 0; i < offset && len > 0; i++, len--) {
*ptr = *pbuf;
pbuf++;
ptr++;
}
HAL_WRITE32(SPI_FLASH_BASE, addr, word);
SpicWaitBusyDoneRtl8195A();
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else {
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
addr += 4;
}
if ((uint32_t)pbuf & 0x03) {
while (len >= 4) {
word = (uint32_t)(*pbuf) | ((uint32_t)(*(pbuf+1)) << 8)|
((uint32_t)(*(pbuf+2)) << 16) | ((uint32_t)(*(pbuf+3)) << 24);
HAL_WRITE32(SPI_FLASH_BASE, addr, word);
SpicWaitBusyDoneRtl8195A();
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else {
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
pbuf += 4;
addr += 4;
len -= 4;
}
} else {
while (len >= 4) {
HAL_WRITE32(SPI_FLASH_BASE, addr, (uint32_t)*((uint32_t *)pbuf));
SpicWaitBusyDoneRtl8195A();
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else {
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
pbuf += 4;
addr += 4;
len -= 4;
}
}
if (len > 0) {
word = HAL_READ32(SPI_FLASH_BASE, addr);
ptr = (uint8_t*)&word;
for (i = 0; i < len; i++) {
*(ptr+i) = *pbuf;
pbuf++;
}
HAL_WRITE32(SPI_FLASH_BASE, addr, word);
SpicWaitBusyDoneRtl8195A();
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else {
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
}
return 0;
}
int flash_ext_stream_write(flash_t *obj, uint32_t addr, uint32_t len, uint8_t *data)
{
int32_t status;
__flash_ext_turnon();
status = __flash_ext_stream_write(obj, addr, len, data);
__flash_ext_turnoff();
return status;
}
int flash_stream_read(flash_t *obj, uint32_t addr, uint32_t len, uint8_t *data)
{
return flash_ext_stream_read(obj, addr, len, data);
}
int flash_stream_write(flash_t *obj, uint32_t addr, uint32_t len, uint8_t *data)
{
return flash_ext_stream_write(obj, addr, len, data);
}
/*
Function Description:
This function performans the same functionality as the function flash_stream_write.
It enhances write performance by reducing overheads.
Users can use either of functions depending on their needs.
* @brief Write a stream of data to specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be read.
* @param length: Specifies the length of the data to write.
* @param data: Specified the pointer of the data to be written.
* @retval status: Success:1 or Failure: Others.
*/
int flash_ext_burst_write(flash_t *obj, uint32_t address ,uint32_t length, uint8_t *data)
{
u32 OccuSize;
u32 ProgramSize;
u32 PageSize;
u8 flashtype = 0;
PageSize = 256;
__flash_ext_turnon();
flashtype = flashobj.SpicInitPara.flashtype;
OccuSize = address & 0xFF;
if((length >= PageSize) ||((length + OccuSize) >= PageSize)){
ProgramSize = PageSize - OccuSize;
} else {
ProgramSize = length;
}
flashobj.Length = length;
while(length > 0){
if(OccuSize){
SpicUserProgramRtl8195A(data, flashobj.SpicInitPara, address, &(flashobj.Length));
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else {
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
address += ProgramSize;
data += ProgramSize;
length -= ProgramSize;
OccuSize = 0;
} else{
while((flashobj.Length) >= PageSize){
SpicUserProgramRtl8195A(data, flashobj.SpicInitPara, address, &(flashobj.Length));
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else {
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
address += PageSize;
data += PageSize;
length -= PageSize;
}
flashobj.Length = length;
if((flashobj.Length) > 0){
SpicUserProgramRtl8195A(data, flashobj.SpicInitPara, address, &(flashobj.Length));
// Wait spic busy done
SpicWaitBusyDoneRtl8195A();
// Wait flash busy done (wip=0)
if(flashtype == FLASH_MICRON){
SpicWaitOperationDoneRtl8195A(flashobj.SpicInitPara);
} else {
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
}
break;
}
}
flashobj.Length = length;
}
__flash_ext_turnoff();
return 0;
}
/**
* @brief Read a stream of data from specified address
* @param obj: Specifies the parameter of flash object.
* @param address: Specifies the address to be read.
* @param len: Specifies the length of the data to read.
* @param data: Specified the address to save the readback data.
* @retval status: Success:1 or Failure: Others.
*/
int flash_ext_burst_read(flash_t *obj, uint32_t address, uint32_t length, uint8_t *data)
{
__flash_ext_turnon();
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
SpicUserReadRtl8195A(length, address, data, SpicOneBitMode);
__flash_ext_turnoff();
return 0;
}
int flash_ext_get_status(flash_t *obj)
{
uint8_t status = 0;
__flash_ext_turnon();
status = SpicGetFlashStatusRefinedRtl8195A(flashobj.SpicInitPara);
__flash_ext_turnoff();
return status;
}
/*
Function Description:
Please refer to the datatsheet of flash for more details of the content of status register.
The block protected area and the corresponding control bits are provided in the flash datasheet.
* @brief Set Status register to enable desired operation
* @param obj: Specifies the parameter of flash object.
* @param data: Specifies which bit users like to set
ex: if users want to set the third bit, data = 0x8.
*/
int flash_ext_set_status(flash_t *obj, uint32_t data)
{
__flash_ext_turnon();
SpicSetFlashStatusRefinedRtl8195A(data, flashobj.SpicInitPara);
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
__flash_ext_turnoff();
return 0;
}
/*
Function Description:
This function aims to reset the status register, please make sure the operation is appropriate.
*/
void flash_ext_reset_status(flash_t *obj)
{
__flash_ext_turnon();
SpicSetFlashStatusRefinedRtl8195A(0, flashobj.SpicInitPara);
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
__flash_ext_turnoff();
}
int flash_ext_get_extend_addr(flash_t *obj)
{
uint8_t addr = 0;
__flash_ext_turnon();
addr = SpicGetExtendAddrRtl8195A(flashobj.SpicInitPara);
__flash_ext_turnoff();
return addr;
}
/*
Function Description:
This function is only for Micron 512Mbit flash to access beyond 128Mbit by switching between four 128 Mbit area.
Please refer to flash datasheet for more information about memory mapping.
*/
int flash_ext_set_extend_addr(flash_t *obj, uint32_t data)
{
__flash_ext_turnon();
SpicSetExtendAddrRtl8195A(data, flashobj.SpicInitPara);
SpicWaitWipDoneRefinedRtl8195A(flashobj.SpicInitPara);
__flash_ext_turnoff();
return 0;
}

View File

@ -0,0 +1,53 @@
/* mbed Microcontroller Library
* Copyright (c) 2013-2016 Realtek Semiconductor Corp.
*
* 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.
*/
#ifndef MBED_FLASH_EXT_H
#define MBED_FLASH_EXT_H
#include "device.h"
#include "flash_api.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FLASH_PAGE_SIZE 256
#define FLASH_SIZE 0x100000
#define FLASH_OFS_START 0xc0000
#define FLASH_OFS_END (FLASH_OFS_START + FLASH_SIZE)
extern void flash_ext_erase_sector(flash_t *obj, uint32_t address);
extern void flash_ext_erase_block(flash_t * obj, uint32_t address);
extern int flash_ext_read_word(flash_t *obj, uint32_t address, uint32_t * data);
extern int flash_ext_write_word(flash_t *obj, uint32_t address, uint32_t data);
extern int flash_ext_stream_read(flash_t *obj, uint32_t address, uint32_t len, uint8_t * data);
extern int flash_ext_stream_write(flash_t *obj, uint32_t address, uint32_t len, uint8_t * data);
extern int flash_stream_read(flash_t *obj, uint32_t addr, uint32_t len, uint8_t *data);
extern int flash_stream_write(flash_t *obj, uint32_t addr, uint32_t len, uint8_t *data);
extern void flash_ext_write_protect(flash_t *obj, uint32_t protect);
extern int flash_ext_get_status(flash_t *obj);
extern int flash_ext_set_status(flash_t *obj, uint32_t data);
extern void flash_ext_reset_status(flash_t *obj);
/* Internal functions for flash API */
extern void __flash_ext_turnon(void);
extern void __flash_ext_turnoff(void);
extern void __flash_ext_erase_sector(flash_t *obj, uint32_t address);
extern int __flash_ext_stream_write(flash_t *obj, uint32_t addr, uint32_t len, const uint8_t *data);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -2972,7 +2972,7 @@
"extra_labels": ["Realtek", "AMEBA", "RTL8195A"], "extra_labels": ["Realtek", "AMEBA", "RTL8195A"],
"macros": ["__RTL8195A__","CONFIG_PLATFORM_8195A","CONFIG_MBED_ENABLED","PLATFORM_CMSIS_RTOS"], "macros": ["__RTL8195A__","CONFIG_PLATFORM_8195A","CONFIG_MBED_ENABLED","PLATFORM_CMSIS_RTOS"],
"supported_toolchains": ["GCC_ARM", "ARM", "IAR"], "supported_toolchains": ["GCC_ARM", "ARM", "IAR"],
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SPI", "TRNG", "EMAC"], "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SPI", "TRNG", "EMAC", "FLASH"],
"features": ["LWIP"], "features": ["LWIP"],
"post_binary_hook": { "post_binary_hook": {
"function": "RTL8195ACode.binary_hook", "function": "RTL8195ACode.binary_hook",