From 4cbfdf8cf1734afb0e5a22981227322949b83e64 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Fri, 23 Aug 2024 07:05:03 +0200 Subject: [PATCH 1/8] [SAMA5D3] Port for 32bit Cortex-A --- Makefile | 4 ++ arch.mk | 133 ++++++++++++++++++++++------------------- docs/Targets.md | 46 ++++++++++++++ hal/sama5d3.c | 94 +++++++++++++++++++++++++++++ hal/sama5d3.ld | 53 ++++++++++++++++ src/boot_arm32.c | 100 +++++++++++++++++++++++++++++++ src/boot_arm32_start.S | 98 ++++++++++++++++++++++++++++++ 7 files changed, 468 insertions(+), 60 deletions(-) create mode 100644 hal/sama5d3.c create mode 100644 hal/sama5d3.ld create mode 100644 src/boot_arm32.c create mode 100644 src/boot_arm32_start.S diff --git a/Makefile b/Makefile index d803e91e0..3accc2b47 100644 --- a/Makefile +++ b/Makefile @@ -130,6 +130,10 @@ ifeq ($(TARGET),nxp_t1024) MAIN_TARGET:=factory_wstage1.bin endif +ifeq ($(TARGET),sama5d3) + MAIN_TARGET:=wolfboot.bin +endif + ifeq ($(FLASH_OTP_KEYSTORE),1) MAIN_TARGET+=tools/keytools/otp/otp-keystore-primer.bin endif diff --git a/arch.mk b/arch.mk index 92dbe8319..f37ca9d15 100644 --- a/arch.mk +++ b/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,102 @@ 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 ($(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 - else - ifeq ($(SPMATH),1) - CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o - endif + ifeq ($(TARGET),sama5d3) + CORTEX_A5=1 endif + +## Cortex CPU + +ifeq ($(CORTEX_A5),1) + CFLAGS+=-mcpu=cortex-a5 -mtune=cortex-a5 -mfpu=vfpv4-d16 -static -z noexecstack + LDLAGS+=-mcpu=cortex-a5 -mtune=cortex-a5 -mtune=cortex-a5 -mfpu=vfpv4-d16 -static -z noexecstack -Ttext 0x300000 + # Cortex-A uses boot_arm32.o + OBJS+=src/boot_arm32.o src/boot_arm32_start.o + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o 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 + # 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 # 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_CORTEX_M_ASM + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o + endif + endif + else + 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_M0),1) - CFLAGS+=-mcpu=cortex-m0 - LDFLAGS+=-mcpu=cortex-m0 + 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_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 ($(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 diff --git a/docs/Targets.md b/docs/Targets.md index c100d4526..bf570c482 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -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,51 @@ 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 + +(TODO) + + + ## Microchip SAME51 SAME51 is a Cortex-M4 microcontroller with a dual-bank, 1MB flash memory divided diff --git a/hal/sama5d3.c b/hal/sama5d3.c new file mode 100644 index 000000000..cce4054f2 --- /dev/null +++ b/hal/sama5d3.c @@ -0,0 +1,94 @@ +/* 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 +#include +#include +#include "image.h" +#ifndef ARCH_ARM +# error "wolfBoot atsama5d3 HAL: wrong architecture selected. Please compile with ARCH=ARM." +#endif + +#define TEST_ENCRYPT + +/* Fixed addresses */ +extern void *kernel_addr, *update_addr, *dts_addr; + +void* hal_get_primary_address(void) +{ + return (void*)&kernel_addr; +} + +void* hal_get_update_address(void) +{ + return (void*)&update_addr; +} + +void* hal_get_dts_address(void) +{ + return (void*)&dts_addr; +} + +void* hal_get_dts_update_address(void) +{ + return NULL; /* Not yet supported */ +} + +/* QSPI functions */ +void qspi_init(uint32_t cpu_clock, uint32_t flash_freq) +{ +} + + +void zynq_init(uint32_t cpu_clock) +{ +} + + + +/* public HAL functions */ +void hal_init(void) +{ +} + +void hal_prepare_boot(void) +{ +} + + +int RAMFUNCTION hal_flash_write(uintptr_t address, const uint8_t *data, int len) +{ + return 0; +} + +void RAMFUNCTION hal_flash_unlock(void) +{ +} + +void RAMFUNCTION hal_flash_lock(void) +{ +} + + +int RAMFUNCTION hal_flash_erase(uintptr_t address, int len) +{ + return 0; +} diff --git a/hal/sama5d3.ld b/hal/sama5d3.ld new file mode 100644 index 000000000..b9fd3fbc8 --- /dev/null +++ b/hal/sama5d3.ld @@ -0,0 +1,53 @@ +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) + +MEMORY +{ + DDR_MEM(rwx): ORIGIN = 0x00300000, LENGTH = 0x000100000 +} + +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 = .; + } +} +_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 */ + diff --git a/src/boot_arm32.c b/src/boot_arm32.c new file mode 100644 index 000000000..5502ff151 --- /dev/null +++ b/src/boot_arm32.c @@ -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 + +#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 diff --git a/src/boot_arm32_start.S b/src/boot_arm32_start.S new file mode 100644 index 000000000..57520ba7f --- /dev/null +++ b/src/boot_arm32_start.S @@ -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 + From bbd4e2b1c3cd79ac8ae6e334770f46d028d6cf8f Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Thu, 29 Aug 2024 13:29:36 +0200 Subject: [PATCH 2/8] [SAMA5D3] Stub for test application --- Makefile | 3 ++- arch.mk | 2 ++ hal/sama5d3.ld | 5 ++++ test-app/ARM-sama5d3.ld | 53 +++++++++++++++++++++++++++++++++++++++++ test-app/Makefile | 6 +++++ test-app/app_sama5d3.c | 39 ++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 test-app/ARM-sama5d3.ld create mode 100644 test-app/app_sama5d3.c diff --git a/Makefile b/Makefile index 3accc2b47..2bc191e93 100644 --- a/Makefile +++ b/Makefile @@ -131,9 +131,10 @@ ifeq ($(TARGET),nxp_t1024) endif ifeq ($(TARGET),sama5d3) - MAIN_TARGET:=wolfboot.bin + 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 diff --git a/arch.mk b/arch.mk index f37ca9d15..63054e54e 100644 --- a/arch.mk +++ b/arch.mk @@ -177,6 +177,8 @@ ifeq ($(ARCH),ARM) ifeq ($(TARGET),sama5d3) CORTEX_A5=1 + UPDATE_OBJS:=src/update_ram.o + CFLAGS+=-DWOLFBOOT_DUALBOOT endif ## Cortex CPU diff --git a/hal/sama5d3.ld b/hal/sama5d3.ld index b9fd3fbc8..2d9181128 100644 --- a/hal/sama5d3.ld +++ b/hal/sama5d3.ld @@ -45,9 +45,14 @@ SECTIONS _end_bss = .; } } + +kernel_addr = 0x040000; +update_addr = 0x080000; + _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 */ + diff --git a/test-app/ARM-sama5d3.ld b/test-app/ARM-sama5d3.ld new file mode 100644 index 000000000..b9fd3fbc8 --- /dev/null +++ b/test-app/ARM-sama5d3.ld @@ -0,0 +1,53 @@ +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) + +MEMORY +{ + DDR_MEM(rwx): ORIGIN = 0x00300000, LENGTH = 0x000100000 +} + +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 = .; + } +} +_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 */ + diff --git a/test-app/Makefile b/test-app/Makefile index 7e095197f..04886efd5 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -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+=../src/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 diff --git a/test-app/app_sama5d3.c b/test-app/app_sama5d3.c new file mode 100644 index 000000000..e518b2af4 --- /dev/null +++ b/test-app/app_sama5d3.c @@ -0,0 +1,39 @@ +/* app_sama5d3.c + * + * Test bare-metal boot application + * + * 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 +#include +#include + +#include "wolfboot/wolfboot.h" + +#ifdef TARGET_sama5d3 + +volatile uint32_t time_elapsed = 0; +void main(void) { + + /* Wait for reboot */ + while(1) + ; +} +#endif /** TARGET_sama5d3 **/ From 888d53876040165aa6aff5c08c4f5f01c19a0ea4 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 4 Sep 2024 17:42:46 +0200 Subject: [PATCH 3/8] [SAMA5D3] Nand flash driver --- .gdbinit | 2 +- arch.mk | 3 +- config/examples/sama5d3.config | 23 ++ hal/sama5d3.c | 402 ++++++++++++++++++++++++++++++++- hal/sama5d3.ld | 2 +- options.mk | 2 +- test-app/ARM-sama5d3.ld | 2 +- 7 files changed, 422 insertions(+), 14 deletions(-) create mode 100644 config/examples/sama5d3.config diff --git a/.gdbinit b/.gdbinit index 676e54df9..e6d2cdfeb 100644 --- a/.gdbinit +++ b/.gdbinit @@ -1,5 +1,5 @@ -tar rem:3333 file wolfboot.elf +tar rem:3333 add-symbol-file test-app/image.elf foc c diff --git a/arch.mk b/arch.mk index 63054e54e..e44405c59 100644 --- a/arch.mk +++ b/arch.mk @@ -178,7 +178,8 @@ ifeq ($(ARCH),ARM) ifeq ($(TARGET),sama5d3) CORTEX_A5=1 UPDATE_OBJS:=src/update_ram.o - CFLAGS+=-DWOLFBOOT_DUALBOOT + CFLAGS+=-DWOLFBOOT_DUALBOOT -DEXT_FLASH -DNAND_FLASH + #CFLAGS+=-DWOLFBOOT_USE_STDLIBC endif ## Cortex CPU diff --git a/config/examples/sama5d3.config b/config/examples/sama5d3.config new file mode 100644 index 000000000..7fac7bbea --- /dev/null +++ b/config/examples/sama5d3.config @@ -0,0 +1,23 @@ +ARCH?=ARM +TARGET?=sama5d3 +SIGN?=ECC256 +HASH?=SHA256 +DEBUG?=1 +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=0x380000 +WOLFBOOT_LOAD_DTS_ADDRESS=0x3C0000 +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x40000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x80000 +WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0 +NO_XIP=1 +IMAGE_HEADER_SIZE=2048 diff --git a/hal/sama5d3.c b/hal/sama5d3.c index cce4054f2..3afecac8c 100644 --- a/hal/sama5d3.c +++ b/hal/sama5d3.c @@ -27,21 +27,403 @@ # error "wolfBoot atsama5d3 HAL: wrong architecture selected. Please compile with ARCH=ARM." #endif -#define TEST_ENCRYPT - /* Fixed addresses */ extern void *kernel_addr, *update_addr, *dts_addr; -void* hal_get_primary_address(void) +#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 AT91C_BASE_DDRCS 0x20000000 +#define AT91C_BASE_CS1 0x40000000 +#define AT91C_BASE_CS2 0x50000000 +#define AT91C_BASE_CS3 0x60000000 +#define AT91C_BASE_NFC_CMD 0x70000000 + +/* NAND flash is mapped to CS3 */ +#define NAND_BASE AT91C_BASE_CS3 + +#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))) +#define NAND_DATAW (*((volatile uint32_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 LOOKUP_TABLE_ALPHA_OFFSET 0x14000 +#define LOOKUP_TABLE_INDEX_OFFSET 0x10000 +#define LOOKUP_TABLE_ALPHA_OFFSET_1024 0x20000 +#define LOOKUP_TABLE_INDEX_OFFSET_1024 0x18000 +*/ + +#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 + + +/* 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) { - return (void*)&kernel_addr; + 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 = 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; +} + + +static uint8_t buffer_page[NAND_FLASH_PAGE_SIZE]; + +int ext_flash_read(uintptr_t address, uint8_t *data, int len) +{ + uint32_t block = address / nand_flash.block_size; /* The block where the address falls in */ + uint32_t page = address / nand_flash.page_size; /* The page where the address falls in */ + uint32_t start_page_in_block = page % nand_flash.pages_per_block; /* The start page within this block */ + uint32_t in_block_offset = 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 */ + uint32_t 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 = (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); + 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; + for (i = 0; i < (len / sizeof(uint32_t)); i++) { + dst[i] = src[i]; + } + } + return len; } -void* hal_get_update_address(void) +int ext_flash_write(uintptr_t address, const uint8_t *data, int len) { - return (void*)&update_addr; + return 0; } +int ext_flash_erase(uintptr_t address, int len) +{ + return 0; +} + +/* SAMA5D3 NAND flash does not have an enable pin */ +void ext_flash_unlock(void) +{ +} + +void ext_flash_lock(void) +{ +} +#endif + void* hal_get_dts_address(void) { return (void*)&dts_addr; @@ -63,10 +445,10 @@ void zynq_init(uint32_t cpu_clock) } - /* public HAL functions */ void hal_init(void) { + nand_read_info(); } void hal_prepare_boot(void) @@ -74,7 +456,7 @@ void hal_prepare_boot(void) } -int RAMFUNCTION hal_flash_write(uintptr_t address, const uint8_t *data, int len) +int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) { return 0; } @@ -88,7 +470,9 @@ void RAMFUNCTION hal_flash_lock(void) } -int RAMFUNCTION hal_flash_erase(uintptr_t address, int len) +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { return 0; } + + diff --git a/hal/sama5d3.ld b/hal/sama5d3.ld index 2d9181128..3789340d7 100644 --- a/hal/sama5d3.ld +++ b/hal/sama5d3.ld @@ -3,7 +3,7 @@ OUTPUT_ARCH(arm) MEMORY { - DDR_MEM(rwx): ORIGIN = 0x00300000, LENGTH = 0x000100000 + DDR_MEM(rwx): ORIGIN = 0x00300000, LENGTH = 0x0007F000 } ENTRY(reset_vector_entry) diff --git a/options.mk b/options.mk index 7184ed67c..1ca96c0c7 100644 --- a/options.mk +++ b/options.mk @@ -196,7 +196,7 @@ ifeq ($(SIGN),ED448) ifeq ($(WOLFBOOT_SMALL_STACK),1) STACK_USAGE?=1024 else - STACK_USAGE?=4376 + STACK_USAGE?=4578 endif endif diff --git a/test-app/ARM-sama5d3.ld b/test-app/ARM-sama5d3.ld index b9fd3fbc8..b0f537fd8 100644 --- a/test-app/ARM-sama5d3.ld +++ b/test-app/ARM-sama5d3.ld @@ -3,7 +3,7 @@ OUTPUT_ARCH(arm) MEMORY { - DDR_MEM(rwx): ORIGIN = 0x00300000, LENGTH = 0x000100000 + DDR_MEM(rwx): ORIGIN = 0x00340000, LENGTH = 0x000100000 } ENTRY(reset_vector_entry) From 76920599b3c260eb9a7e5429ab1457df3bea2b7f Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 16 Sep 2024 20:10:46 +0200 Subject: [PATCH 4/8] [SAMA5D3] Added test-app, moved to SP_ASM --- arch.mk | 14 +++-- config/examples/sama5d3.config | 8 +-- hal/sama5d3.c | 94 ++++++++++++++++++++++++++++---- hal/sama5d3.ld | 12 ++--- test-app/ARM-sama5d3.ld | 3 +- test-app/Makefile | 2 +- test-app/app_sama5d3.c | 43 +++++++++++++++ test-app/boot_arm32_start.S | 99 ++++++++++++++++++++++++++++++++++ 8 files changed, 249 insertions(+), 26 deletions(-) create mode 100644 test-app/boot_arm32_start.S diff --git a/arch.mk b/arch.mk index e44405c59..0bc648df1 100644 --- a/arch.mk +++ b/arch.mk @@ -178,18 +178,24 @@ ifeq ($(ARCH),ARM) ifeq ($(TARGET),sama5d3) CORTEX_A5=1 UPDATE_OBJS:=src/update_ram.o - CFLAGS+=-DWOLFBOOT_DUALBOOT -DEXT_FLASH -DNAND_FLASH + CFLAGS+=-DWOLFBOOT_DUALBOOT -DEXT_FLASH -DNAND_FLASH -fno-builtin -ffreestanding #CFLAGS+=-DWOLFBOOT_USE_STDLIBC endif ## Cortex CPU ifeq ($(CORTEX_A5),1) - CFLAGS+=-mcpu=cortex-a5 -mtune=cortex-a5 -mfpu=vfpv4-d16 -static -z noexecstack - LDLAGS+=-mcpu=cortex-a5 -mtune=cortex-a5 -mtune=cortex-a5 -mfpu=vfpv4-d16 -static -z noexecstack -Ttext 0x300000 + 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 - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o + ifeq ($(NO_ASM),1) + MATH_OBJS+=./lib/wolfssl/wolfcrypt/src/sp_c32.o + else + MATH_OBJS+=./lib/wolfssl/wolfcrypt/src/sp_arm32.o + CFLAGS+=-DWOLFSSL_SP_ARM32_ASM + endif else # All others use boot_arm.o OBJS+=src/boot_arm.o diff --git a/config/examples/sama5d3.config b/config/examples/sama5d3.config index 7fac7bbea..4e062f379 100644 --- a/config/examples/sama5d3.config +++ b/config/examples/sama5d3.config @@ -14,10 +14,10 @@ SPMATH?=1 WOLFBOOT_PARTITION_SIZE?=0x1000000 WOLFBOOT_NO_PARTITIONS=0 WOLFBOOT_SECTOR_SIZE?=0x1000 -WOLFBOOT_LOAD_ADDRESS=0x380000 -WOLFBOOT_LOAD_DTS_ADDRESS=0x3C0000 -WOLFBOOT_PARTITION_BOOT_ADDRESS=0x40000 -WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x80000 +WOLFBOOT_LOAD_ADDRESS=0x201000 +WOLFBOOT_LOAD_DTS_ADDRESS=0x281000 +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x400000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x800000 WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0 NO_XIP=1 IMAGE_HEADER_SIZE=2048 diff --git a/hal/sama5d3.c b/hal/sama5d3.c index 3afecac8c..203087c06 100644 --- a/hal/sama5d3.c +++ b/hal/sama5d3.c @@ -48,10 +48,9 @@ extern void *kernel_addr, *update_addr, *dts_addr; #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_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))) -#define NAND_DATAW (*((volatile uint32_t *)(NAND_BASE))) /* Command set */ #define NAND_CMD_STATUS 0x70 @@ -141,6 +140,80 @@ extern void *kernel_addr, *update_addr, *dts_addr; #define MAX_ECC_BYTES 8 +/* Manual division operation */ +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; +} + +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; +} + +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; +} + /* Static variables to hold nand info */ static uint8_t nand_manif_id; static uint8_t nand_dev_id; @@ -245,7 +318,7 @@ static void nand_read_info(void) 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 = nand_flash.block_size / nand_flash.page_size; + 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); @@ -342,14 +415,14 @@ static int nand_check_bad_block(uint32_t block) } -static uint8_t buffer_page[NAND_FLASH_PAGE_SIZE]; int ext_flash_read(uintptr_t address, uint8_t *data, int len) { - uint32_t block = address / nand_flash.block_size; /* The block where the address falls in */ - uint32_t page = address / nand_flash.page_size; /* The page where the address falls in */ - uint32_t start_page_in_block = page % nand_flash.pages_per_block; /* The start page within this block */ - uint32_t in_block_offset = address % nand_flash.block_size; /* The offset of the address within the block */ + 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 */ uint32_t len_to_read = len; uint8_t *buffer = data; @@ -378,7 +451,7 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len) } while (ret < 0); /* Amount of pages to be read from this block */ - pages_to_read = (sz + nand_flash.page_size - 1) / nand_flash.page_size; + 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--; @@ -397,7 +470,8 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len) if (copy) { uint32_t *dst = (uint32_t *)data; uint32_t *src = (uint32_t *)buffer_page; - for (i = 0; i < (len / sizeof(uint32_t)); i++) { + uint32_t tot_len = (uint32_t)len; + for (i = 0; i < (tot_len >> 2); i++) { dst[i] = src[i]; } } diff --git a/hal/sama5d3.ld b/hal/sama5d3.ld index 3789340d7..c446f1683 100644 --- a/hal/sama5d3.ld +++ b/hal/sama5d3.ld @@ -3,7 +3,7 @@ OUTPUT_ARCH(arm) MEMORY { - DDR_MEM(rwx): ORIGIN = 0x00300000, LENGTH = 0x0007F000 + DDR_MEM(rwx): ORIGIN = 0x00000000, LENGTH = 0x0000F000 } ENTRY(reset_vector_entry) @@ -12,9 +12,9 @@ SECTIONS .text : { _start_text = .; *(.text) - *(.rodata) - *(.rodata*) - . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = ALIGN(4); *(.glue_7) . = ALIGN(4); *(.eh_frame) @@ -46,8 +46,8 @@ SECTIONS } } -kernel_addr = 0x040000; -update_addr = 0x080000; +kernel_addr = 0x0400000; +update_addr = 0x0800000; _romsize = _end_data - _start_text; _sramsize = _end_bss - _start_text; diff --git a/test-app/ARM-sama5d3.ld b/test-app/ARM-sama5d3.ld index b0f537fd8..8f887fe24 100644 --- a/test-app/ARM-sama5d3.ld +++ b/test-app/ARM-sama5d3.ld @@ -3,7 +3,7 @@ OUTPUT_ARCH(arm) MEMORY { - DDR_MEM(rwx): ORIGIN = 0x00340000, LENGTH = 0x000100000 + DDR_MEM(rwx): ORIGIN = 0x00311000, LENGTH = 0x000080000 } ENTRY(reset_vector_entry) @@ -11,6 +11,7 @@ SECTIONS { .text : { _start_text = .; + *(.iv) *(.text) *(.rodata) *(.rodata*) diff --git a/test-app/Makefile b/test-app/Makefile index 04886efd5..47b8acae2 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -146,7 +146,7 @@ ifeq ($(TARGET),stm32c0) endif ifeq ($(TARGET),sama5d3) - APP_OBJS+=../src/boot_arm32_start.o + APP_OBJS+=./boot_arm32_start.o LSCRIPT_TEMPLATE:=$(ARCH)-$(TARGET).ld endif diff --git a/test-app/app_sama5d3.c b/test-app/app_sama5d3.c index e518b2af4..2016a7dd6 100644 --- a/test-app/app_sama5d3.c +++ b/test-app/app_sama5d3.c @@ -28,11 +28,54 @@ #include "wolfboot/wolfboot.h" #ifdef TARGET_sama5d3 +/* Blue LED is PE23, Red LED is PE24 */ + +#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) + +#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) ; } diff --git a/test-app/boot_arm32_start.S b/test-app/boot_arm32_start.S new file mode 100644 index 000000000..55a26462d --- /dev/null +++ b/test-app/boot_arm32_start.S @@ -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 + From 294d62d0c64570e13da986c476fd51738c8c79f6 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 18 Sep 2024 06:22:18 +0200 Subject: [PATCH 5/8] [SAMA5D3] Support for DDR2 memory on -xplained --- config/examples/sama5d3-ddr.config | 23 + .../{sama5d3.config => sama5d3-sram.config} | 0 hal/sama5d3.c | 444 +++++++++++++----- hal/sama5d3.h | 408 ++++++++++++++++ options.mk | 1 + test-app/ARM-sama5d3.ld | 9 +- 6 files changed, 762 insertions(+), 123 deletions(-) create mode 100644 config/examples/sama5d3-ddr.config rename config/examples/{sama5d3.config => sama5d3-sram.config} (100%) create mode 100644 hal/sama5d3.h diff --git a/config/examples/sama5d3-ddr.config b/config/examples/sama5d3-ddr.config new file mode 100644 index 000000000..e42c3ae86 --- /dev/null +++ b/config/examples/sama5d3-ddr.config @@ -0,0 +1,23 @@ +ARCH?=ARM +TARGET?=sama5d3 +SIGN?=ECC256 +HASH?=SHA256 +DEBUG?=1 +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 diff --git a/config/examples/sama5d3.config b/config/examples/sama5d3-sram.config similarity index 100% rename from config/examples/sama5d3.config rename to config/examples/sama5d3-sram.config diff --git a/hal/sama5d3.c b/hal/sama5d3.c index 203087c06..fe4b581e7 100644 --- a/hal/sama5d3.c +++ b/hal/sama5d3.c @@ -19,129 +19,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#include #include #include #include "image.h" +#include "sama5d3.h" + #ifndef ARCH_ARM # error "wolfBoot atsama5d3 HAL: wrong architecture selected. Please compile with ARCH=ARM." #endif -/* 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 AT91C_BASE_DDRCS 0x20000000 -#define AT91C_BASE_CS1 0x40000000 -#define AT91C_BASE_CS2 0x50000000 -#define AT91C_BASE_CS3 0x60000000 -#define AT91C_BASE_NFC_CMD 0x70000000 - -/* NAND flash is mapped to CS3 */ -#define NAND_BASE AT91C_BASE_CS3 - -#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 LOOKUP_TABLE_ALPHA_OFFSET 0x14000 -#define LOOKUP_TABLE_INDEX_OFFSET 0x10000 -#define LOOKUP_TABLE_ALPHA_OFFSET_1024 0x20000 -#define LOOKUP_TABLE_INDEX_OFFSET_1024 0x18000 -*/ - -#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 - +void sleep_us(uint32_t usec); /* Manual division operation */ -int division(uint32_t dividend, +static int division(uint32_t dividend, uint32_t divisor, uint32_t *quotient, uint32_t *remainder) @@ -188,7 +78,7 @@ int division(uint32_t dividend, return 0; } -uint32_t div(uint32_t dividend, uint32_t divisor) +static uint32_t div(uint32_t dividend, uint32_t divisor) { uint32_t quotient = 0; uint32_t remainder = 0; @@ -201,7 +91,7 @@ uint32_t div(uint32_t dividend, uint32_t divisor) return quotient; } -uint32_t mod(uint32_t dividend, uint32_t divisor) +static uint32_t mod(uint32_t dividend, uint32_t divisor) { uint32_t quotient = 0; uint32_t remainder = 0; @@ -214,13 +104,288 @@ uint32_t mod(uint32_t dividend, uint32_t divisor) return remainder; } +/* RAM configuration: 2 x MT47H64M16 on SAMA5D3-Xplained + * 8 Mwords x 8 Banks x 16 bits x 2, total 2 Gbit + */ +static 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 |= (80 << MPDDRC_IOCALIBR_TZQIO_SHIFT); /* 100 cycles at 133MHz is 0.75 us, 100 cycles at 166MHz is 0.6 us */ + 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; @@ -478,6 +643,44 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len) 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) { return 0; @@ -496,7 +699,6 @@ void ext_flash_unlock(void) void ext_flash_lock(void) { } -#endif void* hal_get_dts_address(void) { @@ -522,6 +724,10 @@ void zynq_init(uint32_t cpu_clock) /* public HAL functions */ void hal_init(void) { + pll_init(); + pit_init(); + watchdog_disable(); + ddr_init(); nand_read_info(); } diff --git a/hal/sama5d3.h b/hal/sama5d3.h new file mode 100644 index 000000000..15748adb5 --- /dev/null +++ b/hal/sama5d3.h @@ -0,0 +1,408 @@ + +#ifndef SAMA5D3_HAL_H +#define SAMA5D3_HAL_H + +#include + +/* CPU/Board clock settings */ +#define CPU_FREQ 264000000 +#define MASTER_FREQ 132000000 +#define CRYSTAL_FREQ 12000000 +#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 0x20000000 +#define CS1_BASE 0x40000000 +#define CS2_BASE 0x50000000 +#define CS3_BASE 0x60000000 +#define NFC_CMD_BASE 0x70000000 + +/* 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 + +#endif diff --git a/options.mk b/options.mk index 1ca96c0c7..584b65e3e 100644 --- a/options.mk +++ b/options.mk @@ -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) diff --git a/test-app/ARM-sama5d3.ld b/test-app/ARM-sama5d3.ld index 8f887fe24..bd2808361 100644 --- a/test-app/ARM-sama5d3.ld +++ b/test-app/ARM-sama5d3.ld @@ -3,13 +3,14 @@ OUTPUT_ARCH(arm) MEMORY { - DDR_MEM(rwx): ORIGIN = 0x00311000, LENGTH = 0x000080000 + DDR_MEM(rwx): ORIGIN = 0x20100800, LENGTH = 0x100000 + STACK_MEM(rw): ORIGIN = 0x20000000, LENGTH = 0x00100000 } ENTRY(reset_vector_entry) SECTIONS { - .text : { + .text : AT (ORIGIN(DDR_MEM)) { _start_text = .; *(.iv) *(.text) @@ -39,7 +40,7 @@ SECTIONS } /* collect all uninitialized .bss sections */ - .bss (NOLOAD) : { + .bss (NOLOAD) : { . = ALIGN(4); _start_bss = .; *(.bss) @@ -49,6 +50,6 @@ SECTIONS _romsize = _end_data - _start_text; _sramsize = _end_bss - _start_text; END_STACK = _start_text; -_stack_top = ORIGIN(DDR_MEM) + LENGTH(DDR_MEM); +_stack_top = ORIGIN(STACK_MEM) + LENGTH(STACK_MEM); end = .; /* define a global symbol marking the end of application */ From 6080cc215cdaa9e9b45bde8da9fc371ea714a710 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 30 Sep 2024 13:58:32 +0200 Subject: [PATCH 6/8] [SAMA5D3] Add build test, expand Target.md --- .github/workflows/test-configs.yml | 7 ++++++ config/examples/sama5d3-sram.config | 23 ------------------- .../{sama5d3-ddr.config => sama5d3.config} | 0 docs/Targets.md | 11 ++++++++- 4 files changed, 17 insertions(+), 24 deletions(-) delete mode 100644 config/examples/sama5d3-sram.config rename config/examples/{sama5d3-ddr.config => sama5d3.config} (100%) diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 1df9275be..4760abd5d 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -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: diff --git a/config/examples/sama5d3-sram.config b/config/examples/sama5d3-sram.config deleted file mode 100644 index 4e062f379..000000000 --- a/config/examples/sama5d3-sram.config +++ /dev/null @@ -1,23 +0,0 @@ -ARCH?=ARM -TARGET?=sama5d3 -SIGN?=ECC256 -HASH?=SHA256 -DEBUG?=1 -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=0x201000 -WOLFBOOT_LOAD_DTS_ADDRESS=0x281000 -WOLFBOOT_PARTITION_BOOT_ADDRESS=0x400000 -WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x800000 -WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0 -NO_XIP=1 -IMAGE_HEADER_SIZE=2048 diff --git a/config/examples/sama5d3-ddr.config b/config/examples/sama5d3.config similarity index 100% rename from config/examples/sama5d3-ddr.config rename to config/examples/sama5d3.config diff --git a/docs/Targets.md b/docs/Targets.md index bf570c482..3c65c7615 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -1447,8 +1447,17 @@ Step 3: program `wolfboot.bin` to the beginning of the flash: ### Programming the test application into NAND flash -(TODO) +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 From 238e678db62473ccb518cb6daf14f4c801a168e6 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 30 Sep 2024 15:49:44 +0200 Subject: [PATCH 7/8] [SAMA5D3] Fix nand driver read offset Tested with 6MB image --- hal/sama5d3.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hal/sama5d3.c b/hal/sama5d3.c index fe4b581e7..82fffaa7d 100644 --- a/hal/sama5d3.c +++ b/hal/sama5d3.c @@ -589,7 +589,7 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len) 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 */ - uint32_t len_to_read = len; + int len_to_read = len; uint8_t *buffer = data; uint32_t i; int copy = 0; @@ -624,6 +624,8 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len) /* 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; } From c80937bdead1dfad20152af10b59e57888ff5354 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 2 Oct 2024 10:25:36 +0200 Subject: [PATCH 8/8] Addressed reviewer's comments --- config/examples/sama5d3.config | 2 +- hal/sama5d3.c | 172 ++++++++++++++++----------------- hal/sama5d3.h | 56 +++++++++-- test-app/app_sama5d3.c | 20 +--- 4 files changed, 136 insertions(+), 114 deletions(-) diff --git a/config/examples/sama5d3.config b/config/examples/sama5d3.config index e42c3ae86..f52f84794 100644 --- a/config/examples/sama5d3.config +++ b/config/examples/sama5d3.config @@ -2,7 +2,7 @@ ARCH?=ARM TARGET?=sama5d3 SIGN?=ECC256 HASH?=SHA256 -DEBUG?=1 +DEBUG?=0 VTOR?=1 CORTEX_M0?=0 NO_ASM?=0 diff --git a/hal/sama5d3.c b/hal/sama5d3.c index 82fffaa7d..804dc3d5a 100644 --- a/hal/sama5d3.c +++ b/hal/sama5d3.c @@ -32,82 +32,82 @@ 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; - } + 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; - } - } + 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; + if (end_flag) + continue; - factor += 1 << (shift - 1); - dividend -= divisor_shift >> 1; - } + factor += 1 << (shift - 1); + dividend -= divisor_shift >> 1; + } - if (quotient) - *quotient = factor; + if (quotient) + *quotient = factor; - if (remainder) - *remainder = dividend; + if (remainder) + *remainder = dividend; - return 0; + return 0; } static uint32_t div(uint32_t dividend, uint32_t divisor) { - uint32_t quotient = 0; - uint32_t remainder = 0; - int ret; + uint32_t quotient = 0; + uint32_t remainder = 0; + int ret; - ret = division(dividend, divisor, "ient, &remainder); - if (ret) - return 0xffffffff; + ret = division(dividend, divisor, "ient, &remainder); + if (ret) + return 0xffffffff; - return quotient; + return quotient; } static uint32_t mod(uint32_t dividend, uint32_t divisor) { - uint32_t quotient = 0; - uint32_t remainder = 0; - int ret; + uint32_t quotient = 0; + uint32_t remainder = 0; + int ret; - ret = division(dividend, divisor, "ient, &remainder); - if (ret) - return 0xffffffff; + ret = division(dividend, divisor, "ient, &remainder); + if (ret) + return 0xffffffff; - return remainder; + return remainder; } /* RAM configuration: 2 x MT47H64M16 on SAMA5D3-Xplained * 8 Mwords x 8 Banks x 16 bits x 2, total 2 Gbit */ -static struct dram ddram ={ +static const struct dram ddram ={ .timing = { /* Hardcoded for MT47H64M16, */ .tras = 6, .trcd = 2, @@ -132,7 +132,7 @@ static struct dram ddram ={ void master_clock_set(uint32_t prescaler) { - uint32_t mck = PMC_MCKR & (PMC_MDIV_MASK | PMC_CSS_MASK); + uint32_t mck = PMC_MCKR & (PMC_MDIV_MASK | PMC_CSS_MASK); uint32_t diff = mck ^ prescaler; if (diff & PMC_ALTPRES_MASK) { @@ -262,7 +262,6 @@ static void ddr_init(void) cal &= ~(MPDDRC_IOCALIBR_RDIV_MASK); cal |= MPDDRC_IOCALIBR_RDIV_DDR2_RZQ_50; /* 50 ohm */ cal &= ~(MPDDRC_IOCALIBR_TZQIO_MASK); - //cal |= (80 << MPDDRC_IOCALIBR_TZQIO_SHIFT); /* 100 cycles at 133MHz is 0.75 us, 100 cycles at 166MHz is 0.6 us */ 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; @@ -608,7 +607,7 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len) sz = remaining; do { - ret = nand_check_bad_block(block); + ret = nand_check_bad_block(block); if (ret < 0) { /* Block is bad, skip it */ block++; @@ -661,35 +660,39 @@ void pit_init(void) 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) - */ + 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); + 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; } @@ -704,22 +707,12 @@ void ext_flash_lock(void) void* hal_get_dts_address(void) { - return (void*)&dts_addr; + return (void*)&dts_addr; } void* hal_get_dts_update_address(void) { - return NULL; /* Not yet supported */ -} - -/* QSPI functions */ -void qspi_init(uint32_t cpu_clock, uint32_t flash_freq) -{ -} - - -void zynq_init(uint32_t cpu_clock) -{ + return NULL; /* Not yet supported */ } @@ -740,6 +733,9 @@ 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; } @@ -754,6 +750,8 @@ void RAMFUNCTION hal_flash_lock(void) int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { + (void)address; + (void)len; return 0; } diff --git a/hal/sama5d3.h b/hal/sama5d3.h index 15748adb5..40b99ab25 100644 --- a/hal/sama5d3.h +++ b/hal/sama5d3.h @@ -1,3 +1,25 @@ +/* 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 @@ -5,9 +27,9 @@ #include /* CPU/Board clock settings */ -#define CPU_FREQ 264000000 -#define MASTER_FREQ 132000000 -#define CRYSTAL_FREQ 12000000 +#define CPU_FREQ 264000000UL +#define MASTER_FREQ 132000000UL +#define CRYSTAL_FREQ 12000000UL #define MULA 43 /* PLLA register @@ -309,11 +331,11 @@ extern void *kernel_addr, *update_addr, *dts_addr; #define NAND_FLASH_OOB_SIZE 0x40 /* 64B */ /* Address space mapping for atsama5d3 */ -#define DRAM_BASE 0x20000000 -#define CS1_BASE 0x40000000 -#define CS2_BASE 0x50000000 -#define CS3_BASE 0x60000000 -#define NFC_CMD_BASE 0x70000000 +#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 @@ -405,4 +427,22 @@ extern void *kernel_addr, *update_addr, *dts_addr; #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 diff --git a/test-app/app_sama5d3.c b/test-app/app_sama5d3.c index 2016a7dd6..45de4d452 100644 --- a/test-app/app_sama5d3.c +++ b/test-app/app_sama5d3.c @@ -2,7 +2,7 @@ * * Test bare-metal boot application * - * Copyright (C) 2021 wolfSSL Inc. + * Copyright (C) 2024 wolfSSL Inc. * * This file is part of wolfBoot. * @@ -24,29 +24,13 @@ #include #include #include +#include #include "wolfboot/wolfboot.h" #ifdef TARGET_sama5d3 /* Blue LED is PE23, Red LED is PE24 */ -#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) - #define BLUE_LED_PIN 23 #define RED_LED_PIN 24