diff --git a/cores/arduino/Cache.cpp b/cores/arduino/Cache.cpp index 31f3c25..38ab726 100644 --- a/cores/arduino/Cache.cpp +++ b/cores/arduino/Cache.cpp @@ -242,15 +242,16 @@ bool Cache::Disable() noexcept #if SAME70 +extern "C" [[noreturn]] void vAssertCalled(uint32_t line, const char *file) noexcept; + void Cache::Flush(const volatile void *start, size_t length) noexcept { if ((SCB->CCR & SCB_CCR_DC_Msk) != 0) // if data cache is enabled { - // We assume that the DMA buffer is entirely inside or entirely outside the non-cached RAM area - if (start < (void*)&_nocache_ram_start || start >= (void*)&_nocache_ram_end) + // The DMA buffer should be entirely inside the non-cached RAM area + if ((const char *)start < (const char *)&_nocache_ram_start || (const char *)start + length >= (const char *)&_nocache_ram_end) { - const uint32_t startAddr = reinterpret_cast(start); - SCB_CleanDCache_by_Addr(reinterpret_cast(startAddr & ~3), length + (startAddr & 3)); + vAssertCalled(__LINE__, __FILE__); } } } @@ -262,13 +263,10 @@ void Cache::Invalidate(const volatile void *start, size_t length) noexcept #if SAME70 if ((SCB->CCR & SCB_CCR_DC_Msk) != 0) // if data cache is enabled { - // We assume that the DMA buffer is entirely inside or entirely outside the non-cached RAM area - if (start < (void*)&_nocache_ram_start || start >= (void*)&_nocache_ram_end) + // The DMA buffer should be entirely inside the non-cached RAM area + if ((const char *)start < (const char *)&_nocache_ram_start || (const char *)start + length >= (const char *)&_nocache_ram_end) { - // Caution! if any part of the cache line is dirty, the written data will be lost! - //TODO make this an abort instead of trying to invalidate the cache - const uint32_t startAddr = reinterpret_cast(start); - SCB_InvalidateDCache_by_Addr(reinterpret_cast(startAddr & ~3), length + (startAddr & 3)); + vAssertCalled(__LINE__, __FILE__); } } #else diff --git a/cores/arduino/Flash.cpp b/cores/arduino/Flash.cpp index aa95a00..4b57445 100644 --- a/cores/arduino/Flash.cpp +++ b/cores/arduino/Flash.cpp @@ -156,8 +156,7 @@ extern "C" { * \param pus_page The first page accessed. * \param pus_offset Byte offset in the first page. */ -static void translate_address(Efc **pp_efc, uint32_t ul_addr, - uint16_t *pus_page, uint16_t *pus_offset) +static void translate_address(Efc **pp_efc, uint32_t ul_addr, uint16_t *pus_page, uint16_t *pus_offset) noexcept { Efc *p_efc; uint16_t us_page; @@ -228,7 +227,7 @@ static void translate_address(Efc **pp_efc, uint32_t ul_addr, * \param us_offset Byte offset inside page. * \param pul_addr Computed address (optional). */ -static void compute_address(Efc *p_efc, uint16_t us_page, uint16_t us_offset, uint32_t *pul_addr) +static void compute_address(Efc *p_efc, uint16_t us_page, uint16_t us_offset, uint32_t *pul_addr) noexcept { uint32_t ul_addr; @@ -278,7 +277,7 @@ static void compute_address(Efc *p_efc, uint16_t us_page, uint16_t us_offset, ui * \param pul_actual_start Actual start address of lock range. * \param pul_actual_end Actual end address of lock range. */ -static void compute_lock_range(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) +static void compute_lock_range(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) noexcept { uint32_t ul_actual_start, ul_actual_end; @@ -303,7 +302,7 @@ static void compute_lock_range(uint32_t ul_start, uint32_t ul_end, uint32_t *pul * * \return 0 if successful; otherwise returns an error code. */ -uint32_t flash_init(uint32_t ul_mode, uint32_t ul_fws) +uint32_t flash_init(uint32_t ul_mode, uint32_t ul_fws) noexcept { efc_init(EFC, ul_mode, ul_fws); @@ -322,7 +321,7 @@ uint32_t flash_init(uint32_t ul_mode, uint32_t ul_fws) * * \return 0 if successful; otherwise returns an error code. */ -uint32_t flash_set_wait_state(uint32_t ul_address, uint32_t ul_fws) +uint32_t flash_set_wait_state(uint32_t ul_address, uint32_t ul_fws) noexcept { Efc *p_efc; @@ -341,7 +340,7 @@ uint32_t flash_set_wait_state(uint32_t ul_address, uint32_t ul_fws) * * \return The actual descriptor length. */ -uint32_t flash_get_descriptor(uint32_t ul_address, uint32_t *pul_flash_descriptor, uint32_t ul_size) +uint32_t flash_get_descriptor(uint32_t ul_address, uint32_t *pul_flash_descriptor, uint32_t ul_size) noexcept { Efc *p_efc; uint32_t ul_tmp; @@ -377,7 +376,7 @@ uint32_t flash_get_descriptor(uint32_t ul_address, uint32_t *pul_flash_descripto * * \return The flash total page count. */ -uint32_t flash_get_page_count(const uint32_t *pul_flash_descriptor) +uint32_t flash_get_page_count(const uint32_t *pul_flash_descriptor) noexcept { return (pul_flash_descriptor[1] / pul_flash_descriptor[2]); } @@ -392,7 +391,7 @@ uint32_t flash_get_page_count(const uint32_t *pul_flash_descriptor) * * \return The flash page count per region (plane). */ -uint32_t flash_get_page_count_per_region(const uint32_t *pul_flash_descriptor) +uint32_t flash_get_page_count_per_region(const uint32_t *pul_flash_descriptor) noexcept { return (pul_flash_descriptor[4] / pul_flash_descriptor[2]); } @@ -407,7 +406,7 @@ uint32_t flash_get_page_count_per_region(const uint32_t *pul_flash_descriptor) * * \return The flash region (plane) count. */ -uint32_t flash_get_region_count(const uint32_t *pul_flash_descriptor) +uint32_t flash_get_region_count(const uint32_t *pul_flash_descriptor) noexcept { return (pul_flash_descriptor[3]); } @@ -423,7 +422,7 @@ uint32_t flash_get_region_count(const uint32_t *pul_flash_descriptor) * * \return 0 if successful; otherwise returns an error code. */ -uint32_t flash_erase_all(uint32_t ul_address) +uint32_t flash_erase_all(uint32_t ul_address) noexcept { Efc *p_efc; @@ -444,7 +443,7 @@ uint32_t flash_erase_all(uint32_t ul_address) * * \return 0 if successful; otherwise returns an error code. */ -uint32_t flash_erase_page(uint32_t ul_address, uint8_t uc_page_num) +uint32_t flash_erase_page(uint32_t ul_address, uint8_t uc_page_num) noexcept { Efc *p_efc; uint16_t us_page; @@ -477,7 +476,7 @@ uint32_t flash_erase_page(uint32_t ul_address, uint8_t uc_page_num) * * \return 0 if successful; otherwise returns an error code. */ -uint32_t flash_erase_sector(uint32_t ul_address) +uint32_t flash_erase_sector(uint32_t ul_address) noexcept { Efc *p_efc; uint16_t us_page; @@ -508,7 +507,7 @@ uint32_t flash_erase_sector(uint32_t ul_address) * * \return 0 if successful, otherwise returns an error code. */ -uint32_t flash_write(uint32_t ul_address, const void *p_buffer, uint32_t ul_size, uint32_t ul_erase_flag) +uint32_t flash_write(uint32_t ul_address, const void *p_buffer, uint32_t ul_size, uint32_t ul_erase_flag) noexcept { Efc *p_efc; uint32_t ul_fws_temp; @@ -603,7 +602,7 @@ uint32_t flash_write(uint32_t ul_address, const void *p_buffer, uint32_t ul_size * * \return 0 if successful, otherwise returns an error code. */ -uint32_t flash_lock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) +uint32_t flash_lock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) noexcept { Efc *p_efc; uint32_t ul_actual_start, ul_actual_end; @@ -651,7 +650,7 @@ uint32_t flash_lock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_sta * * \return 0 if successful, otherwise returns an error code. */ -uint32_t flash_unlock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) +uint32_t flash_unlock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) noexcept { Efc *p_efc; uint32_t ul_actual_start, ul_actual_end; @@ -694,7 +693,7 @@ uint32_t flash_unlock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_s * * \return The number of locked regions inside the given address range. */ -uint32_t flash_is_locked(uint32_t ul_start, uint32_t ul_end) +uint32_t flash_is_locked(uint32_t ul_start, uint32_t ul_end) noexcept { Efc *p_efc; uint16_t us_start_page, us_end_page; @@ -771,7 +770,7 @@ uint32_t flash_is_locked(uint32_t ul_start, uint32_t ul_end) * * \return 0 if successful; otherwise returns an error code. */ -uint32_t flash_set_gpnvm(uint32_t ul_gpnvm) +uint32_t flash_set_gpnvm(uint32_t ul_gpnvm) noexcept { if (ul_gpnvm >= GPNVM_NUM_MAX) { return FLASH_RC_INVALID; @@ -795,7 +794,7 @@ uint32_t flash_set_gpnvm(uint32_t ul_gpnvm) * * \return 0 if successful; otherwise returns an error code. */ -uint32_t flash_clear_gpnvm(uint32_t ul_gpnvm) +uint32_t flash_clear_gpnvm(uint32_t ul_gpnvm) noexcept { if (ul_gpnvm >= GPNVM_NUM_MAX) { return FLASH_RC_INVALID; @@ -832,7 +831,7 @@ uint32_t flash_read_gpnvm_bits() noexcept * \retval 0 If the given GPNVM bit is currently cleared. * otherwise returns an error code. */ -uint32_t flash_is_gpnvm_set(uint32_t ul_gpnvm) +uint32_t flash_is_gpnvm_set(uint32_t ul_gpnvm) noexcept { uint32_t ul_gpnvm_bits; diff --git a/cores/arduino/Flash.h b/cores/arduino/Flash.h index 3e221cf..c7d1d66 100644 --- a/cores/arduino/Flash.h +++ b/cores/arduino/Flash.h @@ -94,26 +94,26 @@ typedef enum flash_farg_page_num { #define FLASH_ACCESS_MODE_64 EFC_ACCESS_MODE_64 //! @} -uint32_t flash_init(uint32_t ul_mode, uint32_t ul_fws); -uint32_t flash_set_wait_state(uint32_t ul_address, uint32_t ul_fws); -uint32_t flash_get_descriptor(uint32_t ul_address, uint32_t *pul_flash_descriptor, uint32_t ul_size); -uint32_t flash_get_page_count(const uint32_t *pul_flash_descriptor); -uint32_t flash_get_page_count_per_region(const uint32_t *pul_flash_descriptor); -uint32_t flash_get_region_count(const uint32_t *pul_flash_descriptor); -uint32_t flash_erase_all(uint32_t ul_address); +uint32_t flash_init(uint32_t ul_mode, uint32_t ul_fws) noexcept; +uint32_t flash_set_wait_state(uint32_t ul_address, uint32_t ul_fws) noexcept; +uint32_t flash_get_descriptor(uint32_t ul_address, uint32_t *pul_flash_descriptor, uint32_t ul_size) noexcept; +uint32_t flash_get_page_count(const uint32_t *pul_flash_descriptor) noexcept; +uint32_t flash_get_page_count_per_region(const uint32_t *pul_flash_descriptor) noexcept; +uint32_t flash_get_region_count(const uint32_t *pul_flash_descriptor) noexcept; +uint32_t flash_erase_all(uint32_t ul_address) noexcept; #if (SAM4S || SAM4E || SAM4N || SAM4C || SAMG || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAMS70 || SAME70) -uint32_t flash_erase_page(uint32_t ul_address, uint8_t uc_page_num); -uint32_t flash_erase_sector(uint32_t ul_address); +uint32_t flash_erase_page(uint32_t ul_address, uint8_t uc_page_num) noexcept; +uint32_t flash_erase_sector(uint32_t ul_address) noexcept; #endif -uint32_t flash_write(uint32_t ul_address, const void *p_buffer, uint32_t ul_size, uint32_t ul_erase_flag); -uint32_t flash_lock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end); -uint32_t flash_unlock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end); -uint32_t flash_is_locked(uint32_t ul_start, uint32_t ul_end); -uint32_t flash_set_gpnvm(uint32_t ul_gpnvm); -uint32_t flash_clear_gpnvm(uint32_t ul_gpnvm); -uint32_t flash_is_gpnvm_set(uint32_t ul_gpnvm); +uint32_t flash_write(uint32_t ul_address, const void *p_buffer, uint32_t ul_size, uint32_t ul_erase_flag) noexcept; +uint32_t flash_lock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) noexcept; +uint32_t flash_unlock(uint32_t ul_start, uint32_t ul_end, uint32_t *pul_actual_start, uint32_t *pul_actual_end) noexcept; +uint32_t flash_is_locked(uint32_t ul_start, uint32_t ul_end) noexcept; +uint32_t flash_set_gpnvm(uint32_t ul_gpnvm) noexcept; +uint32_t flash_clear_gpnvm(uint32_t ul_gpnvm) noexcept; +uint32_t flash_is_gpnvm_set(uint32_t ul_gpnvm) noexcept; uint32_t flash_read_gpnvm_bits() noexcept; uint32_t flash_read_unique_id(uint32_t *pul_data) noexcept; // read 4 dwords of unique ID diff --git a/variants/same70/startup_same70.c b/variants/same70/startup_same70.c index 149ae03..21399d3 100644 --- a/variants/same70/startup_same70.c +++ b/variants/same70/startup_same70.c @@ -319,7 +319,7 @@ const DeviceVectors exception_table = { .pfnRSWDT_Handler = (void*) RSWDT_Handler /* 63 Reinforced Secure Watchdog Timer */ }; -// This must be marked noinline so that R0 is loaded with the required value for SP +// This must be marked noinline so that R0 is loaded with the required value for SP. Return is via LR so it's OK to return with a different SP. __attribute((noinline)) void SetStackPointer(uint32_t *topOfStack) { __asm volatile("msr msp, r0"); @@ -329,7 +329,7 @@ __attribute((noinline)) void SetStackPointer(uint32_t *topOfStack) * \brief This is the code that gets called on processor reset. * To initialize the device, and call the main() routine. */ -__attribute__((noreturn)) void Reset_Handler(void) +__attribute__((noreturn, naked)) void Reset_Handler(void) { // If TCM is allocated then SP may point beyond the end of RAM, so move it SetStackPointer(&_ezero_nocache); @@ -348,6 +348,12 @@ __attribute__((noreturn)) void Reset_Handler(void) } } + /* Clear the zero segment */ + for (uint32_t *pDest = &_szero; pDest < &_ezero;) + { + *pDest++ = 0; + } + // Check that no TCM is allocated before we relocate the stack to the top of memory. This uses a RAMFUNC, so we must initialise the relocate segment before here. // The temporary stack we are on is in the non-cached memory segment, so don't clear that segment until after we have relocated the stack. if (flash_read_gpnvm_bits() & ((1ul << 7) | (1ul << 8))) @@ -372,13 +378,7 @@ __attribute__((noreturn)) void Reset_Handler(void) *pDest++ = 0; } - /* Clear the zero segment */ - for (uint32_t *pDest = &_szero; pDest < &_ezero;) - { - *pDest++ = 0; - } - - /* Set the vector table base address */ + // Set the vector table base address const uint32_t * const pSrc = (uint32_t *) & _sfixed; SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk); @@ -401,6 +401,7 @@ __attribute__((noreturn)) void Reset_Handler(void) */ void Dummy_Handler(void) { - while (1) { - } + while (1) { } } + +// End