mirror of https://github.com/wolfSSL/wolfBoot.git
commit
b6b77f01e0
2
.gdbinit
2
.gdbinit
|
@ -1,5 +1,5 @@
|
|||
tar rem:3333
|
||||
file wolfboot.elf
|
||||
tar rem:3333
|
||||
add-symbol-file test-app/image.elf
|
||||
foc c
|
||||
|
||||
|
|
|
@ -22,6 +22,13 @@ jobs:
|
|||
# arch: riscv
|
||||
# config-file: ./config/examples/hifive.config
|
||||
#
|
||||
#
|
||||
sama5d3_test:
|
||||
uses: ./.github/workflows/test-build.yml
|
||||
with:
|
||||
arch: arm
|
||||
config-file: ./config/examples/sama5d3.config
|
||||
|
||||
same51_test:
|
||||
uses: ./.github/workflows/test-build.yml
|
||||
with:
|
||||
|
|
5
Makefile
5
Makefile
|
@ -130,6 +130,11 @@ ifeq ($(TARGET),nxp_t1024)
|
|||
MAIN_TARGET:=factory_wstage1.bin
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),sama5d3)
|
||||
MAIN_TARGET:=wolfboot.bin test-app/image_v1_signed.bin
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(FLASH_OTP_KEYSTORE),1)
|
||||
MAIN_TARGET+=tools/keytools/otp/otp-keystore-primer.bin
|
||||
endif
|
||||
|
|
146
arch.mk
146
arch.mk
|
@ -70,7 +70,6 @@ ifeq ($(ARCH),ARM)
|
|||
CROSS_COMPILE?=arm-none-eabi-
|
||||
CFLAGS+=-mthumb -mlittle-endian -mthumb-interwork -DARCH_ARM
|
||||
LDFLAGS+=-mthumb -mlittle-endian -mthumb-interwork
|
||||
OBJS+=src/boot_arm.o
|
||||
|
||||
## Target specific configuration
|
||||
ifeq ($(TARGET),samr21)
|
||||
|
@ -176,88 +175,111 @@ ifeq ($(ARCH),ARM)
|
|||
SPI_TARGET=stm32
|
||||
endif
|
||||
|
||||
## Cortex-M CPU
|
||||
ifeq ($(CORTEX_M33),1)
|
||||
CFLAGS+=-mcpu=cortex-m33 -DCORTEX_M33
|
||||
LDFLAGS+=-mcpu=cortex-m33
|
||||
ifeq ($(TZEN),1)
|
||||
OBJS+=hal/stm32_tz.o
|
||||
CFLAGS+=-mcmse
|
||||
ifeq ($(WOLFCRYPT_TZ),1)
|
||||
SECURE_OBJS+=./src/wc_callable.o
|
||||
SECURE_OBJS+=./lib/wolfssl/wolfcrypt/src/random.o
|
||||
CFLAGS+=-DWOLFCRYPT_SECURE_MODE
|
||||
SECURE_LDFLAGS+=-Wl,--cmse-implib -Wl,--out-implib=./src/wc_secure_calls.o
|
||||
endif
|
||||
endif # TZEN=1
|
||||
ifeq ($(TARGET),sama5d3)
|
||||
CORTEX_A5=1
|
||||
UPDATE_OBJS:=src/update_ram.o
|
||||
CFLAGS+=-DWOLFBOOT_DUALBOOT -DEXT_FLASH -DNAND_FLASH -fno-builtin -ffreestanding
|
||||
#CFLAGS+=-DWOLFBOOT_USE_STDLIBC
|
||||
endif
|
||||
|
||||
## Cortex CPU
|
||||
|
||||
ifeq ($(CORTEX_A5),1)
|
||||
FPU=-mfpu=vfp4-d16
|
||||
CFLAGS+=-mcpu=cortex-a5 -mtune=cortex-a5 -static -z noexecstack
|
||||
LDLAGS+=-mcpu=cortex-a5 -mtune=cortex-a5 -mtune=cortex-a5 -static -z noexecstack -Ttext 0x300000
|
||||
# Cortex-A uses boot_arm32.o
|
||||
OBJS+=src/boot_arm32.o src/boot_arm32_start.o
|
||||
ifeq ($(NO_ASM),1)
|
||||
ifeq ($(SPMATH),1)
|
||||
ifeq ($(NO_ASM),1)
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
|
||||
else
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
|
||||
endif
|
||||
endif
|
||||
MATH_OBJS+=./lib/wolfssl/wolfcrypt/src/sp_c32.o
|
||||
else
|
||||
ifeq ($(SPMATH),1)
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
|
||||
endif
|
||||
MATH_OBJS+=./lib/wolfssl/wolfcrypt/src/sp_arm32.o
|
||||
CFLAGS+=-DWOLFSSL_SP_ARM32_ASM
|
||||
endif
|
||||
else
|
||||
ifeq ($(CORTEX_M7),1)
|
||||
CFLAGS+=-mcpu=cortex-m7
|
||||
LDFLAGS+=-mcpu=cortex-m7
|
||||
ifeq ($(SPMATH),1)
|
||||
ifeq ($(NO_ASM),1)
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
|
||||
else
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
|
||||
# All others use boot_arm.o
|
||||
OBJS+=src/boot_arm.o
|
||||
ifeq ($(CORTEX_M33),1)
|
||||
CFLAGS+=-mcpu=cortex-m33 -DCORTEX_M33
|
||||
LDFLAGS+=-mcpu=cortex-m33
|
||||
ifeq ($(TZEN),1)
|
||||
OBJS+=hal/stm32_tz.o
|
||||
CFLAGS+=-mcmse
|
||||
ifeq ($(WOLFCRYPT_TZ),1)
|
||||
SECURE_OBJS+=./src/wc_callable.o
|
||||
SECURE_OBJS+=./lib/wolfssl/wolfcrypt/src/random.o
|
||||
CFLAGS+=-DWOLFCRYPT_SECURE_MODE
|
||||
SECURE_LDFLAGS+=-Wl,--cmse-implib -Wl,--out-implib=./src/wc_secure_calls.o
|
||||
endif
|
||||
endif
|
||||
else
|
||||
ifeq ($(CORTEX_M0),1)
|
||||
CFLAGS+=-mcpu=cortex-m0
|
||||
LDFLAGS+=-mcpu=cortex-m0
|
||||
endif # TZEN=1
|
||||
ifeq ($(NO_ASM),1)
|
||||
ifeq ($(SPMATH),1)
|
||||
ifeq ($(NO_ASM),1)
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
|
||||
else
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_THUMB_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_armthumb.o
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
|
||||
endif
|
||||
endif
|
||||
else
|
||||
ifeq ($(CORTEX_M3),1)
|
||||
|
||||
CFLAGS+=-mcpu=cortex-m3
|
||||
LDFLAGS+=-mcpu=cortex-m3
|
||||
ifeq ($(SPMATH),1)
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
|
||||
endif
|
||||
endif
|
||||
else
|
||||
ifeq ($(CORTEX_M7),1)
|
||||
CFLAGS+=-mcpu=cortex-m7
|
||||
LDFLAGS+=-mcpu=cortex-m7
|
||||
ifeq ($(SPMATH),1)
|
||||
ifeq ($(NO_ASM),1)
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
|
||||
else
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
|
||||
endif
|
||||
endif
|
||||
else
|
||||
ifeq ($(CORTEX_M0),1)
|
||||
CFLAGS+=-mcpu=cortex-m0
|
||||
LDFLAGS+=-mcpu=cortex-m0
|
||||
ifeq ($(SPMATH),1)
|
||||
ifeq ($(NO_ASM),1)
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
|
||||
else
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_THUMB_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_armthumb.o
|
||||
endif
|
||||
endif
|
||||
else
|
||||
ifeq ($(CORTEX_M3),1)
|
||||
CFLAGS+=-mcpu=cortex-m3
|
||||
LDFLAGS+=-mcpu=cortex-m3
|
||||
ifeq ($(NO_ASM),1)
|
||||
ifeq ($(SPMATH),1)
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
|
||||
endif
|
||||
else
|
||||
ifeq ($(SPMATH),1)
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM -DWOLFSSL_SP_NO_UMAAL
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
|
||||
endif
|
||||
endif
|
||||
else
|
||||
# default Cortex M4
|
||||
CFLAGS+=-mcpu=cortex-m4
|
||||
LDFLAGS+=-mcpu=cortex-m4
|
||||
ifeq ($(NO_ASM),1)
|
||||
ifeq ($(SPMATH),1)
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
|
||||
endif
|
||||
else
|
||||
CFLAGS+=-fomit-frame-pointer # required with debug builds only
|
||||
ifeq ($(SPMATH),1)
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM -DWOLFSSL_SP_NO_UMAAL
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
|
||||
endif
|
||||
endif
|
||||
else
|
||||
# default Cortex M4
|
||||
CFLAGS+=-mcpu=cortex-m4
|
||||
LDFLAGS+=-mcpu=cortex-m4
|
||||
ifeq ($(NO_ASM),1)
|
||||
ifeq ($(SPMATH),1)
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
|
||||
endif
|
||||
else
|
||||
CFLAGS+=-fomit-frame-pointer # required with debug builds only
|
||||
ifeq ($(SPMATH),1)
|
||||
CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM
|
||||
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
ARCH?=ARM
|
||||
TARGET?=sama5d3
|
||||
SIGN?=ECC256
|
||||
HASH?=SHA256
|
||||
DEBUG?=0
|
||||
VTOR?=1
|
||||
CORTEX_M0?=0
|
||||
NO_ASM?=0
|
||||
EXT_FLASH?=1
|
||||
NAND_FLASH?=1
|
||||
SPI_FLASH?=0
|
||||
V?=0
|
||||
SPMATH?=1
|
||||
WOLFBOOT_PARTITION_SIZE?=0x1000000
|
||||
WOLFBOOT_NO_PARTITIONS=0
|
||||
WOLFBOOT_SECTOR_SIZE?=0x1000
|
||||
WOLFBOOT_LOAD_ADDRESS=0x20100800
|
||||
WOLFBOOT_LOAD_DTS_ADDRESS=0x21100800
|
||||
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x400000
|
||||
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x800000
|
||||
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0
|
||||
NO_XIP=1
|
||||
IMAGE_HEADER_SIZE=2048
|
|
@ -8,6 +8,7 @@ This README describes configuration of supported targets.
|
|||
* [Cypress PSoC-6](#cypress-psoc-6)
|
||||
* [Infineon AURIX TC3xx](#infineon-aurix-tc3xx)
|
||||
* [Intel x86-64 Intel FSP](#intel-x86_64-with-intel-fsp-support)
|
||||
* [Microchip SAMA5D3](#microchip-sama5d3)
|
||||
* [Microchip SAME51](#microchip-same51)
|
||||
* [NXP Kinetis](#nxp-kinetis)
|
||||
* [NXP LPC54xxx](#nxp-lpc54xxx)
|
||||
|
@ -1405,6 +1406,60 @@ the monitor command sequence below:
|
|||
(gdb) mon psoc6 reset_halt
|
||||
```
|
||||
|
||||
|
||||
## Microchip SAMA5D3
|
||||
|
||||
SAMA5D3 is a Cortex-A5 Microprocessor. The ATSAMA5D3-XPLAINED is the evaluation
|
||||
board used for wolfBoot port, which also equips a 2MB NAND flash. WolfBoot
|
||||
replaces the default first stage bootloader (at91bootstrap).
|
||||
|
||||
### Building wolfBoot
|
||||
|
||||
An example configuration file is provided.
|
||||
|
||||
`cp config/examples/sama5d3.config .config`
|
||||
|
||||
Run make to build wolfBoot.bin and the test application
|
||||
|
||||
`make`
|
||||
|
||||
### Programming wolfboot.bin into NAND flash
|
||||
|
||||
To flash any firmware image into the device NVMs, you need the tool `sam-ba`,
|
||||
distributed by Microchip.
|
||||
|
||||
This procedure has been tested using sam-ba v.3.8 using ATSAMA5D3-XPLAINED board,
|
||||
with JP6 (aka the `SPI_CS` jumper) removed, so the system boots from NAND by
|
||||
default.
|
||||
|
||||
Step 1: install the tool, connect a J-Link device to the J24 JTAG connector then run the
|
||||
following command to activate "lowlevel" mode:
|
||||
|
||||
`sam-ba -p j-link -b sama5d3-xplained -t 5 -a lowlevel`
|
||||
|
||||
Step 2: erase the entire NAND flash:
|
||||
|
||||
`sam-ba -p j-link -b sama5d3-xplained -t 5 -a nandflash -c erase`
|
||||
|
||||
Step 3: program `wolfboot.bin` to the beginning of the flash:
|
||||
|
||||
`sam-ba -p j-link -b sama5d3-xplained -t 5 -a nandflash -c writeboot:wolfboot.bin`
|
||||
|
||||
### Programming the test application into NAND flash
|
||||
|
||||
The application can be written to a second partition in nand,
|
||||
e.g. at address "0x40000"
|
||||
|
||||
`sam-ba -p j-link -b sama5d3-xplained -t 5 -a nandflash -c write:test-app/image_v1_signed.bin:0x400000`
|
||||
|
||||
With the example configuration, wolfBoot will evaluate two alternative images
|
||||
at addresses 0x400000 and 0x800000, authenticate, load to DRAM and stage from
|
||||
`LOAD_ADDRESS`.
|
||||
|
||||
Ensure that the application is compiled to run from `LOAD_ADDRESS`.
|
||||
Check `test-app/ARM-sama5d3.ld` for details.
|
||||
|
||||
|
||||
## Microchip SAME51
|
||||
|
||||
SAME51 is a Cortex-M4 microcontroller with a dual-bank, 1MB flash memory divided
|
||||
|
|
|
@ -0,0 +1,758 @@
|
|||
/* atsama5d3.c
|
||||
*
|
||||
* Copyright (C) 2024 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 <string.h>
|
||||
#include <target.h>
|
||||
#include "image.h"
|
||||
#include "sama5d3.h"
|
||||
|
||||
#ifndef ARCH_ARM
|
||||
# error "wolfBoot atsama5d3 HAL: wrong architecture selected. Please compile with ARCH=ARM."
|
||||
#endif
|
||||
|
||||
void sleep_us(uint32_t usec);
|
||||
|
||||
/* Manual division operation */
|
||||
static int division(uint32_t dividend,
|
||||
uint32_t divisor,
|
||||
uint32_t *quotient,
|
||||
uint32_t *remainder)
|
||||
{
|
||||
uint32_t shift;
|
||||
uint32_t divisor_shift;
|
||||
uint32_t factor = 0;
|
||||
unsigned char end_flag = 0;
|
||||
|
||||
if (!divisor)
|
||||
return 0xffffffff;
|
||||
|
||||
if (dividend < divisor) {
|
||||
*quotient = 0;
|
||||
*remainder = dividend;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (dividend >= divisor) {
|
||||
for (shift = 0, divisor_shift = divisor;
|
||||
dividend >= divisor_shift;
|
||||
divisor_shift <<= 1, shift++) {
|
||||
if (dividend - divisor_shift < divisor_shift) {
|
||||
factor += 1 << shift;
|
||||
dividend -= divisor_shift;
|
||||
end_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (end_flag)
|
||||
continue;
|
||||
|
||||
factor += 1 << (shift - 1);
|
||||
dividend -= divisor_shift >> 1;
|
||||
}
|
||||
|
||||
if (quotient)
|
||||
*quotient = factor;
|
||||
|
||||
if (remainder)
|
||||
*remainder = dividend;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t div(uint32_t dividend, uint32_t divisor)
|
||||
{
|
||||
uint32_t quotient = 0;
|
||||
uint32_t remainder = 0;
|
||||
int ret;
|
||||
|
||||
ret = division(dividend, divisor, "ient, &remainder);
|
||||
if (ret)
|
||||
return 0xffffffff;
|
||||
|
||||
return quotient;
|
||||
}
|
||||
|
||||
static uint32_t mod(uint32_t dividend, uint32_t divisor)
|
||||
{
|
||||
uint32_t quotient = 0;
|
||||
uint32_t remainder = 0;
|
||||
int ret;
|
||||
|
||||
ret = division(dividend, divisor, "ient, &remainder);
|
||||
if (ret)
|
||||
return 0xffffffff;
|
||||
|
||||
return remainder;
|
||||
}
|
||||
|
||||
/* RAM configuration: 2 x MT47H64M16 on SAMA5D3-Xplained
|
||||
* 8 Mwords x 8 Banks x 16 bits x 2, total 2 Gbit
|
||||
*/
|
||||
static const struct dram ddram ={
|
||||
.timing = { /* Hardcoded for MT47H64M16, */
|
||||
.tras = 6,
|
||||
.trcd = 2,
|
||||
.twr = 2,
|
||||
.trc = 8,
|
||||
.trp = 2,
|
||||
.trrd = 2,
|
||||
.twtr = 2,
|
||||
.tmrd = 2,
|
||||
.trfc = 17,
|
||||
.txsnr = 19,
|
||||
.txsrd = 200,
|
||||
.txp = 2,
|
||||
.txard = 8,
|
||||
.txards = 8,
|
||||
.trpa = 2,
|
||||
.trtp = 2,
|
||||
.tfaw = 6,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void master_clock_set(uint32_t prescaler)
|
||||
{
|
||||
uint32_t mck = PMC_MCKR & (PMC_MDIV_MASK | PMC_CSS_MASK);
|
||||
uint32_t diff = mck ^ prescaler;
|
||||
|
||||
if (diff & PMC_ALTPRES_MASK) {
|
||||
/* Clear ALT_PRES field and extra PRES bit */
|
||||
mck &= ~((1 << 13 | PMC_ALTPRES_MASK));
|
||||
mck |= (prescaler & (PMC_ALTPRES_MASK));
|
||||
PMC_MCKR = mck;
|
||||
while ((PMC_SR & PMC_SR_MCKRDY) == 0)
|
||||
;
|
||||
|
||||
}
|
||||
if (diff & PMC_MDIV_MASK) {
|
||||
mck &= ~PMC_MDIV_MASK;
|
||||
mck |= (prescaler & PMC_MDIV_MASK);
|
||||
PMC_MCKR = mck;
|
||||
while ((PMC_SR & PMC_SR_MCKRDY) == 0)
|
||||
;
|
||||
}
|
||||
if (diff & PMC_PLLADIV_MASK) {
|
||||
mck &= ~PMC_PLLADIV_MASK;
|
||||
mck |= (prescaler & PMC_PLLADIV_MASK);
|
||||
PMC_MCKR = mck;
|
||||
while ((PMC_SR & PMC_SR_MCKRDY) == 0)
|
||||
;
|
||||
}
|
||||
if (diff & PMC_H32MXDIV_MASK) {
|
||||
mck &= ~PMC_H32MXDIV_MASK;
|
||||
mck |= (prescaler & PMC_H32MXDIV_MASK);
|
||||
PMC_MCKR = mck;
|
||||
while ((PMC_SR & PMC_SR_MCKRDY) == 0)
|
||||
;
|
||||
}
|
||||
if (diff & PMC_CSS_MASK) {
|
||||
mck &= ~PMC_CSS_MASK;
|
||||
mck |= (prescaler & PMC_CSS_MASK);
|
||||
PMC_MCKR = mck;
|
||||
while ((PMC_SR & PMC_SR_MCKRDY) == 0)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static void pll_init(void)
|
||||
{
|
||||
/* Disable PLLA */
|
||||
PMC_PLLA &= PLLA_CKGR_SRCA;
|
||||
asm volatile("dmb");
|
||||
/* Configure PLLA */
|
||||
PMC_PLLA = PLLA_CONFIG;
|
||||
/* Wait for the PLLA to lock */
|
||||
|
||||
while (!(PMC_SR & PMC_SR_LOCKA))
|
||||
;
|
||||
/* Set the current charge pump */
|
||||
PMC_PLLICPR = PLLICPR_CONFIG;
|
||||
|
||||
/* Set main clock */
|
||||
master_clock_set(PRESCALER_MAIN_CLOCK);
|
||||
|
||||
/* Set PLLA clock */
|
||||
master_clock_set(PRESCALER_PLLA_CLOCK);
|
||||
}
|
||||
|
||||
|
||||
static void ddr_init(void)
|
||||
{
|
||||
uint32_t val;
|
||||
uint32_t rtr, md, cr, tpr0, tpr1, tpr2;
|
||||
uint32_t col, row, cas, bank;
|
||||
uint32_t cal;
|
||||
uint32_t ba_offset = 0;
|
||||
uint32_t pmc_pcr;
|
||||
volatile uint32_t *dram_base = (volatile uint32_t *)DRAM_BASE;
|
||||
|
||||
/* Step 1: Calculate register values
|
||||
*
|
||||
*/
|
||||
md = MPDDRC_MD_DDR2_SDRAM | MPDDRC_MD_DBW_32BIT;
|
||||
col = MPDDRC_NC_10; /* 10/9 column address */
|
||||
row = MPDDRC_NR_13; /* 13-bit row address */
|
||||
cas = 3 << MPDDRC_CAS_SHIFT; /* CAS latency 3 */
|
||||
bank = 1 << MPDDRC_NB_SHIFT; /* NB_BANKS = 8 */
|
||||
cr = col | row | bank | cas | MPDDRC_CR_DECOD_INTERLEAVED | MPDDRC_UNAL
|
||||
| MPDDRC_NDQS_DISABLED;
|
||||
ba_offset = 12; /* Based on col = MPDDRC_NC_10, DBW 32 bit, interleaved */
|
||||
|
||||
/* Set timing parameters using hardcoded values */
|
||||
rtr = 0x40F;
|
||||
tpr0 = (ddram.timing.tras << MPDDRC_TRAS_SHIFT) |
|
||||
(ddram.timing.trcd << MPDDRC_TRCD_SHIFT) |
|
||||
(ddram.timing.twr << MPDDRC_TWR_SHIFT) |
|
||||
(ddram.timing.trc << MPDDRC_TRC_SHIFT) |
|
||||
(ddram.timing.trp << MPDDRC_TRP_SHIFT) |
|
||||
(ddram.timing.trrd << MPDDRC_TRRD_SHIFT) |
|
||||
(ddram.timing.twtr << MPDDRC_TWTR_SHIFT) |
|
||||
(ddram.timing.tmrd << MPDDRC_TMRD_SHIFT);
|
||||
|
||||
|
||||
tpr1 = (ddram.timing.trfc << MPDDRC_TRFC_SHIFT) |
|
||||
(ddram.timing.txsnr << MPDDRC_TXSNR_SHIFT) |
|
||||
(ddram.timing.txsrd << MPDDRC_TXSRD_SHIFT) |
|
||||
(ddram.timing.txp << MPDDRC_TXP_SHIFT);
|
||||
|
||||
tpr2 = (ddram.timing.txard << MPDDRC_TXARD_SHIFT) |
|
||||
(ddram.timing.txards << MPDDRC_TXARDS_SHIFT) |
|
||||
(ddram.timing.trpa << MPDDRC_TRPA_SHIFT) |
|
||||
(ddram.timing.trtp << MPDDRC_TRTP_SHIFT) |
|
||||
(ddram.timing.tfaw << MPDDRC_TFAW_SHIFT);
|
||||
|
||||
/* Step 2: Enable the DDR2 SDRAM controller
|
||||
*
|
||||
*/
|
||||
/* Turn on the DDRAM controller peripheral clock */
|
||||
PMC_PCR = MPDDRC_PMCID;
|
||||
pmc_pcr = PMC_PCR & (~PMC_PCR_DIV_MASK);
|
||||
pmc_pcr |= PMC_PCR_CMD | PMC_PCR_EN;
|
||||
PMC_PCR = pmc_pcr;
|
||||
|
||||
/* Enable DDR in system clock */
|
||||
PMC_SCER = MPDDRC_SCERID;
|
||||
|
||||
sleep_us(10); /* 10 us */
|
||||
|
||||
/* Step 3: Calibration
|
||||
*
|
||||
*/
|
||||
cal = MPDDRC_IO_CALIBR;
|
||||
cal &= ~(MPDDRC_IOCALIBR_RDIV_MASK);
|
||||
cal |= MPDDRC_IOCALIBR_RDIV_DDR2_RZQ_50; /* 50 ohm */
|
||||
cal &= ~(MPDDRC_IOCALIBR_TZQIO_MASK);
|
||||
cal |= (100 << MPDDRC_IOCALIBR_TZQIO_SHIFT); /* 100 cycles at 133MHz is 0.75 us, 100 cycles at 166MHz is 0.6 us */
|
||||
|
||||
MPDDRC_IO_CALIBR = cal;
|
||||
|
||||
/* Data path configuration */
|
||||
MPDDRC_RD_DATA_PATH = 0x01; /* One cycle read delay */
|
||||
|
||||
/* Write calibration again */
|
||||
MPDDRC_IO_CALIBR = cal;
|
||||
|
||||
/* Step 4: Program the DDR2 SDRAM controller
|
||||
*
|
||||
*/
|
||||
|
||||
/* Program the memory device type */
|
||||
MPDDRC_MD = md;
|
||||
|
||||
/* Program the features into configuration registers */
|
||||
MPDDRC_CR = cr;
|
||||
MPDDRC_TPR0 = tpr0;
|
||||
MPDDRC_TPR1 = tpr1;
|
||||
MPDDRC_TPR2 = tpr2;
|
||||
|
||||
/* Send a NOP command via mode register */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_NOP;
|
||||
*dram_base = 0;
|
||||
|
||||
sleep_us(200); /* 200 us */
|
||||
|
||||
/* Send a second NOP command to set CKE high */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_NOP;
|
||||
*dram_base = 0;
|
||||
sleep_us(1); /* min 200 ns */
|
||||
|
||||
/* Issue precharge all command */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_PRECHARGE;
|
||||
*dram_base = 0;
|
||||
sleep_us(1); /* min 15 ns */
|
||||
|
||||
/* Issue external load command to set temperature mode (EMR2) */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_EXT_LOAD;
|
||||
*(volatile uint32_t *)(DRAM_BASE + (0x2 << ba_offset)) = 0x00000000;
|
||||
sleep_us(1); /* min 15 ns */
|
||||
|
||||
/* Issue external load command to set DLL to 0 (EMR3)*/
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_EXT_LOAD;
|
||||
*(volatile uint32_t *)(DRAM_BASE + (0x3 << ba_offset)) = 0x00000000;
|
||||
sleep_us(1); /* min 200 cycles */
|
||||
|
||||
/* Issue external load command to program D.I.C. (EMR1) */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_EXT_LOAD;
|
||||
*(volatile uint32_t *)(DRAM_BASE + (0x1 << ba_offset)) = 0x00000000;
|
||||
sleep_us(1); /* min 200 cycles */
|
||||
|
||||
/* Reset DLL via Configuration Register */
|
||||
MPDDRC_CR |= MPDDRC_CR_ENABLE_DLL_RESET;
|
||||
|
||||
/* Issue load command to set DLL to 1 */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_LOAD;
|
||||
*dram_base = 0;
|
||||
sleep_us(1); /* min 15 ns */
|
||||
|
||||
/* Issue a precharge command */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_PRECHARGE;
|
||||
*dram_base = 0;
|
||||
sleep_us(1); /* min 400 ns */
|
||||
|
||||
/* Issue two auto-refresh cycles */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_AUTO_REFRESH;
|
||||
*dram_base = 0;
|
||||
sleep_us(1); /* min 400 ns */
|
||||
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_AUTO_REFRESH;
|
||||
*dram_base = 0;
|
||||
sleep_us(1); /* min 400 ns */
|
||||
|
||||
/* Disable DLL reset */
|
||||
MPDDRC_CR &= ~MPDDRC_CR_ENABLE_DLL_RESET;
|
||||
|
||||
/* Issue a mode register LOAD command */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_LOAD;
|
||||
*dram_base = 0;
|
||||
sleep_us(1); /* min 15 ns */
|
||||
|
||||
|
||||
/* Trigger OCD default calibration */
|
||||
MPDDRC_CR |= MPDDRC_CR_OCD_DEFAULT;
|
||||
sleep_us(1); /* min 15 ns */
|
||||
|
||||
/* Issue a mode register LOAD command (EMR1) */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_EXT_LOAD;
|
||||
*(volatile uint32_t *)(DRAM_BASE + (0x1 << ba_offset)) = 0x00000000;
|
||||
sleep_us(1); /* min 15 ns */
|
||||
|
||||
/* Exit OCD default calibration */
|
||||
MPDDRC_CR &= ~MPDDRC_CR_OCD_DEFAULT;
|
||||
sleep_us(1); /* min 15 ns */
|
||||
|
||||
/* Issue a mode register LOAD command (EMR1) */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_EXT_LOAD;
|
||||
*(volatile uint32_t *)(DRAM_BASE + (0x1 << ba_offset)) = 0x00000000;
|
||||
sleep_us(1); /* min 15 ns */
|
||||
|
||||
/* Switch mode to NORMAL */
|
||||
MPDDRC_MR = MPDDRC_MR_MODE_NORMAL;
|
||||
*dram_base = 0;
|
||||
sleep_us(1); /* min 15 ns */
|
||||
|
||||
/* Perform a write access to the DDR2-SDRAM */
|
||||
*(dram_base) = 0xA5A5A5D1;
|
||||
|
||||
/* finally, set the refresh rate */
|
||||
MPDDRC_RTR = rtr;
|
||||
|
||||
/* DDR is now ready to use. Wait for the end of calibration */
|
||||
sleep_us(10);
|
||||
}
|
||||
|
||||
/* Static variables to hold nand info */
|
||||
static uint8_t nand_manif_id;
|
||||
static uint8_t nand_dev_id;
|
||||
static char nand_onfi_id[4];
|
||||
|
||||
struct nand_flash {
|
||||
uint16_t revision;
|
||||
uint16_t features;
|
||||
uint16_t ext_page_len;
|
||||
uint16_t parameter_page;
|
||||
|
||||
uint32_t page_size;
|
||||
uint32_t block_size;
|
||||
uint32_t block_count;
|
||||
uint32_t pages_per_block;
|
||||
uint32_t pages_per_device;
|
||||
uint32_t total_size;
|
||||
|
||||
uint16_t bad_block_pos;
|
||||
uint16_t ecc_bytes;
|
||||
uint16_t eccpos[MAX_ECC_BYTES];
|
||||
uint16_t eccwordsize;
|
||||
|
||||
uint32_t bus_width;
|
||||
uint32_t oob_size;
|
||||
} nand_flash = { 0 };
|
||||
|
||||
static void nand_wait_ready(void)
|
||||
{
|
||||
NAND_CMD = NAND_CMD_STATUS;
|
||||
while (!(NAND_DATA & 0x40));
|
||||
}
|
||||
|
||||
|
||||
static void nand_read_id(uint8_t *manif_id, uint8_t *dev_id)
|
||||
{
|
||||
NAND_CMD = NAND_CMD_READID;
|
||||
NAND_ADDR = 0x00;
|
||||
*manif_id = NAND_DATA;
|
||||
*dev_id = NAND_DATA;
|
||||
}
|
||||
|
||||
static void nand_reset(void)
|
||||
{
|
||||
NAND_CMD = NAND_CMD_RESET;
|
||||
nand_wait_ready();
|
||||
}
|
||||
|
||||
|
||||
static void write_column_address(uint32_t col_address)
|
||||
{
|
||||
NAND_ADDR = col_address & 0xFF;
|
||||
NAND_ADDR = (col_address >> 8) & 0xFF;
|
||||
NAND_ADDR = (col_address >> 16) & 0xFF;
|
||||
}
|
||||
|
||||
static void write_row_address(uint32_t row_address)
|
||||
{
|
||||
NAND_ADDR = row_address & 0xFF;
|
||||
NAND_ADDR = (row_address >> 8) & 0xFF;
|
||||
NAND_ADDR = (row_address >> 16) & 0xFF;
|
||||
NAND_ADDR = (row_address >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
static void nand_read_info(void)
|
||||
{
|
||||
uint8_t onfi_data[ONFI_PARAMS_SIZE];
|
||||
uint32_t i;
|
||||
|
||||
nand_reset();
|
||||
|
||||
nand_read_id(&nand_manif_id, &nand_dev_id);
|
||||
NAND_CMD = NAND_CMD_READID;
|
||||
NAND_ADDR = 0x20;
|
||||
nand_onfi_id[0] = NAND_DATA;
|
||||
nand_onfi_id[1] = NAND_DATA;
|
||||
nand_onfi_id[2] = NAND_DATA;
|
||||
nand_onfi_id[3] = NAND_DATA;
|
||||
if (memcmp(nand_onfi_id, "ONFI", 4) != 0) {
|
||||
/* Fail: no ONFI support */
|
||||
asm("bkpt 0");
|
||||
return;
|
||||
}
|
||||
memset(&nand_flash, 0, sizeof(nand_flash));
|
||||
memset(nand_flash.eccpos, 0xFF, sizeof(nand_flash.eccpos));
|
||||
NAND_CMD = NAND_CMD_READ_ONFI;
|
||||
NAND_ADDR = 0x00;
|
||||
nand_wait_ready();
|
||||
NAND_CMD = NAND_CMD_READ1;
|
||||
for (i = 0; i < ONFI_PARAMS_SIZE; i++) {
|
||||
onfi_data[i] = NAND_DATA;
|
||||
}
|
||||
/* Store ONFI parameters in nand_flash struct */
|
||||
nand_flash.page_size = *(uint16_t *)(onfi_data + PARAMS_POS_PAGESIZE);
|
||||
nand_flash.pages_per_block = *(uint16_t *)(onfi_data + PARAMS_POS_BLOCKSIZE);
|
||||
nand_flash.block_size = nand_flash.page_size * nand_flash.pages_per_block;
|
||||
nand_flash.block_count = *(uint16_t *)(onfi_data + PARAMS_POS_NBBLOCKS);
|
||||
nand_flash.total_size = nand_flash.block_count * nand_flash.block_size;
|
||||
nand_flash.ecc_bytes = *(uint16_t *)(onfi_data + PARAMS_POS_ECC_BITS);
|
||||
nand_flash.bad_block_pos = (*(uint16_t *)(onfi_data + PARAMS_POS_FEATURES)) & 1;
|
||||
nand_flash.ext_page_len = *(uint16_t *)(onfi_data + PARAMS_POS_EXT_PARAM_PAGE_LEN);
|
||||
nand_flash.parameter_page = *(uint16_t *)(onfi_data + PARAMS_POS_PARAMETER_PAGE);
|
||||
nand_flash.pages_per_block = div(nand_flash.block_size, nand_flash.page_size);
|
||||
nand_flash.pages_per_device = nand_flash.pages_per_block * nand_flash.block_count;
|
||||
nand_flash.oob_size = *(uint16_t *)(onfi_data + PARAMS_POS_OOBSIZE);
|
||||
nand_flash.revision = *(uint16_t *)(onfi_data + PARAMS_POS_REVISION);
|
||||
nand_flash.features = *(uint16_t *)(onfi_data + PARAMS_POS_FEATURES);
|
||||
nand_flash.bus_width = (onfi_data[PARAMS_POS_FEATURES] & PARAMS_FEATURE_BUSWIDTH) ? 16 : 8;
|
||||
if (nand_flash.ecc_bytes <= MAX_ECC_BYTES) {
|
||||
for (int i = 0; i < nand_flash.ecc_bytes; i++) {
|
||||
nand_flash.eccpos[i] = *(uint16_t *)(onfi_data + PARAMS_POS_ECC_BITS + i * 2);
|
||||
}
|
||||
}
|
||||
if (nand_flash.page_size != NAND_FLASH_PAGE_SIZE) {
|
||||
/* Fail: unsupported page size */
|
||||
asm("bkpt 0");
|
||||
}
|
||||
if (nand_flash.oob_size != NAND_FLASH_OOB_SIZE) {
|
||||
/* Fail: unsupported oob size */
|
||||
asm("bkpt 0");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void set_col_addr(uint32_t col_address)
|
||||
{
|
||||
uint32_t page_size = nand_flash.page_size;
|
||||
while (page_size > 0) {
|
||||
NAND_ADDR = col_address & 0xFF;
|
||||
col_address >>= 8;
|
||||
page_size >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_row_addr(uint32_t row_address)
|
||||
{
|
||||
uint32_t pages_per_device = nand_flash.pages_per_device;
|
||||
while (pages_per_device > 0) {
|
||||
NAND_ADDR = row_address & 0xFF;
|
||||
row_address >>= 8;
|
||||
pages_per_device >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static int nand_device_read(uint32_t row_address, uint8_t *data, int mode)
|
||||
{
|
||||
uint32_t col_address = 0x00;
|
||||
uint32_t tot_len = 0;
|
||||
uint32_t page_size = nand_flash.page_size;
|
||||
uint32_t pages_per_device = nand_flash.pages_per_device;
|
||||
uint32_t i;
|
||||
|
||||
if (mode == NAND_MODE_DATAPAGE) {
|
||||
tot_len = nand_flash.page_size;
|
||||
} else if (mode == NAND_MODE_INFO) {
|
||||
tot_len = nand_flash.oob_size;
|
||||
col_address = nand_flash.page_size;
|
||||
} else if (mode == NAND_MODE_DATABLOCK) {
|
||||
tot_len = nand_flash.block_size;
|
||||
} else {
|
||||
/* Fail: unknown mode */
|
||||
return -1;
|
||||
}
|
||||
NAND_CMD = NAND_CMD_READ1;
|
||||
|
||||
set_col_addr(col_address);
|
||||
set_row_addr(row_address);
|
||||
|
||||
NAND_CMD = NAND_CMD_READ2;
|
||||
nand_wait_ready();
|
||||
NAND_CMD = NAND_CMD_READ1;
|
||||
for (i = 0; i < tot_len; i++) {
|
||||
data[i] = NAND_DATA;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nand_read_page(uint32_t block, uint32_t page, uint8_t *data)
|
||||
{
|
||||
uint32_t row_address = block * nand_flash.pages_per_block + page;
|
||||
return nand_device_read(row_address, data, NAND_MODE_DATAPAGE);
|
||||
}
|
||||
|
||||
static int nand_check_bad_block(uint32_t block)
|
||||
{
|
||||
uint32_t row_address = block * nand_flash.pages_per_block;
|
||||
uint8_t oob[NAND_FLASH_OOB_SIZE];
|
||||
uint32_t page;
|
||||
for (page = 0; page < 2; page++) {
|
||||
nand_device_read(row_address + page, oob, NAND_MODE_INFO);
|
||||
if (oob[0] != 0xFF) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ext_flash_read(uintptr_t address, uint8_t *data, int len)
|
||||
{
|
||||
uint8_t buffer_page[NAND_FLASH_PAGE_SIZE];
|
||||
uint32_t block = div(address, nand_flash.block_size); /* The block where the address falls in */
|
||||
uint32_t page = div(address, nand_flash.page_size); /* The page where the address falls in */
|
||||
uint32_t start_page_in_block = mod(page, nand_flash.pages_per_block); /* The start page within this block */
|
||||
uint32_t in_block_offset = mod(address, nand_flash.block_size); /* The offset of the address within the block */
|
||||
uint32_t remaining = nand_flash.block_size - in_block_offset; /* How many bytes remaining to read in the first block */
|
||||
int len_to_read = len;
|
||||
uint8_t *buffer = data;
|
||||
uint32_t i;
|
||||
int copy = 0;
|
||||
int ret;
|
||||
|
||||
if (len < (int)nand_flash.page_size) {
|
||||
buffer = buffer_page;
|
||||
copy = 1;
|
||||
len_to_read = nand_flash.page_size;
|
||||
}
|
||||
|
||||
while (len_to_read > 0) {
|
||||
uint32_t sz = len_to_read;
|
||||
uint32_t pages_to_read;
|
||||
if (sz > remaining)
|
||||
sz = remaining;
|
||||
|
||||
do {
|
||||
ret = nand_check_bad_block(block);
|
||||
if (ret < 0) {
|
||||
/* Block is bad, skip it */
|
||||
block++;
|
||||
}
|
||||
} while (ret < 0);
|
||||
|
||||
/* Amount of pages to be read from this block */
|
||||
pages_to_read = div((sz + nand_flash.page_size - 1), nand_flash.page_size);
|
||||
|
||||
if (pages_to_read * nand_flash.page_size > remaining)
|
||||
pages_to_read--;
|
||||
|
||||
/* Read (remaining) pages off a block */
|
||||
for (i = 0; i < pages_to_read; i++) {
|
||||
nand_read_page(block, start_page_in_block + i, buffer);
|
||||
if (sz > nand_flash.page_size)
|
||||
sz = nand_flash.page_size;
|
||||
len_to_read -= sz;
|
||||
buffer += sz;
|
||||
}
|
||||
/* The block is over, move to the next one */
|
||||
block++;
|
||||
start_page_in_block = 0;
|
||||
remaining = nand_flash.block_size;
|
||||
}
|
||||
if (copy) {
|
||||
uint32_t *dst = (uint32_t *)data;
|
||||
uint32_t *src = (uint32_t *)buffer_page;
|
||||
uint32_t tot_len = (uint32_t)len;
|
||||
for (i = 0; i < (tot_len >> 2); i++) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void pit_init(void)
|
||||
{
|
||||
uint32_t pmc_pcr;
|
||||
|
||||
/* Turn on clock for PIT */
|
||||
PMC_PCR = PIT_PMCID;
|
||||
pmc_pcr = PMC_PCR & (~PMC_PCR_DIV_MASK);
|
||||
pmc_pcr |= PMC_PCR_CMD | PMC_PCR_EN;
|
||||
PMC_PCR = pmc_pcr;
|
||||
|
||||
/* Set clock source to MCK/2 */
|
||||
PIT_MR = MAX_PIV | PIT_MR_EN;
|
||||
}
|
||||
|
||||
void sleep_us(uint32_t usec)
|
||||
{
|
||||
uint32_t base = PIT_PIIR;
|
||||
uint32_t delay;
|
||||
uint32_t current;
|
||||
|
||||
/* Since our division function which costs much run time
|
||||
* causes the delay time error.
|
||||
* So here using shifting to implement the division.
|
||||
* to change "1000" to "1024", this cause some inaccuacy,
|
||||
* but it is acceptable.
|
||||
* ((MASTER_CLOCK / 1024) * usec) / (16 * 1024)
|
||||
*/
|
||||
delay = ((MASTER_FREQ >> 10) * usec) >> 14;
|
||||
do {
|
||||
current = PIT_PIIR;
|
||||
current -= base;
|
||||
} while (current < delay);
|
||||
}
|
||||
|
||||
int ext_flash_write(uintptr_t address, const uint8_t *data, int len)
|
||||
{
|
||||
/* TODO */
|
||||
(void)address;
|
||||
(void)data;
|
||||
(void)len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext_flash_erase(uintptr_t address, int len)
|
||||
{
|
||||
/* TODO */
|
||||
(void)address;
|
||||
(void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SAMA5D3 NAND flash does not have an enable pin */
|
||||
void ext_flash_unlock(void)
|
||||
{
|
||||
}
|
||||
|
||||
void ext_flash_lock(void)
|
||||
{
|
||||
}
|
||||
|
||||
void* hal_get_dts_address(void)
|
||||
{
|
||||
return (void*)&dts_addr;
|
||||
}
|
||||
|
||||
void* hal_get_dts_update_address(void)
|
||||
{
|
||||
return NULL; /* Not yet supported */
|
||||
}
|
||||
|
||||
|
||||
/* public HAL functions */
|
||||
void hal_init(void)
|
||||
{
|
||||
pll_init();
|
||||
pit_init();
|
||||
watchdog_disable();
|
||||
ddr_init();
|
||||
nand_read_info();
|
||||
}
|
||||
|
||||
void hal_prepare_boot(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
||||
{
|
||||
(void)address;
|
||||
(void)data;
|
||||
(void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RAMFUNCTION hal_flash_unlock(void)
|
||||
{
|
||||
}
|
||||
|
||||
void RAMFUNCTION hal_flash_lock(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
|
||||
{
|
||||
(void)address;
|
||||
(void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,448 @@
|
|||
/* sama5d3.h
|
||||
*
|
||||
* Header file for SAMA5D3 HAL
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef SAMA5D3_HAL_H
|
||||
#define SAMA5D3_HAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* CPU/Board clock settings */
|
||||
#define CPU_FREQ 264000000UL
|
||||
#define MASTER_FREQ 132000000UL
|
||||
#define CRYSTAL_FREQ 12000000UL
|
||||
#define MULA 43
|
||||
|
||||
/* PLLA register
|
||||
*/
|
||||
|
||||
#define PLLA_DIVA_SHIFT 0
|
||||
#define PLLA_DIVA_MASK (0xFF << PLLA_DIVA_SHIFT)
|
||||
#define PLLA_COUNT_SHIFT 8
|
||||
#define PLLA_COUNT_MASK (0x3F << PLLA_COUNT_SHIFT)
|
||||
#define PLLA_CKGR_OUTA_SHIFT 14
|
||||
#define PLLA_CKGR_OUTA_MASK (0x3 << PLLA_CKGR_OUTA_SHIFT)
|
||||
#define PLLA_MULA_SHIFT 18
|
||||
#define PLLA_MULA_MASK (0x7F << PLLA_MULA_SHIFT)
|
||||
#define PLLA_CKGR_SRCA (0x1 << 29)
|
||||
|
||||
/* PMC version 1 */
|
||||
#define PMC_BASE 0xFFFFFC00
|
||||
#define PMC_SCER *(volatile uint32_t *)(PMC_BASE + 0x0000)
|
||||
#define PMC_UCKR *(volatile uint32_t *)(PMC_BASE + 0x001C)
|
||||
#define PMC_PLLA *(volatile uint32_t *)(PMC_BASE + 0x0028)
|
||||
#define PMC_MCKR *(volatile uint32_t *)(PMC_BASE + 0x0030)
|
||||
#define PMC_SR *(volatile uint32_t *)(PMC_BASE + 0x0068)
|
||||
#define PMC_PLLICPR *(volatile uint32_t *)(PMC_BASE + 0x0080)
|
||||
#define PMC_PCR *(volatile uint32_t *)(PMC_BASE + 0x010C)
|
||||
|
||||
#define PMC_PLLADIV_SHIFT 12
|
||||
#define PMC_PLLADIV_MASK (0x1 << PMC_PLLADIV_SHIFT)
|
||||
#define PMC_PLLADIV_1 (0x0 << PMC_PLLADIV_SHIFT)
|
||||
#define PMC_PLLADIV_2 (0x1 << PMC_PLLADIV_SHIFT)
|
||||
|
||||
#define PMC_CSS_SHIFT 0
|
||||
#define PMC_CSS_MASK (0x3 << PMC_CSS_SHIFT)
|
||||
#define PMC_CSS_SLOW_CLK (0x0 << PMC_CSS_SHIFT)
|
||||
#define PMC_CSS_MAIN_CLK (0x1 << PMC_CSS_SHIFT)
|
||||
#define PMC_CSS_PLLA_CLK (0x2 << PMC_CSS_SHIFT)
|
||||
#define PMC_CSS_UPLL_CLK (0x3 << PMC_CSS_SHIFT)
|
||||
#define PMC_PRES_SHIFT 2
|
||||
#define PMC_PRES_MASK (0xF << PMC_PRES_SHIFT)
|
||||
#define PMC_ALTPRES_SHIFT 4
|
||||
#define PMC_ALTPRES_MASK (0xF << PMC_ALTPRES_SHIFT)
|
||||
#define PMC_MDIV_SHIFT 8
|
||||
#define PMC_MDIV_MASK (0x3 << PMC_MDIV_SHIFT)
|
||||
#define PMC_MDIV_1 (0x0 << PMC_MDIV_SHIFT)
|
||||
#define PMC_MDIV_2 (0x1 << PMC_MDIV_SHIFT)
|
||||
#define PMC_MDIV_3 (0x2 << PMC_MDIV_SHIFT)
|
||||
#define PMC_MDIV_4 (0x3 << PMC_MDIV_SHIFT)
|
||||
#define PMC_H32MXDIV_SHIFT 24
|
||||
#define PMC_H32MXDIV_MASK (0x1 << PMC_H32MXDIV_SHIFT)
|
||||
|
||||
|
||||
#define PMC_SR_LOCKA (0x1 << 1)
|
||||
#define PMC_SR_MCKRDY (0x1 << 3)
|
||||
|
||||
#define PMC_PLLICPR_ICPPLLA_SHIFT 0
|
||||
#define PMC_PLLICPR_ICPPLLA_MASK (0x7 << PMC_PLLICPR_ICPPLLA_SHIFT)
|
||||
#define PMC_PLLICPR_IPLLA_SHIFT 8
|
||||
#define PMC_PLLICPR_IPLLA_MASK (0xF << PMC_PLLICPR_IPLLA_SHIFT)
|
||||
|
||||
#define PMC_PCR_CMD (0x1 << 12)
|
||||
#define PMC_PCR_EN (0x1 << 28)
|
||||
#define PMC_PCR_DIV_SHIFT 13
|
||||
#define PMC_PCR_DIV_MASK (0x3 << PMC_PCR_DIV_SHIFT)
|
||||
|
||||
|
||||
|
||||
/* Specific configuration for 264/132/12 MHz */
|
||||
|
||||
#define PLL_PCK (((CRYSTAL_FREQ * (PLLA_MULA + 1)) / 2))
|
||||
#define PLL_MCK (BOARD_PCK / 2)
|
||||
#define PLL_CKGR_PLLA (PLLA_CKGR_SRCA | (0 << PLLA_CKGR_OUTA_SHIFT))
|
||||
#define PLL_PLLACOUNT (PLLA_COUNT_MASK)
|
||||
#define PLL_MULA ((MULA << PLLA_MULA_SHIFT) & PLLA_MULA_MASK)
|
||||
#define PLL_DIVA (0x01 & PLLA_DIVA_MASK)
|
||||
#define PLLA_CONFIG (PLL_CKGR_PLLA | PLL_PLLACOUNT | PLL_MULA | PLL_DIVA)
|
||||
|
||||
#define PRESCALER_MAIN_CLOCK (PMC_PLLADIV_2 | PMC_MDIV_2 | PMC_CSS_MAIN_CLK)
|
||||
#define PRESCALER_PLLA_CLOCK (PMC_PLLADIV_2 | PMC_MDIV_2 | PMC_CSS_PLLA_CLK)
|
||||
|
||||
#define PLLICPR_CONFIG (0x0 << PMC_PLLICPR_ICPPLLA_SHIFT | 0x3 << PMC_PLLICPR_IPLLA_SHIFT)
|
||||
|
||||
|
||||
/* PIT
|
||||
*
|
||||
*/
|
||||
|
||||
#define PIT_BASE 0xFFFFFE30
|
||||
#define PIT_MR *(volatile uint32_t *)(PIT_BASE + 0x00)
|
||||
#define PIT_SR *(volatile uint32_t *)(PIT_BASE + 0x04)
|
||||
#define PIT_PIVR *(volatile uint32_t *)(PIT_BASE + 0x08)
|
||||
#define PIT_PIIR *(volatile uint32_t *)(PIT_BASE + 0x0C)
|
||||
|
||||
|
||||
|
||||
|
||||
/* DRAM setup
|
||||
*/
|
||||
|
||||
#define MPDDRC_BASE 0xFFFFEA00
|
||||
#define MPDDRC_MR *(volatile uint32_t *)(MPDDRC_BASE + 0x00) /* Mode Register */
|
||||
#define MPDDRC_RTR *(volatile uint32_t *)(MPDDRC_BASE + 0x04) /* Refresh Timer Register */
|
||||
#define MPDDRC_CR *(volatile uint32_t *)(MPDDRC_BASE + 0x08) /* Configuration Register */
|
||||
#define MPDDRC_TPR0 *(volatile uint32_t *)(MPDDRC_BASE + 0x0C) /* Timing Parameter 0 Register */
|
||||
#define MPDDRC_TPR1 *(volatile uint32_t *)(MPDDRC_BASE + 0x10) /* Timing Parameter 1 Register */
|
||||
#define MPDDRC_TPR2 *(volatile uint32_t *)(MPDDRC_BASE + 0x14) /* Timing Parameter 2 Register */
|
||||
/* Reserved 0x18 */
|
||||
#define MPDDRC_LPR *(volatile uint32_t *)(MPDDRC_BASE + 0x1C) /* Low-power Register */
|
||||
#define MPDDRC_MD *(volatile uint32_t *)(MPDDRC_BASE + 0x20) /* Memory Device Register */
|
||||
#define MPDDRC_HS *(volatile uint32_t *)(MPDDRC_BASE + 0x24) /* High Speed Register */
|
||||
#define MPDDRC_LPDDR2_LPR *(volatile uint32_t *)(MPDDRC_BASE + 0x28) /* LPDDR2 Low-power Register */
|
||||
#define MPDDRC_LPDDR2_CAL_MR4 *(volatile uint32_t *)(MPDDRC_BASE + 0x2C) /* LPDDR2 Calibration and MR4 Register */
|
||||
#define MPDDRC_LPDDR2_TIM_CAL *(volatile uint32_t *)(MPDDRC_BASE + 0x30) /* LPDDR2 Timing Calibration Register */
|
||||
#define MPDDRC_IO_CALIBR *(volatile uint32_t *)(MPDDRC_BASE + 0x34) /* I/O Calibration Register */
|
||||
#define MPDDRC_OCMS *(volatile uint32_t *)(MPDDRC_BASE + 0x38) /* OCMS Register */
|
||||
#define MPDDRC_OCMS_KEY1 *(volatile uint32_t *)(MPDDRC_BASE + 0x3C) /* OCMS Key 1 Register */
|
||||
#define MPDDRC_OCMS_KEY2 *(volatile uint32_t *)(MPDDRC_BASE + 0x40) /* OCMS Key 2 Register */
|
||||
/* Reserved 0x44 to 0x58 */
|
||||
#define MPDDRC_RD_DATA_PATH *(volatile uint32_t *)(MPDDRC_BASE + 0x5C) /* Read Data Path Register */
|
||||
/* Reserved 0x60 to 0x70 */
|
||||
#define MPDDRC_DLL_MO *(volatile uint32_t *)(MPDDRC_BASE + 0x74) /* DLL Master Offset Register */
|
||||
#define MPDDRC_DLL_SOF *(volatile uint32_t *)(MPDDRC_BASE + 0x78) /* DLL Slave Offset Register */
|
||||
#define MPDDRC_DLL_MS *(volatile uint32_t *)(MPDDRC_BASE + 0x7C) /* DLL Master Status Register */
|
||||
#define MPDDRC_DLL_SS0 *(volatile uint32_t *)(MPDDRC_BASE + 0x80) /* DLL Slave 0 Status Register */
|
||||
#define MPDDRC_DLL_SS1 *(volatile uint32_t *)(MPDDRC_BASE + 0x84) /* DLL Slave 1 Status Register */
|
||||
#define MPDDRC_DLL_SS2 *(volatile uint32_t *)(MPDDRC_BASE + 0x88) /* DLL Slave 2 Status Register */
|
||||
#define MPDDRC_DLL_SS3 *(volatile uint32_t *)(MPDDRC_BASE + 0x8C) /* DLL Slave 3 Status Register */
|
||||
/* Reserved 0x90 to 0xE0 */
|
||||
#define MPDDRC_WPMR *(volatile uint32_t *)(MPDDRC_BASE + 0xE4) /* Write Protection Mode Register */
|
||||
#define MPDDRC_WPSR *(volatile uint32_t *)(MPDDRC_BASE + 0xE8) /* Write Protection Status Register */
|
||||
|
||||
|
||||
/* MPDDRC_CR: shift, mask, values */
|
||||
#define MPDDRC_NC_SHIFT 0 /* Number of Column Bits */
|
||||
#define MPDDRC_NC_MASK (0x3 << MPDDRC_NC_SHIFT)
|
||||
#define MPDDRC_NC_9 (0x0 << MPDDRC_NC_SHIFT)
|
||||
#define MPDDRC_NC_10 (0x1 << MPDDRC_NC_SHIFT)
|
||||
#define MPDDRC_NC_11 (0x2 << MPDDRC_NC_SHIFT)
|
||||
#define MPDDRC_NC_12 (0x3 << MPDDRC_NC_SHIFT)
|
||||
|
||||
#define MPDDRC_NR_SHIFT 2 /* Number of Row Bits */
|
||||
#define MPDDRC_NR_MASK (0x3 << MPDDRC_NR_SHIFT)
|
||||
#define MPDDRC_NR_11 (0x0 << MPDDRC_NR_SHIFT)
|
||||
#define MPDDRC_NR_12 (0x1 << MPDDRC_NR_SHIFT)
|
||||
#define MPDDRC_NR_13 (0x2 << MPDDRC_NR_SHIFT)
|
||||
#define MPDDRC_NR_14 (0x3 << MPDDRC_NR_SHIFT)
|
||||
|
||||
#define MPDDRC_CAS_SHIFT 4 /* CAS Latency */
|
||||
#define MPDDRC_CAS_MASK (0x7 << MPDDRC_CAS_SHIFT)
|
||||
#define MPDDRC_NB_SHIFT 20 /* Number of Banks */
|
||||
#define MPDDRC_NB_MASK (0x1 << MPDDRC_NB_SHIFT)
|
||||
|
||||
#define MPDDRC_MD_DBW_SHIFT 4 /* Data Bus Width */
|
||||
#define MPDDRC_MD_DBW_MASK (0x1 << MPDDRC_MD_DBW_SHIFT)
|
||||
|
||||
#define MPDDRC_NQDS_DISABLED_SHIFT 21 /* NAND Data Queue in DDR2 SDRAM */
|
||||
#define MPDDRC_NDQS_DISABLED (0x1 << MPDDRC_NQDS_DISABLED_SHIFT)
|
||||
|
||||
#define MPDDRC_UNAL_SHIFT 23 /* Support Unaligned Access */
|
||||
#define MPDDRC_UNAL (0x1 << MPDDRC_UNAL_SHIFT)
|
||||
|
||||
#define REF_WIN 32
|
||||
#define REF_CYCLE 2048
|
||||
|
||||
/* Configuration register */
|
||||
#define MPDDRC_CR_NC_SHIFT 0
|
||||
#define MPDDRC_CR_NC_MASK (0x3 << MPDDRC_CR_NC_SHIFT)
|
||||
#define MPDDRC_CR_NR_SHIFT 2
|
||||
#define MPDDRC_CR_NR_MASK (0x3 << MPDDRC_CR_NR_SHIFT)
|
||||
#define MPDDRC_CR_CAS_SHIFT 4
|
||||
#define MPDDRC_CR_CAS_MASK (0x7 << MPDDRC_CR_CAS_SHIFT)
|
||||
|
||||
#define MPDDRC_CR_ENABLE_DLL_RESET (1 << 7)
|
||||
|
||||
#define MPDDRC_CR_NB_SHIFT 8
|
||||
#define MPDDRC_CR_NB_MASK (0x1 << MPDDRC_CR_NB_SHIFT)
|
||||
|
||||
#define MPDDRC_CR_DECOD_INTERLEAVED (1 << 22)
|
||||
|
||||
|
||||
/* Memory device register */
|
||||
#define MPDDRC_MD_SDRAM (0x0 << 0)
|
||||
#define MPDDRC_MD_LP_SDRAM (0x1 << 0)
|
||||
#define MPDDRC_MD_DDR_SDRAM (0x2 << 0)
|
||||
#define MPDDRC_MD_LP_DDR_SDRAM (0x3 << 0)
|
||||
#define MPDDRC_MD_DDR3_SDRAM (0x4 << 0)
|
||||
#define MPDDRC_MD_LPDDR3_SDRAM (0x5 << 0)
|
||||
#define MPDDRC_MD_DDR2_SDRAM (0x6 << 0)
|
||||
#define MPDDRC_MD_LPDDR2_SDRAM (0x7 << 0)
|
||||
|
||||
#define MPDDRC_MD_DBW_32BIT (0x0 << 4)
|
||||
#define MPDDRC_MD_DBW_16BIT (0x1 << 4)
|
||||
|
||||
|
||||
/* Mode register */
|
||||
#define MPDDRC_MR_MODE_NORMAL 0
|
||||
#define MPDDRC_MR_MODE_NOP 1
|
||||
#define MPDDRC_MR_MODE_PRECHARGE 2
|
||||
#define MPDDRC_MR_MODE_LOAD 3
|
||||
#define MPDDRC_MR_MODE_AUTO_REFRESH 4
|
||||
#define MPDDRC_MR_MODE_EXT_LOAD 5
|
||||
#define MPDDRC_MR_MODE_DEEP_POWER 6
|
||||
#define MPDDRC_MR_MODE_LPDDR2_PDE 7
|
||||
|
||||
#define MPDDRC_CR_OCD_DEFAULT (0x7 << 12)
|
||||
|
||||
|
||||
#define MPDDRC_TRAS_SHIFT 0
|
||||
#define MPDDRC_TRCD_SHIFT 4
|
||||
#define MPDDRC_TWR_SHIFT 8
|
||||
#define MPDDRC_TRC_SHIFT 12
|
||||
#define MPDDRC_TRP_SHIFT 16
|
||||
#define MPDDRC_TRRD_SHIFT 20
|
||||
#define MPDDRC_TWTR_SHIFT 24
|
||||
#define MPDDRC_TMRD_SHIFT 28
|
||||
|
||||
#define MPDDRC_TRFC_SHIFT 0
|
||||
#define MPDDRC_TXSNR_SHIFT 8
|
||||
#define MPDDRC_TXSRD_SHIFT 16
|
||||
#define MPDDRC_TXP_SHIFT 24
|
||||
|
||||
#define MPDDRC_TXARD_SHIFT 0
|
||||
#define MPDDRC_TXARDS_SHIFT 4
|
||||
#define MPDDRC_TRPA_SHIFT 8
|
||||
#define MPDDRC_TRTP_SHIFT 12
|
||||
#define MPDDRC_TFAW_SHIFT 16
|
||||
|
||||
/* Calibration register */
|
||||
#define MPDDRC_IOCALIBR_RDIV_SHIFT 0
|
||||
#define MPDDRC_IOCALIBR_RDIV_MASK (0x7 << MPDDRC_IOCALIBR_RDIV_SHIFT)
|
||||
#define MPDDRC_IOCALIBR_RDIV_DDR2_RZQ_50 (4 << MPDDRC_IOCALIBR_RDIV_SHIFT)
|
||||
|
||||
#define MPDDRC_IOCALIBR_TZQIO_SHIFT 8
|
||||
#define MPDDRC_IOCALIBR_TZQIO_MASK (0x7F << MPDDRC_IOCALIBR_TZQIO_SHIFT)
|
||||
|
||||
/* Read data path register */
|
||||
#define MPDDRC_RD_DATA_PATH_CYCLES_SHIFT 0
|
||||
#define MPDDRC_RD_DATA_PATH_CYCLES_MASK (0x3 << MPDDRC_RD_DATA_PATH_CYCLES_SHIFT)
|
||||
|
||||
|
||||
|
||||
/* MPDDRC Device clock */
|
||||
#define MPDDRC_PMCID 0x31 /* dec: 49 for SAMA5D3 */
|
||||
#define MPDDRC_SCERID (1 << 2)
|
||||
|
||||
/* PIT device clock */
|
||||
#define PIT_PMCID 0x03 /* dec: 3 for SAMA5D3 */
|
||||
#define MAX_PIV 0xfffff
|
||||
#define PIT_MR_EN (1 << 24)
|
||||
|
||||
|
||||
struct dram {
|
||||
struct dram_timing {
|
||||
uint32_t tras;
|
||||
uint32_t trcd;
|
||||
uint32_t twr;
|
||||
uint32_t trc;
|
||||
uint32_t trp;
|
||||
uint32_t trrd;
|
||||
uint32_t twtr;
|
||||
uint32_t tmrd;
|
||||
uint32_t trfc;
|
||||
uint32_t txsnr;
|
||||
uint32_t txsrd;
|
||||
uint32_t txp;
|
||||
uint32_t txard;
|
||||
uint32_t txards;
|
||||
uint32_t trpa;
|
||||
uint32_t trtp;
|
||||
uint32_t tfaw;
|
||||
} timing;
|
||||
};
|
||||
|
||||
/* Watchdog
|
||||
*/
|
||||
#define WDT_BASE 0xFFFFFD40
|
||||
#define WDT_CR *(volatile uint32_t *)(WDT_BASE + 0x00)
|
||||
#define WDT_MR *(volatile uint32_t *)(WDT_BASE + 0x04)
|
||||
#define WDT_SR *(volatile uint32_t *)(WDT_BASE + 0x08)
|
||||
|
||||
#define WDT_MD_WDDIS (0x1 << 15)
|
||||
#define WDT_MD_WDRSTEN (0x1 << 14)
|
||||
|
||||
static inline void watchdog_disable(void)
|
||||
{
|
||||
WDT_MR |= WDT_MD_WDDIS;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* NAND flash
|
||||
*/
|
||||
|
||||
/* Fixed addresses */
|
||||
extern void *kernel_addr, *update_addr, *dts_addr;
|
||||
|
||||
#if defined(EXT_FLASH) && defined(NAND_FLASH)
|
||||
|
||||
/* Constant for local buffers */
|
||||
#define NAND_FLASH_PAGE_SIZE 0x800 /* 2KB */
|
||||
#define NAND_FLASH_OOB_SIZE 0x40 /* 64B */
|
||||
|
||||
/* Address space mapping for atsama5d3 */
|
||||
#define DRAM_BASE 0x20000000UL
|
||||
#define CS1_BASE 0x40000000UL
|
||||
#define CS2_BASE 0x50000000UL
|
||||
#define CS3_BASE 0x60000000UL
|
||||
#define NFC_CMD_BASE 0x70000000UL
|
||||
|
||||
/* NAND flash is mapped to CS3 */
|
||||
#define NAND_BASE CS3_BASE
|
||||
|
||||
#define NAND_MASK_ALE (1 << 21)
|
||||
#define NAND_MASK_CLE (1 << 22)
|
||||
#define NAND_CMD (*((volatile uint8_t *)(NAND_BASE | NAND_MASK_CLE)))
|
||||
#define NAND_ADDR (*((volatile uint8_t *)(NAND_BASE | NAND_MASK_ALE)))
|
||||
#define NAND_DATA (*((volatile uint8_t *)(NAND_BASE)))
|
||||
|
||||
/* Command set */
|
||||
#define NAND_CMD_STATUS 0x70
|
||||
#define NAND_CMD_READ1 0x00
|
||||
#define NAND_CMD_READ2 0x30
|
||||
#define NAND_CMD_READID 0x90
|
||||
#define NAND_CMD_RESET 0xFF
|
||||
#define NAND_CMD_ERASE1 0x60
|
||||
#define NAND_CMD_ERASE2 0xD0
|
||||
#define NAND_CMD_WRITE1 0x80
|
||||
#define NAND_CMD_WRITE2 0x10
|
||||
|
||||
/* Small block */
|
||||
#define NAND_CMD_READ_A0 0x00
|
||||
#define NAND_CMD_READ_A1 0x01
|
||||
#define NAND_CMD_READ_C 0x50
|
||||
#define NAND_CMD_WRITE_A 0x00
|
||||
#define NAND_CMD_WRITE_C 0x50
|
||||
|
||||
|
||||
/* ONFI */
|
||||
#define NAND_CMD_READ_ONFI 0xEC
|
||||
|
||||
/* Features set/get */
|
||||
#define NAND_CMD_GET_FEATURES 0xEE
|
||||
#define NAND_CMD_SET_FEATURES 0xEF
|
||||
|
||||
/* ONFI parameters and definitions */
|
||||
#define ONFI_PARAMS_SIZE 256
|
||||
|
||||
#define PARAMS_POS_REVISION 4
|
||||
#define PARAMS_REVISION_1_0 (0x1 << 1)
|
||||
#define PARAMS_REVISION_2_0 (0x1 << 2)
|
||||
#define PARAMS_REVISION_2_1 (0x1 << 3)
|
||||
|
||||
#define PARAMS_POS_FEATURES 6
|
||||
#define PARAMS_FEATURE_BUSWIDTH (0x1 << 0)
|
||||
#define PARAMS_FEATURE_EXTENDED_PARAM (0x1 << 7)
|
||||
|
||||
#define PARAMS_POS_OPT_CMD 8
|
||||
#define PARAMS_OPT_CMD_SET_GET_FEATURES (0x1 << 2)
|
||||
|
||||
#define PARAMS_POS_EXT_PARAM_PAGE_LEN 12
|
||||
#define PARAMS_POS_PARAMETER_PAGE 14
|
||||
#define PARAMS_POS_PAGESIZE 80
|
||||
#define PARAMS_POS_OOBSIZE 84
|
||||
#define PARAMS_POS_BLOCKSIZE 92
|
||||
#define PARAMS_POS_NBBLOCKS 96
|
||||
#define PARAMS_POS_ECC_BITS 112
|
||||
|
||||
#define PARAMS_POS_TIMING_MODE 129
|
||||
#define PARAMS_TIMING_MODE_0 (1 << 0)
|
||||
#define PARAMS_TIMING_MODE_1 (1 << 1)
|
||||
#define PARAMS_TIMING_MODE_2 (1 << 2)
|
||||
#define PARAMS_TIMING_MODE_3 (1 << 3)
|
||||
#define PARAMS_TIMING_MODE_4 (1 << 4)
|
||||
#define PARAMS_TIMING_MODE_5 (1 << 5)
|
||||
|
||||
#define PARAMS_POS_CRC 254
|
||||
|
||||
#define ONFI_CRC_BASE 0x4F4E
|
||||
|
||||
#define ONFI_MAX_SECTIONS 8
|
||||
|
||||
#define ONFI_SECTION_TYPE_0 0
|
||||
#define ONFI_SECTION_TYPE_1 1
|
||||
#define ONFI_SECTION_TYPE_2 2
|
||||
|
||||
/* Read access modes */
|
||||
#define NAND_MODE_DATAPAGE 1
|
||||
#define NAND_MODE_INFO 2
|
||||
#define NAND_MODE_DATABLOCK 3
|
||||
|
||||
#define nand_flash_read ext_flash_read
|
||||
#define nand_flash_write ext_flash_write
|
||||
#define nand_flash_erase ext_flash_erase
|
||||
#define nand_flash_unlock ext_flash_unlock
|
||||
#define nand_flash_lock ext_flash_lock
|
||||
|
||||
#define MAX_ECC_BYTES 8
|
||||
#endif
|
||||
|
||||
#define GPIOE_BASE 0xFFFFFA00
|
||||
|
||||
#define GPIOE_PER *(volatile uint32_t *)(GPIOE_BASE + 0x00)
|
||||
#define GPIOE_PDR *(volatile uint32_t *)(GPIOE_BASE + 0x04)
|
||||
#define GPIOE_PSR *(volatile uint32_t *)(GPIOE_BASE + 0x08)
|
||||
#define GPIOE_OER *(volatile uint32_t *)(GPIOE_BASE + 0x10)
|
||||
#define GPIOE_ODR *(volatile uint32_t *)(GPIOE_BASE + 0x14)
|
||||
#define GPIOE_OSR *(volatile uint32_t *)(GPIOE_BASE + 0x18)
|
||||
#define GPIOE_SODR *(volatile uint32_t *)(GPIOE_BASE + 0x30)
|
||||
#define GPIOE_CODR *(volatile uint32_t *)(GPIOE_BASE + 0x34)
|
||||
#define GPIOE_IER *(volatile uint32_t *)(GPIOE_BASE + 0x40)
|
||||
#define GPIOE_IDR *(volatile uint32_t *)(GPIOE_BASE + 0x44)
|
||||
#define GPIOE_MDER *(volatile uint32_t *)(GPIOE_BASE + 0x50)
|
||||
#define GPIOE_MDDR *(volatile uint32_t *)(GPIOE_BASE + 0x54)
|
||||
#define GPIOE_PPUDR *(volatile uint32_t *)(GPIOE_BASE + 0x60)
|
||||
#define GPIOE_PPUER *(volatile uint32_t *)(GPIOE_BASE + 0x64)
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,58 @@
|
|||
OUTPUT_FORMAT("elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
DDR_MEM(rwx): ORIGIN = 0x00000000, LENGTH = 0x0000F000
|
||||
}
|
||||
|
||||
ENTRY(reset_vector_entry)
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
_start_text = .;
|
||||
*(.text)
|
||||
*(.rodata)
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
*(.glue_7)
|
||||
. = ALIGN(4);
|
||||
*(.eh_frame)
|
||||
. = ALIGN(4);
|
||||
_end_text = . ;
|
||||
}
|
||||
|
||||
/* collect all initialized .data sections */
|
||||
/* .data : AT ( ADDR (.text) + SIZEOF (.text) SIZEOF (.ARM.*) { */
|
||||
|
||||
. = ALIGN(4);
|
||||
.dummy : {
|
||||
_edummy = .;
|
||||
}
|
||||
|
||||
.data : AT (LOADADDR(.dummy)) {
|
||||
_start_data = .;
|
||||
*(.vectors)
|
||||
*(.data)
|
||||
_end_data = .;
|
||||
}
|
||||
|
||||
/* collect all uninitialized .bss sections */
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
_start_bss = .;
|
||||
*(.bss)
|
||||
_end_bss = .;
|
||||
}
|
||||
}
|
||||
|
||||
kernel_addr = 0x0400000;
|
||||
update_addr = 0x0800000;
|
||||
|
||||
_romsize = _end_data - _start_text;
|
||||
_sramsize = _end_bss - _start_text;
|
||||
END_STACK = _start_text;
|
||||
_stack_top = ORIGIN(DDR_MEM) + LENGTH(DDR_MEM);
|
||||
end = .; /* define a global symbol marking the end of application */
|
||||
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
WOLFCRYPT_OBJS+=./lib/wolfssl/wolfcrypt/src/asn.o
|
||||
USE_GCC?=1
|
||||
|
||||
# Support for Built-in ROT into OTP flash memory
|
||||
ifeq ($(FLASH_OTP_KEYSTORE),1)
|
||||
|
@ -196,7 +197,7 @@ ifeq ($(SIGN),ED448)
|
|||
ifeq ($(WOLFBOOT_SMALL_STACK),1)
|
||||
STACK_USAGE?=1024
|
||||
else
|
||||
STACK_USAGE?=4376
|
||||
STACK_USAGE?=4578
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/* boot_arm32.c
|
||||
*
|
||||
* Bring up, vectors and do_boot for 32bit Cortex-A microprocessors.
|
||||
*
|
||||
* Copyright (C) 2024 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 "image.h"
|
||||
#include "loader.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
|
||||
extern unsigned int __bss_start__;
|
||||
extern unsigned int __bss_end__;
|
||||
static volatile unsigned int cpu_id;
|
||||
extern unsigned int *END_STACK;
|
||||
|
||||
extern void main(void);
|
||||
|
||||
void boot_entry_C(void)
|
||||
{
|
||||
register unsigned int *dst;
|
||||
/* Initialize the BSS section to 0 */
|
||||
dst = &__bss_start__;
|
||||
while (dst < (unsigned int *)&__bss_end__) {
|
||||
*dst = 0U;
|
||||
dst++;
|
||||
}
|
||||
|
||||
/* Run wolfboot! */
|
||||
main();
|
||||
}
|
||||
|
||||
/* This is the main loop for the bootloader.
|
||||
*
|
||||
* It performs the following actions:
|
||||
* - Call the application entry point
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef MMU
|
||||
void RAMFUNCTION do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
|
||||
#else
|
||||
void RAMFUNCTION do_boot(const uint32_t *app_offset)
|
||||
#endif
|
||||
{
|
||||
/* Set application address via r4 */
|
||||
asm volatile("mov r4, %0" : : "r"(app_offset));
|
||||
|
||||
#ifdef MMU
|
||||
/* Move the dts pointer to r5 (as first argument) */
|
||||
asm volatile("mov r5, %0" : : "r"(dts_offset));
|
||||
#else
|
||||
asm volatile("mov r5, 0");
|
||||
#endif
|
||||
|
||||
/* Zero registers r1, r2, r3 */
|
||||
asm volatile("mov r3, 0");
|
||||
asm volatile("mov r2, 0");
|
||||
asm volatile("mov r1, 0");
|
||||
|
||||
/* Move the dts pointer to r0 (as first argument) */
|
||||
asm volatile("mov r0, r5");
|
||||
|
||||
/* Unconditionally jump to app_entry at r4 */
|
||||
asm volatile("bx r4");
|
||||
}
|
||||
|
||||
#ifdef RAM_CODE
|
||||
|
||||
#define AIRCR *(volatile uint32_t *)(0xE000ED0C)
|
||||
#define AIRCR_VKEY (0r05FA << 16)
|
||||
#define AIRCR_SYSRESETREQ (1 << 2)
|
||||
|
||||
void RAMFUNCTION arch_reboot(void)
|
||||
{
|
||||
AIRCR = AIRCR_SYSRESETREQ | AIRCR_VKEY;
|
||||
while(1)
|
||||
;
|
||||
wolfBoot_panic();
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* Arm32 (32bit Cortex-A) boot up
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
.section start
|
||||
.text
|
||||
|
||||
/* startup entry point */
|
||||
.globl reset_vector_entry
|
||||
.align 4
|
||||
reset_vector_entry:
|
||||
/* Exception vectors (should be a branch to be detected as a valid code by the rom */
|
||||
_exception_vectors:
|
||||
b isr_reset /* reset */
|
||||
b isr_empty /* Undefined Instruction */
|
||||
b isr_swi /* Software Interrupt */
|
||||
b isr_pabt /* Prefetch Abort */
|
||||
b dabt_vector /* Data Abort */
|
||||
.word _romsize /* Size of the binary for ROMCode loading */
|
||||
b isr_irq /* IRQ : read the AIC */
|
||||
b isr_fiq /* FIQ */
|
||||
|
||||
isr_empty:
|
||||
b isr_empty
|
||||
isr_swi:
|
||||
b isr_swi
|
||||
isr_pabt:
|
||||
b isr_pabt
|
||||
dabt_vector:
|
||||
subs pc, r14, #4 /* return */
|
||||
nop
|
||||
isr_rsvd:
|
||||
b isr_rsvd
|
||||
isr_irq:
|
||||
b isr_irq
|
||||
isr_fiq:
|
||||
b isr_fiq
|
||||
|
||||
|
||||
/* Reset handler procedure. Prepare the memory and call main() */
|
||||
isr_reset:
|
||||
/* Initialize the stack pointer */
|
||||
ldr sp,=_stack_top
|
||||
/* Save BootROM supplied boot source information to stack */
|
||||
push {r4}
|
||||
|
||||
/* Copy the data section */
|
||||
ldr r2, =_lp_data
|
||||
ldmia r2, {r1, r3, r4}
|
||||
1:
|
||||
cmp r3, r4
|
||||
ldrcc r2, [r1], #4
|
||||
strcc r2, [r3], #4
|
||||
bcc 1b
|
||||
|
||||
/* Zero bss area */
|
||||
adr r2, _lp_bss
|
||||
ldmia r2, {r3, r4}
|
||||
mov r2, #0
|
||||
1:
|
||||
cmp r3, r4
|
||||
strcc r2, [r3], #4
|
||||
bcc 1b
|
||||
|
||||
/* Jump to main() */
|
||||
ldr r4, = main
|
||||
mov lr, pc
|
||||
bx r4
|
||||
|
||||
/* main() should never return */
|
||||
_panic:
|
||||
b _panic
|
||||
|
||||
.align
|
||||
_lp_data:
|
||||
.word _start_data
|
||||
.word _end_data
|
||||
|
||||
_lp_bss:
|
||||
.word _start_bss
|
||||
.word _end_bss
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
OUTPUT_FORMAT("elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
DDR_MEM(rwx): ORIGIN = 0x20100800, LENGTH = 0x100000
|
||||
STACK_MEM(rw): ORIGIN = 0x20000000, LENGTH = 0x00100000
|
||||
}
|
||||
|
||||
ENTRY(reset_vector_entry)
|
||||
SECTIONS
|
||||
{
|
||||
.text : AT (ORIGIN(DDR_MEM)) {
|
||||
_start_text = .;
|
||||
*(.iv)
|
||||
*(.text)
|
||||
*(.rodata)
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
*(.glue_7)
|
||||
. = ALIGN(4);
|
||||
*(.eh_frame)
|
||||
. = ALIGN(4);
|
||||
_end_text = . ;
|
||||
}
|
||||
|
||||
/* collect all initialized .data sections */
|
||||
/* .data : AT ( ADDR (.text) + SIZEOF (.text) SIZEOF (.ARM.*) { */
|
||||
|
||||
. = ALIGN(4);
|
||||
.dummy : {
|
||||
_edummy = .;
|
||||
}
|
||||
|
||||
.data : AT (LOADADDR(.dummy)) {
|
||||
_start_data = .;
|
||||
*(.vectors)
|
||||
*(.data)
|
||||
_end_data = .;
|
||||
}
|
||||
|
||||
/* collect all uninitialized .bss sections */
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(4);
|
||||
_start_bss = .;
|
||||
*(.bss)
|
||||
_end_bss = .;
|
||||
}
|
||||
}
|
||||
_romsize = _end_data - _start_text;
|
||||
_sramsize = _end_bss - _start_text;
|
||||
END_STACK = _start_text;
|
||||
_stack_top = ORIGIN(STACK_MEM) + LENGTH(STACK_MEM);
|
||||
end = .; /* define a global symbol marking the end of application */
|
||||
|
|
@ -36,6 +36,7 @@ ifeq ($(HASH),SHA3_384)
|
|||
endif
|
||||
|
||||
|
||||
|
||||
ifeq ($(TARGET),ti_hercules)
|
||||
APP_OBJS:=app_$(TARGET).o ../test-app/libwolfboot.o
|
||||
CFLAGS+=-I"../include"
|
||||
|
@ -144,6 +145,11 @@ ifeq ($(TARGET),stm32c0)
|
|||
LSCRIPT_TEMPLATE=ARM-stm32c0.ld
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),sama5d3)
|
||||
APP_OBJS+=./boot_arm32_start.o
|
||||
LSCRIPT_TEMPLATE:=$(ARCH)-$(TARGET).ld
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),stm32l4)
|
||||
APP_OBJS+=$(STM32CUBE)/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.o
|
||||
APP_OBJS+=$(STM32CUBE)/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.o
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* app_sama5d3.c
|
||||
*
|
||||
* Test bare-metal boot application
|
||||
*
|
||||
* Copyright (C) 2024 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 <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <hal/sama5d3.h>
|
||||
|
||||
#include "wolfboot/wolfboot.h"
|
||||
|
||||
#ifdef TARGET_sama5d3
|
||||
/* Blue LED is PE23, Red LED is PE24 */
|
||||
|
||||
#define BLUE_LED_PIN 23
|
||||
#define RED_LED_PIN 24
|
||||
|
||||
void led_init(uint32_t pin)
|
||||
{
|
||||
uint32_t mask = 1U << pin;
|
||||
GPIOE_MDDR |= mask;
|
||||
GPIOE_PER |= mask;
|
||||
GPIOE_IDR |= mask;
|
||||
GPIOE_PPUDR |= mask;
|
||||
GPIOE_CODR |= mask;
|
||||
}
|
||||
|
||||
void led_put(uint32_t pin, int val)
|
||||
{
|
||||
uint32_t mask = 1U << pin;
|
||||
if (val)
|
||||
GPIOE_SODR |= mask;
|
||||
else
|
||||
GPIOE_CODR |= mask;
|
||||
}
|
||||
|
||||
volatile uint32_t time_elapsed = 0;
|
||||
void main(void) {
|
||||
|
||||
/* Wait for reboot */
|
||||
led_init(RED_LED_PIN);
|
||||
led_put(RED_LED_PIN, 1);
|
||||
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
#endif /** TARGET_sama5d3 **/
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* Arm32 (32bit Cortex-A) boot up
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
.section start
|
||||
.text
|
||||
|
||||
/* startup entry point */
|
||||
.globl reset_vector_entry
|
||||
.align 4
|
||||
.section .iv
|
||||
reset_vector_entry:
|
||||
/* Exception vectors (should be a branch to be detected as a valid code by the rom */
|
||||
_exception_vectors:
|
||||
b isr_reset /* reset */
|
||||
b isr_empty /* Undefined Instruction */
|
||||
b isr_swi /* Software Interrupt */
|
||||
b isr_pabt /* Prefetch Abort */
|
||||
b dabt_vector /* Data Abort */
|
||||
.word _romsize /* Size of the binary for ROMCode loading */
|
||||
b isr_irq /* IRQ : read the AIC */
|
||||
b isr_fiq /* FIQ */
|
||||
|
||||
isr_empty:
|
||||
b isr_empty
|
||||
isr_swi:
|
||||
b isr_swi
|
||||
isr_pabt:
|
||||
b isr_pabt
|
||||
dabt_vector:
|
||||
subs pc, r14, #4 /* return */
|
||||
nop
|
||||
isr_rsvd:
|
||||
b isr_rsvd
|
||||
isr_irq:
|
||||
b isr_irq
|
||||
isr_fiq:
|
||||
b isr_fiq
|
||||
|
||||
|
||||
/* Reset handler procedure. Prepare the memory and call main() */
|
||||
isr_reset:
|
||||
/* Initialize the stack pointer */
|
||||
ldr sp,=_stack_top
|
||||
/* Save BootROM supplied boot source information to stack */
|
||||
push {r4}
|
||||
|
||||
/* Copy the data section */
|
||||
ldr r2, =_lp_data
|
||||
ldmia r2, {r1, r3, r4}
|
||||
1:
|
||||
cmp r3, r4
|
||||
ldrcc r2, [r1], #4
|
||||
strcc r2, [r3], #4
|
||||
bcc 1b
|
||||
|
||||
/* Zero bss area */
|
||||
adr r2, _lp_bss
|
||||
ldmia r2, {r3, r4}
|
||||
mov r2, #0
|
||||
1:
|
||||
cmp r3, r4
|
||||
strcc r2, [r3], #4
|
||||
bcc 1b
|
||||
|
||||
/* Jump to main() */
|
||||
ldr r4, = main
|
||||
mov lr, pc
|
||||
bx r4
|
||||
|
||||
/* main() should never return */
|
||||
_panic:
|
||||
b _panic
|
||||
|
||||
.align
|
||||
_lp_data:
|
||||
.word _start_data
|
||||
.word _end_data
|
||||
|
||||
_lp_bss:
|
||||
.word _start_bss
|
||||
.word _end_bss
|
||||
|
Loading…
Reference in New Issue