From 59f4ec8ae8385c2af4f2f6e064552279637e7976 Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Sun, 9 Oct 2016 13:26:46 +0800 Subject: [PATCH] CC2538 Flash Driver (#772) * CC2538 flash driver --- examples/platforms/cc2538/Makefile.am | 6 +- examples/platforms/cc2538/cc2538-reg.h | 4 + examples/platforms/cc2538/flash.c | 168 ++++++++++++++++++++++++ examples/platforms/cc2538/rom-utility.h | 72 ++++++++++ include/platform/flash.h | 2 +- 5 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 examples/platforms/cc2538/flash.c create mode 100644 examples/platforms/cc2538/rom-utility.h diff --git a/examples/platforms/cc2538/Makefile.am b/examples/platforms/cc2538/Makefile.am index cb2118f51..a1ab9ec62 100644 --- a/examples/platforms/cc2538/Makefile.am +++ b/examples/platforms/cc2538/Makefile.am @@ -38,13 +38,14 @@ libopenthread_cc2538_a_CPPFLAGS = \ libopenthread_cc2538_a_SOURCES = \ alarm.c \ - misc.c \ + flash.c \ logging.c \ + misc.c \ platform.c \ radio.c \ random.c \ - uart.c \ startup-gcc.c \ + uart.c \ $(NULL) if OPENTHREAD_ENABLE_DIAG @@ -56,6 +57,7 @@ endif noinst_HEADERS = \ cc2538-reg.h \ platform-cc2538.h \ + rom-utility.h \ $(NULL) if OPENTHREAD_BUILD_COVERAGE diff --git a/examples/platforms/cc2538/cc2538-reg.h b/examples/platforms/cc2538/cc2538-reg.h index 1b837dea7..c85277547 100644 --- a/examples/platforms/cc2538/cc2538-reg.h +++ b/examples/platforms/cc2538/cc2538-reg.h @@ -201,4 +201,8 @@ #define SOC_ADC_ADCCON1_RCTRL0 0x00000004 // ADCCON1 RCTRL bit 0 #define SOC_ADC_ADCCON1_RCTRL1 0x00000008 // ADCCON1 RCTRL bit 1 +#define FLASH_BASE 0x00200000 // Flash base address +#define FLASH_CTRL_FCTL 0x400D3008 // Flash control +#define FLASH_CTRL_DIECFG0 0x400D3014 // Flash information + #endif diff --git a/examples/platforms/cc2538/flash.c b/examples/platforms/cc2538/flash.c new file mode 100644 index 000000000..332030152 --- /dev/null +++ b/examples/platforms/cc2538/flash.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2016, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "platform-cc2538.h" +#include "rom-utility.h" + +#define FLASH_CTRL_FCTL_BUSY 0x00000080 + +enum +{ + FLASH_PAGE_SIZE = 0x800, +}; + +static ThreadError romStatusToThread(int32_t aStatus) +{ + ThreadError error = kThreadError_None; + + switch (aStatus) + { + case 0: + error = kThreadError_None; + break; + + case -1: + error = kThreadError_Failed; + break; + + case -2: + error = kThreadError_InvalidArgs; + break; + + default: + error = kThreadError_Abort; + } + + return error; +} + +ThreadError otPlatFlashInit(void) +{ + return kThreadError_None; +} + +uint32_t otPlatFlashGetSize(void) +{ + uint32_t reg = (HWREG(FLASH_CTRL_DIECFG0) & 0x00000070) >> 4; + + return reg ? (0x20000 * reg) : 0x10000; +} + +ThreadError otPlatFlashErasePage(uint32_t aAddress) +{ + ThreadError error = kThreadError_None; + int32_t status; + uint32_t address; + + VerifyOrExit(aAddress < otPlatFlashGetSize(), error = kThreadError_InvalidArgs); + + address = FLASH_BASE + aAddress - (aAddress & (FLASH_PAGE_SIZE - 1)); + status = ROM_PageErase(address, FLASH_PAGE_SIZE); + error = romStatusToThread(status); + +exit: + return error; +} + +ThreadError otPlatFlashStatusWait(uint32_t aTimeout) +{ + ThreadError error = kThreadError_None; + uint32_t start = otPlatAlarmGetNow(); + uint32_t busy = 1; + + while (busy && ((otPlatAlarmGetNow() - start) < aTimeout)) + { + busy = HWREG(FLASH_CTRL_FCTL) & FLASH_CTRL_FCTL_BUSY; + } + + VerifyOrExit(!busy, error = kThreadError_Busy); + +exit: + return error; +} + +uint32_t otPlatFlashWrite(uint32_t aAddress, uint8_t *aData, uint32_t aSize) +{ + int32_t status; + uint32_t busy = 1; + + VerifyOrExit(((aAddress + aSize) < otPlatFlashGetSize()) && + (!(aAddress & 3)) && (!(aSize & 3)), aSize = 0); + + status = ROM_ProgramFlash((uint32_t *)aData, aAddress + FLASH_BASE, aSize); + + while (busy) + { + busy = HWREG(FLASH_CTRL_FCTL) & FLASH_CTRL_FCTL_BUSY; + } + + VerifyOrExit(romStatusToThread(status) == kThreadError_None, aSize = 0); + +exit: + return aSize; +} + +uint32_t otPlatFlashRead(uint32_t aAddress, uint8_t *aData, uint32_t aSize) +{ + uint32_t size = 0; + + VerifyOrExit((aAddress + aSize) < otPlatFlashGetSize(), ;); + + while (size <= aSize) + { + uint32_t reg = HWREG(aAddress + FLASH_BASE); + uint8_t *byte = (uint8_t *)® + uint8_t maxIndex = 4; + + if (size == (aSize - aSize % 4)) + { + maxIndex = aSize % 4; + } + + for (uint8_t index = 0; index < maxIndex; index++, byte++, aData++) + { + *aData = *byte; + } + + size += maxIndex; + aAddress += maxIndex; + } + +exit: + return size; +} diff --git a/examples/platforms/cc2538/rom-utility.h b/examples/platforms/cc2538/rom-utility.h new file mode 100644 index 000000000..05982367d --- /dev/null +++ b/examples/platforms/cc2538/rom-utility.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ROM_UTILITY_H_ +#define ROM_UTILITY_H_ + +#define ROM_API_TABLE_ADDR 0x00000048 + +typedef uint32_t (* volatile FPTR_CRC32_T)(uint8_t * /*pData*/, uint32_t /*byteCount*/); +typedef uint32_t (* volatile FPTR_GETFLSIZE_T)(void); +typedef uint32_t (* volatile FPTR_GETCHIPID_T)(void); +typedef int32_t (* volatile FPTR_PAGEERASE_T)(uint32_t /*FlashAddr*/, uint32_t /*Size*/); +typedef int32_t (* volatile FPTR_PROGFLASH_T)(uint32_t * /*pRamData*/, uint32_t /*FlashAdr*/, uint32_t /*ByteCount*/); +typedef void (* volatile FPTR_RESETDEV_T)(void); +typedef void *(* volatile FPTR_MEMSET_T)(void * /*s*/, int32_t /*c*/, uint32_t /*n*/); +typedef void *(* volatile FPTR_MEMCPY_T)(void * /*s1*/, const void * /*s2*/, uint32_t /*n*/); +typedef int32_t (* volatile FPTR_MEMCMP_T)(const void * /*s1*/, const void * /*s2*/, uint32_t /*n*/); +typedef void *(* volatile FPTR_MEMMOVE_T)(void * /*s1*/, const void * /*s2*/, uint32_t /*n*/); + +typedef struct +{ + FPTR_CRC32_T Crc32; + FPTR_GETFLSIZE_T GetFlashSize; + FPTR_GETCHIPID_T GetChipId; + FPTR_PAGEERASE_T PageErase; + FPTR_PROGFLASH_T ProgramFlash; + FPTR_RESETDEV_T ResetDevice; + FPTR_MEMSET_T memset; + FPTR_MEMCPY_T memcpy; + FPTR_MEMCMP_T memcmp; + FPTR_MEMMOVE_T memmove; +} ROM_API_T; + +#define P_ROM_API ((ROM_API_T*) ROM_API_TABLE_ADDR) + +#define ROM_Crc32(a,b) P_ROM_API->Crc32(a,b) +#define ROM_GetFlashSize() P_ROM_API->GetFlashSize() +#define ROM_GetChipId() P_ROM_API->GetChipId() +#define ROM_PageErase(a,b) P_ROM_API->PageErase(a,b) +#define ROM_ProgramFlash(a,b,c) P_ROM_API->ProgramFlash(a,b,c) +#define ROM_ResetDevice() P_ROM_API->ResetDevice() +#define ROM_Memset(a,b,c) P_ROM_API->memset(a,b,c) +#define ROM_Memcpy(a,b,c) P_ROM_API->memcpy(a,b,c) +#define ROM_Memcmp(a,b,c) P_ROM_API->memcmp(a,b,c) +#define ROM_Memmove(a,b,c) P_ROM_API->memmove(a,b,c) + +#endif // ROM_UTILITY_H_ diff --git a/include/platform/flash.h b/include/platform/flash.h index b87591348..b1a6f4be6 100644 --- a/include/platform/flash.h +++ b/include/platform/flash.h @@ -78,7 +78,7 @@ ThreadError otPlatFlashErasePage(uint32_t aAddress); /** * Check whether flash is ready or busy. * - * @param[in] aTimeout The interval waiting for the flash operation to be done and become ready again. + * @param[in] aTimeout The interval in milliseconds waiting for the flash operation to be done and become ready again. * zero indicates that it is a polling function, and returns current status of flash immediately. * non-zero indicates that it is blocking there until the operation is done and become ready, or timeout expires. *