From 76920599b3c260eb9a7e5429ab1457df3bea2b7f Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Mon, 16 Sep 2024 20:10:46 +0200 Subject: [PATCH] [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 e44405c5..0bc648df 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 7fac7bbe..4e062f37 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 3afecac8..203087c0 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 3789340d..c446f168 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 b0f537fd..8f887fe2 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 04886efd..47b8acae 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 e518b2af..2016a7dd 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 00000000..55a26462 --- /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 +