-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replacing iap_function with C RAM functions
- It's not possible to write true RAM functions in rust (yet) where everything inside the function must not touch flash (needed for flash controller operations) - Port ASF versions of efc_perform_fcr and efc_perform_read_sequence * Made a bit more generic so no compiler defines so the included static libraries should work for any atsam4 chip that uses EEFC/EFC - Added some examples on how to access the unique id and user signature - Was having a lot of issues trying to run functions from ROM so this code has been removed (efc_perform_fcr is the equivalent RAM function that ASF uses)
- Loading branch information
1 parent
2847826
commit d3a8697
Showing
10 changed files
with
584 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
name: C | ||
|
||
on: [push, pull_request] | ||
|
||
jobs: | ||
c: | ||
name: C Extension Build Check | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v1 | ||
- name: Install dependencies | ||
run: | | ||
sudo apt-get update | ||
sudo apt-get install -y gcc-arm-none-eabi | ||
- name: Build | ||
run: | | ||
c/build.bash |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
use std::env; | ||
use std::fs; | ||
use std::path::PathBuf; | ||
|
||
fn main() { | ||
let target = env::var("TARGET").unwrap(); | ||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); | ||
|
||
if target.starts_with("thumbv") { | ||
// Static library used for efc C functions | ||
fs::copy(format!("bin/{}.a", target), out_dir.join("libatsam4-hal.a")).unwrap(); | ||
println!("cargo:rustc-link-lib=static=atsam4-hal"); | ||
} | ||
|
||
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
println!("cargo:rustc-link-search={}", out.display()); | ||
|
||
println!("cargo:rerun-if-changed=build.rs"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# C Extensions for atsam4-hal | ||
|
||
In some minimal cases, it's necessary to use C in order to do things that is not currently possible in Rust. | ||
`build.bash` will compile the C code into the necessary static libraries that can be used during the build process. | ||
The intent is that the static libraries are checked into git so that an embedded C compiler is not needed during a normal build. | ||
|
||
|
||
## Functions | ||
|
||
- efc_perform_read_sequence() | ||
* Must be run entirely from RAM as the flash controller cannot read processor instructions from flash while accessing special | ||
regions of EEFC (Enhanced Embedded Flash Controller). | ||
The chip will crash immediately if you attempt to read instructions from flash during this mode. | ||
- efc_perform_fcr() | ||
* Alternate to the IAP function that runs in RAM instead of ROM | ||
|
||
|
||
## Re-Building | ||
|
||
**Dependencies** | ||
- arm-none-eabi-gcc (Arch Linux: arm-none-eabi-gcc) | ||
- arm-none-eabi-ar (Arch Linux: arm-none-eabi-binutils) | ||
|
||
```bash | ||
./build.bash | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -euxo pipefail | ||
|
||
# Get directory script is in | ||
SOURCE="${BASH_SOURCE[0]}" | ||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink | ||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" | ||
SOURCE="$(readlink "$SOURCE")" | ||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located | ||
done | ||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" | ||
TOP=$(realpath "${DIR}/..") | ||
BIN=${TOP}/bin | ||
|
||
# Remove existing blobs because otherwise this will append object files to the old blobs | ||
rm -f "${BIN}"/*.a | ||
|
||
arm-none-eabi-gcc -c -march=armv7e-m "${DIR}/efc.c" -o "${BIN}/efc.o" | ||
arm-none-eabi-ar crs "${BIN}/thumbv7em-none-eabi.a" "${BIN}/efc.o" | ||
|
||
arm-none-eabi-gcc -c -march=armv7e-m "${DIR}/efc.c" -DHAS_FPU -o "${BIN}/efc.o" | ||
arm-none-eabi-ar crs "${BIN}/thumbv7em-none-eabihf.a" "${BIN}/efc.o" | ||
|
||
# Cleanup object files | ||
rm -f "${BIN}"/*.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/** | ||
* \file | ||
* | ||
* Copyright (c) 2012-2018 Microchip Technology Inc. and its subsidiaries. | ||
* | ||
* \asf_license_start | ||
* | ||
* \page License | ||
* | ||
* Subject to your compliance with these terms, you may use Microchip | ||
* software and any derivatives exclusively with Microchip products. | ||
* It is your responsibility to comply with third party license terms applicable | ||
* to your use of third party software (including open source software) that | ||
* may accompany Microchip software. | ||
* | ||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, | ||
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, | ||
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, | ||
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE | ||
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL | ||
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE | ||
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE | ||
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT | ||
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY | ||
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, | ||
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. | ||
* | ||
* \asf_license_stop | ||
* | ||
*/ | ||
/* | ||
* Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a> | ||
*/ | ||
|
||
#ifndef _SAM4S_EFC_COMPONENT_ | ||
#define _SAM4S_EFC_COMPONENT_ | ||
|
||
/* IO definitions (access restrictions to peripheral registers) */ | ||
/** | ||
\defgroup CMSIS_glob_defs CMSIS Global Defines | ||
<strong>IO Type Qualifiers</strong> are used | ||
\li to specify the access to peripheral variables. | ||
\li for automatic generation of peripheral register debug information. | ||
*/ | ||
#ifdef __cplusplus | ||
#define __I volatile /*!< Defines 'read only' permissions */ | ||
#else | ||
#define __I volatile const /*!< Defines 'read only' permissions */ | ||
#endif | ||
#define __O volatile /*!< Defines 'write only' permissions */ | ||
#define __IO volatile /*!< Defines 'read / write' permissions */ | ||
|
||
/* ============================================================================= */ | ||
/** SOFTWARE API DEFINITION FOR Embedded Flash Controller */ | ||
/* ============================================================================= */ | ||
/** \addtogroup SAM4S_EFC Embedded Flash Controller */ | ||
/*@{*/ | ||
|
||
#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) | ||
/** \brief Efc hardware registers */ | ||
typedef struct { | ||
__IO uint32_t EEFC_FMR; /**< \brief (Efc Offset: 0x00) EEFC Flash Mode Register */ | ||
__O uint32_t EEFC_FCR; /**< \brief (Efc Offset: 0x04) EEFC Flash Command Register */ | ||
__I uint32_t EEFC_FSR; /**< \brief (Efc Offset: 0x08) EEFC Flash Status Register */ | ||
__I uint32_t EEFC_FRR; /**< \brief (Efc Offset: 0x0C) EEFC Flash Result Register */ | ||
} Efc; | ||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */ | ||
/* -------- EEFC_FMR : (EFC Offset: 0x00) EEFC Flash Mode Register -------- */ | ||
#define EEFC_FMR_FRDY (0x1u << 0) /**< \brief (EEFC_FMR) Ready Interrupt Enable */ | ||
#define EEFC_FMR_FWS_Pos 8 | ||
#define EEFC_FMR_FWS_Msk (0xfu << EEFC_FMR_FWS_Pos) /**< \brief (EEFC_FMR) Flash Wait State */ | ||
#define EEFC_FMR_FWS(value) ((EEFC_FMR_FWS_Msk & ((value) << EEFC_FMR_FWS_Pos))) | ||
#define EEFC_FMR_SCOD (0x1u << 16) /**< \brief (EEFC_FMR) Sequential Code Optimization Disable */ | ||
#define EEFC_FMR_FAM (0x1u << 24) /**< \brief (EEFC_FMR) Flash Access Mode */ | ||
#define EEFC_FMR_CLOE (0x1u << 26) /**< \brief (EEFC_FMR) Code Loop Optimization Enable */ | ||
/* -------- EEFC_FCR : (EFC Offset: 0x04) EEFC Flash Command Register -------- */ | ||
#define EEFC_FCR_FCMD_Pos 0 | ||
#define EEFC_FCR_FCMD_Msk (0xffu << EEFC_FCR_FCMD_Pos) /**< \brief (EEFC_FCR) Flash Command */ | ||
#define EEFC_FCR_FCMD_GETD (0x0u << 0) /**< \brief (EEFC_FCR) Get Flash descriptor */ | ||
#define EEFC_FCR_FCMD_WP (0x1u << 0) /**< \brief (EEFC_FCR) Write page */ | ||
#define EEFC_FCR_FCMD_WPL (0x2u << 0) /**< \brief (EEFC_FCR) Write page and lock */ | ||
#define EEFC_FCR_FCMD_EWP (0x3u << 0) /**< \brief (EEFC_FCR) Erase page and write page */ | ||
#define EEFC_FCR_FCMD_EWPL (0x4u << 0) /**< \brief (EEFC_FCR) Erase page and write page then lock */ | ||
#define EEFC_FCR_FCMD_EA (0x5u << 0) /**< \brief (EEFC_FCR) Erase all */ | ||
#define EEFC_FCR_FCMD_EPA (0x7u << 0) /**< \brief (EEFC_FCR) Erase pages */ | ||
#define EEFC_FCR_FCMD_SLB (0x8u << 0) /**< \brief (EEFC_FCR) Set lock bit */ | ||
#define EEFC_FCR_FCMD_CLB (0x9u << 0) /**< \brief (EEFC_FCR) Clear lock bit */ | ||
#define EEFC_FCR_FCMD_GLB (0xAu << 0) /**< \brief (EEFC_FCR) Get lock bit */ | ||
#define EEFC_FCR_FCMD_SGPB (0xBu << 0) /**< \brief (EEFC_FCR) Set GPNVM bit */ | ||
#define EEFC_FCR_FCMD_CGPB (0xCu << 0) /**< \brief (EEFC_FCR) Clear GPNVM bit */ | ||
#define EEFC_FCR_FCMD_GGPB (0xDu << 0) /**< \brief (EEFC_FCR) Get GPNVM bit */ | ||
#define EEFC_FCR_FCMD_STUI (0xEu << 0) /**< \brief (EEFC_FCR) Start read unique identifier */ | ||
#define EEFC_FCR_FCMD_SPUI (0xFu << 0) /**< \brief (EEFC_FCR) Stop read unique identifier */ | ||
#define EEFC_FCR_FCMD_GCALB (0x10u << 0) /**< \brief (EEFC_FCR) Get CALIB bit */ | ||
#define EEFC_FCR_FCMD_ES (0x11u << 0) /**< \brief (EEFC_FCR) Erase sector */ | ||
#define EEFC_FCR_FCMD_WUS (0x12u << 0) /**< \brief (EEFC_FCR) Write user signature */ | ||
#define EEFC_FCR_FCMD_EUS (0x13u << 0) /**< \brief (EEFC_FCR) Erase user signature */ | ||
#define EEFC_FCR_FCMD_STUS (0x14u << 0) /**< \brief (EEFC_FCR) Start read user signature */ | ||
#define EEFC_FCR_FCMD_SPUS (0x15u << 0) /**< \brief (EEFC_FCR) Stop read user signature */ | ||
#define EEFC_FCR_FARG_Pos 8 | ||
#define EEFC_FCR_FARG_Msk (0xffffu << EEFC_FCR_FARG_Pos) /**< \brief (EEFC_FCR) Flash Command Argument */ | ||
#define EEFC_FCR_FARG(value) ((EEFC_FCR_FARG_Msk & ((value) << EEFC_FCR_FARG_Pos))) | ||
#define EEFC_FCR_FKEY_Pos 24 | ||
#define EEFC_FCR_FKEY_Msk (0xffu << EEFC_FCR_FKEY_Pos) /**< \brief (EEFC_FCR) Flash Writing Protection Key */ | ||
#define EEFC_FCR_FKEY_PASSWD (0x5Au << 24) /**< \brief (EEFC_FCR) The 0x5A value enables the command defined by the bits of the register. If the field is written with a different value, the write is not performed and no action is started. */ | ||
/* -------- EEFC_FSR : (EFC Offset: 0x08) EEFC Flash Status Register -------- */ | ||
#define EEFC_FSR_FRDY (0x1u << 0) /**< \brief (EEFC_FSR) Flash Ready Status */ | ||
#define EEFC_FSR_FCMDE (0x1u << 1) /**< \brief (EEFC_FSR) Flash Command Error Status */ | ||
#define EEFC_FSR_FLOCKE (0x1u << 2) /**< \brief (EEFC_FSR) Flash Lock Error Status */ | ||
#define EEFC_FSR_FLERR (0x1u << 3) /**< \brief (EEFC_FSR) Flash Error Status */ | ||
/* -------- EEFC_FRR : (EFC Offset: 0x0C) EEFC Flash Result Register -------- */ | ||
#define EEFC_FRR_FVALUE_Pos 0 | ||
#define EEFC_FRR_FVALUE_Msk (0xffffffffu << EEFC_FRR_FVALUE_Pos) /**< \brief (EEFC_FRR) Flash Result Value */ | ||
|
||
/*@}*/ | ||
|
||
|
||
#endif /* _SAM4S_EFC_COMPONENT_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/** | ||
* \file | ||
* | ||
* \brief Enhanced Embedded Flash Controller (EEFC) driver for SAM. | ||
* | ||
* Copyright (c) 2011-2018 Microchip Technology Inc. and its subsidiaries. | ||
* | ||
* \asf_license_start | ||
* | ||
* \page License | ||
* | ||
* Subject to your compliance with these terms, you may use Microchip | ||
* software and any derivatives exclusively with Microchip products. | ||
* It is your responsibility to comply with third party license terms applicable | ||
* to your use of third party software (including open source software) that | ||
* may accompany Microchip software. | ||
* | ||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, | ||
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, | ||
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, | ||
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE | ||
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL | ||
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE | ||
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE | ||
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT | ||
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY | ||
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, | ||
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. | ||
* | ||
* \asf_license_stop | ||
* | ||
*/ | ||
/* | ||
* Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a> | ||
*/ | ||
|
||
#include "efc.h" | ||
|
||
/** | ||
* RAM Functions provided by ASF | ||
* These functions are difficult/impossible to replicate in pure rust as you cannot have any flash accesses | ||
* during these functions. | ||
* | ||
* These functions have been adapted to use a very small subset of ASF headers and be portable across | ||
* atsam4 chips. | ||
*/ | ||
|
||
/* Flash Writing Protection Key */ | ||
#define FWP_KEY 0x5Au | ||
|
||
#define EEFC_FCR_FCMD(value) \ | ||
((EEFC_FCR_FCMD_Msk & ((value) << EEFC_FCR_FCMD_Pos))) | ||
#define EEFC_ERROR_FLAGS (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR) | ||
|
||
|
||
/** | ||
* \brief Perform read sequence. Supported sequences are read Unique ID and | ||
* read User Signature | ||
* | ||
* \param p_efc Pointer to an EFC instance. | ||
* \param ul_cmd_st Start command to perform. | ||
* \param ul_cmd_sp Stop command to perform. | ||
* \param p_ul_buf Pointer to an data buffer. | ||
* \param ul_size Buffer size. | ||
* \param p_ul_data Address of flash region being used. | ||
* Usually 0x00400000u (IFLASH0_ADDR or READ_BUFF_ADDR0) | ||
* | ||
* \return 0 if successful, otherwise returns an error code. | ||
*/ | ||
__attribute__ ((__noinline__)) | ||
__attribute__ ((section(".data"))) | ||
uint32_t efc_perform_read_sequence(Efc *p_efc, | ||
uint32_t ul_cmd_st, uint32_t ul_cmd_sp, | ||
uint32_t *p_ul_buf, uint32_t ul_size, uint32_t *p_ul_data) | ||
{ | ||
volatile uint32_t ul_status; | ||
uint32_t ul_cnt; | ||
|
||
if (p_ul_buf == NULL) { | ||
return EFC_RC_INVALID; | ||
} | ||
|
||
p_efc->EEFC_FMR |= (0x1u << 16); | ||
|
||
/* Send the Start Read command */ | ||
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(0) | ||
| EEFC_FCR_FCMD(ul_cmd_st); | ||
|
||
/* Wait for the FRDY bit in the Flash Programming Status Register | ||
* (EEFC_FSR) falls. | ||
*/ | ||
do { | ||
ul_status = p_efc->EEFC_FSR; | ||
} while ((ul_status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY); | ||
|
||
/* The data is located in the first address of the Flash | ||
* memory mapping. | ||
*/ | ||
for (ul_cnt = 0; ul_cnt < ul_size; ul_cnt++) { | ||
p_ul_buf[ul_cnt] = p_ul_data[ul_cnt]; | ||
} | ||
|
||
/* To stop the read mode */ | ||
p_efc->EEFC_FCR = | ||
EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(0) | | ||
EEFC_FCR_FCMD(ul_cmd_sp); | ||
|
||
/* Wait for the FRDY bit in the Flash Programming Status Register (EEFC_FSR) | ||
* rises. | ||
*/ | ||
do { | ||
ul_status = p_efc->EEFC_FSR; | ||
} while ((ul_status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY); | ||
|
||
p_efc->EEFC_FMR &= ~(0x1u << 16); | ||
|
||
return EFC_RC_OK; | ||
} | ||
|
||
/** | ||
* \brief Perform command. | ||
* | ||
* \param p_efc Pointer to an EFC instance. | ||
* \param ul_fcr Flash command. | ||
* | ||
* \return The current status. | ||
*/ | ||
__attribute__ ((__noinline__)) | ||
__attribute__ ((section(".data"))) | ||
uint32_t efc_perform_fcr(Efc *p_efc, uint32_t ul_fcr) | ||
{ | ||
volatile uint32_t ul_status; | ||
|
||
p_efc->EEFC_FCR = ul_fcr; | ||
do { | ||
ul_status = p_efc->EEFC_FSR; | ||
} while ((ul_status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY); | ||
|
||
return (ul_status & EEFC_ERROR_FLAGS); | ||
} |
Oops, something went wrong.