mirror of https://github.com/wolfSSL/wolfBoot.git
687 lines
21 KiB
C
687 lines
21 KiB
C
/* va416x0.c
|
|
*
|
|
* Copyright (C) 2026 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>
|
|
|
|
#ifndef WOLFBOOT_UNIT_TEST_VA416X0_FRAM
|
|
#include "image.h"
|
|
#include "string.h"
|
|
|
|
#include "va416x0.h"
|
|
|
|
/* Vorago HAL includes */
|
|
#include "va416xx_hal.h"
|
|
#include "va416xx_hal_clkgen.h"
|
|
#include "va416xx_hal_irqrouter.h"
|
|
#include "va416xx_hal_timer.h"
|
|
#include "va416xx_hal_ioconfig.h"
|
|
#include "va416xx_hal_spi.h"
|
|
|
|
#ifdef USE_HAL_SPI_FRAM
|
|
#include "spi_fram.h"
|
|
#endif
|
|
|
|
#include "printf.h"
|
|
#include "loader.h"
|
|
#endif
|
|
|
|
#ifndef WOLFBOOT_UNIT_TEST_VA416X0_FRAM
|
|
const stc_iocfg_pin_cfg_t bootDefaultConfig[] =
|
|
{
|
|
{VOR_PORTB,14,en_iocfg_dir_dncare, {{.fltclk=0,.invinp=0,.iewo=0,.opendrn=0,.invout=0,.plevel=0,.pen=0,.pwoa=0,.funsel=3,.iodis=0}}}, /* UART1 TX */
|
|
{VOR_PORTB,15,en_iocfg_dir_dncare, {{.fltclk=0,.invinp=0,.iewo=0,.opendrn=0,.invout=0,.plevel=0,.pen=0,.pwoa=0,.funsel=3,.iodis=0}}}, /* UART1 RX */
|
|
|
|
{VOR_PORTG, 0,en_iocfg_dir_dncare, {{.fltclk=0,.invinp=0,.iewo=0,.opendrn=0,.invout=0,.plevel=0,.pen=0,.pwoa=0,.funsel=1,.iodis=0}}}, /* UART0 TX */
|
|
{VOR_PORTG, 1,en_iocfg_dir_dncare, {{.fltclk=0,.invinp=0,.iewo=0,.opendrn=0,.invout=0,.plevel=0,.pen=0,.pwoa=0,.funsel=1,.iodis=0}}}, /* UART0 RX */
|
|
{VOR_PORTG, 2,en_iocfg_dir_output, {{.fltclk=0,.invinp=0,.iewo=0,.opendrn=0,.invout=0,.plevel=0,.pen=0,.pwoa=0,.funsel=1,.iodis=0}}}, /* out low */
|
|
|
|
{VOR_PORTG, 5,en_iocfg_dir_output, {{.fltclk=0,.invinp=0,.iewo=0,.opendrn=0,.invout=0,.plevel=0,.pen=0,.pwoa=0,.funsel=0,.iodis=0}}}, /* LED DS2 */
|
|
{VOR_PORTF,15,en_iocfg_dir_output, {{.fltclk=0,.invinp=0,.iewo=0,.opendrn=0,.invout=0,.plevel=0,.pen=0,.pwoa=0,.funsel=0,.iodis=0}}}, /* LED DS4 */
|
|
{0} /* end of array - with optimizations end of array was not being properly detected*/
|
|
};
|
|
|
|
|
|
#ifdef DEBUG_UART
|
|
|
|
#if defined(DEBUG_UART_NUM) && DEBUG_UART_NUM == 0
|
|
#define DEBUG_UART_BASE VOR_UART0
|
|
#elif defined(DEBUG_UART_NUM) && DEBUG_UART_NUM == 1
|
|
#define DEBUG_UART_BASE VOR_UART1
|
|
#elif defined(DEBUG_UART_NUM) && DEBUG_UART_NUM == 2
|
|
#define DEBUG_UART_BASE VOR_UART2
|
|
#endif
|
|
|
|
#ifndef DEBUG_UART_BASE
|
|
/* default to UART0 */
|
|
#define DEBUG_UART_BASE VOR_UART0
|
|
#endif
|
|
|
|
#ifndef DEBUG_UART_BAUD
|
|
#define DEBUG_UART_BAUD 115200
|
|
#endif
|
|
|
|
#define UART_CLK (SystemCoreClock / 4)
|
|
#define UART2_CLK (SystemCoreClock / 2)
|
|
|
|
#define UART_CALC_CLOCKSCALE(_scc,_baud) ((_scc / (_baud * 16)) << \
|
|
UART_CLKSCALE_INT_Pos) | \
|
|
(((((_scc % (_baud * 16)) * \
|
|
64 + (_baud * 8)) / \
|
|
(_baud * 16))) << \
|
|
UART_CLKSCALE_FRAC_Pos)
|
|
|
|
|
|
static void UartInit(VOR_UART_Type* uart, uint32_t baudrate)
|
|
{
|
|
if (VOR_UART0 == uart) {
|
|
VOR_SYSCONFIG->PERIPHERAL_CLK_ENABLE |= CLK_ENABLE_UART0;
|
|
uart->CLKSCALE = UART_CALC_CLOCKSCALE(UART_CLK, baudrate);
|
|
} else if (VOR_UART1 == uart) {
|
|
VOR_SYSCONFIG->PERIPHERAL_CLK_ENABLE |= CLK_ENABLE_UART1;
|
|
uart->CLKSCALE = UART_CALC_CLOCKSCALE(UART_CLK, baudrate);
|
|
} else if (VOR_UART2 == uart) {
|
|
VOR_SYSCONFIG->PERIPHERAL_CLK_ENABLE |= CLK_ENABLE_UART2;
|
|
uart->CLKSCALE = UART_CALC_CLOCKSCALE(UART2_CLK, baudrate);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
/* Configure word size and RTS behavior. */
|
|
uart->CTRL = (3 << UART_CTRL_WORDSIZE_Pos) | (UART_CTRL_DEFRTS_Msk);
|
|
|
|
/* Enable CTS flow control IO, if needed */
|
|
#ifdef configUART_CTS_FLOW_CONTROL
|
|
uart->CTRL |= UART_CTRL_AUTOCTS_Msk;
|
|
#endif
|
|
|
|
/* Enable RTS flow control IO, if needed */
|
|
#ifdef configUART_RTS_FLOW_CONTROL
|
|
uart->CTRL |= UART_CTRL_AUTORTS_Msk;
|
|
#endif
|
|
|
|
/* Enable RX interrupts as soon as a character is received */
|
|
uart->IRQ_ENB = UART_IRQ_ENB_IRQ_RX_Msk;
|
|
uart->RXFIFOIRQTRG = 1;
|
|
uart->TXFIFOIRQTRG = 8;
|
|
|
|
if (VOR_UART0 == uart) {
|
|
NVIC_SetPriority(UART0_RX_IRQn, 1);
|
|
NVIC_EnableIRQ(UART0_RX_IRQn);
|
|
} else if (VOR_UART1 == uart) {
|
|
NVIC_SetPriority(UART1_RX_IRQn, 1);
|
|
NVIC_EnableIRQ(UART1_RX_IRQn);
|
|
} else {
|
|
NVIC_SetPriority(UART2_RX_IRQn, 1);
|
|
NVIC_EnableIRQ(UART2_RX_IRQn);
|
|
}
|
|
|
|
/* Enable UART */
|
|
uart->ENABLE = (UART_ENABLE_RXENABLE_Msk |
|
|
UART_ENABLE_TXENABLE_Msk);
|
|
|
|
/* send a break to let rx state machine reset */
|
|
uart->TXBREAK = 32;
|
|
}
|
|
|
|
void uart_init(void)
|
|
{
|
|
UartInit(DEBUG_UART_BASE, DEBUG_UART_BAUD);
|
|
}
|
|
|
|
void uart_write(const char* buf, unsigned int sz)
|
|
{
|
|
uint32_t pos = 0;
|
|
while (sz-- > 0) {
|
|
char c = buf[pos++];
|
|
if (c == '\n') { /* handle CRLF */
|
|
while((DEBUG_UART_BASE->TXSTATUS & UART_TXSTATUS_WRRDY_Msk) == 0);
|
|
DEBUG_UART_BASE->DATA = '\r';
|
|
}
|
|
while((DEBUG_UART_BASE->TXSTATUS & UART_TXSTATUS_WRRDY_Msk) == 0);
|
|
DEBUG_UART_BASE->DATA = c;
|
|
}
|
|
}
|
|
|
|
void uart_flush(void)
|
|
{
|
|
/* wait for TX FIFO to be empty */
|
|
while (DEBUG_UART_BASE->TXSTATUS & UART_TXSTATUS_WRBUSY_Msk);
|
|
}
|
|
#endif /* DEBUG_UART */
|
|
#endif /* !WOLFBOOT_UNIT_TEST_VA416X0_FRAM */
|
|
|
|
|
|
/* FRAM Driver */
|
|
/* Commands */
|
|
#define FRAM_WREN 0x06
|
|
#define FRAM_WRDI 0x04
|
|
#define FRAM_RDSR 0x05
|
|
#define FRAM_WRSR 0x01
|
|
#define FRAM_READ 0x03
|
|
#define FRAM_WRITE 0x02
|
|
#define FRAM_RDID 0x9F
|
|
#define FRAM_SLEEP 0xB9
|
|
|
|
#ifndef USE_HAL_SPI_FRAM
|
|
static hal_spi_handle_t spiHandle;
|
|
|
|
static void FRAM_WaitIdle(uint8_t spiBank)
|
|
{
|
|
if (spiBank >= SPI_NUM_BANKS) {
|
|
return;
|
|
}
|
|
|
|
/* Wait until TxBuf sends all */
|
|
while (!(VOR_SPI->BANK[spiBank].STATUS & SPI_STATUS_TFE_Msk));
|
|
/* Wait here until bytes are fully transmitted */
|
|
while (VOR_SPI->BANK[spiBank].STATUS & SPI_STATUS_BUSY_Msk);
|
|
/* Clear Tx & RX fifo */
|
|
VOR_SPI->BANK[spiBank].FIFO_CLR =
|
|
(SPI_FIFO_CLR_RXFIFO_Msk | SPI_FIFO_CLR_TXFIFO_Msk);
|
|
}
|
|
|
|
static void FRAM_AbortWriteTransaction(uint8_t spiBank)
|
|
{
|
|
/* Terminate a split write transaction after a command-phase failure so
|
|
* the next FRAM operation does not inherit the previous chip-select state.
|
|
*/
|
|
FRAM_WaitIdle(spiBank);
|
|
spiHandle.state = hal_spi_state_ready;
|
|
}
|
|
|
|
/* Init SPI FRAM access */
|
|
hal_status_t FRAM_Init(uint8_t spiBank, uint8_t csNum)
|
|
{
|
|
hal_status_t status = hal_status_ok;
|
|
uint8_t spiData[2];
|
|
|
|
/* Initialize the SPI handle */
|
|
memset(&spiHandle, 0, sizeof(spiHandle));
|
|
spiHandle.locked = false;
|
|
spiHandle.state = hal_spi_state_reset;
|
|
spiHandle.spi = &VOR_SPI->BANK[spiBank];
|
|
spiHandle.init.blockmode = true;
|
|
spiHandle.init.bmstall = true;
|
|
spiHandle.init.clkDiv = 2; /* 40MHz */
|
|
spiHandle.init.loopback = false;
|
|
spiHandle.init.mdlycap = false;
|
|
spiHandle.init.mode = hal_spi_clkmode_0;
|
|
spiHandle.init.ms = hal_spi_ms_master;
|
|
spiHandle.init.chipSelect = csNum;
|
|
spiHandle.init.wordLen = 8;
|
|
|
|
status = HAL_Spi_Init(&spiHandle);
|
|
if (status == hal_status_ok) {
|
|
spiData[0] = FRAM_WREN; /* Set Write Enable Latch(WEL) bit */
|
|
status = HAL_Spi_Transmit(&spiHandle, spiData, 1, 0, true);
|
|
HAL_Timer_DelayMs(1);
|
|
if (status == hal_status_ok)
|
|
status = HAL_Spi_Transmit(&spiHandle, spiData, 1, 0, true);
|
|
if (status == hal_status_ok) {
|
|
spiData[0] = FRAM_WRSR; /* Write single-byte Status Register message */
|
|
spiData[1] = 0x00; /* Clear the BP1/BP0 protection */
|
|
status = HAL_Spi_Transmit(&spiHandle, spiData, 2, 0, true);
|
|
}
|
|
FRAM_WaitIdle(spiBank);
|
|
spiHandle.state = hal_spi_state_ready;
|
|
}
|
|
wolfBoot_printf("FRAM_Init: status %d\n", status);
|
|
return status;
|
|
}
|
|
|
|
hal_status_t FRAM_Write(uint8_t spiBank, uint32_t addr, uint8_t *buf,
|
|
uint32_t len)
|
|
{
|
|
hal_status_t status = hal_status_ok;
|
|
uint8_t spiData[4];
|
|
|
|
/* Validate input parameters */
|
|
if (buf == NULL || len == 0) {
|
|
return hal_status_badParam;
|
|
}
|
|
/* Bounds check: ensure write doesn't exceed FRAM size */
|
|
if (addr >= FRAM_SIZE || (addr + len) > FRAM_SIZE) {
|
|
return hal_status_badParam;
|
|
}
|
|
|
|
#ifdef DEBUG_EXT_FLASH
|
|
wolfBoot_printf("fram write: addr 0x%x, dst 0x%x, len %d\n",
|
|
addr, buf, len);
|
|
#endif
|
|
|
|
FRAM_WaitIdle(spiBank);
|
|
|
|
spiData[0] = FRAM_WREN;
|
|
status = HAL_Spi_Transmit(&spiHandle, spiData, 1, 0, true);
|
|
if (status != hal_status_ok)
|
|
return status;
|
|
spiData[0] = FRAM_WRITE; /* Write command */
|
|
spiData[1] = (uint8_t)((addr>>16) & 0xFF); /* Address high byte */
|
|
spiData[2] = (uint8_t)((addr>>8) & 0xFF); /* Address mid byte */
|
|
spiData[3] = (uint8_t)( addr & 0xFF); /* Address low byte */
|
|
status = HAL_Spi_Transmit(&spiHandle, spiData, 4, 0, false);
|
|
if (status != hal_status_ok) {
|
|
FRAM_AbortWriteTransaction(spiBank);
|
|
return status;
|
|
}
|
|
return HAL_Spi_Transmit(&spiHandle, buf, len, 0, true);
|
|
}
|
|
|
|
hal_status_t FRAM_Read(uint8_t spiBank, uint32_t addr, uint8_t *buf,
|
|
uint32_t len)
|
|
{
|
|
uint8_t spiData[4];
|
|
|
|
/* Validate input parameters */
|
|
if (buf == NULL || len == 0) {
|
|
return hal_status_badParam;
|
|
}
|
|
/* Bounds check: ensure read doesn't exceed FRAM size */
|
|
if (addr >= FRAM_SIZE || (addr + len) > FRAM_SIZE) {
|
|
return hal_status_badParam;
|
|
}
|
|
|
|
#ifdef DEBUG_EXT_FLASH
|
|
wolfBoot_printf("fram read: addr 0x%x, dst 0x%x, len %d\n",
|
|
addr, buf, len);
|
|
#endif
|
|
|
|
FRAM_WaitIdle(spiBank);
|
|
|
|
spiData[0] = FRAM_READ; /* Read command */
|
|
spiData[1] = (uint8_t)((addr>>16) & 0xFF); /* Address high byte */
|
|
spiData[2] = (uint8_t)((addr>>8) & 0xFF); /* Address mid byte */
|
|
spiData[3] = (uint8_t)( addr & 0xFF); /* Address low byte */
|
|
return HAL_Spi_TransmitReceive(&spiHandle, spiData, buf, 4, 4, len, 0, true);
|
|
}
|
|
#endif
|
|
|
|
#ifndef FRAM_ERASE_VALUE
|
|
#define FRAM_ERASE_VALUE 0xFF
|
|
#endif
|
|
hal_status_t FRAM_Erase(uint8_t spiBank, uint32_t addr, uint32_t len)
|
|
{
|
|
hal_status_t status;
|
|
uint8_t data[32];
|
|
|
|
#ifdef DEBUG_EXT_FLASH
|
|
wolfBoot_printf("fram erase: addr 0x%x, len %d\n", addr, len);
|
|
#endif
|
|
|
|
/* Write 0xFF to the address and length */
|
|
memset(data, FRAM_ERASE_VALUE, sizeof(data));
|
|
|
|
while (len > 0) {
|
|
uint32_t erase_len = (len > sizeof(data)) ? sizeof(data) : len;
|
|
status = FRAM_Write(ROM_SPI_BANK, addr, data, erase_len);
|
|
if (status != hal_status_ok) {
|
|
/* Return the hal_status_t unmodified; ext_flash_erase() is
|
|
* the single negation point to a negative error code. */
|
|
return status;
|
|
}
|
|
addr += erase_len;
|
|
len -= erase_len;
|
|
}
|
|
return hal_status_ok;
|
|
}
|
|
|
|
#ifndef WOLFBOOT_UNIT_TEST_VA416X0_FRAM
|
|
|
|
void RAMFUNCTION hal_flash_unlock(void)
|
|
{
|
|
|
|
}
|
|
|
|
void RAMFUNCTION hal_flash_lock(void)
|
|
{
|
|
|
|
}
|
|
|
|
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
|
{
|
|
/* not supported - no internal flash */
|
|
(void)address;
|
|
(void)data;
|
|
(void)len;
|
|
return 0;
|
|
}
|
|
|
|
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
|
|
{
|
|
/* not supported - no internal flash */
|
|
(void)address;
|
|
(void)len;
|
|
return 0;
|
|
}
|
|
#endif /* !WOLFBOOT_UNIT_TEST_VA416X0_FRAM */
|
|
|
|
#ifdef EXT_FLASH
|
|
void ext_flash_lock(void)
|
|
{
|
|
/* Disable writes to code memory space */
|
|
VOR_SYSCONFIG->ROM_PROT &= ~SYSCONFIG_ROM_PROT_WREN_Msk;
|
|
}
|
|
|
|
void ext_flash_unlock(void)
|
|
{
|
|
/* Enable writes to code memory space */
|
|
VOR_SYSCONFIG->ROM_PROT |= SYSCONFIG_ROM_PROT_WREN_Msk;
|
|
}
|
|
|
|
/* The VA416xx code RAM (IRAM, 0x00000000-0x0003FFFF) silently drops 8/16-bit
|
|
* stores when WREN=1 -- only word-aligned 32-bit stores stick (the ECC
|
|
* machinery computes parity per word and rejects sub-word writes without
|
|
* fault). A generic byte-wise memcpy/memset on the IRAM shadow appears to
|
|
* succeed but leaves the destination unchanged. These helpers do a
|
|
* read-modify-write of the containing word for each up-to-4-byte group, so
|
|
* the only stores emitted are 32-bit STR through a volatile pointer (which
|
|
* the compiler is required to emit verbatim, i.e. exactly one STR). */
|
|
static void iram_write(void *dst, const void *src, int len)
|
|
{
|
|
while (len > 0) {
|
|
/* Pointer-width mask: ~3u is 32 bits and would zero the high
|
|
* word of the address on 64-bit platforms. */
|
|
uintptr_t addr = (uintptr_t)dst & ~(uintptr_t)3;
|
|
uint32_t off = (uintptr_t)dst & 3u;
|
|
uint32_t word = *(volatile uint32_t *)addr;
|
|
uint8_t *wp = (uint8_t *)&word;
|
|
while (len > 0 && off < 4u) {
|
|
wp[off++] = *(const uint8_t *)src;
|
|
src = (const uint8_t *)src + 1;
|
|
dst = (uint8_t *)dst + 1;
|
|
len--;
|
|
}
|
|
*(volatile uint32_t *)addr = word;
|
|
}
|
|
}
|
|
|
|
static void iram_fill(void *dst, uint8_t val, int len)
|
|
{
|
|
while (len > 0) {
|
|
/* Pointer-width mask (see iram_write). */
|
|
uintptr_t addr = (uintptr_t)dst & ~(uintptr_t)3;
|
|
uint32_t off = (uintptr_t)dst & 3u;
|
|
uint32_t word = *(volatile uint32_t *)addr;
|
|
uint8_t *wp = (uint8_t *)&word;
|
|
while (len > 0 && off < 4u) {
|
|
wp[off++] = val;
|
|
dst = (uint8_t *)dst + 1;
|
|
len--;
|
|
}
|
|
*(volatile uint32_t *)addr = word;
|
|
}
|
|
}
|
|
|
|
int ext_flash_write(uintptr_t address, const uint8_t *data, int len)
|
|
{
|
|
hal_status_t status;
|
|
#ifdef DEBUG_EXT_FLASH
|
|
wolfBoot_printf("ext write: addr 0x%x, dst 0x%x, len %d\n",
|
|
address, data, len);
|
|
#endif
|
|
status = FRAM_Write(ROM_SPI_BANK, address, (uint8_t*)data, len);
|
|
if (status == hal_status_ok) {
|
|
/* update the shadow IRAM (word-aligned stores; see iram_write) */
|
|
iram_write((void*)address, data, len);
|
|
}
|
|
else {
|
|
return -(int)status; /* convert to negative error code */
|
|
}
|
|
return len;
|
|
}
|
|
|
|
int ext_flash_read(uintptr_t address, uint8_t *data, int len)
|
|
{
|
|
hal_status_t status;
|
|
#ifdef DEBUG_EXT_FLASH
|
|
wolfBoot_printf("ext read: addr 0x%x, dst 0x%x, len %d\n",
|
|
address, data, len);
|
|
#endif
|
|
status = FRAM_Read(ROM_SPI_BANK, address, data, len);
|
|
if (status == hal_status_ok) {
|
|
/* update the shadow IRAM (word-aligned stores; see iram_write) */
|
|
iram_write((void*)address, data, len);
|
|
}
|
|
else {
|
|
return -(int)status; /* convert to negative error code */
|
|
}
|
|
return len;
|
|
}
|
|
|
|
int ext_flash_erase(uintptr_t address, int len)
|
|
{
|
|
hal_status_t status;
|
|
#ifdef DEBUG_EXT_FLASH
|
|
wolfBoot_printf("ext erase: addr 0x%x, len %d\n", address, len);
|
|
#endif
|
|
status = FRAM_Erase(ROM_SPI_BANK, address, len);
|
|
if (status == hal_status_ok) {
|
|
/* update the shadow IRAM (word-aligned stores; see iram_fill) */
|
|
iram_fill((void*)address, 0xFF, len);
|
|
}
|
|
else {
|
|
return -(int)status; /* convert to negative error code */
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef TEST_EXT_FLASH
|
|
|
|
#ifndef TEST_EXT_ADDRESS
|
|
/* Start Address for test 246KB */
|
|
#define TEST_EXT_ADDRESS (246 * 1024)
|
|
#endif
|
|
|
|
static int test_ext_flash(void)
|
|
{
|
|
int ret;
|
|
uint32_t i;
|
|
uint8_t pageData[WOLFBOOT_SECTOR_SIZE] = { 0 };
|
|
|
|
#ifndef READONLY
|
|
/* Erase sector */
|
|
ret = ext_flash_erase(TEST_EXT_ADDRESS, sizeof(pageData));
|
|
wolfBoot_printf("Sector Erase: Ret %d\n", ret);
|
|
|
|
/* Write Page */
|
|
for (i=0; i<sizeof(pageData); i++) {
|
|
pageData[i] = (i & 0xff);
|
|
}
|
|
ret = ext_flash_write(TEST_EXT_ADDRESS, pageData, sizeof(pageData));
|
|
wolfBoot_printf("Page Write: Ret %d\n", ret);
|
|
#endif
|
|
|
|
/* Read page */
|
|
memset(pageData, 0, sizeof(pageData));
|
|
ret = ext_flash_read(TEST_EXT_ADDRESS, pageData, sizeof(pageData));
|
|
wolfBoot_printf("Page Read: Ret %d\n", ret);
|
|
|
|
wolfBoot_printf("Checking...\n");
|
|
/* Check data */
|
|
for (i=0; i<sizeof(pageData); i++) {
|
|
#if defined(DEBUG_QSPI) && DEBUG_QSPI > 1
|
|
wolfBoot_printf("check[%3d] %02x\n", i, pageData[i]);
|
|
#endif
|
|
if (pageData[i] != (i & 0xff)) {
|
|
wolfBoot_printf("Check Data @ %d failed\n", i);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
wolfBoot_printf("Flash Test Passed\n");
|
|
return ret;
|
|
}
|
|
#endif /* TEST_EXT_FLASH */
|
|
#endif /* EXT_FLASH */
|
|
|
|
#ifndef WOLFBOOT_UNIT_TEST_VA416X0_FRAM
|
|
#ifdef __WOLFBOOT /* build for wolfBoot only */
|
|
/* Configure Error Detection and Correction (EDAC) */
|
|
static void ConfigEdac(uint32_t ramScrub, uint32_t romScrub)
|
|
{
|
|
VOR_SYSCONFIG->RAM0_SCRUB = ramScrub;
|
|
VOR_SYSCONFIG->RAM1_SCRUB = ramScrub;
|
|
VOR_SYSCONFIG->ROM_SCRUB = romScrub;
|
|
|
|
IRQROUTER_ENABLE_CLOCK();
|
|
NVIC_EnableIRQ(EDAC_MBE_IRQn);
|
|
NVIC_SetPriority(EDAC_MBE_IRQn, 0);
|
|
NVIC_EnableIRQ(EDAC_SBE_IRQn);
|
|
NVIC_SetPriority(EDAC_SBE_IRQn, 0);
|
|
|
|
VOR_SYSCONFIG->IRQ_ENB = 0x3f; /* enable all IRQ */
|
|
}
|
|
#endif /* __WOLFBOOT */
|
|
|
|
void hal_init(void)
|
|
{
|
|
hal_status_t status;
|
|
|
|
/* get clock settings and update SystemCoreClock */
|
|
SystemCoreClockUpdate();
|
|
|
|
|
|
#ifdef __WOLFBOOT /* build for wolfBoot only */
|
|
/* Configure PLL to set CPU clock to 100MHz - 40MHz crystal * 2.5 */
|
|
status = HAL_Clkgen_PLL(CLK_CTRL0_XTAL_N_PLL2P5X);
|
|
if (status != hal_status_ok) {
|
|
/* continue anyways */
|
|
}
|
|
|
|
/* Disable Watchdog - should be already disabled out of reset */
|
|
VOR_WATCH_DOG->WDOGLOCK = WATCHDOG_UNLOCK_KEY;
|
|
VOR_WATCH_DOG->WDOGCONTROL = 0x0;
|
|
NVIC_ClearPendingIRQ(WATCHDOG_IRQn);
|
|
|
|
/* set FPU CP10 and CP11 Full Access */
|
|
SCB->CPACR |= (CPACR_CP10_FULL_ACCESS | CPACR_CP11_FULL_ACCESS);
|
|
|
|
/* Init EDAC */
|
|
ConfigEdac(WOLFBOOT_EDAC_RAM_SCRUB, WOLFBOOT_EDAC_ROM_SCRUB);
|
|
#endif /* __WOLFBOOT */
|
|
|
|
/* Call SDK HAL initialization function */
|
|
status = HAL_Init();
|
|
if (status != hal_status_ok) {
|
|
/* continue anyways */
|
|
}
|
|
|
|
/* Configure the pins */
|
|
status = HAL_Iocfg_SetupPins(bootDefaultConfig);
|
|
if (status != hal_status_ok) {
|
|
/* continue anyways */
|
|
}
|
|
|
|
#ifdef DEBUG_UART
|
|
uart_init();
|
|
#ifdef __WOLFBOOT
|
|
uart_write("wolfBoot HAL Init\n", 18);
|
|
#endif
|
|
#endif
|
|
|
|
/* Init the FRAM SPI device */
|
|
status = FRAM_Init(ROM_SPI_BANK, ROM_SPI_CSN);
|
|
if (status != hal_status_ok) {
|
|
#ifdef DEBUG
|
|
wolfBoot_printf("FRAM_Init failed\n");
|
|
#endif
|
|
/* continue anyways */
|
|
}
|
|
|
|
#ifdef TEST_EXT_FLASH
|
|
test_ext_flash();
|
|
#endif
|
|
}
|
|
|
|
void hal_prepare_boot(void)
|
|
{
|
|
#ifdef DEBUG_UART
|
|
uart_flush();
|
|
|
|
/* Disable UART to give app a clean state */
|
|
DEBUG_UART_BASE->IRQ_ENB = 0;
|
|
DEBUG_UART_BASE->ENABLE = 0;
|
|
#if defined(DEBUG_UART_NUM) && DEBUG_UART_NUM == 1
|
|
NVIC_DisableIRQ(UART1_RX_IRQn);
|
|
NVIC_ClearPendingIRQ(UART1_RX_IRQn);
|
|
#elif defined(DEBUG_UART_NUM) && DEBUG_UART_NUM == 2
|
|
NVIC_DisableIRQ(UART2_RX_IRQn);
|
|
NVIC_ClearPendingIRQ(UART2_RX_IRQn);
|
|
#else /* default: UART0 */
|
|
NVIC_DisableIRQ(UART0_RX_IRQn);
|
|
NVIC_ClearPendingIRQ(UART0_RX_IRQn);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef WOLFBOOT_RESTORE_CLOCK
|
|
/* Restore clock to heart-beat oscillator */
|
|
(void)HAL_Clkgen_Init(CLK_CFG_HBO);
|
|
SystemCoreClockUpdate();
|
|
#endif
|
|
|
|
/* Disable SysTick - enabled by Vorago SDK HAL_Init() */
|
|
SysTick->CTRL = 0;
|
|
SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk;
|
|
|
|
/* Disable EDAC interrupts - enabled by ConfigEdac() */
|
|
NVIC_DisableIRQ(EDAC_MBE_IRQn);
|
|
NVIC_DisableIRQ(EDAC_SBE_IRQn);
|
|
NVIC_ClearPendingIRQ(EDAC_MBE_IRQn);
|
|
NVIC_ClearPendingIRQ(EDAC_SBE_IRQn);
|
|
|
|
/* Disable system config IRQs */
|
|
VOR_SYSCONFIG->IRQ_ENB = 0;
|
|
}
|
|
|
|
#if defined(WOLFBOOT_UPDATE_DISK) || defined(BOOT_BENCHMARK)
|
|
/* Microsecond timer for boot benchmarking.
|
|
* Uses SysTick counter (counts down each ms tick) combined with
|
|
* HAL_time_ms (incremented by SysTick_Handler every 1ms).
|
|
* SysTick->LOAD = (SystemCoreClock / 1000) - 1 (configured by HAL_Init).
|
|
* SysTick->VAL counts down from LOAD to 0.
|
|
*/
|
|
uint64_t hal_get_timer_us(void)
|
|
{
|
|
extern volatile uint64_t HAL_time_ms;
|
|
uint32_t load = SysTick->LOAD;
|
|
uint64_t ms;
|
|
uint32_t val;
|
|
uint32_t elapsed_ticks;
|
|
|
|
/* Stable read: retry until ms matches before and after reading VAL.
|
|
* Avoids a 1ms jump if the SysTick IRQ fires mid-read and makes the
|
|
* timer non-monotonic (would break udelay() comparisons). */
|
|
do {
|
|
ms = HAL_time_ms;
|
|
val = SysTick->VAL;
|
|
} while (ms != HAL_time_ms);
|
|
|
|
/* VAL counts LOAD..0 over LOAD+1 ticks, so elapsed = (LOAD+1) - VAL. */
|
|
elapsed_ticks = (load + 1U) - val;
|
|
if (elapsed_ticks > load)
|
|
elapsed_ticks = load + 1U;
|
|
|
|
return (ms * 1000ULL) +
|
|
((uint64_t)elapsed_ticks * 1000000ULL / SystemCoreClock);
|
|
}
|
|
#endif
|
|
#endif /* !WOLFBOOT_UNIT_TEST_VA416X0_FRAM */
|