wolfBoot/hal/ti_hercules.c

264 lines
7.0 KiB
C

/* ti_hercules.c
*
* Copyright (C) 2021 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdint.h>
#include <string.h>
#include <target.h>
#include "image.h"
#include "hal.h"
#include "printf.h"
#ifndef CORTEX_R5
# error "wolfBoot TI Hercules HAL: wrong architecture selected. Please compile with TARGET=ti_hercules."
#endif
#include <F021.h>
#include <stdio.h>
/* #define FLASH_DEMO 1 */
/* public HAL functions */
void hal_init(void)
{
int freq_MHz = 16;
int st = Fapi_initializeFlashBanks(freq_MHz);
if (st != 0) {
wolfBoot_printf("Failed Fapi_initializeFlashBanks(%d) => (%d)\n", freq_MHz, st);
return;
}
#if defined(FLASH_DEMO) && FLASH_DEMO
{
uint32_t address = 0x1E0000;
const char msg[] = "wolfBoot was here!";
hal_flash_unlock();
if (hal_flash_erase(address, 7)) {
wolfBoot_printf("failed to erase\n");
}
if(hal_flash_write(address, msg, sizeof(msg))) {
wolfBoot_printf("failed to program\n");
}
hal_flash_lock();
if(memcmp(msg, (void*)address, sizeof(msg))) {
wolfBoot_printf("msg and flash don't match\n");
}
/* stall here to prevent accidentally including this in production */
while (1)
;
}
#endif
}
void hal_prepare_boot(void)
{
}
static inline Fapi_FlashBankType RAMFUNCTION f021_lookup_bank(uint32_t address) {
Fapi_FlashBankType bank = Fapi_FlashBank0;
if (address >= 0x200000) {
bank = Fapi_FlashBank1;
}
return bank;
}
static inline int RAMFUNCTION hal_flash_unlock_helper(uint32_t address) {
uint16_t en = 0xffff;
Fapi_FlashBankType bank = f021_lookup_bank(address);
while(FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
;
int st = Fapi_setActiveFlashBank(bank);
if (st != 0) {
wolfBoot_printf("Failed Fapi_setActiveFlashBank(%d) => (%d)\n", bank, st);
return -1;
}
st = Fapi_enableMainBankSectors(en);
if (st != 0) {
wolfBoot_printf("Failed Fapi_enableMainBankSectors() => (%d)\n", st);
return -1;
}
while(FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
;
return 0;
}
#define WRITE_BLOCK_SIZE FLASHBUFFER_SIZE
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
{
int st = 0;
int off = 0;
int blk_size = WRITE_BLOCK_SIZE;
uint8_t temp[WRITE_BLOCK_SIZE];
hal_flash_unlock_helper(address);
while(FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
;
if(len < WRITE_BLOCK_SIZE) {
memcpy(temp, (void*)(address - (address%WRITE_BLOCK_SIZE)), WRITE_BLOCK_SIZE);
memcpy(temp + (address%WRITE_BLOCK_SIZE), data, len);
st = Fapi_issueProgrammingCommand((void*)(address - (address%WRITE_BLOCK_SIZE)),
(uint8_t*)temp,
WRITE_BLOCK_SIZE,
NULL,
0,
Fapi_AutoEccGeneration);
} else {
off = 0;
blk_size = WRITE_BLOCK_SIZE;
while(off < len && st == 0) {
blk_size = WRITE_BLOCK_SIZE;
if (len-off < blk_size) {
blk_size = len - off;
}
st = Fapi_issueProgrammingCommand((void*)((uint8_t*)(address) + off),
(uint8_t*)data + off,
blk_size,
NULL,
0,
Fapi_AutoEccGeneration);
while(FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
;
off += blk_size;
}
}
if (st != 0) {
wolfBoot_printf("Failed Fapi_issueProgrammingCommand() => (%d)\n", st);
return -1;
}
while(FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
;
return 0;
}
void RAMFUNCTION hal_flash_unlock(void)
{
hal_flash_unlock_helper(0);
}
void RAMFUNCTION hal_flash_lock(void)
{
/* disable all sectors */
int st = Fapi_enableMainBankSectors(0);
if (st != 0) {
wolfBoot_printf("Failed Fapi_enableMainBankSectors() => (%d)\n", st);
return;
}
while(FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady)
;
}
static inline int RAMFUNCTION f021_flash_erase(uint32_t address) {
hal_flash_unlock_helper(address);
int st = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (void*)address);
if (st != 0) {
wolfBoot_printf("Failed Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, 0x%08x) => (%d)\n",
address, st);
return -1;
}
while(FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy)
;
if(FAPI_GET_FSM_STATUS != 0) {
wolfBoot_printf("failed to erase\n");
return -1;
}
return 0;
}
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
{
int ret = 0;
int found_start = 0;
int i;
Fapi_FlashBankType bank = f021_lookup_bank(address);
Fapi_FlashBankSectorsType bank_sectors;
uint32_t cur = 0;
uint32_t end = address + len;
Fapi_StatusType st = Fapi_getBankSectors(bank, &bank_sectors);
if (st != Fapi_Status_Success) {
return -1;
}
cur = bank_sectors.u32BankStartAddress;
hal_flash_unlock_helper(address);
for(i=0; i < bank_sectors.u32NumberOfSectors; i++) {
/* perfectly done */
if (end == cur && found_start) {
ret = 0;
break;
}
/* would erase past end */
else if (end < cur + bank_sectors.au16SectorSizes[i] * 1024) {
ret = -2;
break;
}
else if (address <= cur) {
if (address == cur) {
found_start = 1;
}
/* start address doesn't align with start of real sector */
if (!found_start && address < cur) {
ret = -3;
break;
}
ret = f021_flash_erase(cur);
if (ret != 0) {
break;
}
}
else {
/* intentionally fall through as loop hasn't found the start */
}
cur += bank_sectors.au16SectorSizes[i] * 1024;
}
return ret;
}