diff --git a/.github/workflows/tockbot-nightly.yml b/.github/workflows/tockbot-nightly.yml new file mode 100644 index 0000000000..158373505d --- /dev/null +++ b/.github/workflows/tockbot-nightly.yml @@ -0,0 +1,134 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2024. + +name: "Tockbot" + +on: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + inputs: + dispatch-job: + description: 'Which job to execute (choose between "all", "maint-nightly")' + required: true + default: 'all' + dry-run: + description: 'Whether to execute the jobs as dry-run' + required: true + default: true + +jobs: + dispatcher: + runs-on: ubuntu-latest + + # This job determines which other jobs should be run: + outputs: + run-maint-nightly: ${{ steps.dispatch-logic.outputs.run-maint-nightly }} + dry-run: ${{ steps.dispatch-logic.outputs.dry-run }} + + steps: + # On pushes we want to check whether any changes have been made + # to the Tockbot code base. Disabled for now: + - uses: actions/checkout@v4 + + # Dispatcher business logic: + - name: Dispatch Tockbot Jobs + id: dispatch-logic + env: + DISPATCH_JOB: ${{ github.event.inputs.dispatch-job }} + DISPATCH_DRY_RUN: ${{ github.event.inputs.dry-run }} + run: | + if [ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]; then + if [ "$DISPATCH_DRY_RUN" == "true" ]; then + echo "dry-run=true" >> $GITHUB_OUTPUT + elif [ "$DISPATCH_DRY_RUN" == "false" ]; then + echo "dry-run=false" >> $GITHUB_OUTPUT + else + echo "Error: dry-run not a boolean: \"$DISPATCH_DRY_RUN\"" >&2 + exit 1 + fi + + if [ "$DISPATCH_JOB" == "all" ]; then + echo "run-maint-nightly=true" >> $GITHUB_OUTPUT + elif [ "$DISPATCH_JOB" == "maint-nightly" ]; then + echo "run-maint-nightly=true" >> $GITHUB_OUTPUT + else + echo "Error: unknown job \"$DISPATCH_JOB\"" >&2 + exit 1 + fi + elif [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then + echo "dry-run=true" >> $GITHUB_OUTPUT + echo "run-maint-nightly=true" >> $GITHUB_OUTPUT + elif [ "$GITHUB_EVENT_NAME" == "schedule" ]; then + echo "dry-run=false" >> $GITHUB_OUTPUT + echo "run-maint-nightly=true" >> $GITHUB_OUTPUT + else + echo "Error: unknown event name \"$GITHUB_EVENT_NAME\"" >&2 + exit 1 + fi + + maint-nightly: + runs-on: ubuntu-latest + + # Only run this job if the dispatcher determined to schedule the + # "maint-nightly" or "dry-run" jobs: + needs: dispatcher + if: ${{ needs.dispatcher.outputs.run-maint-nightly == 'true' && needs.dispatcher.outputs.dry-run != 'true' }} + + permissions: + # Give GITHUB_TOKEN write permissions to modify PRs and issues: + pull-requests: write + issues: write + + steps: + # Requires a tock checkout to run from: + - uses: actions/checkout@v4 + + # Setup Python and install dependencies: + - uses: actions/setup-python@v5 + - name: Install Python Dependencies + run: pip install -r tools/tockbot/requirements.txt + + # Run nightly tockbot maintenance: + - name: Nightly Tockbot Maintenance + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DRY_RUN: ${{ needs.dispatcher.outputs.dry-run == 'true' && '-n' || '' }} + run: | + cd tools/tockbot/ + ./tockbot.py -v $DRY_RUN maint-nightly -c ./maint_nightly.yaml + + # We'd like to avoid duplicating this, either by using conditionals in the + # permissions key, or by using YAML anchors, neither of which are supported by + # GH Actions... + maint-nightly-dry-run: + runs-on: ubuntu-latest + + # Only run this job if the dispatcher determined to schedule the + # "maint-nightly" or "dry-run" jobs: + needs: dispatcher + if: ${{ needs.dispatcher.outputs.run-maint-nightly == 'true' && needs.dispatcher.outputs.dry-run == 'true' }} + + permissions: + # Dry-run, read-only access: + pull-requests: read + issues: read + + steps: + # Requires a tock checkout to run from: + - uses: actions/checkout@v4 + + # Setup Python and install dependencies: + - uses: actions/setup-python@v5 + - name: Install Python Dependencies + run: pip install -r tools/tockbot/requirements.txt + + # Run nightly tockbot maintenance: + - name: Nightly Tockbot Maintenance + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DRY_RUN: ${{ needs.dispatcher.outputs.dry-run == 'true' && '-n' || '' }} + run: | + cd tools/tockbot/ + ./tockbot.py -v $DRY_RUN maint-nightly -c ./maint_nightly.yaml diff --git a/Cargo.toml b/Cargo.toml index e4be134394..0f4ca54e85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ members = [ "boards/msp_exp432p401r", "boards/microbit_v2", "boards/wm1110dev", + "boards/makepython-nrf52840", "boards/nordic/nrf52840dk", "boards/nordic/nrf52840_dongle", "boards/nordic/nrf52dk", diff --git a/arch/cortex-m/src/lib.rs b/arch/cortex-m/src/lib.rs index 858523ed29..6fae6e533e 100644 --- a/arch/cortex-m/src/lib.rs +++ b/arch/cortex-m/src/lib.rs @@ -384,12 +384,12 @@ pub unsafe fn print_cortexm_state(writer: &mut dyn Write) { // ARM assembly since it will not compile. /////////////////////////////////////////////////////////////////// -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe extern "C" fn unhandled_interrupt() { unimplemented!() } -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe extern "C" fn initialize_ram_jump_to_main() { unimplemented!() } diff --git a/arch/cortex-m/src/mpu.rs b/arch/cortex-m/src/mpu.rs index 15b937851a..353947c185 100644 --- a/arch/cortex-m/src/mpu.rs +++ b/arch/cortex-m/src/mpu.rs @@ -10,7 +10,6 @@ use core::cmp; use core::fmt; use core::num::NonZeroUsize; -use kernel; use kernel::platform::mpu; use kernel::utilities::cells::OptionalCell; use kernel::utilities::math; diff --git a/arch/cortex-m/src/scb.rs b/arch/cortex-m/src/scb.rs index 2b254506f4..b5727ab123 100644 --- a/arch/cortex-m/src/scb.rs +++ b/arch/cortex-m/src/scb.rs @@ -316,7 +316,7 @@ pub unsafe fn disable_fpca() { } // Mock implementation for tests on Travis-CI. -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe fn disable_fpca() { // Dummy read register, to satisfy the `Readable` trait import on // non-ARM platforms. diff --git a/arch/cortex-m/src/support.rs b/arch/cortex-m/src/support.rs index fc69a1497a..7e748bde38 100644 --- a/arch/cortex-m/src/support.rs +++ b/arch/cortex-m/src/support.rs @@ -3,7 +3,6 @@ // Copyright Tock Contributors 2022. use crate::scb; -use core::ops::FnOnce; #[cfg(all(target_arch = "arm", target_os = "none"))] #[inline(always)] @@ -40,19 +39,19 @@ where } // Mock implementations for tests on Travis-CI. -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] /// NOP instruction (mock) pub fn nop() { unimplemented!() } -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] /// WFI instruction (mock) pub unsafe fn wfi() { unimplemented!() } -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe fn atomic(_f: F) -> R where F: FnOnce() -> R, diff --git a/arch/cortex-m0/src/lib.rs b/arch/cortex-m0/src/lib.rs index 3ea42e6852..9a9d6f1517 100644 --- a/arch/cortex-m0/src/lib.rs +++ b/arch/cortex-m0/src/lib.rs @@ -72,7 +72,7 @@ unsafe extern "C" fn hard_fault_handler_kernel(faulting_stack: *mut u32) -> ! { } // Mock implementation for tests on Travis-CI. -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] unsafe extern "C" fn generic_isr() { unimplemented!() } @@ -167,7 +167,7 @@ global_asm!( ); // Mock implementation for tests on Travis-CI. -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] unsafe extern "C" fn systick_handler_m0() { unimplemented!() } @@ -210,7 +210,7 @@ global_asm!( ); // Mock implementation for tests on Travis-CI. -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] unsafe extern "C" fn svc_handler() { unimplemented!() } @@ -249,7 +249,7 @@ svc_handler: ); // Mock implementation for tests on Travis-CI. -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] unsafe extern "C" fn hard_fault_handler() { unimplemented!() } @@ -365,7 +365,7 @@ impl cortexm::CortexMVariant for CortexM0 { const HARD_FAULT_HANDLER: unsafe extern "C" fn() = hard_fault_handler; // Mock implementation for tests on Travis-CI. - #[cfg(not(any(target_arch = "arm", target_os = "none")))] + #[cfg(not(all(target_arch = "arm", target_os = "none")))] unsafe fn switch_to_user( _user_stack: *const usize, _process_regs: &mut [usize; 8], diff --git a/arch/cortex-m0p/src/lib.rs b/arch/cortex-m0p/src/lib.rs index 65601f3450..30c9958860 100644 --- a/arch/cortex-m0p/src/lib.rs +++ b/arch/cortex-m0p/src/lib.rs @@ -31,7 +31,7 @@ pub use cortexm::CortexMVariant; use cortexm0::CortexM0; // Mock implementation for tests on Travis-CI. -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe extern "C" fn svc_handler_m0p() { unimplemented!() } @@ -96,7 +96,7 @@ impl cortexm::CortexMVariant for CortexM0P { CortexM0::switch_to_user(user_stack, process_regs) } - #[cfg(not(any(target_arch = "arm", target_os = "none")))] + #[cfg(not(all(target_arch = "arm", target_os = "none")))] unsafe fn switch_to_user( _user_stack: *const usize, _process_regs: &mut [usize; 8], diff --git a/arch/cortex-m3/src/lib.rs b/arch/cortex-m3/src/lib.rs index 33c481c679..360c326cb9 100644 --- a/arch/cortex-m3/src/lib.rs +++ b/arch/cortex-m3/src/lib.rs @@ -39,7 +39,7 @@ impl cortexm::CortexMVariant for CortexM3 { cortexv7m::switch_to_user_arm_v7m(user_stack, process_regs) } - #[cfg(not(any(target_arch = "arm", target_os = "none")))] + #[cfg(not(all(target_arch = "arm", target_os = "none")))] unsafe fn switch_to_user( _user_stack: *const usize, _process_regs: &mut [usize; 8], diff --git a/arch/cortex-m4/src/lib.rs b/arch/cortex-m4/src/lib.rs index 08fe9dcd86..45aabff6f4 100644 --- a/arch/cortex-m4/src/lib.rs +++ b/arch/cortex-m4/src/lib.rs @@ -41,7 +41,7 @@ impl cortexm::CortexMVariant for CortexM4 { cortexv7m::switch_to_user_arm_v7m(user_stack, process_regs) } - #[cfg(not(any(target_arch = "arm", target_os = "none")))] + #[cfg(not(all(target_arch = "arm", target_os = "none")))] unsafe fn switch_to_user( _user_stack: *const usize, _process_regs: &mut [usize; 8], diff --git a/arch/cortex-m7/src/lib.rs b/arch/cortex-m7/src/lib.rs index 2a58763b3d..2a9fcbb39f 100644 --- a/arch/cortex-m7/src/lib.rs +++ b/arch/cortex-m7/src/lib.rs @@ -41,7 +41,7 @@ impl cortexm::CortexMVariant for CortexM7 { cortexv7m::switch_to_user_arm_v7m(user_stack, process_regs) } - #[cfg(not(any(target_arch = "arm", target_os = "none")))] + #[cfg(not(all(target_arch = "arm", target_os = "none")))] unsafe fn switch_to_user( _user_stack: *const usize, _process_regs: &mut [usize; 8], diff --git a/arch/cortex-v7m/src/lib.rs b/arch/cortex-v7m/src/lib.rs index 5fdf094a72..31683a9cbe 100644 --- a/arch/cortex-v7m/src/lib.rs +++ b/arch/cortex-v7m/src/lib.rs @@ -561,22 +561,22 @@ pub fn ipsr_isr_number_to_str(isr_number: usize) -> &'static str { // ARM assembly since it will not compile. /////////////////////////////////////////////////////////////////// -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe extern "C" fn systick_handler_arm_v7m() { unimplemented!() } -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe extern "C" fn svc_handler_arm_v7m() { unimplemented!() } -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe extern "C" fn generic_isr_arm_v7m() { unimplemented!() } -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe extern "C" fn switch_to_user_arm_v7m( _user_stack: *const u8, _process_regs: &mut [usize; 8], @@ -584,7 +584,7 @@ pub unsafe extern "C" fn switch_to_user_arm_v7m( unimplemented!() } -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe extern "C" fn hard_fault_handler_arm_v7m() { unimplemented!() } diff --git a/arch/riscv/src/csr/mcycle.rs b/arch/riscv/src/csr/mcycle.rs index 3a2e6f99fd..7384bb33d7 100644 --- a/arch/riscv/src/csr/mcycle.rs +++ b/arch/riscv/src/csr/mcycle.rs @@ -13,7 +13,7 @@ register_bitfields![usize, // `mcycleh` is the higher XLEN bits of the number of elapsed cycles. // It does not exist on riscv64. -#[cfg(any(target_arch = "riscv32", not(target_os = "none")))] +#[cfg(not(target_arch = "riscv64"))] register_bitfields![usize, pub mcycleh [ mcycleh OFFSET(0) NUMBITS(crate::XLEN) [] diff --git a/arch/riscv/src/csr/minstret.rs b/arch/riscv/src/csr/minstret.rs index e94b034136..a930418998 100644 --- a/arch/riscv/src/csr/minstret.rs +++ b/arch/riscv/src/csr/minstret.rs @@ -13,7 +13,7 @@ register_bitfields![usize, // `minstreth` is the higher XLEN bits of the number of elapsed instructions. // It does not exist on riscv64. -#[cfg(any(target_arch = "riscv32", not(target_os = "none")))] +#[cfg(not(target_arch = "riscv64"))] register_bitfields![usize, pub minstreth [ minstreth OFFSET(0) NUMBITS(crate::XLEN) [] diff --git a/arch/riscv/src/csr/mod.rs b/arch/riscv/src/csr/mod.rs index 876b5708b0..ca8b3018f0 100644 --- a/arch/riscv/src/csr/mod.rs +++ b/arch/riscv/src/csr/mod.rs @@ -43,38 +43,38 @@ pub mod utvec; // something (as it would be if compiled for a host OS). pub struct CSR { - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub minstreth: ReadWriteRiscvCsr, pub minstret: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub mcycleh: ReadWriteRiscvCsr, pub mcycle: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub pmpcfg0: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub pmpcfg1: ReadWriteRiscvCsr, pub pmpcfg2: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub pmpcfg3: ReadWriteRiscvCsr, pub pmpcfg4: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub pmpcfg5: ReadWriteRiscvCsr, pub pmpcfg6: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub pmpcfg7: ReadWriteRiscvCsr, pub pmpcfg8: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub pmpcfg9: ReadWriteRiscvCsr, pub pmpcfg10: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub pmpcfg11: ReadWriteRiscvCsr, pub pmpcfg12: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub pmpcfg13: ReadWriteRiscvCsr, pub pmpcfg14: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub pmpcfg15: ReadWriteRiscvCsr, pub pmpaddr0: ReadWriteRiscvCsr, @@ -152,7 +152,7 @@ pub struct CSR { pub mstatus: ReadWriteRiscvCsr, pub mseccfg: ReadWriteRiscvCsr, - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub mseccfgh: ReadWriteRiscvCsr, pub utvec: ReadWriteRiscvCsr, @@ -161,37 +161,37 @@ pub struct CSR { // Define the "addresses" of each CSR register. pub const CSR: &CSR = &CSR { - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] minstreth: ReadWriteRiscvCsr::new(), minstret: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] mcycleh: ReadWriteRiscvCsr::new(), mcycle: ReadWriteRiscvCsr::new(), pmpcfg0: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pmpcfg1: ReadWriteRiscvCsr::new(), pmpcfg2: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pmpcfg3: ReadWriteRiscvCsr::new(), pmpcfg4: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pmpcfg5: ReadWriteRiscvCsr::new(), pmpcfg6: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pmpcfg7: ReadWriteRiscvCsr::new(), pmpcfg8: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pmpcfg9: ReadWriteRiscvCsr::new(), pmpcfg10: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pmpcfg11: ReadWriteRiscvCsr::new(), pmpcfg12: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pmpcfg13: ReadWriteRiscvCsr::new(), pmpcfg14: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pmpcfg15: ReadWriteRiscvCsr::new(), pmpaddr0: ReadWriteRiscvCsr::new(), @@ -269,7 +269,7 @@ pub const CSR: &CSR = &CSR { mstatus: ReadWriteRiscvCsr::new(), mseccfg: ReadWriteRiscvCsr::new(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] mseccfgh: ReadWriteRiscvCsr::new(), utvec: ReadWriteRiscvCsr::new(), @@ -278,7 +278,7 @@ pub const CSR: &CSR = &CSR { impl CSR { // resets the cycle counter to 0 - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub fn reset_cycle_counter(&self) { // Write lower first so that we don't overflow before writing the upper CSR.mcycle.write(mcycle::mcycle::mcycle.val(0)); @@ -292,7 +292,7 @@ impl CSR { } // reads the cycle counter - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] pub fn read_cycle_counter(&self) -> u64 { let (mut top, mut bot): (usize, usize); @@ -319,28 +319,28 @@ impl CSR { pub fn pmpconfig_get(&self, index: usize) -> usize { match index { 0 => self.pmpcfg0.get(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 1 => self.pmpcfg1.get(), 2 => self.pmpcfg2.get(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 3 => self.pmpcfg3.get(), 4 => self.pmpcfg4.get(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 5 => self.pmpcfg5.get(), 6 => self.pmpcfg6.get(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 7 => self.pmpcfg7.get(), 8 => self.pmpcfg8.get(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 9 => self.pmpcfg9.get(), 10 => self.pmpcfg10.get(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 11 => self.pmpcfg11.get(), 12 => self.pmpcfg12.get(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 13 => self.pmpcfg13.get(), 14 => self.pmpcfg14.get(), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 15 => self.pmpcfg15.get(), _ => unreachable!(), } @@ -349,28 +349,28 @@ impl CSR { pub fn pmpconfig_set(&self, index: usize, value: usize) { match index { 0 => self.pmpcfg0.set(value), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 1 => self.pmpcfg1.set(value), 2 => self.pmpcfg2.set(value), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 3 => self.pmpcfg3.set(value), 4 => self.pmpcfg4.set(value), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 5 => self.pmpcfg5.set(value), 6 => self.pmpcfg6.set(value), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 7 => self.pmpcfg7.set(value), 8 => self.pmpcfg8.set(value), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 9 => self.pmpcfg9.set(value), 10 => self.pmpcfg10.set(value), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 11 => self.pmpcfg11.set(value), 12 => self.pmpcfg12.set(value), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 13 => self.pmpcfg13.set(value), 14 => self.pmpcfg14.set(value), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 15 => self.pmpcfg15.set(value), _ => unreachable!(), } @@ -383,28 +383,28 @@ impl CSR { ) { match index { 0 => self.pmpcfg0.modify(field), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 1 => self.pmpcfg1.modify(field), 2 => self.pmpcfg2.modify(field), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 3 => self.pmpcfg3.modify(field), 4 => self.pmpcfg4.modify(field), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 5 => self.pmpcfg5.modify(field), 6 => self.pmpcfg6.modify(field), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 7 => self.pmpcfg7.modify(field), 8 => self.pmpcfg8.modify(field), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 9 => self.pmpcfg9.modify(field), 10 => self.pmpcfg10.modify(field), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 11 => self.pmpcfg11.modify(field), 12 => self.pmpcfg12.modify(field), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 13 => self.pmpcfg13.modify(field), 14 => self.pmpcfg14.modify(field), - #[cfg(any(target_arch = "riscv32", not(target_os = "none")))] + #[cfg(not(target_arch = "riscv64"))] 15 => self.pmpcfg15.modify(field), _ => unreachable!(), } diff --git a/arch/riscv/src/csr/mseccfg.rs b/arch/riscv/src/csr/mseccfg.rs index 6100e9c789..7f6b02bc4e 100644 --- a/arch/riscv/src/csr/mseccfg.rs +++ b/arch/riscv/src/csr/mseccfg.rs @@ -5,7 +5,7 @@ use kernel::utilities::registers::register_bitfields; // Default to 32 bit if compiling for debug/testing. -#[cfg(any(target_arch = "riscv32", not(target_os = "none")))] +#[cfg(not(target_arch = "riscv64"))] register_bitfields![usize, pub mseccfg [ mml OFFSET(0) NUMBITS(1) [], @@ -14,7 +14,7 @@ register_bitfields![usize, ] ]; -#[cfg(any(target_arch = "riscv32", not(target_os = "none")))] +#[cfg(not(target_arch = "riscv64"))] register_bitfields![usize, pub mseccfgh [ // This isn't a real entry, it just avoids compilation errors diff --git a/arch/riscv/src/csr/pmpaddr.rs b/arch/riscv/src/csr/pmpaddr.rs index bd57b53caf..ac62830cf0 100644 --- a/arch/riscv/src/csr/pmpaddr.rs +++ b/arch/riscv/src/csr/pmpaddr.rs @@ -5,7 +5,7 @@ use kernel::utilities::registers::register_bitfields; // Default to 32 bit if compiling for debug/testing. -#[cfg(any(target_arch = "riscv32", not(target_os = "none")))] +#[cfg(not(target_arch = "riscv64"))] register_bitfields![usize, pub pmpaddr [ addr OFFSET(0) NUMBITS(crate::XLEN) [] diff --git a/arch/riscv/src/csr/pmpconfig.rs b/arch/riscv/src/csr/pmpconfig.rs index eedf0cf5bc..a341be5f13 100644 --- a/arch/riscv/src/csr/pmpconfig.rs +++ b/arch/riscv/src/csr/pmpconfig.rs @@ -5,7 +5,10 @@ use kernel::utilities::registers::register_bitfields; // Default to 32 bit if compiling for debug/testing. -#[cfg(any(target_arch = "riscv32", not(target_os = "none")))] +#[cfg(any( + target_arch = "riscv32", + all(not(target_arch = "riscv32"), not(target_arch = "riscv64")) +))] register_bitfields![usize, pub pmpcfg [ r0 OFFSET(0) NUMBITS(1) [], diff --git a/arch/riscv/src/lib.rs b/arch/riscv/src/lib.rs index 6f5239225f..dedfb1ad0d 100644 --- a/arch/riscv/src/lib.rs +++ b/arch/riscv/src/lib.rs @@ -17,5 +17,8 @@ pub const XLEN: usize = 64; // Default to 32 bit if no architecture is specified of if this is being // compiled for testing on a different architecture. -#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_os = "none")))] +#[cfg(not(all( + any(target_arch = "riscv32", target_arch = "riscv64"), + target_os = "none" +)))] pub const XLEN: usize = 32; diff --git a/arch/rv32i/src/lib.rs b/arch/rv32i/src/lib.rs index 3ea32065d8..8a8d3d1ab4 100644 --- a/arch/rv32i/src/lib.rs +++ b/arch/rv32i/src/lib.rs @@ -181,7 +181,7 @@ pub unsafe fn configure_trap_handler(mode: PermissionMode) { } // Mock implementation for tests on Travis-CI. -#[cfg(not(any(target_arch = "riscv32", target_os = "none")))] +#[cfg(not(all(target_arch = "riscv32", target_os = "none")))] pub extern "C" fn _start_trap() { unimplemented!() } @@ -475,7 +475,7 @@ pub unsafe fn semihost_command(command: usize, arg0: usize, arg1: usize) -> usiz } // Mock implementation for tests on Travis-CI. -#[cfg(not(any(target_arch = "riscv32", target_os = "none")))] +#[cfg(not(all(target_arch = "riscv32", target_os = "none")))] pub unsafe fn semihost_command(_command: usize, _arg0: usize, _arg1: usize) -> usize { unimplemented!() } diff --git a/arch/rv32i/src/support.rs b/arch/rv32i/src/support.rs index 083a92c87c..ad148da50a 100644 --- a/arch/rv32i/src/support.rs +++ b/arch/rv32i/src/support.rs @@ -5,7 +5,6 @@ //! Core low-level operations. use crate::csr::{mstatus::mstatus, CSR}; -use core::ops::FnOnce; #[cfg(all(target_arch = "riscv32", target_os = "none"))] #[inline(always)] @@ -51,13 +50,13 @@ where } // Mock implementations for tests on Travis-CI. -#[cfg(not(any(target_arch = "riscv32", target_os = "none")))] +#[cfg(not(all(target_arch = "riscv32", target_os = "none")))] /// NOP instruction (mock) pub fn nop() { unimplemented!() } -#[cfg(not(any(target_arch = "riscv32", target_os = "none")))] +#[cfg(not(all(target_arch = "riscv32", target_os = "none")))] /// WFI instruction (mock) pub unsafe fn wfi() { unimplemented!() diff --git a/arch/rv32i/src/syscall.rs b/arch/rv32i/src/syscall.rs index c6b1c1599c..ba13ae4875 100644 --- a/arch/rv32i/src/syscall.rs +++ b/arch/rv32i/src/syscall.rs @@ -4,13 +4,11 @@ //! Kernel-userland system call interface for RISC-V architecture. -use core::convert::TryInto; use core::fmt::Write; use core::mem::size_of; use core::ops::Range; use crate::csr::mcause; -use kernel; use kernel::errorcode::ErrorCode; use kernel::syscall::ContextSwitchReason; @@ -214,7 +212,7 @@ impl kernel::syscall::UserspaceKernelBoundary for SysCall { } // Mock implementation for tests on Travis-CI. - #[cfg(not(any(target_arch = "riscv32", target_os = "none")))] + #[cfg(not(all(target_arch = "riscv32", target_os = "none")))] unsafe fn switch_to_process( &self, _accessible_memory_start: *const u8, diff --git a/boards/acd52832/src/main.rs b/boards/acd52832/src/main.rs index ca3784d13e..e26ecb442e 100644 --- a/boards/acd52832/src/main.rs +++ b/boards/acd52832/src/main.rs @@ -667,12 +667,12 @@ unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/apollo3/lora_things_plus/src/io.rs b/boards/apollo3/lora_things_plus/src/io.rs index 77cc11f498..4e4bccdc12 100644 --- a/boards/apollo3/lora_things_plus/src/io.rs +++ b/boards/apollo3/lora_things_plus/src/io.rs @@ -8,7 +8,6 @@ use core::panic::PanicInfo; use crate::CHIP; use crate::PROCESSES; use crate::PROCESS_PRINTER; -use apollo3; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/apollo3/lora_things_plus/src/main.rs b/boards/apollo3/lora_things_plus/src/main.rs index ff2750737f..d078b1d200 100644 --- a/boards/apollo3/lora_things_plus/src/main.rs +++ b/boards/apollo3/lora_things_plus/src/main.rs @@ -497,12 +497,12 @@ unsafe fn setup() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/apollo3/redboard_artemis_atp/src/io.rs b/boards/apollo3/redboard_artemis_atp/src/io.rs index 19974826be..59dde25453 100644 --- a/boards/apollo3/redboard_artemis_atp/src/io.rs +++ b/boards/apollo3/redboard_artemis_atp/src/io.rs @@ -8,7 +8,6 @@ use core::panic::PanicInfo; use crate::CHIP; use crate::PROCESSES; use crate::PROCESS_PRINTER; -use apollo3; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/apollo3/redboard_artemis_atp/src/main.rs b/boards/apollo3/redboard_artemis_atp/src/main.rs index 006acc9db9..0e177f274c 100644 --- a/boards/apollo3/redboard_artemis_atp/src/main.rs +++ b/boards/apollo3/redboard_artemis_atp/src/main.rs @@ -366,12 +366,12 @@ unsafe fn setup() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/apollo3/redboard_artemis_nano/src/io.rs b/boards/apollo3/redboard_artemis_nano/src/io.rs index 19974826be..59dde25453 100644 --- a/boards/apollo3/redboard_artemis_nano/src/io.rs +++ b/boards/apollo3/redboard_artemis_nano/src/io.rs @@ -8,7 +8,6 @@ use core::panic::PanicInfo; use crate::CHIP; use crate::PROCESSES; use crate::PROCESS_PRINTER; -use apollo3; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/apollo3/redboard_artemis_nano/src/main.rs b/boards/apollo3/redboard_artemis_nano/src/main.rs index f311e7c6c0..266d18cc1c 100644 --- a/boards/apollo3/redboard_artemis_nano/src/main.rs +++ b/boards/apollo3/redboard_artemis_nano/src/main.rs @@ -423,12 +423,12 @@ unsafe fn setup() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/arty_e21/src/io.rs b/boards/arty_e21/src/io.rs index 38cb9eac19..cfb43c8b6f 100644 --- a/boards/arty_e21/src/io.rs +++ b/boards/arty_e21/src/io.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT // Copyright Tock Contributors 2022. -use arty_e21_chip; use core::fmt::Write; use core::panic::PanicInfo; use core::str; @@ -10,8 +9,6 @@ use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::gpio; use kernel::hil::led; -use rv32i; -use sifive; use crate::CHIP; use crate::PROCESSES; diff --git a/boards/arty_e21/src/main.rs b/boards/arty_e21/src/main.rs index 99b53008be..2626eb6ad9 100644 --- a/boards/arty_e21/src/main.rs +++ b/boards/arty_e21/src/main.rs @@ -282,12 +282,12 @@ unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/clue_nrf52840/src/io.rs b/boards/clue_nrf52840/src/io.rs index 7c0bf99df6..930ddc53ab 100644 --- a/boards/clue_nrf52840/src/io.rs +++ b/boards/clue_nrf52840/src/io.rs @@ -6,7 +6,6 @@ use core::fmt::Write; use core::panic::PanicInfo; use kernel::ErrorCode; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/clue_nrf52840/src/main.rs b/boards/clue_nrf52840/src/main.rs index 1addf47c48..be054aa2ce 100644 --- a/boards/clue_nrf52840/src/main.rs +++ b/boards/clue_nrf52840/src/main.rs @@ -144,6 +144,11 @@ type SHT3xSensor = components::sht3x::SHT3xComponentType< type TemperatureDriver = components::temperature::TemperatureComponentType; type HumidityDriver = components::humidity::HumidityComponentType; +type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; + /// Supported drivers by the platform pub struct Platform { ble_radio: &'static capsules_extra::ble_advertising_driver::BLE< @@ -154,7 +159,7 @@ pub struct Platform { nrf52::rtc::Rtc<'static>, >, >, - ieee802154_radio: &'static capsules_extra::ieee802154::RadioDriver<'static>, + ieee802154_radio: &'static Ieee802154Driver, console: &'static capsules_core::console::Console<'static>, proximity: &'static capsules_extra::proximity::ProximitySensor<'static>, gpio: &'static capsules_core::gpio::GPIO<'static, nrf52::gpio::GPIOPin<'static>>, @@ -811,12 +816,12 @@ unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/components/src/analog_comparator.rs b/boards/components/src/analog_comparator.rs index b41d26216a..edfb4d8290 100644 --- a/boards/components/src/analog_comparator.rs +++ b/boards/components/src/analog_comparator.rs @@ -25,7 +25,6 @@ use capsules_extra::analog_comparator::AnalogComparator; use core::mem::MaybeUninit; -use kernel; use kernel::capabilities; use kernel::component::Component; use kernel::create_capability; diff --git a/boards/components/src/ble.rs b/boards/components/src/ble.rs index ad145b33d0..7a98983570 100644 --- a/boards/components/src/ble.rs +++ b/boards/components/src/ble.rs @@ -10,7 +10,6 @@ //! let ble_radio = BLEComponent::new(board_kernel, &nrf52::ble_radio::RADIO, mux_alarm).finalize(); //! ``` -use capsules_core; use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm; use core::mem::MaybeUninit; use kernel::capabilities; diff --git a/boards/components/src/ieee802154.rs b/boards/components/src/ieee802154.rs index c34e2ec7c5..6fa0048fd1 100644 --- a/boards/components/src/ieee802154.rs +++ b/boards/components/src/ieee802154.rs @@ -54,6 +54,8 @@ macro_rules! mux_aes128ccm_component_static { };}; } +pub type MuxAes128ccmComponentType = MuxAES128CCM<'static, A>; + pub struct MuxAes128ccmComponent + AES128Ctr + AES128CBC + AES128ECB> { aes: &'static A, } @@ -95,10 +97,39 @@ macro_rules! ieee802154_component_static { > ); - let mux_mac = kernel::static_buf!(capsules_extra::ieee802154::virtual_mac::MuxMac<'static>); - let mac_user = - kernel::static_buf!(capsules_extra::ieee802154::virtual_mac::MacUser<'static>); - let radio_driver = kernel::static_buf!(capsules_extra::ieee802154::RadioDriver<'static>); + let mux_mac = kernel::static_buf!( + capsules_extra::ieee802154::virtual_mac::MuxMac< + 'static, + capsules_extra::ieee802154::framer::Framer< + 'static, + capsules_extra::ieee802154::mac::AwakeMac<'static, $R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, $A>, + >, + > + ); + let mac_user = kernel::static_buf!( + capsules_extra::ieee802154::virtual_mac::MacUser< + 'static, + capsules_extra::ieee802154::framer::Framer< + 'static, + capsules_extra::ieee802154::mac::AwakeMac<'static, $R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, $A>, + >, + > + ); + let radio_driver = kernel::static_buf!( + capsules_extra::ieee802154::RadioDriver< + 'static, + capsules_extra::ieee802154::virtual_mac::MacUser< + 'static, + capsules_extra::ieee802154::framer::Framer< + 'static, + capsules_extra::ieee802154::mac::AwakeMac<'static, $R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, $A>, + >, + >, + > + ); let radio_buf = kernel::static_buf!([u8; kernel::hil::radio::MAX_BUF_SIZE]); let radio_rx_buf = kernel::static_buf!([u8; kernel::hil::radio::MAX_BUF_SIZE]); @@ -120,6 +151,24 @@ macro_rules! ieee802154_component_static { };}; } +pub type Ieee802154ComponentType = capsules_extra::ieee802154::RadioDriver< + 'static, + capsules_extra::ieee802154::virtual_mac::MacUser< + 'static, + capsules_extra::ieee802154::framer::Framer< + 'static, + capsules_extra::ieee802154::mac::AwakeMac<'static, R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, A>, + >, + >, +>; + +pub type Ieee802154ComponentMacDeviceType = capsules_extra::ieee802154::framer::Framer< + 'static, + capsules_extra::ieee802154::mac::AwakeMac<'static, R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, A>, +>; + pub struct Ieee802154Component< R: 'static + kernel::hil::radio::Radio<'static>, A: 'static + AES128<'static> + AES128Ctr + AES128CBC + AES128ECB, @@ -176,17 +225,64 @@ impl< capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, A>, >, >, - &'static mut MaybeUninit>, - &'static mut MaybeUninit>, - &'static mut MaybeUninit>, + &'static mut MaybeUninit< + capsules_extra::ieee802154::virtual_mac::MuxMac< + 'static, + capsules_extra::ieee802154::framer::Framer< + 'static, + AwakeMac<'static, R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, A>, + >, + >, + >, + &'static mut MaybeUninit< + capsules_extra::ieee802154::virtual_mac::MacUser< + 'static, + capsules_extra::ieee802154::framer::Framer< + 'static, + AwakeMac<'static, R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, A>, + >, + >, + >, + &'static mut MaybeUninit< + capsules_extra::ieee802154::RadioDriver< + 'static, + capsules_extra::ieee802154::virtual_mac::MacUser< + 'static, + capsules_extra::ieee802154::framer::Framer< + 'static, + AwakeMac<'static, R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, A>, + >, + >, + >, + >, &'static mut MaybeUninit<[u8; radio::MAX_BUF_SIZE]>, &'static mut MaybeUninit<[u8; radio::MAX_BUF_SIZE]>, &'static mut MaybeUninit<[u8; CRYPT_SIZE]>, &'static mut MaybeUninit<[u8; radio::MAX_BUF_SIZE]>, ); type Output = ( - &'static capsules_extra::ieee802154::RadioDriver<'static>, - &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static>, + &'static capsules_extra::ieee802154::RadioDriver< + 'static, + capsules_extra::ieee802154::virtual_mac::MacUser< + 'static, + capsules_extra::ieee802154::framer::Framer< + 'static, + AwakeMac<'static, R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, A>, + >, + >, + >, + &'static capsules_extra::ieee802154::virtual_mac::MuxMac< + 'static, + capsules_extra::ieee802154::framer::Framer< + 'static, + AwakeMac<'static, R>, + capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, A>, + >, + >, ); fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output { diff --git a/boards/components/src/lib.rs b/boards/components/src/lib.rs index 28f27f9585..ea96df6da2 100644 --- a/boards/components/src/lib.rs +++ b/boards/components/src/lib.rs @@ -77,6 +77,7 @@ pub mod si7021; pub mod siphash; pub mod sound_pressure; pub mod spi; +pub mod ssd1306; pub mod st77xx; pub mod temperature; pub mod temperature_rp2040; diff --git a/boards/components/src/nonvolatile_storage.rs b/boards/components/src/nonvolatile_storage.rs index fa5d174e3f..38f657e6e4 100644 --- a/boards/components/src/nonvolatile_storage.rs +++ b/boards/components/src/nonvolatile_storage.rs @@ -15,8 +15,8 @@ //! &sam4l::flashcalw::FLASH_CONTROLLER, //! 0x60000, //! 0x20000, -//! &_sstorage as *const u8 as usize, -//! &_estorage as *const u8 as usize, +//! core::ptr::addr_of!(_sstorage) as usize, +//! core::ptr::addr_of!(_estorage) as usize, //! ) //! .finalize(components::nonvolatile_storage_component_static!( //! sam4l::flashcalw::FLASHCALW diff --git a/boards/components/src/process_console.rs b/boards/components/src/process_console.rs index 6b94686b3e..34a7fd2171 100644 --- a/boards/components/src/process_console.rs +++ b/boards/components/src/process_console.rs @@ -143,15 +143,15 @@ impl> Component // pointers to them. let kernel_addresses = unsafe { process_console::KernelAddresses { - stack_start: &_sstack as *const u8, - stack_end: &_estack as *const u8, - text_start: &_stext as *const u8, - text_end: &_etext as *const u8, - read_only_data_start: &_srodata as *const u8, - relocations_start: &_srelocate as *const u8, - relocations_end: &_erelocate as *const u8, - bss_start: &_szero as *const u8, - bss_end: &_ezero as *const u8, + stack_start: core::ptr::addr_of!(_sstack), + stack_end: core::ptr::addr_of!(_estack), + text_start: core::ptr::addr_of!(_stext), + text_end: core::ptr::addr_of!(_etext), + read_only_data_start: core::ptr::addr_of!(_srodata), + relocations_start: core::ptr::addr_of!(_srelocate), + relocations_end: core::ptr::addr_of!(_erelocate), + bss_start: core::ptr::addr_of!(_szero), + bss_end: core::ptr::addr_of!(_ezero), } }; diff --git a/boards/components/src/screen.rs b/boards/components/src/screen.rs index 7b65be8769..4b9e8ac580 100644 --- a/boards/components/src/screen.rs +++ b/boards/components/src/screen.rs @@ -31,10 +31,12 @@ //! ``` use capsules_extra::screen::Screen; +use capsules_extra::screen_shared::ScreenShared; use core::mem::MaybeUninit; use kernel::capabilities; use kernel::component::Component; use kernel::create_capability; +use kernel::hil; #[macro_export] macro_rules! screen_component_static { @@ -99,3 +101,71 @@ impl Component for ScreenComponent screen } } + +#[macro_export] +macro_rules! screen_shared_component_static { + ($s:literal, $S:ty $(,)?) => {{ + let buffer = kernel::static_buf!([u8; $s]); + let screen = kernel::static_buf!(capsules_extra::screen_shared::ScreenShared<$S>); + + (buffer, screen) + };}; +} + +pub type ScreenSharedComponentType = capsules_extra::screen_shared::ScreenShared<'static, S>; + +pub struct ScreenSharedComponent< + const SCREEN_BUF_LEN: usize, + S: hil::screen::Screen<'static> + 'static, +> { + board_kernel: &'static kernel::Kernel, + driver_num: usize, + screen: &'static S, + apps_regions: &'static [capsules_extra::screen_shared::AppScreenRegion], +} + +impl> + ScreenSharedComponent +{ + pub fn new( + board_kernel: &'static kernel::Kernel, + driver_num: usize, + screen: &'static S, + apps_regions: &'static [capsules_extra::screen_shared::AppScreenRegion], + ) -> ScreenSharedComponent { + ScreenSharedComponent { + board_kernel, + driver_num, + screen, + apps_regions, + } + } +} + +impl> Component + for ScreenSharedComponent +{ + type StaticInput = ( + &'static mut MaybeUninit<[u8; SCREEN_BUF_LEN]>, + &'static mut MaybeUninit>, + ); + type Output = &'static ScreenShared<'static, S>; + + fn finalize(self, static_input: Self::StaticInput) -> Self::Output { + let grant_cap = create_capability!(capabilities::MemoryAllocationCapability); + let grant_screen = self.board_kernel.create_grant(self.driver_num, &grant_cap); + + let buffer = static_input.0.write([0; SCREEN_BUF_LEN]); + + let screen = static_input.1.write(ScreenShared::new( + self.screen, + grant_screen, + buffer, + self.apps_regions, + )); + + kernel::hil::screen::Screen::set_client(self.screen, screen); + + screen + } +} diff --git a/boards/components/src/ssd1306.rs b/boards/components/src/ssd1306.rs new file mode 100644 index 0000000000..1669c385c0 --- /dev/null +++ b/boards/components/src/ssd1306.rs @@ -0,0 +1,89 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2024. + +//! Components for the SSD1306 OLED screen. +//! +//! Usage +//! ----- +//! ```rust +//! +//! let ssd1306_i2c = components::i2c::I2CComponent::new(i2c_bus, 0x3c) +//! .finalize(components::i2c_component_static!(nrf52840::i2c::TWI)); +//! +//! let ssd1306 = components::ssd1306::Ssd1306Component::new(ssd1306_i2c, true) +//! .finalize(components::ssd1306_component_static!(nrf52840::i2c::TWI)); +//! ``` + +use core::mem::MaybeUninit; +use kernel::component::Component; +use kernel::hil; + +// Setup static space for the objects. +#[macro_export] +macro_rules! ssd1306_component_static { + ($I: ty $(,)?) => {{ + let buffer = kernel::static_buf!([u8; capsules_extra::ssd1306::BUFFER_SIZE]); + let ssd1306 = kernel::static_buf!( + capsules_extra::ssd1306::Ssd1306< + 'static, + capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, $I>, + > + ); + + (buffer, ssd1306) + };}; +} + +pub type Ssd1306ComponentType = capsules_extra::ssd1306::Ssd1306< + 'static, + capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, I>, +>; + +pub struct Ssd1306Component + 'static> { + i2c_device: &'static capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, I>, + use_charge_pump: bool, +} + +impl + 'static> Ssd1306Component { + pub fn new( + i2c_device: &'static capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, I>, + use_charge_pump: bool, + ) -> Ssd1306Component { + Ssd1306Component { + i2c_device, + use_charge_pump, + } + } +} + +impl + 'static> Component for Ssd1306Component { + type StaticInput = ( + &'static mut MaybeUninit<[u8; capsules_extra::ssd1306::BUFFER_SIZE]>, + &'static mut MaybeUninit< + capsules_extra::ssd1306::Ssd1306< + 'static, + capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, I>, + >, + >, + ); + type Output = &'static capsules_extra::ssd1306::Ssd1306< + 'static, + capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, I>, + >; + + fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output { + let buffer = static_buffer + .0 + .write([0; capsules_extra::ssd1306::BUFFER_SIZE]); + + let ssd1306 = static_buffer.1.write(capsules_extra::ssd1306::Ssd1306::new( + self.i2c_device, + buffer, + self.use_charge_pump, + )); + self.i2c_device.set_client(ssd1306); + + ssd1306 + } +} diff --git a/boards/components/src/thread_network.rs b/boards/components/src/thread_network.rs index 653bfc9ab7..cabb59b075 100644 --- a/boards/components/src/thread_network.rs +++ b/boards/components/src/thread_network.rs @@ -26,7 +26,6 @@ //! )); //! ``` -use capsules_core; use capsules_core::virtualizers::virtual_aes_ccm::MuxAES128CCM; use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm; use capsules_extra::net::ipv6::ipv6_send::IP6SendStruct; @@ -42,7 +41,6 @@ use capsules_extra::net::udp::udp_recv::MuxUdpReceiver; use capsules_extra::net::udp::udp_recv::UDPReceiver; use capsules_extra::net::udp::udp_send::{MuxUdpSender, UDPSendStruct, UDPSender}; use core::mem::MaybeUninit; -use kernel; use kernel::capabilities; use kernel::capabilities::NetworkCapabilityCreationCapability; use kernel::component::Component; diff --git a/boards/components/src/udp_driver.rs b/boards/components/src/udp_driver.rs index 96ab8cf75f..438e2e9f05 100644 --- a/boards/components/src/udp_driver.rs +++ b/boards/components/src/udp_driver.rs @@ -21,7 +21,6 @@ //! .finalize(components::udp_driver_component_static!()); //! ``` -use capsules_core; use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm; use capsules_extra::net::ipv6::ip_utils::IPAddr; use capsules_extra::net::ipv6::ipv6_send::IP6SendStruct; @@ -33,7 +32,6 @@ use capsules_extra::net::udp::udp_recv::MuxUdpReceiver; use capsules_extra::net::udp::udp_recv::UDPReceiver; use capsules_extra::net::udp::udp_send::{MuxUdpSender, UDPSendStruct, UDPSender}; use core::mem::MaybeUninit; -use kernel; use kernel::capabilities; use kernel::capabilities::NetworkCapabilityCreationCapability; use kernel::component::Component; diff --git a/boards/components/src/udp_mux.rs b/boards/components/src/udp_mux.rs index 19eae60dea..021c97264a 100644 --- a/boards/components/src/udp_mux.rs +++ b/boards/components/src/udp_mux.rs @@ -27,7 +27,6 @@ // Author: Hudson Ayers // Last Modified: 5/21/2019 -use capsules_core; use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm}; use capsules_extra::ieee802154::device::MacDevice; use capsules_extra::net::ieee802154::MacAddress; @@ -46,7 +45,6 @@ use capsules_extra::net::udp::udp_recv::MuxUdpReceiver; use capsules_extra::net::udp::udp_send::MuxUdpSender; use capsules_extra::net::udp::UDPHeader; use core::mem::MaybeUninit; -use kernel; use kernel::capabilities; use kernel::component::Component; use kernel::create_capability; @@ -67,7 +65,7 @@ pub const MAX_PAYLOAD_LEN: usize = 200; //The max size UDP message that can be s // Setup static space for the objects. #[macro_export] macro_rules! udp_mux_component_static { - ($A:ty $(,)?) => {{ + ($A:ty, $M:ty $(,)?) => {{ use capsules_core; use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm}; use capsules_extra::net::sixlowpan::{sixlowpan_compression, sixlowpan_state}; @@ -77,7 +75,7 @@ macro_rules! udp_mux_component_static { let alarm = kernel::static_buf!(VirtualMuxAlarm<'static, $A>); let mac_user = - kernel::static_buf!(capsules_extra::ieee802154::virtual_mac::MacUser<'static>); + kernel::static_buf!(capsules_extra::ieee802154::virtual_mac::MacUser<'static, $M>); let sixlowpan = kernel::static_buf!( sixlowpan_state::Sixlowpan< 'static, @@ -156,8 +154,8 @@ macro_rules! udp_mux_component_static { };}; } -pub struct UDPMuxComponent + 'static> { - mux_mac: &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static>, +pub struct UDPMuxComponent + 'static, M: MacDevice<'static> + 'static> { + mux_mac: &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static, M>, ctx_pfix_len: u8, ctx_pfix: [u8; 16], dst_mac_addr: MacAddress, @@ -166,9 +164,9 @@ pub struct UDPMuxComponent + 'static> { alarm_mux: &'static MuxAlarm<'static, A>, } -impl + 'static> UDPMuxComponent { +impl + 'static, M: MacDevice<'static>> UDPMuxComponent { pub fn new( - mux_mac: &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static>, + mux_mac: &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static, M>, ctx_pfix_len: u8, ctx_pfix: [u8; 16], dst_mac_addr: MacAddress, @@ -188,10 +186,10 @@ impl + 'static> UDPMuxComponent { } } -impl + 'static> Component for UDPMuxComponent { +impl + 'static, M: MacDevice<'static>> Component for UDPMuxComponent { type StaticInput = ( &'static mut MaybeUninit>, - &'static mut MaybeUninit>, + &'static mut MaybeUninit>, &'static mut MaybeUninit< sixlowpan_state::Sixlowpan< 'static, diff --git a/boards/esp32-c3-devkitM-1/src/main.rs b/boards/esp32-c3-devkitM-1/src/main.rs index 060ff04073..205a5d4e04 100644 --- a/boards/esp32-c3-devkitM-1/src/main.rs +++ b/boards/esp32-c3-devkitM-1/src/main.rs @@ -306,12 +306,12 @@ unsafe fn setup() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/hail/src/io.rs b/boards/hail/src/io.rs index de71b5dd72..733f7e2ebe 100644 --- a/boards/hail/src/io.rs +++ b/boards/hail/src/io.rs @@ -5,7 +5,6 @@ use core::fmt::Write; use core::panic::PanicInfo; use core::str; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/hail/src/main.rs b/boards/hail/src/main.rs index 013783eeda..1e9390e351 100644 --- a/boards/hail/src/main.rs +++ b/boards/hail/src/main.rs @@ -543,12 +543,12 @@ unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, fault_policy, diff --git a/boards/hifive1/src/io.rs b/boards/hifive1/src/io.rs index 6c0fd863a3..16be4d4088 100644 --- a/boards/hifive1/src/io.rs +++ b/boards/hifive1/src/io.rs @@ -5,12 +5,10 @@ use core::fmt::Write; use core::panic::PanicInfo; use core::str; -use e310_g002; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::gpio; use kernel::hil::led; -use rv32i; use crate::CHIP; use crate::PROCESSES; diff --git a/boards/hifive1/src/main.rs b/boards/hifive1/src/main.rs index 2ba4c1c34c..4b3504c6d5 100644 --- a/boards/hifive1/src/main.rs +++ b/boards/hifive1/src/main.rs @@ -147,15 +147,15 @@ fn load_processes_not_inlined(board_kernel: &'static Kernel, chip: &'st let app_flash = unsafe { core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ) }; let app_memory = unsafe { core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ) }; diff --git a/boards/hifive_inventor/src/io.rs b/boards/hifive_inventor/src/io.rs index b1dadac184..94f6b8708d 100644 --- a/boards/hifive_inventor/src/io.rs +++ b/boards/hifive_inventor/src/io.rs @@ -5,11 +5,9 @@ use core::fmt::Write; use core::panic::PanicInfo; use core::str; -use e310_g003; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; -use rv32i; use crate::CHIP; use crate::PROCESSES; diff --git a/boards/hifive_inventor/src/main.rs b/boards/hifive_inventor/src/main.rs index f5b747b5f6..0f6deebc6a 100644 --- a/boards/hifive_inventor/src/main.rs +++ b/boards/hifive_inventor/src/main.rs @@ -294,12 +294,12 @@ unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/imix/src/io.rs b/boards/imix/src/io.rs index 0287cab21b..c43fddac44 100644 --- a/boards/imix/src/io.rs +++ b/boards/imix/src/io.rs @@ -4,12 +4,10 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; use kernel::hil::uart::{self, Configure}; -use sam4l; use crate::CHIP; use crate::PROCESSES; diff --git a/boards/imix/src/main.rs b/boards/imix/src/main.rs index c1583b8b6f..6763e91d26 100644 --- a/boards/imix/src/main.rs +++ b/boards/imix/src/main.rs @@ -115,6 +115,13 @@ type SI7021Sensor = components::si7021::SI7021ComponentType< type TemperatureDriver = components::temperature::TemperatureComponentType; type HumidityDriver = components::humidity::HumidityComponentType; +type Rf233 = capsules_extra::rf233::RF233< + 'static, + VirtualSpiMasterDevice<'static, sam4l::spi::SpiHw<'static>>, +>; +type Ieee802154MacDevice = + components::ieee802154::Ieee802154ComponentMacDeviceType>; + struct Imix { pconsole: &'static capsules_core::process_console::ProcessConsole< 'static, @@ -671,10 +678,10 @@ pub unsafe fn main() { board_kernel, capsules_extra::nonvolatile_storage_driver::DRIVER_NUM, &peripherals.flash_controller, - 0x60000, // Start address for userspace accessible region - 0x20000, // Length of userspace accessible region - &_sstorage as *const u8 as usize, //start address of kernel region - &_estorage as *const u8 as usize - &_sstorage as *const u8 as usize, // length of kernel region + 0x60000, // Start address for userspace accessible region + 0x20000, // Length of userspace accessible region + core::ptr::addr_of!(_sstorage) as usize, //start address of kernel region + core::ptr::addr_of!(_estorage) as usize - core::ptr::addr_of!(_sstorage) as usize, // length of kernel region ) .finalize(components::nonvolatile_storage_component_static!( sam4l::flashcalw::FLASHCALW @@ -705,7 +712,10 @@ pub unsafe fn main() { local_ip_ifaces, mux_alarm, ) - .finalize(components::udp_mux_component_static!(sam4l::ast::Ast)); + .finalize(components::udp_mux_component_static!( + sam4l::ast::Ast, + Ieee802154MacDevice + )); // UDP driver initialization happens here let udp_driver = components::udp_driver::UDPDriverComponent::new( @@ -826,12 +836,12 @@ pub unsafe fn main() { &imix, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/imix/src/test/icmp_lowpan_test.rs b/boards/imix/src/test/icmp_lowpan_test.rs index 72953e448c..be4b1cf57e 100644 --- a/boards/imix/src/test/icmp_lowpan_test.rs +++ b/boards/imix/src/test/icmp_lowpan_test.rs @@ -67,8 +67,18 @@ pub struct LowpanICMPTest<'a, A: time::Alarm<'a>> { net_cap: &'static NetworkCapability, } +type Rf233 = capsules_extra::rf233::RF233< + 'static, + capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice< + 'static, + sam4l::spi::SpiHw<'static>, + >, +>; +type Ieee802154MacDevice = + components::ieee802154::Ieee802154ComponentMacDeviceType>; + pub unsafe fn run( - mux_mac: &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static>, + mux_mac: &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static, Ieee802154MacDevice>, mux_alarm: &'static MuxAlarm<'static, sam4l::ast::Ast>, ) { let create_cap = create_capability!(NetworkCapabilityCreationCapability); @@ -81,7 +91,7 @@ pub unsafe fn run( IpVisibilityCapability::new(&create_cap) ); let radio_mac = static_init!( - capsules_extra::ieee802154::virtual_mac::MacUser<'static>, + capsules_extra::ieee802154::virtual_mac::MacUser<'static, Ieee802154MacDevice>, capsules_extra::ieee802154::virtual_mac::MacUser::new(mux_mac) ); mux_mac.add_user(radio_mac); diff --git a/boards/imix/src/test/ipv6_lowpan_test.rs b/boards/imix/src/test/ipv6_lowpan_test.rs index 444401221f..eb1d252802 100644 --- a/boards/imix/src/test/ipv6_lowpan_test.rs +++ b/boards/imix/src/test/ipv6_lowpan_test.rs @@ -119,6 +119,16 @@ static mut UDP_DGRAM: [u8; PAYLOAD_LEN - UDP_HDR_SIZE] = [0; PAYLOAD_LEN - UDP_H static mut IP6_DG_OPT: Option = None; //END changes +type Rf233 = capsules_extra::rf233::RF233< + 'static, + capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice< + 'static, + sam4l::spi::SpiHw<'static>, + >, +>; +type Ieee802154MacDevice = + components::ieee802154::Ieee802154ComponentMacDeviceType>; + pub struct LowpanTest<'a, A: time::Alarm<'a>> { alarm: &'a A, sixlowpan_tx: TxState<'a>, @@ -127,14 +137,14 @@ pub struct LowpanTest<'a, A: time::Alarm<'a>> { } pub unsafe fn initialize_all( - mux_mac: &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static>, + mux_mac: &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static, Ieee802154MacDevice>, mux_alarm: &'static MuxAlarm<'static, sam4l::ast::Ast>, ) -> &'static LowpanTest< 'static, capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, sam4l::ast::Ast<'static>>, > { let radio_mac = static_init!( - capsules_extra::ieee802154::virtual_mac::MacUser<'static>, + capsules_extra::ieee802154::virtual_mac::MacUser<'static, Ieee802154MacDevice>, capsules_extra::ieee802154::virtual_mac::MacUser::new(mux_mac) ); mux_mac.add_user(radio_mac); diff --git a/boards/imxrt1050-evkb/src/main.rs b/boards/imxrt1050-evkb/src/main.rs index 4a702ecbd2..ac7fde7b49 100644 --- a/boards/imxrt1050-evkb/src/main.rs +++ b/boards/imxrt1050-evkb/src/main.rs @@ -521,12 +521,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/litex/arty/src/main.rs b/boards/litex/arty/src/main.rs index 71c3e60268..7ace4a411a 100644 --- a/boards/litex/arty/src/main.rs +++ b/boards/litex/arty/src/main.rs @@ -270,15 +270,15 @@ pub unsafe fn main() { let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new( rv32i::pmp::kernel_protection::FlashRegion( rv32i::pmp::NAPOTRegionSpec::new( - &_sflash as *const u8, // start - &_eflash as *const u8 as usize - &_sflash as *const u8 as usize, // size + core::ptr::addr_of!(_sflash), + core::ptr::addr_of!(_eflash) as usize - core::ptr::addr_of!(_sflash) as usize, ) .unwrap(), ), rv32i::pmp::kernel_protection::RAMRegion( rv32i::pmp::NAPOTRegionSpec::new( - &_ssram as *const u8, // start - &_esram as *const u8 as usize - &_ssram as *const u8 as usize, // size + core::ptr::addr_of!(_ssram), + core::ptr::addr_of!(_esram) as usize - core::ptr::addr_of!(_ssram) as usize, ) .unwrap(), ), @@ -291,8 +291,8 @@ pub unsafe fn main() { ), rv32i::pmp::kernel_protection::KernelTextRegion( rv32i::pmp::TORRegionSpec::new( - &_stext as *const u8, // start - &_etext as *const u8, // end + core::ptr::addr_of!(_stext), + core::ptr::addr_of!(_etext), ) .unwrap(), ), @@ -603,12 +603,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/litex/sim/src/main.rs b/boards/litex/sim/src/main.rs index 8a6ef34c6a..b8cf702d58 100644 --- a/boards/litex/sim/src/main.rs +++ b/boards/litex/sim/src/main.rs @@ -269,15 +269,15 @@ pub unsafe fn main() { let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new( rv32i::pmp::kernel_protection::FlashRegion( rv32i::pmp::NAPOTRegionSpec::new( - &_sflash as *const u8, // start - &_eflash as *const u8 as usize - &_sflash as *const u8 as usize, // size + core::ptr::addr_of!(_sflash), + core::ptr::addr_of!(_eflash) as usize - core::ptr::addr_of!(_sflash) as usize, ) .unwrap(), ), rv32i::pmp::kernel_protection::RAMRegion( rv32i::pmp::NAPOTRegionSpec::new( - &_ssram as *const u8, // start - &_esram as *const u8 as usize - &_ssram as *const u8 as usize, // size + core::ptr::addr_of!(_ssram), + core::ptr::addr_of!(_esram) as usize - core::ptr::addr_of!(_ssram) as usize, ) .unwrap(), ), @@ -290,8 +290,8 @@ pub unsafe fn main() { ), rv32i::pmp::kernel_protection::KernelTextRegion( rv32i::pmp::TORRegionSpec::new( - &_stext as *const u8, // start - &_etext as *const u8, // end + core::ptr::addr_of!(_stext), + core::ptr::addr_of!(_etext), ) .unwrap(), ), @@ -676,12 +676,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/makepython-nrf52840/Cargo.toml b/boards/makepython-nrf52840/Cargo.toml new file mode 100644 index 0000000000..bc820b59b6 --- /dev/null +++ b/boards/makepython-nrf52840/Cargo.toml @@ -0,0 +1,21 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2022. + +[package] +name = "makepython-nrf52840" +version.workspace = true +authors.workspace = true +build = "../build.rs" +edition.workspace = true + +[dependencies] +cortexm4 = { path = "../../arch/cortex-m4" } +kernel = { path = "../../kernel" } +nrf52 = { path = "../../chips/nrf52" } +nrf52840 = { path = "../../chips/nrf52840" } +components = { path = "../components" } +nrf52_components = { path = "../nordic/nrf52_components" } + +capsules-core = { path = "../../capsules/core" } +capsules-extra = { path = "../../capsules/extra" } diff --git a/boards/makepython-nrf52840/Makefile b/boards/makepython-nrf52840/Makefile new file mode 100644 index 0000000000..7f1258392c --- /dev/null +++ b/boards/makepython-nrf52840/Makefile @@ -0,0 +1,30 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2022. + +# Makefile for building the tock kernel for the Arduino Nano 33 BLE board. + +TOCK_ARCH=cortex-m4 +TARGET=thumbv7em-none-eabi +PLATFORM=makepython-nrf52840 + +include ../Makefile.common + +ifdef PORT + FLAGS += --port $(PORT) +endif + +# Default target for installing the kernel. +.PHONY: install +install: program + +# Upload the kernel using tockloader and the tock bootloader +.PHONY: program +program: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin + tockloader $(FLAGS) flash --address 0x10000 $< + +.PHONY: flash-bootloader +flash-bootloader: + curl -L --output /tmp/makepython-nrf52840-bootloader_v1.1.3.bin https://github.com/tock/tock-bootloader/releases/download/v1.1.3/makepython-nrf52840-bootloader_v1.1.3.bin + tockloader flash --address 0 /tmp/makepython-nrf52840-bootloader_v1.1.3.bin + rm /tmp/makepython-nrf52840-bootloader_v1.1.3.bin diff --git a/boards/makepython-nrf52840/README.md b/boards/makepython-nrf52840/README.md new file mode 100644 index 0000000000..d38b2f8746 --- /dev/null +++ b/boards/makepython-nrf52840/README.md @@ -0,0 +1,52 @@ +MakePython nRF52840 +=================== + + + +The [MakePython nRF52840](https://www.makerfabs.com/makepython-nrf52840.html) is +a development board with the Nordic nRF52840 SoC and a 128 x 64 pixel OLED +display. + + +## Getting Started + +First, follow the [Tock Getting Started guide](../../doc/Getting_Started.md). + +The MakePython nRF52840 is designed to be programmed using an external JLink +programmer. We would like to avoid this requirement, so we use the [Tock +Bootloader](https://github.com/tock/tock-bootloader) which allows us to program +the board over the UART connection. However, we still require the programmer one +time to flash the bootloader. + +To flash the bootloader we must connect a JLink programmer. The easiest way is +to use an nRF52840dk board. + +### Connect the nRF52840dk to the MakePython-nRF52840 + +First we jumper the board as shown with the following pin mappings + +| nRF52840dk | MakePython-nRF52840 | +|------------|---------------------| +| GND | GND | +| SWD SEL | +3V3 | +| SWD CLK | SWDCLK | +| SWD IO | SWDDIO | + +Make sure _both_ the nRF52840dk board and the MakePython-nRF52840 board are +attached to your computer via two USB connections. + +Then: + +``` +make flash-bootloader +``` + +This will use JLinkExe to flash the bootloader using the nRF52840dk's onboard +jtag hardware. + +### Using the Bootloader + +The bootloader activates when the reset button is pressed twice in quick +succession. The green LED will stay on when the bootloader is active. + +Once the bootloader is installed tockloader will work as expected. diff --git a/boards/makepython-nrf52840/layout.ld b/boards/makepython-nrf52840/layout.ld new file mode 100644 index 0000000000..d5950e39c4 --- /dev/null +++ b/boards/makepython-nrf52840/layout.ld @@ -0,0 +1,14 @@ +/* Licensed under the Apache License, Version 2.0 or the MIT License. */ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* Copyright Tock Contributors 2023. */ + +MEMORY +{ + rom (rx) : ORIGIN = 0x00010000, LENGTH = 256K + prog (rx) : ORIGIN = 0x00050000, LENGTH = 704K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K +} + +PAGE_SIZE = 4K; + +INCLUDE ../kernel_layout.ld diff --git a/boards/makepython-nrf52840/src/io.rs b/boards/makepython-nrf52840/src/io.rs new file mode 100644 index 0000000000..fefaab2a82 --- /dev/null +++ b/boards/makepython-nrf52840/src/io.rs @@ -0,0 +1,142 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2022. + +use core::fmt::Write; +use core::panic::PanicInfo; + +use cortexm4; +use kernel::debug; +use kernel::debug::IoWrite; +use kernel::hil::led; +use kernel::hil::uart::{self}; +use kernel::ErrorCode; +use nrf52840::gpio::Pin; + +use crate::CHIP; +use crate::PROCESSES; +use crate::PROCESS_PRINTER; +use kernel::hil::uart::Transmit; +use kernel::utilities::cells::VolatileCell; + +struct Writer { + initialized: bool, +} + +static mut WRITER: Writer = Writer { initialized: false }; + +impl Write for Writer { + fn write_str(&mut self, s: &str) -> ::core::fmt::Result { + self.write(s.as_bytes()); + Ok(()) + } +} + +const BUF_LEN: usize = 512; +static mut STATIC_PANIC_BUF: [u8; BUF_LEN] = [0; BUF_LEN]; + +static mut DUMMY: DummyUsbClient = DummyUsbClient { + fired: VolatileCell::new(false), +}; + +struct DummyUsbClient { + fired: VolatileCell, +} + +impl uart::TransmitClient for DummyUsbClient { + fn transmitted_buffer(&self, _: &'static mut [u8], _: usize, _: Result<(), ErrorCode>) { + self.fired.set(true); + } +} + +impl IoWrite for Writer { + fn write(&mut self, buf: &[u8]) -> usize { + if !self.initialized { + self.initialized = true; + } + // Here we mimic a synchronous UART output by calling transmit_buffer + // on the CDC stack and then spinning on USB interrupts until the transaction + // is complete. If the USB or CDC stack panicked, this may fail. It will also + // fail if the panic occurred prior to the USB connection being initialized. + // In the latter case, the LEDs should still blink in the panic pattern. + + // spin so that if any USB DMA is ongoing it will finish + // we should only need this on the first call to write() + let mut i = 0; + loop { + i += 1; + cortexm4::support::nop(); + if i > 10000 { + break; + } + } + + // copy_from_slice() requires equal length slices + // This will truncate any writes longer than BUF_LEN, but simplifies the + // code. In practice, BUF_LEN=512 always seems sufficient for the size of + // individual calls to write made by the panic handler. + let mut max = BUF_LEN; + if buf.len() < BUF_LEN { + max = buf.len(); + } + + unsafe { + // If CDC_REF_FOR_PANIC is not yet set we panicked very early, + // and not much we can do. Don't want to double fault, + // so just return. + super::CDC_REF_FOR_PANIC.map(|cdc| { + // Lots of unsafe dereferencing of global static mut objects here. + // However, this should be okay, because it all happens within + // a single thread, and: + // - This is the only place the global CDC_REF_FOR_PANIC is used, the logic is the same + // as applies for the global CHIP variable used in the panic handler. + // - We do create multiple mutable references to the STATIC_PANIC_BUF, but we never + // access the STATIC_PANIC_BUF after a slice of it is passed to transmit_buffer + // until the slice has been returned in the uart callback. + // - Similarly, only this function uses the global DUMMY variable, and we do not + // mutate it. + let usb = &mut cdc.controller(); + STATIC_PANIC_BUF[..max].copy_from_slice(&buf[..max]); + let static_buf = &mut STATIC_PANIC_BUF; + cdc.set_transmit_client(&DUMMY); + let _ = cdc.transmit_buffer(static_buf, max); + loop { + if let Some(interrupt) = cortexm4::nvic::next_pending() { + if interrupt == 39 { + usb.handle_interrupt(); + } + let n = cortexm4::nvic::Nvic::new(interrupt); + n.clear_pending(); + n.enable(); + } + if DUMMY.fired.get() { + // buffer finished transmitting, return so we can output additional + // messages when requested by the panic handler. + break; + } + } + DUMMY.fired.set(false); + }); + } + buf.len() + } +} + +/// We just use the standard default provided by the debug module in the kernel. +#[cfg(not(test))] +#[no_mangle] +#[panic_handler] +pub unsafe fn panic_fmt(pi: &PanicInfo) -> ! { + let led_kernel_pin = &nrf52840::gpio::GPIOPin::new(Pin::P1_10); + let led = &mut led::LedLow::new(led_kernel_pin); + let writer = &mut WRITER; + debug::panic( + &mut [led], + writer, + pi, + &cortexm4::support::nop, + &PROCESSES, + &CHIP, + &PROCESS_PRINTER, + ) +} diff --git a/boards/makepython-nrf52840/src/main.rs b/boards/makepython-nrf52840/src/main.rs new file mode 100644 index 0000000000..b8fd94744b --- /dev/null +++ b/boards/makepython-nrf52840/src/main.rs @@ -0,0 +1,751 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2022. + +//! Tock kernel for the MakePython nRF52840. +//! +//! It is based on nRF52840 SoC. + +#![no_std] +// Disable this attribute when documenting, as a workaround for +// https://github.com/rust-lang/rust/issues/62184. +#![cfg_attr(not(doc), no_main)] +#![deny(missing_docs)] + +use kernel::capabilities; +use kernel::component::Component; +use kernel::hil::led::LedLow; +use kernel::hil::time::Counter; +use kernel::hil::usb::Client; +use kernel::platform::{KernelResources, SyscallDriverLookup}; +use kernel::scheduler::round_robin::RoundRobinSched; +#[allow(unused_imports)] +use kernel::{create_capability, debug, debug_gpio, debug_verbose, static_init}; + +use nrf52840::gpio::Pin; +use nrf52840::interrupt_service::Nrf52840DefaultPeripherals; + +// The datasheet and website and everything say this is connected to P1.10, but +// actually looking at the hardware files (and what actually works) is that the +// LED is connected to P1.11 (as of a board I received in September 2023). +// +// https://github.com/Makerfabs/NRF52840/issues/1 +const LED_PIN: Pin = Pin::P1_11; + +const BUTTON_RST_PIN: Pin = Pin::P0_18; +const BUTTON_PIN: Pin = Pin::P1_15; + +const GPIO_D0: Pin = Pin::P0_23; +const GPIO_D1: Pin = Pin::P0_12; +const GPIO_D2: Pin = Pin::P0_09; +const GPIO_D3: Pin = Pin::P0_07; + +const _UART_TX_PIN: Pin = Pin::P0_06; +const _UART_RX_PIN: Pin = Pin::P0_08; + +/// I2C pins for all of the sensors. +const I2C_SDA_PIN: Pin = Pin::P0_26; +const I2C_SCL_PIN: Pin = Pin::P0_27; + +// Constants related to the configuration of the 15.4 network stack +/// Personal Area Network ID for the IEEE 802.15.4 radio +const PAN_ID: u16 = 0xABCD; +/// Gateway (or next hop) MAC Address +const DST_MAC_ADDR: capsules_extra::net::ieee802154::MacAddress = + capsules_extra::net::ieee802154::MacAddress::Short(49138); +const DEFAULT_CTX_PREFIX_LEN: u8 = 8; //Length of context for 6LoWPAN compression +const DEFAULT_CTX_PREFIX: [u8; 16] = [0x0_u8; 16]; //Context for 6LoWPAN Compression + +/// UART Writer for panic!()s. +pub mod io; + +// How should the kernel respond when a process faults. For this board we choose +// to stop the app and print a notice, but not immediately panic. This allows +// users to debug their apps, but avoids issues with using the USB/CDC stack +// synchronously for panic! too early after the board boots. +const FAULT_RESPONSE: kernel::process::StopWithDebugFaultPolicy = + kernel::process::StopWithDebugFaultPolicy {}; + +// Number of concurrent processes this platform supports. +const NUM_PROCS: usize = 8; + +// State for loading and holding applications. +static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] = + [None; NUM_PROCS]; + +static mut CHIP: Option<&'static nrf52840::chip::NRF52> = None; +static mut PROCESS_PRINTER: Option<&'static kernel::process::ProcessPrinterText> = None; +static mut CDC_REF_FOR_PANIC: Option< + &'static capsules_extra::usb::cdc::CdcAcm< + 'static, + nrf52::usbd::Usbd, + capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc>, + >, +> = None; +static mut NRF52_POWER: Option<&'static nrf52840::power::Power> = None; + +/// Dummy buffer that causes the linker to reserve enough space for the stack. +#[no_mangle] +#[link_section = ".stack_buffer"] +pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000]; + +// Function for the CDC/USB stack to use to enter the bootloader. +fn baud_rate_reset_bootloader_enter() { + unsafe { + // 0x90 is the magic value the bootloader expects + NRF52_POWER.unwrap().set_gpregret(0x90); + cortexm4::scb::reset(); + } +} + +fn crc(s: &'static str) -> u32 { + kernel::utilities::helpers::crc32_posix(s.as_bytes()) +} + +//------------------------------------------------------------------------------ +// SYSCALL DRIVER TYPE DEFINITIONS +//------------------------------------------------------------------------------ + +type AlarmDriver = components::alarm::AlarmDriverComponentType>; + +type Screen = components::ssd1306::Ssd1306ComponentType>; +type ScreenDriver = components::screen::ScreenSharedComponentType; + +type Checker = kernel::process_checker::basic::AppCheckerNames<'static, fn(&'static str) -> u32>; + +type Ieee802154MacDevice = components::ieee802154::Ieee802154ComponentMacDeviceType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; +type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; + +/// Supported drivers by the platform +pub struct Platform { + ble_radio: &'static capsules_extra::ble_advertising_driver::BLE< + 'static, + nrf52::ble_radio::Radio<'static>, + capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm< + 'static, + nrf52::rtc::Rtc<'static>, + >, + >, + ieee802154_radio: &'static Ieee802154Driver, + console: &'static capsules_core::console::Console<'static>, + pconsole: &'static capsules_core::process_console::ProcessConsole< + 'static, + { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN }, + capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm< + 'static, + nrf52::rtc::Rtc<'static>, + >, + components::process_console::Capability, + >, + gpio: &'static capsules_core::gpio::GPIO<'static, nrf52::gpio::GPIOPin<'static>>, + led: &'static capsules_core::led::LedDriver< + 'static, + LedLow<'static, nrf52::gpio::GPIOPin<'static>>, + 1, + >, + adc: &'static capsules_core::adc::AdcVirtualized<'static>, + rng: &'static capsules_core::rng::RngDriver<'static>, + ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>, + alarm: &'static AlarmDriver, + button: &'static capsules_core::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>, + screen: &'static ScreenDriver, + udp_driver: &'static capsules_extra::net::udp::UDPDriver<'static>, + scheduler: &'static RoundRobinSched<'static>, + checker: &'static Checker, + systick: cortexm4::systick::SysTick, +} + +impl SyscallDriverLookup for Platform { + fn with_driver(&self, driver_num: usize, f: F) -> R + where + F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R, + { + match driver_num { + capsules_core::console::DRIVER_NUM => f(Some(self.console)), + capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)), + capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)), + capsules_core::led::DRIVER_NUM => f(Some(self.led)), + capsules_core::button::DRIVER_NUM => f(Some(self.button)), + capsules_core::adc::DRIVER_NUM => f(Some(self.adc)), + capsules_core::rng::DRIVER_NUM => f(Some(self.rng)), + capsules_extra::screen::DRIVER_NUM => f(Some(self.screen)), + capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)), + capsules_extra::ieee802154::DRIVER_NUM => f(Some(self.ieee802154_radio)), + capsules_extra::net::udp::DRIVER_NUM => f(Some(self.udp_driver)), + kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), + _ => f(None), + } + } +} + +impl KernelResources>> + for Platform +{ + type SyscallDriverLookup = Self; + type SyscallFilter = (); + type ProcessFault = (); + type CredentialsCheckingPolicy = Checker; + type Scheduler = RoundRobinSched<'static>; + type SchedulerTimer = cortexm4::systick::SysTick; + type WatchDog = (); + type ContextSwitchCallback = (); + + fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup { + self + } + fn syscall_filter(&self) -> &Self::SyscallFilter { + &() + } + fn process_fault(&self) -> &Self::ProcessFault { + &() + } + fn credentials_checking_policy(&self) -> &'static Self::CredentialsCheckingPolicy { + self.checker + } + fn scheduler(&self) -> &Self::Scheduler { + self.scheduler + } + fn scheduler_timer(&self) -> &Self::SchedulerTimer { + &self.systick + } + fn watchdog(&self) -> &Self::WatchDog { + &() + } + fn context_switch_callback(&self) -> &Self::ContextSwitchCallback { + &() + } +} + +/// This is in a separate, inline(never) function so that its stack frame is +/// removed when this function returns. Otherwise, the stack space used for +/// these static_inits is wasted. +#[inline(never)] +pub unsafe fn start() -> ( + &'static kernel::Kernel, + Platform, + &'static nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>, +) { + nrf52840::init(); + + let ieee802154_ack_buf = static_init!( + [u8; nrf52840::ieee802154_radio::ACK_BUF_SIZE], + [0; nrf52840::ieee802154_radio::ACK_BUF_SIZE] + ); + + // Initialize chip peripheral drivers + let nrf52840_peripherals = static_init!( + Nrf52840DefaultPeripherals, + Nrf52840DefaultPeripherals::new(ieee802154_ack_buf) + ); + + // set up circular peripheral dependencies + nrf52840_peripherals.init(); + let base_peripherals = &nrf52840_peripherals.nrf52; + + // Save a reference to the power module for resetting the board into the + // bootloader. + NRF52_POWER = Some(&base_peripherals.pwr_clk); + + let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES)); + + // Do nRF configuration and setup. This is shared code with other nRF-based + // platforms. + nrf52_components::startup::NrfStartupComponent::new( + false, + BUTTON_RST_PIN, + nrf52840::uicr::Regulator0Output::DEFAULT, + &base_peripherals.nvmc, + ) + .finalize(()); + + //-------------------------------------------------------------------------- + // CAPABILITIES + //-------------------------------------------------------------------------- + + // Create capabilities that the board needs to call certain protected kernel + // functions. + let process_management_capability = + create_capability!(capabilities::ProcessManagementCapability); + let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability); + + //-------------------------------------------------------------------------- + // DEBUG GPIO + //-------------------------------------------------------------------------- + + // Configure kernel debug GPIOs as early as possible. These are used by the + // `debug_gpio!(0, toggle)` macro. We configure these early so that the + // macro is available during most of the setup code and kernel execution. + kernel::debug::assign_gpios(Some(&nrf52840_peripherals.gpio_port[LED_PIN]), None, None); + + //-------------------------------------------------------------------------- + // GPIO + //-------------------------------------------------------------------------- + + let gpio = components::gpio::GpioComponent::new( + board_kernel, + capsules_core::gpio::DRIVER_NUM, + components::gpio_component_helper!( + nrf52840::gpio::GPIOPin, + 0 => &nrf52840_peripherals.gpio_port[GPIO_D0], + 1 => &nrf52840_peripherals.gpio_port[GPIO_D1], + 2 => &nrf52840_peripherals.gpio_port[GPIO_D2], + 3 => &nrf52840_peripherals.gpio_port[GPIO_D3], + ), + ) + .finalize(components::gpio_component_static!(nrf52840::gpio::GPIOPin)); + + //-------------------------------------------------------------------------- + // LEDs + //-------------------------------------------------------------------------- + + let led = components::led::LedsComponent::new().finalize(components::led_component_static!( + LedLow<'static, nrf52840::gpio::GPIOPin>, + LedLow::new(&nrf52840_peripherals.gpio_port[LED_PIN]), + )); + + //-------------------------------------------------------------------------- + // BUTTONS + //-------------------------------------------------------------------------- + + let button = components::button::ButtonComponent::new( + board_kernel, + capsules_core::button::DRIVER_NUM, + components::button_component_helper!( + nrf52840::gpio::GPIOPin, + ( + &nrf52840_peripherals.gpio_port[BUTTON_PIN], + kernel::hil::gpio::ActivationMode::ActiveLow, + kernel::hil::gpio::FloatingState::PullUp + ) + ), + ) + .finalize(components::button_component_static!( + nrf52840::gpio::GPIOPin + )); + + //-------------------------------------------------------------------------- + // ALARM & TIMER + //-------------------------------------------------------------------------- + + let rtc = &base_peripherals.rtc; + let _ = rtc.start(); + + let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc) + .finalize(components::alarm_mux_component_static!(nrf52::rtc::Rtc)); + let alarm = components::alarm::AlarmDriverComponent::new( + board_kernel, + capsules_core::alarm::DRIVER_NUM, + mux_alarm, + ) + .finalize(components::alarm_component_static!(nrf52::rtc::Rtc)); + + //-------------------------------------------------------------------------- + // UART & CONSOLE & DEBUG + //-------------------------------------------------------------------------- + + // Setup the CDC-ACM over USB driver that we will use for UART. + // We use the Arduino Vendor ID and Product ID since the device is the same. + + // Create the strings we include in the USB descriptor. We use the hardcoded + // DEVICEADDR register on the nRF52 to set the serial number. + let serial_number_buf = static_init!([u8; 17], [0; 17]); + let serial_number_string: &'static str = + nrf52::ficr::FICR_INSTANCE.address_str(serial_number_buf); + let strings = static_init!( + [&str; 3], + [ + "MakePython", // Manufacturer + "NRF52840 - TockOS", // Product + serial_number_string, // Serial number + ] + ); + + let cdc = components::cdc::CdcAcmComponent::new( + &nrf52840_peripherals.usbd, + capsules_extra::usb::cdc::MAX_CTRL_PACKET_SIZE_NRF52840, + 0x2341, + 0x005a, + strings, + mux_alarm, + Some(&baud_rate_reset_bootloader_enter), + ) + .finalize(components::cdc_acm_component_static!( + nrf52::usbd::Usbd, + nrf52::rtc::Rtc + )); + CDC_REF_FOR_PANIC = Some(cdc); //for use by panic handler + + // Process Printer for displaying process information. + let process_printer = components::process_printer::ProcessPrinterTextComponent::new() + .finalize(components::process_printer_text_component_static!()); + PROCESS_PRINTER = Some(process_printer); + + // Create a shared UART channel for the console and for kernel debug. + let uart_mux = components::console::UartMuxComponent::new(cdc, 115200) + .finalize(components::uart_mux_component_static!()); + + let pconsole = components::process_console::ProcessConsoleComponent::new( + board_kernel, + uart_mux, + mux_alarm, + process_printer, + Some(cortexm4::support::reset), + ) + .finalize(components::process_console_component_static!( + nrf52::rtc::Rtc<'static> + )); + + // Setup the console. + let console = components::console::ConsoleComponent::new( + board_kernel, + capsules_core::console::DRIVER_NUM, + uart_mux, + ) + .finalize(components::console_component_static!()); + // Create the debugger object that handles calls to `debug!()`. + components::debug_writer::DebugWriterComponent::new(uart_mux) + .finalize(components::debug_writer_component_static!()); + + //-------------------------------------------------------------------------- + // RANDOM NUMBERS + //-------------------------------------------------------------------------- + + let rng = components::rng::RngComponent::new( + board_kernel, + capsules_core::rng::DRIVER_NUM, + &base_peripherals.trng, + ) + .finalize(components::rng_component_static!()); + + //-------------------------------------------------------------------------- + // ADC + //-------------------------------------------------------------------------- + base_peripherals.adc.calibrate(); + + let adc_mux = components::adc::AdcMuxComponent::new(&base_peripherals.adc) + .finalize(components::adc_mux_component_static!(nrf52840::adc::Adc)); + + let adc_syscall = + components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM) + .finalize(components::adc_syscall_component_helper!( + // A0 + components::adc::AdcComponent::new( + adc_mux, + nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput2) + ) + .finalize(components::adc_component_static!(nrf52840::adc::Adc)), + // A1 + components::adc::AdcComponent::new( + adc_mux, + nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput3) + ) + .finalize(components::adc_component_static!(nrf52840::adc::Adc)), + // A2 + components::adc::AdcComponent::new( + adc_mux, + nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput6) + ) + .finalize(components::adc_component_static!(nrf52840::adc::Adc)), + // A3 + components::adc::AdcComponent::new( + adc_mux, + nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput5) + ) + .finalize(components::adc_component_static!(nrf52840::adc::Adc)), + // A4 + components::adc::AdcComponent::new( + adc_mux, + nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput7) + ) + .finalize(components::adc_component_static!(nrf52840::adc::Adc)), + // A5 + components::adc::AdcComponent::new( + adc_mux, + nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput0) + ) + .finalize(components::adc_component_static!(nrf52840::adc::Adc)), + // A6 + components::adc::AdcComponent::new( + adc_mux, + nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput4) + ) + .finalize(components::adc_component_static!(nrf52840::adc::Adc)), + // A7 + components::adc::AdcComponent::new( + adc_mux, + nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput1) + ) + .finalize(components::adc_component_static!(nrf52840::adc::Adc)), + )); + + //-------------------------------------------------------------------------- + // SCREEN + //-------------------------------------------------------------------------- + + let i2c_bus = components::i2c::I2CMuxComponent::new(&base_peripherals.twi0, None) + .finalize(components::i2c_mux_component_static!(nrf52840::i2c::TWI)); + base_peripherals.twi0.configure( + nrf52840::pinmux::Pinmux::new(I2C_SCL_PIN as u32), + nrf52840::pinmux::Pinmux::new(I2C_SDA_PIN as u32), + ); + + // I2C address is b011110X, and on this board D/CÌ… is GND. + let ssd1306_i2c = components::i2c::I2CComponent::new(i2c_bus, 0x3c) + .finalize(components::i2c_component_static!(nrf52840::i2c::TWI)); + + // Create the ssd1306 object for the actual screen driver. + let ssd1306 = components::ssd1306::Ssd1306Component::new(ssd1306_i2c, true) + .finalize(components::ssd1306_component_static!(nrf52840::i2c::TWI)); + + // Create a Driver for userspace access to the screen. + // let screen = components::screen::ScreenComponent::new( + // board_kernel, + // capsules_extra::screen::DRIVER_NUM, + // ssd1306, + // Some(ssd1306), + // ) + // .finalize(components::screen_component_static!(1032)); + + let apps_regions = static_init!( + [capsules_extra::screen_shared::AppScreenRegion; 3], + [ + capsules_extra::screen_shared::AppScreenRegion::new( + kernel::process::ShortID::Fixed(core::num::NonZeroU32::new(crc("circle")).unwrap()), + 0, // x + 0, // y + 8 * 8, // width + 8 * 8 // height + ), + capsules_extra::screen_shared::AppScreenRegion::new( + kernel::process::ShortID::Fixed(core::num::NonZeroU32::new(crc("count")).unwrap()), + 8 * 8, // x + 0, // y + 8 * 8, // width + 4 * 8 // height + ), + capsules_extra::screen_shared::AppScreenRegion::new( + kernel::process::ShortID::Fixed( + core::num::NonZeroU32::new(crc("tock-scroll")).unwrap() + ), + 8 * 8, // x + 4 * 8, // y + 8 * 8, // width + 4 * 8 // height + ) + ] + ); + + let screen = components::screen::ScreenSharedComponent::new( + board_kernel, + capsules_extra::screen::DRIVER_NUM, + ssd1306, + apps_regions, + ) + .finalize(components::screen_shared_component_static!(1032, Screen)); + + //-------------------------------------------------------------------------- + // WIRELESS + //-------------------------------------------------------------------------- + + let ble_radio = components::ble::BLEComponent::new( + board_kernel, + capsules_extra::ble_advertising_driver::DRIVER_NUM, + &base_peripherals.ble_radio, + mux_alarm, + ) + .finalize(components::ble_component_static!( + nrf52840::rtc::Rtc, + nrf52840::ble_radio::Radio + )); + + use capsules_extra::net::ieee802154::MacAddress; + + let aes_mux = components::ieee802154::MuxAes128ccmComponent::new(&base_peripherals.ecb) + .finalize(components::mux_aes128ccm_component_static!( + nrf52840::aes::AesECB + )); + + let device_id = nrf52840::ficr::FICR_INSTANCE.id(); + let device_id_bottom_16 = u16::from_le_bytes([device_id[0], device_id[1]]); + let (ieee802154_radio, mux_mac) = components::ieee802154::Ieee802154Component::new( + board_kernel, + capsules_extra::ieee802154::DRIVER_NUM, + &nrf52840_peripherals.ieee802154_radio, + aes_mux, + PAN_ID, + device_id_bottom_16, + device_id, + ) + .finalize(components::ieee802154_component_static!( + nrf52840::ieee802154_radio::Radio, + nrf52840::aes::AesECB<'static> + )); + use capsules_extra::net::ipv6::ip_utils::IPAddr; + + let local_ip_ifaces = static_init!( + [IPAddr; 3], + [ + IPAddr([ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, + ]), + IPAddr([ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, + ]), + IPAddr::generate_from_mac(capsules_extra::net::ieee802154::MacAddress::Short( + device_id_bottom_16 + )), + ] + ); + + let (udp_send_mux, udp_recv_mux, udp_port_table) = components::udp_mux::UDPMuxComponent::new( + mux_mac, + DEFAULT_CTX_PREFIX_LEN, + DEFAULT_CTX_PREFIX, + DST_MAC_ADDR, + MacAddress::Short(device_id_bottom_16), + local_ip_ifaces, + mux_alarm, + ) + .finalize(components::udp_mux_component_static!( + nrf52840::rtc::Rtc, + Ieee802154MacDevice + )); + + // UDP driver initialization happens here + let udp_driver = components::udp_driver::UDPDriverComponent::new( + board_kernel, + capsules_extra::net::udp::DRIVER_NUM, + udp_send_mux, + udp_recv_mux, + udp_port_table, + local_ip_ifaces, + ) + .finalize(components::udp_driver_component_static!(nrf52840::rtc::Rtc)); + + //-------------------------------------------------------------------------- + // APP ID CHECKING + //-------------------------------------------------------------------------- + + let checker = static_init!( + kernel::process_checker::basic::AppCheckerNames u32>, + kernel::process_checker::basic::AppCheckerNames::new(&(crc as fn(&'static str) -> u32)) + ); + kernel::deferred_call::DeferredCallClient::register(checker); + + //-------------------------------------------------------------------------- + // FINAL SETUP AND BOARD BOOT + //-------------------------------------------------------------------------- + + // Start all of the clocks. Low power operation will require a better + // approach than this. + nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(()); + + let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES) + .finalize(components::round_robin_component_static!(NUM_PROCS)); + + let platform = Platform { + ble_radio, + ieee802154_radio, + console, + pconsole, + adc: adc_syscall, + led, + button, + gpio, + rng, + screen, + alarm, + udp_driver, + ipc: kernel::ipc::IPC::new( + board_kernel, + kernel::ipc::DRIVER_NUM, + &memory_allocation_capability, + ), + scheduler, + checker, + systick: cortexm4::systick::SysTick::new_with_calibration(64000000), + }; + + let chip = static_init!( + nrf52840::chip::NRF52, + nrf52840::chip::NRF52::new(nrf52840_peripherals) + ); + CHIP = Some(chip); + + // Configure the USB stack to enable a serial port over CDC-ACM. + cdc.enable(); + cdc.attach(); + + //-------------------------------------------------------------------------- + // TESTS + //-------------------------------------------------------------------------- + // test::linear_log_test::run( + // mux_alarm, + // &nrf52840_peripherals.nrf52.nvmc, + // ); + // test::log_test::run( + // mux_alarm, + // &nrf52840_peripherals.nrf52.nvmc, + // ); + + debug!("Initialization complete. Entering main loop."); + let _ = platform.pconsole.start(); + + ssd1306.init_screen(); + + //-------------------------------------------------------------------------- + // PROCESSES AND MAIN LOOP + //-------------------------------------------------------------------------- + + // These symbols are defined in the linker script. + extern "C" { + /// Beginning of the ROM region containing app images. + static _sapps: u8; + /// End of the ROM region containing app images. + static _eapps: u8; + /// Beginning of the RAM region for app memory. + static mut _sappmem: u8; + /// End of the RAM region for app memory. + static _eappmem: u8; + } + + kernel::process::load_and_check_processes( + board_kernel, + &platform, + chip, + core::slice::from_raw_parts( + &_sapps as *const u8, + &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + ), + core::slice::from_raw_parts_mut( + &mut _sappmem as *mut u8, + &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + ), + &mut PROCESSES, + &FAULT_RESPONSE, + &process_management_capability, + ) + .unwrap_or_else(|err| { + debug!("Error loading processes!"); + debug!("{:?}", err); + }); + + (board_kernel, platform, chip) +} + +/// Main function called after RAM initialized. +#[no_mangle] +pub unsafe fn main() { + let main_loop_capability = create_capability!(capabilities::MainLoopCapability); + + let (board_kernel, platform, chip) = start(); + board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability); +} diff --git a/boards/microbit_v2/src/io.rs b/boards/microbit_v2/src/io.rs index 5151943f98..170e9c6aea 100644 --- a/boards/microbit_v2/src/io.rs +++ b/boards/microbit_v2/src/io.rs @@ -5,7 +5,6 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/microbit_v2/src/main.rs b/boards/microbit_v2/src/main.rs index ea2c60cc01..85a3970026 100644 --- a/boards/microbit_v2/src/main.rs +++ b/boards/microbit_v2/src/main.rs @@ -763,12 +763,12 @@ unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/msp_exp432p401r/src/main.rs b/boards/msp_exp432p401r/src/main.rs index 90d8b87707..8d724debaa 100644 --- a/boards/msp_exp432p401r/src/main.rs +++ b/boards/msp_exp432p401r/src/main.rs @@ -452,12 +452,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/nano33ble/src/io.rs b/boards/nano33ble/src/io.rs index a3d6b46ba8..56f11c700a 100644 --- a/boards/nano33ble/src/io.rs +++ b/boards/nano33ble/src/io.rs @@ -5,7 +5,6 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/nano33ble/src/main.rs b/boards/nano33ble/src/main.rs index ffad0d5a80..c301cbf784 100644 --- a/boards/nano33ble/src/main.rs +++ b/boards/nano33ble/src/main.rs @@ -119,6 +119,14 @@ type HTS221Sensor = components::hts221::Hts221ComponentType< >; type TemperatureDriver = components::temperature::TemperatureComponentType; type HumidityDriver = components::humidity::HumidityComponentType; +type Ieee802154MacDevice = components::ieee802154::Ieee802154ComponentMacDeviceType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; +type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; /// Supported drivers by the platform pub struct Platform { @@ -130,7 +138,7 @@ pub struct Platform { nrf52::rtc::Rtc<'static>, >, >, - ieee802154_radio: &'static capsules_extra::ieee802154::RadioDriver<'static>, + ieee802154_radio: &'static Ieee802154Driver, console: &'static capsules_core::console::Console<'static>, pconsole: &'static capsules_core::process_console::ProcessConsole< 'static, @@ -577,7 +585,10 @@ pub unsafe fn start() -> ( local_ip_ifaces, mux_alarm, ) - .finalize(components::udp_mux_component_static!(nrf52840::rtc::Rtc)); + .finalize(components::udp_mux_component_static!( + nrf52840::rtc::Rtc, + Ieee802154MacDevice + )); // UDP driver initialization happens here let udp_driver = components::udp_driver::UDPDriverComponent::new( @@ -672,12 +683,12 @@ pub unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/nano_rp2040_connect/src/main.rs b/boards/nano_rp2040_connect/src/main.rs index 4cc18973c7..573b58ce4e 100644 --- a/boards/nano_rp2040_connect/src/main.rs +++ b/boards/nano_rp2040_connect/src/main.rs @@ -12,8 +12,6 @@ #![cfg_attr(not(doc), no_main)] #![deny(missing_docs)] -use core::arch::global_asm; - use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm; use components::gpio::GpioComponent; use components::led::LedsComponent; @@ -166,7 +164,8 @@ extern "C" { fn jump_to_bootloader(); } -global_asm!( +#[cfg(all(target_arch = "arm", target_os = "none"))] +core::arch::global_asm!( " .section .jump_to_bootloader, \"ax\" .global jump_to_bootloader @@ -598,12 +597,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/nordic/nrf52840_dongle/src/io.rs b/boards/nordic/nrf52840_dongle/src/io.rs index 1fcb26e92d..55aed6e2f6 100644 --- a/boards/nordic/nrf52840_dongle/src/io.rs +++ b/boards/nordic/nrf52840_dongle/src/io.rs @@ -4,7 +4,6 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/nordic/nrf52840_dongle/src/main.rs b/boards/nordic/nrf52840_dongle/src/main.rs index 4cd683d7ec..609f3131b2 100644 --- a/boards/nordic/nrf52840_dongle/src/main.rs +++ b/boards/nordic/nrf52840_dongle/src/main.rs @@ -26,7 +26,7 @@ use kernel::scheduler::round_robin::RoundRobinSched; use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init}; use nrf52840::gpio::Pin; use nrf52840::interrupt_service::Nrf52840DefaultPeripherals; -use nrf52_components::{self, UartChannel, UartPins}; +use nrf52_components::{UartChannel, UartPins}; // The nRF52840 Dongle LEDs const LED1_PIN: Pin = Pin::P0_06; @@ -80,6 +80,11 @@ pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000]; type TemperatureDriver = components::temperature::TemperatureComponentType>; +type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; + /// Supported drivers by the platform pub struct Platform { ble_radio: &'static capsules_extra::ble_advertising_driver::BLE< @@ -87,7 +92,7 @@ pub struct Platform { nrf52840::ble_radio::Radio<'static>, VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>, >, - ieee802154_radio: &'static capsules_extra::ieee802154::RadioDriver<'static>, + ieee802154_radio: &'static Ieee802154Driver, button: &'static capsules_core::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>, pconsole: &'static capsules_core::process_console::ProcessConsole< 'static, @@ -456,12 +461,12 @@ pub unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/nordic/nrf52840dk/src/io.rs b/boards/nordic/nrf52840dk/src/io.rs index d13eaf4bca..2645e61a52 100644 --- a/boards/nordic/nrf52840dk/src/io.rs +++ b/boards/nordic/nrf52840dk/src/io.rs @@ -4,7 +4,6 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/nordic/nrf52840dk/src/main.rs b/boards/nordic/nrf52840dk/src/main.rs index 644bafd55d..787ae15076 100644 --- a/boards/nordic/nrf52840dk/src/main.rs +++ b/boards/nordic/nrf52840dk/src/main.rs @@ -87,7 +87,7 @@ use kernel::scheduler::round_robin::RoundRobinSched; use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init}; use nrf52840::gpio::Pin; use nrf52840::interrupt_service::Nrf52840DefaultPeripherals; -use nrf52_components::{self, UartChannel, UartPins}; +use nrf52_components::{UartChannel, UartPins}; #[allow(dead_code)] mod test; @@ -185,6 +185,15 @@ type KVDriver = components::kv::KVDriverComponentType; type TemperatureDriver = components::temperature::TemperatureComponentType>; +type Ieee802154MacDevice = components::ieee802154::Ieee802154ComponentMacDeviceType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; +type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; + /// Supported drivers by the platform pub struct Platform { ble_radio: &'static capsules_extra::ble_advertising_driver::BLE< @@ -192,7 +201,7 @@ pub struct Platform { nrf52840::ble_radio::Radio<'static>, VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>, >, - ieee802154_radio: &'static capsules_extra::ieee802154::RadioDriver<'static>, + ieee802154_radio: &'static Ieee802154Driver, button: &'static capsules_core::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>, pconsole: &'static capsules_core::process_console::ProcessConsole< 'static, @@ -598,7 +607,10 @@ pub unsafe fn start() -> ( local_ip_ifaces, mux_alarm, ) - .finalize(components::udp_mux_component_static!(nrf52840::rtc::Rtc)); + .finalize(components::udp_mux_component_static!( + nrf52840::rtc::Rtc, + Ieee802154MacDevice + )); // UDP driver initialization happens here let udp_driver = components::udp_driver::UDPDriverComponent::new( @@ -942,12 +954,12 @@ pub unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/nordic/nrf52_components/src/startup.rs b/boards/nordic/nrf52_components/src/startup.rs index 2876602ce5..16f7dbc7f4 100644 --- a/boards/nordic/nrf52_components/src/startup.rs +++ b/boards/nordic/nrf52_components/src/startup.rs @@ -9,7 +9,6 @@ use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm}; use capsules_extra::segger_rtt::SeggerRtt; -use components; use core::mem::MaybeUninit; use kernel::component::Component; use nrf52::gpio::Pin; diff --git a/boards/nordic/nrf52dk/src/io.rs b/boards/nordic/nrf52dk/src/io.rs index 2967322164..d8eb4950df 100644 --- a/boards/nordic/nrf52dk/src/io.rs +++ b/boards/nordic/nrf52dk/src/io.rs @@ -4,7 +4,6 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/nordic/nrf52dk/src/main.rs b/boards/nordic/nrf52dk/src/main.rs index ca7b9190c0..7791b577ce 100644 --- a/boards/nordic/nrf52dk/src/main.rs +++ b/boards/nordic/nrf52dk/src/main.rs @@ -82,7 +82,7 @@ use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, use nrf52832::gpio::Pin; use nrf52832::interrupt_service::Nrf52832DefaultPeripherals; use nrf52832::rtc::Rtc; -use nrf52_components::{self, UartChannel, UartPins}; +use nrf52_components::{UartChannel, UartPins}; // The nRF52 DK LEDs (see back of board) const LED1_PIN: Pin = Pin::P0_17; @@ -483,12 +483,12 @@ pub unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/nucleo_f429zi/src/io.rs b/boards/nucleo_f429zi/src/io.rs index 497419ccb8..c43cb5aeeb 100644 --- a/boards/nucleo_f429zi/src/io.rs +++ b/boards/nucleo_f429zi/src/io.rs @@ -5,15 +5,12 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; - use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; use kernel::hil::uart; use kernel::hil::uart::Configure; -use stm32f429zi; use stm32f429zi::gpio::PinId; use crate::CHIP; diff --git a/boards/nucleo_f429zi/src/main.rs b/boards/nucleo_f429zi/src/main.rs index af7d0023fd..299983c010 100644 --- a/boards/nucleo_f429zi/src/main.rs +++ b/boards/nucleo_f429zi/src/main.rs @@ -306,17 +306,17 @@ unsafe fn setup_peripherals( rtc.enable_clock(); } -/// Statically initialize the core peripherals for the chip. -/// /// This is in a separate, inline(never) function so that its stack frame is /// removed when this function returns. Otherwise, the stack space used for /// these static_inits is wasted. #[inline(never)] -unsafe fn create_peripherals() -> ( - &'static mut Stm32f429ziDefaultPeripherals<'static>, - &'static stm32f429zi::syscfg::Syscfg<'static>, - &'static stm32f429zi::dma::Dma1<'static>, +unsafe fn start() -> ( + &'static kernel::Kernel, + NucleoF429ZI, + &'static stm32f429zi::chip::Stm32f4xx<'static, Stm32f429ziDefaultPeripherals<'static>>, ) { + stm32f429zi::init(); + // We use the default HSI 16Mhz clock let rcc = static_init!(stm32f429zi::rcc::Rcc, stm32f429zi::rcc::Rcc::new()); @@ -335,17 +335,6 @@ unsafe fn create_peripherals() -> ( Stm32f429ziDefaultPeripherals, Stm32f429ziDefaultPeripherals::new(rcc, exti, dma1, dma2) ); - (peripherals, syscfg, dma1) -} - -/// Main function. -/// -/// This is called after RAM initialization is complete. -#[no_mangle] -pub unsafe fn main() { - stm32f429zi::init(); - - let (peripherals, syscfg, dma1) = create_peripherals(); peripherals.init(); let base_peripherals = &peripherals.stm32f4; @@ -384,7 +373,6 @@ pub unsafe fn main() { // Create capabilities that the board needs to call certain protected kernel // functions. let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability); - let main_loop_capability = create_capability!(capabilities::MainLoopCapability); let process_management_capability = create_capability!(capabilities::ProcessManagementCapability); @@ -697,12 +685,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, @@ -718,10 +706,14 @@ pub unsafe fn main() { .finalize(components::multi_alarm_test_component_buf!(stm32f429zi::tim2::Tim2)) .run();*/ - board_kernel.kernel_loop( - &nucleo_f429zi, - chip, - Some(&nucleo_f429zi.ipc), - &main_loop_capability, - ); + (board_kernel, nucleo_f429zi, chip) +} + +/// Main function called after RAM initialized. +#[no_mangle] +pub unsafe fn main() { + let main_loop_capability = create_capability!(capabilities::MainLoopCapability); + + let (board_kernel, platform, chip) = start(); + board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability); } diff --git a/boards/nucleo_f446re/src/io.rs b/boards/nucleo_f446re/src/io.rs index 4d604dea88..b5ddbe8b33 100644 --- a/boards/nucleo_f446re/src/io.rs +++ b/boards/nucleo_f446re/src/io.rs @@ -5,15 +5,12 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; - use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; use kernel::hil::uart; use kernel::hil::uart::Configure; -use stm32f446re; use stm32f446re::gpio::PinId; use crate::CHIP; diff --git a/boards/nucleo_f446re/src/main.rs b/boards/nucleo_f446re/src/main.rs index b8872b6011..2f636e8ea7 100644 --- a/boards/nucleo_f446re/src/main.rs +++ b/boards/nucleo_f446re/src/main.rs @@ -257,17 +257,17 @@ unsafe fn setup_peripherals(tim2: &stm32f446re::tim2::Tim2) { cortexm4::nvic::Nvic::new(stm32f446re::nvic::TIM2).enable(); } -/// Statically initialize the core peripherals for the chip. -/// /// This is in a separate, inline(never) function so that its stack frame is /// removed when this function returns. Otherwise, the stack space used for /// these static_inits is wasted. #[inline(never)] -unsafe fn create_peripherals() -> ( - &'static mut Stm32f446reDefaultPeripherals<'static>, - &'static stm32f446re::syscfg::Syscfg<'static>, - &'static stm32f446re::dma::Dma1<'static>, +unsafe fn start() -> ( + &'static kernel::Kernel, + NucleoF446RE, + &'static stm32f446re::chip::Stm32f4xx<'static, Stm32f446reDefaultPeripherals<'static>>, ) { + stm32f446re::init(); + // We use the default HSI 16Mhz clock let rcc = static_init!(stm32f446re::rcc::Rcc, stm32f446re::rcc::Rcc::new()); let syscfg = static_init!( @@ -285,17 +285,6 @@ unsafe fn create_peripherals() -> ( Stm32f446reDefaultPeripherals, Stm32f446reDefaultPeripherals::new(rcc, exti, dma1, dma2) ); - (peripherals, syscfg, dma1) -} - -/// Main function. -/// -/// This is called after RAM initialization is complete. -#[no_mangle] -pub unsafe fn main() { - stm32f446re::init(); - - let (peripherals, syscfg, dma1) = create_peripherals(); peripherals.init(); let base_peripherals = &peripherals.stm32f4; @@ -331,7 +320,6 @@ pub unsafe fn main() { // Create capabilities that the board needs to call certain protected kernel // functions. let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability); - let main_loop_capability = create_capability!(capabilities::MainLoopCapability); let process_management_capability = create_capability!(capabilities::ProcessManagementCapability); @@ -539,12 +527,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, @@ -559,10 +547,15 @@ pub unsafe fn main() { /*components::test::multi_alarm_test::MultiAlarmTestComponent::new(mux_alarm) .finalize(components::multi_alarm_test_component_buf!(stm32f446re::tim2::Tim2)) .run();*/ - board_kernel.kernel_loop( - &nucleo_f446re, - chip, - Some(&nucleo_f446re.ipc), - &main_loop_capability, - ); + + (board_kernel, nucleo_f446re, chip) +} + +/// Main function called after RAM initialized. +#[no_mangle] +pub unsafe fn main() { + let main_loop_capability = create_capability!(capabilities::MainLoopCapability); + + let (board_kernel, platform, chip) = start(); + board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability); } diff --git a/boards/opentitan/src/main.rs b/boards/opentitan/src/main.rs index 1d8d1e63f7..776c053a39 100644 --- a/boards/opentitan/src/main.rs +++ b/boards/opentitan/src/main.rs @@ -335,15 +335,15 @@ unsafe fn setup() -> ( let earlgrey_epmp = earlgrey::epmp::EarlGreyEPMP::new_debug( earlgrey::epmp::FlashRegion( rv32i::pmp::NAPOTRegionSpec::new( - &_sflash as *const u8, // start - &_eflash as *const u8 as usize - &_sflash as *const u8 as usize, // size + core::ptr::addr_of!(_sflash), + core::ptr::addr_of!(_eflash) as usize - core::ptr::addr_of!(_sflash) as usize, ) .unwrap(), ), earlgrey::epmp::RAMRegion( rv32i::pmp::NAPOTRegionSpec::new( - &_ssram as *const u8, // start - &_esram as *const u8 as usize - &_ssram as *const u8 as usize, // size + core::ptr::addr_of!(_ssram), + core::ptr::addr_of!(_esram) as usize - core::ptr::addr_of!(_ssram) as usize, ) .unwrap(), ), @@ -356,8 +356,8 @@ unsafe fn setup() -> ( ), earlgrey::epmp::KernelTextRegion( rv32i::pmp::TORRegionSpec::new( - &_stext as *const u8, // start - &_etext as *const u8, // end + core::ptr::addr_of!(_stext), + core::ptr::addr_of!(_etext), ) .unwrap(), ), @@ -589,8 +589,8 @@ unsafe fn setup() -> ( // Allocate a flash protection region (associated cfg number: 0), for the code section. if let Err(e) = peripherals.flash_ctrl.mp_set_region_perms( - &_manifest as *const u8 as usize, - &_etext as *const u8 as usize, + core::ptr::addr_of!(_manifest) as usize, + core::ptr::addr_of!(_etext) as usize, 0, &mp_cfg, ) { @@ -739,8 +739,8 @@ unsafe fn setup() -> ( crate::otbn::find_app( "otbn-rsa", core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), ) { @@ -859,12 +859,12 @@ unsafe fn setup() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/opentitan/src/tests/otbn.rs b/boards/opentitan/src/tests/otbn.rs index 63305e0eeb..380fb266b7 100644 --- a/boards/opentitan/src/tests/otbn.rs +++ b/boards/opentitan/src/tests/otbn.rs @@ -109,8 +109,8 @@ fn otbn_run_rsa_binary() { crate::otbn::find_app( "otbn-rsa", core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), ) } { diff --git a/boards/particle_boron/src/io.rs b/boards/particle_boron/src/io.rs index 6963564a09..3e8127d968 100644 --- a/boards/particle_boron/src/io.rs +++ b/boards/particle_boron/src/io.rs @@ -4,7 +4,6 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/particle_boron/src/main.rs b/boards/particle_boron/src/main.rs index 8485e93d9d..5ec3caf873 100644 --- a/boards/particle_boron/src/main.rs +++ b/boards/particle_boron/src/main.rs @@ -91,6 +91,11 @@ pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000]; type TemperatureDriver = components::temperature::TemperatureComponentType>; +type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; + /// Supported drivers by the platform pub struct Platform { ble_radio: &'static capsules_extra::ble_advertising_driver::BLE< @@ -98,7 +103,7 @@ pub struct Platform { nrf52840::ble_radio::Radio<'static>, VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>, >, - ieee802154_radio: &'static capsules_extra::ieee802154::RadioDriver<'static>, + ieee802154_radio: &'static Ieee802154Driver, button: &'static capsules_core::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>, console: &'static capsules_core::console::Console<'static>, gpio: &'static capsules_core::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>, @@ -599,12 +604,12 @@ pub unsafe fn start_particle_boron() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/pico_explorer_base/src/main.rs b/boards/pico_explorer_base/src/main.rs index b0fe1d1d2c..319856bc06 100644 --- a/boards/pico_explorer_base/src/main.rs +++ b/boards/pico_explorer_base/src/main.rs @@ -12,8 +12,6 @@ #![cfg_attr(not(doc), no_main)] #![deny(missing_docs)] -use core::arch::global_asm; - use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm; use components::gpio::GpioComponent; use components::led::LedsComponent; @@ -176,7 +174,8 @@ extern "C" { fn jump_to_bootloader(); } -global_asm!( +#[cfg(all(target_arch = "arm", target_os = "none"))] +core::arch::global_asm!( " .section .jump_to_bootloader, \"ax\" .global jump_to_bootloader @@ -682,12 +681,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/qemu_rv32_virt/src/main.rs b/boards/qemu_rv32_virt/src/main.rs index befda9db61..cf67134f8e 100644 --- a/boards/qemu_rv32_virt/src/main.rs +++ b/boards/qemu_rv32_virt/src/main.rs @@ -183,15 +183,15 @@ pub unsafe fn main() { let epmp = rv32i::pmp::kernel_protection_mml_epmp::KernelProtectionMMLEPMP::new( rv32i::pmp::kernel_protection_mml_epmp::FlashRegion( rv32i::pmp::NAPOTRegionSpec::new( - &_sflash as *const u8, // start - &_eflash as *const u8 as usize - &_sflash as *const u8 as usize, // size + core::ptr::addr_of!(_sflash), + core::ptr::addr_of!(_eflash) as usize - core::ptr::addr_of!(_sflash) as usize, ) .unwrap(), ), rv32i::pmp::kernel_protection_mml_epmp::RAMRegion( rv32i::pmp::NAPOTRegionSpec::new( - &_ssram as *const u8, // start - &_esram as *const u8 as usize - &_ssram as *const u8 as usize, // size + core::ptr::addr_of!(_ssram), + core::ptr::addr_of!(_esram) as usize - core::ptr::addr_of!(_ssram) as usize, ) .unwrap(), ), @@ -204,8 +204,8 @@ pub unsafe fn main() { ), rv32i::pmp::kernel_protection_mml_epmp::KernelTextRegion( rv32i::pmp::TORRegionSpec::new( - &_stext as *const u8, // start - &_etext as *const u8, // end + core::ptr::addr_of!(_stext), + core::ptr::addr_of!(_etext), ) .unwrap(), ), @@ -533,12 +533,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/raspberry_pi_pico/src/main.rs b/boards/raspberry_pi_pico/src/main.rs index 4929052e12..f80c6b4adc 100644 --- a/boards/raspberry_pi_pico/src/main.rs +++ b/boards/raspberry_pi_pico/src/main.rs @@ -12,8 +12,6 @@ #![cfg_attr(not(doc), no_main)] #![deny(missing_docs)] -use core::arch::global_asm; - use capsules_core::i2c_master::I2CMasterDriver; use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm; use components::date_time_component_static; @@ -167,7 +165,8 @@ extern "C" { fn jump_to_bootloader(); } -global_asm!( +#[cfg(all(target_arch = "arm", target_os = "none"))] +core::arch::global_asm!( " .section .jump_to_bootloader, \"ax\" .global jump_to_bootloader @@ -591,12 +590,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/redboard_redv/src/io.rs b/boards/redboard_redv/src/io.rs index 6c0fd863a3..16be4d4088 100644 --- a/boards/redboard_redv/src/io.rs +++ b/boards/redboard_redv/src/io.rs @@ -5,12 +5,10 @@ use core::fmt::Write; use core::panic::PanicInfo; use core::str; -use e310_g002; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::gpio; use kernel::hil::led; -use rv32i; use crate::CHIP; use crate::PROCESSES; diff --git a/boards/redboard_redv/src/main.rs b/boards/redboard_redv/src/main.rs index b55508fb43..baa1c9d5f4 100644 --- a/boards/redboard_redv/src/main.rs +++ b/boards/redboard_redv/src/main.rs @@ -311,12 +311,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/sma_q3/src/io.rs b/boards/sma_q3/src/io.rs index f9f5cbb1b0..59f71c771d 100644 --- a/boards/sma_q3/src/io.rs +++ b/boards/sma_q3/src/io.rs @@ -4,7 +4,6 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/sma_q3/src/main.rs b/boards/sma_q3/src/main.rs index b050d7177e..c7d2787358 100644 --- a/boards/sma_q3/src/main.rs +++ b/boards/sma_q3/src/main.rs @@ -79,6 +79,11 @@ type Bmp280Sensor = components::bmp280::Bmp280ComponentType< >; type TemperatureDriver = components::temperature::TemperatureComponentType; +type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType< + nrf52840::ieee802154_radio::Radio<'static>, + nrf52840::aes::AesECB<'static>, +>; + /// Supported drivers by the platform pub struct Platform { temperature: &'static TemperatureDriver, @@ -87,7 +92,7 @@ pub struct Platform { nrf52840::ble_radio::Radio<'static>, VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>, >, - ieee802154_radio: &'static capsules_extra::ieee802154::RadioDriver<'static>, + ieee802154_radio: &'static Ieee802154Driver, button: &'static capsules_core::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>, pconsole: &'static capsules_core::process_console::ProcessConsole< 'static, @@ -474,12 +479,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/stm32f3discovery/src/io.rs b/boards/stm32f3discovery/src/io.rs index b509fb994e..cd15ba94e5 100644 --- a/boards/stm32f3discovery/src/io.rs +++ b/boards/stm32f3discovery/src/io.rs @@ -11,7 +11,6 @@ use kernel::hil::led; use kernel::hil::uart; use kernel::hil::uart::Configure; -use stm32f303xc; use stm32f303xc::gpio::PinId; use crate::CHIP; diff --git a/boards/stm32f3discovery/src/main.rs b/boards/stm32f3discovery/src/main.rs index a854ef9770..2c10ec5876 100644 --- a/boards/stm32f3discovery/src/main.rs +++ b/boards/stm32f3discovery/src/main.rs @@ -770,8 +770,8 @@ pub unsafe fn main() { &peripherals.flash, 0x08038000, // Start address for userspace accesible region 0x8000, // Length of userspace accesible region (16 pages) - &_sstorage as *const u8 as usize, - &_estorage as *const u8 as usize - &_sstorage as *const u8 as usize, + core::ptr::addr_of!(_sstorage) as usize, + core::ptr::addr_of!(_estorage) as usize - core::ptr::addr_of!(_sstorage) as usize, ) .finalize(components::nonvolatile_storage_component_static!( stm32f303xc::flash::Flash @@ -843,12 +843,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/stm32f412gdiscovery/src/io.rs b/boards/stm32f412gdiscovery/src/io.rs index a6281733f6..fcd0ff2999 100644 --- a/boards/stm32f412gdiscovery/src/io.rs +++ b/boards/stm32f412gdiscovery/src/io.rs @@ -5,15 +5,12 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; - use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; use kernel::hil::uart; use kernel::hil::uart::Configure; -use stm32f412g; use stm32f412g::gpio::PinId; use crate::CHIP; diff --git a/boards/stm32f412gdiscovery/src/main.rs b/boards/stm32f412gdiscovery/src/main.rs index 5cd6ea0894..45bf52735b 100644 --- a/boards/stm32f412gdiscovery/src/main.rs +++ b/boards/stm32f412gdiscovery/src/main.rs @@ -806,12 +806,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/stm32f429idiscovery/src/io.rs b/boards/stm32f429idiscovery/src/io.rs index 61a7e7dd7b..6bbc94fad5 100644 --- a/boards/stm32f429idiscovery/src/io.rs +++ b/boards/stm32f429idiscovery/src/io.rs @@ -5,15 +5,12 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; - use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; use kernel::hil::uart; use kernel::hil::uart::Configure; -use stm32f429zi; use stm32f429zi::gpio::PinId; use crate::CHIP; diff --git a/boards/stm32f429idiscovery/src/main.rs b/boards/stm32f429idiscovery/src/main.rs index 3ba0ca96cb..559618ca69 100644 --- a/boards/stm32f429idiscovery/src/main.rs +++ b/boards/stm32f429idiscovery/src/main.rs @@ -621,12 +621,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/swervolf/src/main.rs b/boards/swervolf/src/main.rs index 1b18037bf7..3bc2d02098 100644 --- a/boards/swervolf/src/main.rs +++ b/boards/swervolf/src/main.rs @@ -233,12 +233,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/teensy40/src/main.rs b/boards/teensy40/src/main.rs index b4f3c2fe23..81b25a6857 100644 --- a/boards/teensy40/src/main.rs +++ b/boards/teensy40/src/main.rs @@ -348,12 +348,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/weact_f401ccu6/src/io.rs b/boards/weact_f401ccu6/src/io.rs index 6e4154c4e4..e65d7ef826 100644 --- a/boards/weact_f401ccu6/src/io.rs +++ b/boards/weact_f401ccu6/src/io.rs @@ -5,15 +5,12 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; - use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; use kernel::hil::uart; use kernel::hil::uart::Configure; -use stm32f401cc; use stm32f401cc::gpio::PinId; use crate::CHIP; diff --git a/boards/weact_f401ccu6/src/main.rs b/boards/weact_f401ccu6/src/main.rs index 432a16572e..e3b988f9a4 100644 --- a/boards/weact_f401ccu6/src/main.rs +++ b/boards/weact_f401ccu6/src/main.rs @@ -473,12 +473,12 @@ pub unsafe fn main() { board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/boards/wm1110dev/src/io.rs b/boards/wm1110dev/src/io.rs index 31bdc05a4c..20aba9e6e7 100644 --- a/boards/wm1110dev/src/io.rs +++ b/boards/wm1110dev/src/io.rs @@ -5,7 +5,6 @@ use core::fmt::Write; use core::panic::PanicInfo; -use cortexm4; use kernel::debug; use kernel::debug::IoWrite; use kernel::hil::led; diff --git a/boards/wm1110dev/src/main.rs b/boards/wm1110dev/src/main.rs index e4620652d5..52197400ea 100644 --- a/boards/wm1110dev/src/main.rs +++ b/boards/wm1110dev/src/main.rs @@ -493,12 +493,12 @@ pub unsafe fn start() -> ( board_kernel, chip, core::slice::from_raw_parts( - &_sapps as *const u8, - &_eapps as *const u8 as usize - &_sapps as *const u8 as usize, + core::ptr::addr_of!(_sapps), + core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize, ), core::slice::from_raw_parts_mut( - &mut _sappmem as *mut u8, - &_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize, + core::ptr::addr_of_mut!(_sappmem), + core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize, ), &mut PROCESSES, &FAULT_RESPONSE, diff --git a/capsules/core/src/adc.rs b/capsules/core/src/adc.rs index f96a17c36d..18b20350ed 100644 --- a/capsules/core/src/adc.rs +++ b/capsules/core/src/adc.rs @@ -54,7 +54,6 @@ use core::cell::Cell; use core::cmp; -use core::convert::TryFrom; use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; use kernel::hil; diff --git a/capsules/core/src/process_console.rs b/capsules/core/src/process_console.rs index dac03bf233..26b4a6ad7f 100644 --- a/capsules/core/src/process_console.rs +++ b/capsules/core/src/process_console.rs @@ -344,7 +344,6 @@ struct CommandHistory<'a, const COMMAND_HISTORY_LEN: usize> { cmds: &'a mut [Command; COMMAND_HISTORY_LEN], cmd_idx: usize, cmd_is_modified: bool, - modified_byte: u8, } impl<'a, const COMMAND_HISTORY_LEN: usize> CommandHistory<'a, COMMAND_HISTORY_LEN> { @@ -353,7 +352,6 @@ impl<'a, const COMMAND_HISTORY_LEN: usize> CommandHistory<'a, COMMAND_HISTORY_LE cmds: cmds_buffer, cmd_idx: 0, cmd_is_modified: false, - modified_byte: EOL, } } @@ -369,22 +367,6 @@ impl<'a, const COMMAND_HISTORY_LEN: usize> CommandHistory<'a, COMMAND_HISTORY_LE } } - /// Checks if the command line was modified - /// before pressing Up or Down keys - /// and saves the current modified command - /// into the history - fn change_cmd_from(&mut self, cmd: &[u8]) { - match self.modified_byte { - BS | DEL => { - self.cmds[0].clear(); - self.write_to_first(cmd); - } - _ => { - self.modified_byte = EOL; - } - } - } - fn write_to_first(&mut self, cmd: &[u8]) { let mut cmd_arr = [0; COMMAND_BUF_LEN]; cmd_arr.copy_from_slice(cmd); @@ -1227,8 +1209,6 @@ impl<'a, const COMMAND_HISTORY_LEN: usize, A: Alarm<'a>, C: ProcessManagementCap } else { ht.prev_cmd_idx() } { - ht.change_cmd_from(command); - let next_command_len = ht.cmds[next_index].len; for _ in cursor..index { @@ -1304,7 +1284,15 @@ impl<'a, const COMMAND_HISTORY_LEN: usize, A: Alarm<'a>, C: ProcessManagementCap // not to permit accumulation of the text if COMMAND_HISTORY_LEN > 1 { self.command_history.map(|ht| { - ht.cmds[0].delete_byte(cursor - 1); + if ht.cmd_is_modified { + // Copy the last command into the unfinished command + + ht.cmds[0].clear(); + ht.write_to_first(command); + ht.cmd_is_modified = false; + } else { + ht.cmds[0].delete_byte(cursor); + } }); } } @@ -1366,15 +1354,21 @@ impl<'a, const COMMAND_HISTORY_LEN: usize, A: Alarm<'a>, C: ProcessManagementCap // not to permit accumulation of the text if COMMAND_HISTORY_LEN > 1 { self.command_history.map(|ht| { - ht.cmds[0].delete_byte(cursor - 1); + if ht.cmd_is_modified { + // Copy the last command into the unfinished command + + ht.cmds[0].clear(); + ht.write_to_first(command); + ht.cmd_is_modified = false; + } else { + ht.cmds[0].delete_byte(cursor - 1); + } }); } } - } else if (COMMAND_HISTORY_LEN > 1) && (esc_state.has_started()) { - self.command_history - .map(|ht| ht.modified_byte = previous_byte); } else if index < (command.len() - 1) && read_buf[0] < ASCII_LIMIT + && !esc_state.has_started() && !esc_state.in_progress() { // For some reason, sometimes reads return > 127 but no error, diff --git a/capsules/extra/src/air_quality.rs b/capsules/extra/src/air_quality.rs index a36682691b..95391c6ebb 100644 --- a/capsules/extra/src/air_quality.rs +++ b/capsules/extra/src/air_quality.rs @@ -24,7 +24,6 @@ //! ``` use core::cell::Cell; -use core::convert::TryFrom; use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; use kernel::hil; use kernel::syscall::{CommandReturn, SyscallDriver}; diff --git a/capsules/extra/src/ieee802154/device.rs b/capsules/extra/src/ieee802154/device.rs index 03ec7dda50..b4cfc3557c 100644 --- a/capsules/extra/src/ieee802154/device.rs +++ b/capsules/extra/src/ieee802154/device.rs @@ -73,6 +73,25 @@ pub trait MacDevice<'a> { security_needed: Option<(SecurityLevel, KeyId)>, ) -> Result; + /// Creates an IEEE 802.15.4 Frame object that is compatible with the + /// MAC transmit and append payload methods. This serves to provide + /// functionality for sending packets fully formed by the userprocess + /// and that the 15.4 capsule does not modify. The len field may be less + /// than the length of the buffer as the len field is the length of + /// the current frame while the buffer is the maximum 15.4 frame size. + /// + /// - `buf`: The buffer to be used for the frame + /// - `len`: The length of the frame + /// + /// Returns a Result: + /// - on success a Frame object. + /// - on failure an error returning the buffer. + fn buf_to_frame( + &self, + buf: &'static mut [u8], + len: usize, + ) -> Result; + /// Transmits a frame that has been prepared by the above process. If the /// transmission process fails, the buffer inside the frame is returned so /// that it can be re-used. diff --git a/capsules/extra/src/ieee802154/driver.rs b/capsules/extra/src/ieee802154/driver.rs index 06e07efe6e..bc72a77645 100644 --- a/capsules/extra/src/ieee802154/driver.rs +++ b/capsules/extra/src/ieee802154/driver.rs @@ -177,14 +177,46 @@ impl KeyDescriptor { } } +/// Denotes the type of pending transmission. A `Parse(..)` PendingTX +/// indicates that the 15.4 framer will need to form the packet header +/// from the provided address and security level. A `Raw` PendingTX +/// is formed by the userprocess and passes through the Framer unchanged. +enum PendingTX { + Parse(u16, Option<(SecurityLevel, KeyId)>), + Raw, + Empty, +} + +impl Default for PendingTX { + /// The default PendingTX is `Empty` + fn default() -> Self { + PendingTX::Empty + } +} + +impl PendingTX { + /// Returns true if the PendingTX state is `Empty` + fn is_empty(&self) -> bool { + match self { + PendingTX::Empty => true, + _ => false, + } + } + + /// Take the pending transmission, replacing it with `Empty` and return the current PendingTx + fn take(&mut self) -> PendingTX { + core::mem::replace(self, PendingTX::Empty) + } +} + #[derive(Default)] pub struct App { - pending_tx: Option<(u16, Option<(SecurityLevel, KeyId)>)>, + pending_tx: PendingTX, } -pub struct RadioDriver<'a> { +pub struct RadioDriver<'a, M: device::MacDevice<'a>> { /// Underlying MAC device, possibly multiplexed - mac: &'a dyn device::MacDevice<'a>, + mac: &'a M, /// List of (short address, long address) pairs representing IEEE 802.15.4 /// neighbors. @@ -227,9 +259,9 @@ pub struct RadioDriver<'a> { backup_device_procedure: OptionalCell<&'a dyn framer::DeviceProcedure>, } -impl<'a> RadioDriver<'a> { +impl<'a, M: device::MacDevice<'a>> RadioDriver<'a, M> { pub fn new( - mac: &'a dyn device::MacDevice<'a>, + mac: &'a M, grant: Grant< App, UpcallCount<{ upcall::COUNT }>, @@ -383,7 +415,7 @@ impl<'a> RadioDriver<'a> { for app in self.apps.iter() { let processid = app.processid(); app.enter(|app, _| { - if app.pending_tx.is_some() { + if !app.pending_tx.is_empty() { pending_app = Some(processid); } }); @@ -413,56 +445,77 @@ impl<'a> RadioDriver<'a> { /// idle and the app has a pending transmission. #[inline] fn perform_tx_sync(&self, processid: ProcessId) -> Result<(), ErrorCode> { - self.apps.enter(processid, |app, kerel_data| { - let (dst_addr, security_needed) = match app.pending_tx.take() { - Some(pending_tx) => pending_tx, - None => { - return Ok(()); - } - }; - let result = self.kernel_tx.take().map_or(Err(ErrorCode::NOMEM), |kbuf| { - // Prepare the frame headers - let pan = self.mac.get_pan(); - let dst_addr = MacAddress::Short(dst_addr); - let src_addr = MacAddress::Short(self.mac.get_address()); - let mut frame = match self.mac.prepare_data_frame( - kbuf, - pan, - dst_addr, - pan, - src_addr, - security_needed, - ) { - Ok(frame) => frame, - Err(kbuf) => { - self.kernel_tx.replace(kbuf); - return Err(ErrorCode::FAIL); + self.apps.enter(processid, |app, kernel_data| { + // The use of this take method is somewhat overkill, but serves to ensure that + // this, or future, implementations do not forget to "remove" the pending_tx + // from the app after processing. + let curr_tx = app.pending_tx.take(); + + // Before beginning the transmission process, confirm that the PendingTX + // is not Empty. In the Empty case, there is nothing to transmit and we + // can return Ok(()) immediately as there is nothing to transmit. + if let PendingTX::Empty = curr_tx { return Ok(()) } + + // At a high level, we must form a Frame from the provided userproceess data, + // place this frame into a static buffer, and then transmit the frame. This is + // somewhat complicated by the need to error handle each of these steps and also + // provide Raw and Parse sending modes (i.e. Raw mode userprocess fully forms + // 15.4 packet and Parse mode the 15.4 framer forms the packet from the userprocess + // parameters and payload). Because we first take this kernel buffer, we must + // replace the `kernel_tx` buffer upon handling any error. + self.kernel_tx.take().map_or(Err(ErrorCode::NOMEM), |kbuf| { + match curr_tx { + PendingTX::Empty => { + unreachable!("PendingTX::Empty should have been handled earlier with guard statement.") + } + PendingTX::Raw => { + // Here we form an empty frame from the buffer to later be filled by the specified + // userprocess frame data. Note, we must allocate the needed buffer for the frame, + // but set the `len` field to 0 as the frame is empty. + self.mac.buf_to_frame(kbuf, 0).map_err(|(err, buf)| { + self.kernel_tx.replace(buf); + err + })}, + PendingTX::Parse(dst_addr, security_needed) => { + // Prepare the frame headers + let pan = self.mac.get_pan(); + let dst_addr = MacAddress::Short(dst_addr); + let src_addr = MacAddress::Short(self.mac.get_address()); + self.mac.prepare_data_frame( + kbuf, + pan, + dst_addr, + pan, + src_addr, + security_needed, + ).map_or_else(|err_buf| { + self.kernel_tx.replace(err_buf); + Err(ErrorCode::FAIL) + }, | frame| + Ok(frame) + ) } - }; - - // Append the payload: there must be one - let result = kerel_data - .get_readonly_processbuffer(ro_allow::WRITE) - .and_then(|write| write.enter(|payload| frame.append_payload_process(payload))) - .unwrap_or(Err(ErrorCode::INVAL)); - if result != Ok(()) { - return result; } + }).map(|mut frame| { - // Finally, transmit the frame - match self.mac.transmit(frame) { - Ok(()) => Ok(()), - Err((ecode, buf)) => { - self.kernel_tx.put(Some(buf)); - Err(ecode) - } + // Obtain the payload from the userprocess, append the "payload" to the previously formed frame + // and pass the frame to be transmitted. Note, the term "payload" is somewhat misleading in the + // case of Raw transmission as the payload is the entire 15.4 frame. + kernel_data + .get_readonly_processbuffer(ro_allow::WRITE) + .and_then(|write| write.enter(|payload| + frame.append_payload_process(payload) + ))?.map( |()| + { + self.mac.transmit(frame).map_or_else(|(errorcode, error_buf)| { + self.kernel_tx.replace(error_buf); + Err(errorcode) + }, |()| {self.current_app.set(processid); Ok(()) } + ) } - }); - if result == Ok(()) { - self.current_app.set(processid); - } - result + )? })? + })? } /// Schedule the next transmission if there is one pending. Performs the @@ -491,7 +544,7 @@ impl<'a> RadioDriver<'a> { } } -impl DeferredCallClient for RadioDriver<'static> { +impl<'a, M: device::MacDevice<'a>> DeferredCallClient for RadioDriver<'a, M> { fn handle_deferred_call(&self) { let _ = self .apps @@ -517,7 +570,7 @@ impl DeferredCallClient for RadioDriver<'static> { } } -impl framer::DeviceProcedure for RadioDriver<'_> { +impl<'a, M: device::MacDevice<'a>> framer::DeviceProcedure for RadioDriver<'a, M> { /// Gets the long address corresponding to the neighbor that matches the given /// MAC address. If no such neighbor exists, returns `None`. fn lookup_addr_long(&self, addr: MacAddress) -> Option<[u8; 8]> { @@ -544,7 +597,7 @@ impl framer::DeviceProcedure for RadioDriver<'_> { } } -impl framer::KeyProcedure for RadioDriver<'_> { +impl<'a, M: device::MacDevice<'a>> framer::KeyProcedure for RadioDriver<'a, M> { /// Gets the key corresponding to the key that matches the given security /// level `level` and key ID `key_id`. If no such key matches, returns /// `None`. @@ -573,7 +626,7 @@ impl framer::KeyProcedure for RadioDriver<'_> { } } -impl SyscallDriver for RadioDriver<'_> { +impl<'a, M: device::MacDevice<'a>> SyscallDriver for RadioDriver<'a, M> { /// IEEE 802.15.4 MAC device control. /// /// For some of the below commands, one 32-bit argument is not enough to @@ -623,6 +676,10 @@ impl SyscallDriver for RadioDriver<'_> { /// 9 bytes: the key ID (might not use all bytes) + /// 16 bytes: the key. /// - `25`: Remove the key at an index. + /// - `26`: Transmit a frame (parse required). Take the provided payload and + /// parameters to encrypt, form headers, and transmit the frame. + /// - `27`: Transmit a frame (raw). Transmit preformed 15.4 frame (i.e. + /// headers and security etc completed by userprocess). fn command( &self, command_number: usize, @@ -862,7 +919,7 @@ impl SyscallDriver for RadioDriver<'_> { 26 => { self.apps .enter(processid, |app, kernel_data| { - if app.pending_tx.is_some() { + if !app.pending_tx.is_empty() { // Cannot support more than one pending tx per process. return Err(ErrorCode::BUSY); } @@ -900,7 +957,13 @@ impl SyscallDriver for RadioDriver<'_> { if next_tx.is_none() { return Err(ErrorCode::INVAL); } - app.pending_tx = next_tx; + + match next_tx { + Some((dst_addr, sec)) => { + app.pending_tx = PendingTX::Parse(dst_addr, sec) + } + None => app.pending_tx = PendingTX::Empty, + } Ok(()) }) .map_or_else( @@ -911,6 +974,21 @@ impl SyscallDriver for RadioDriver<'_> { }, ) } + 27 => { + self.apps + .enter(processid, |app, _| { + if !app.pending_tx.is_empty() { + // Cannot support more than one pending tx per process. + return Err(ErrorCode::BUSY); + } + app.pending_tx = PendingTX::Raw; + Ok(()) + }) + .map_or_else( + |err| CommandReturn::failure(err.into()), + |_| self.do_next_tx_sync(processid).into(), + ) + } _ => CommandReturn::failure(ErrorCode::NOSUPPORT), } } @@ -920,7 +998,7 @@ impl SyscallDriver for RadioDriver<'_> { } } -impl device::TxClient for RadioDriver<'_> { +impl<'a, M: device::MacDevice<'a>> device::TxClient for RadioDriver<'a, M> { fn send_done(&self, spi_buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>) { self.kernel_tx.replace(spi_buf); self.current_app.take().map(|processid| { @@ -957,7 +1035,7 @@ fn encode_address(addr: &Option) -> usize { ((AddressMode::from(addr) as usize) << 16) | short_addr_only } -impl device::RxClient for RadioDriver<'_> { +impl<'a, M: device::MacDevice<'a>> device::RxClient for RadioDriver<'a, M> { fn receive<'b>(&self, buf: &'b [u8], header: Header<'b>, data_offset: usize, data_len: usize) { self.apps.each(|_, _, kernel_data| { let read_present = kernel_data diff --git a/capsules/extra/src/ieee802154/framer.rs b/capsules/extra/src/ieee802154/framer.rs index a173a3419d..5cf5a4f733 100644 --- a/capsules/extra/src/ieee802154/framer.rs +++ b/capsules/extra/src/ieee802154/framer.rs @@ -99,7 +99,52 @@ use kernel::ErrorCode; #[derive(Eq, PartialEq, Debug)] pub struct Frame { buf: &'static mut [u8], - info: FrameInfo, + info: FrameInfoWrap, +} + +/// This enum wraps the `FrameInfo` struct and allows each sending type +/// (Parse or Raw) to only store the relevant information. In the +/// case of a Raw send, the `FrameInfo` struct is irrelevant as the +/// packet has been fully formed by the userprocess. For a Raw send, +/// we only require knowledge on the frame length. In the case of a +/// Parse send, the wrapper provides all required frame header information. +#[derive(Eq, PartialEq, Debug)] +enum FrameInfoWrap { + Raw(usize), + Parse(FrameInfo), +} + +impl FrameInfoWrap { + /// Obtain secured_length of the Frame + pub fn secured_length(&self) -> usize { + match self { + FrameInfoWrap::Parse(info) => info.secured_length(), + FrameInfoWrap::Raw(len) => *len, + } + } + + /// Obtain unsecured_length of the Frame + pub fn unsecured_length(&self) -> usize { + match self { + FrameInfoWrap::Parse(info) => info.unsecured_length(), + FrameInfoWrap::Raw(len) => *len, + } + } + + /// Fetcher of the FrameInfo struct for Parse sending. Panics if + /// called for Raw sending. + pub fn get_info(&self) -> FrameInfo { + match self { + FrameInfoWrap::Raw(_) => { + // This should never be called for a Raw send. The Framer should never + // require information other than the Frame length for a Raw send. This + // warrants a panic condition as fetching the `FrameInfo` struct for a + // Raw send is undefined behavior. + panic!("FrameInfoWrap::Raw called when expecting FrameInfoWrap::Parse") + } + FrameInfoWrap::Parse(info) => *info, + } + } } /// This contains just enough information about a frame to determine @@ -144,8 +189,13 @@ impl Frame { } let begin = radio::PSDU_OFFSET + self.info.unsecured_length(); self.buf[begin..begin + payload.len()].copy_from_slice(payload); - self.info.data_len += payload.len(); - + match self.info { + FrameInfoWrap::Raw(len) => self.info = FrameInfoWrap::Raw(len + payload.len()), + FrameInfoWrap::Parse(mut info) => { + info.data_len += payload.len(); + self.info = FrameInfoWrap::Parse(info); + } + } Ok(()) } @@ -160,8 +210,13 @@ impl Frame { } let begin = radio::PSDU_OFFSET + self.info.unsecured_length(); payload_buf.copy_to_slice(&mut self.buf[begin..begin + payload_buf.len()]); - self.info.data_len += payload_buf.len(); - + match self.info { + FrameInfoWrap::Raw(len) => self.info = FrameInfoWrap::Raw(len + payload_buf.len()), + FrameInfoWrap::Parse(mut info) => { + info.data_len += payload_buf.len(); + self.info = FrameInfoWrap::Parse(info); + } + } Ok(()) } } @@ -287,13 +342,13 @@ enum TxState { /// There is no frame to be transmitted. Idle, /// There is a valid frame that needs to be secured before transmission. - ReadyToEncrypt(FrameInfo, &'static mut [u8]), + ReadyToEncrypt(FrameInfoWrap, &'static mut [u8]), /// There is currently a frame being encrypted by the encryption facility. #[allow(dead_code)] - Encrypting(FrameInfo), + Encrypting(FrameInfoWrap), /// There is a frame that is completely secured or does not require /// security, and is waiting to be passed to the radio. - ReadyToTransmit(FrameInfo, &'static mut [u8]), + ReadyToTransmit(FrameInfoWrap, &'static mut [u8]), } #[derive(Eq, PartialEq, Debug)] @@ -301,14 +356,14 @@ enum RxState { /// There is no frame that has been received. Idle, /// There is a secured frame that needs to be decrypted. - ReadyToDecrypt(FrameInfo, &'static mut [u8]), + ReadyToDecrypt(FrameInfoWrap, &'static mut [u8]), /// A secured frame is currently being decrypted by the decryption facility. #[allow(dead_code)] - Decrypting(FrameInfo), + Decrypting(FrameInfoWrap), /// There is an unsecured frame that needs to be re-parsed and exposed to /// the client. #[allow(dead_code)] - ReadyToYield(FrameInfo, &'static mut [u8]), + ReadyToYield(FrameInfoWrap, &'static mut [u8]), } /// This struct wraps an IEEE 802.15.4 radio device `kernel::hil::radio::Radio` @@ -383,7 +438,16 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { /// Performs the first checks in the security procedure. The rest of the /// steps are performed as part of the transmission pipeline. /// Returns the next `TxState` to enter. - fn outgoing_frame_security(&self, buf: &'static mut [u8], frame_info: FrameInfo) -> TxState { + fn outgoing_frame_security( + &self, + buf: &'static mut [u8], + frame_info_wrap: FrameInfoWrap, + ) -> TxState { + let frame_info = match frame_info_wrap { + FrameInfoWrap::Parse(info) => info, + FrameInfoWrap::Raw(_) => return TxState::ReadyToTransmit(frame_info_wrap, buf), + }; + // IEEE 802.15.4-2015: 9.2.1, outgoing frame security // Steps a-e have already been performed in the frame preparation step, // so we only need to dispatch on the security parameters in the frame info @@ -392,12 +456,12 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { if level == SecurityLevel::None { // This case should never occur if the FrameInfo was // prepared by prepare_data_frame - TxState::ReadyToTransmit(frame_info, buf) + TxState::ReadyToTransmit(frame_info_wrap, buf) } else { - TxState::ReadyToEncrypt(frame_info, buf) + TxState::ReadyToEncrypt(frame_info_wrap, buf) } } - None => TxState::ReadyToTransmit(frame_info, buf), + None => TxState::ReadyToTransmit(frame_info_wrap, buf), } } @@ -500,7 +564,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { self.mac.set_receive_buffer(buf); RxState::Idle } - Some(frame_info) => RxState::ReadyToDecrypt(frame_info, buf), + Some(frame_info) => RxState::ReadyToDecrypt(FrameInfoWrap::Parse(frame_info), buf), } } @@ -514,14 +578,14 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { let (next_state, result) = match state { TxState::Idle => (TxState::Idle, Ok(())), TxState::ReadyToEncrypt(info, buf) => { - match info.security_params { + match info.get_info().security_params { None => { // `ReadyToEncrypt` should only be entered when // `security_params` is not `None`. (TxState::Idle, Err((ErrorCode::FAIL, buf))) } Some((level, key, nonce)) => { - let (m_off, m_len) = info.ccm_encrypt_ranges(); + let (m_off, m_len) = info.get_info().ccm_encrypt_ranges(); let (a_off, m_off) = (radio::PSDU_OFFSET, radio::PSDU_OFFSET + m_off); @@ -536,7 +600,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { a_off, m_off, m_len, - info.mic_len, + info.get_info().mic_len, level.encryption_needed(), true, ); @@ -582,14 +646,14 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { let next_state = match state { RxState::Idle => RxState::Idle, RxState::ReadyToDecrypt(info, buf) => { - match info.security_params { + match info.get_info().security_params { None => { // `ReadyToDecrypt` should only be entered when // `security_params` is not `None`. RxState::Idle } Some((level, key, nonce)) => { - let (m_off, m_len) = info.ccm_encrypt_ranges(); + let (m_off, m_len) = info.get_info().ccm_encrypt_ranges(); let (a_off, m_off) = (radio::PSDU_OFFSET, radio::PSDU_OFFSET + m_off); // Crypto setup failed; fail receiving packet and return to idle @@ -620,7 +684,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { a_off, m_off, m_len, - info.mic_len, + info.get_info().mic_len, level.encryption_needed(), true, ) @@ -816,19 +880,36 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> { match header.encode(&mut buf[radio::PSDU_OFFSET..], true).done() { Some((data_offset, mac_payload_offset)) => Ok(Frame { buf: buf, - info: FrameInfo { + info: FrameInfoWrap::Parse(FrameInfo { frame_type: FrameType::Data, mac_payload_offset: mac_payload_offset, data_offset: data_offset, data_len: 0, mic_len: mic_len, security_params: security_desc.map(|(sec, key, nonce)| (sec.level, key, nonce)), - }, + }), }), None => Err(buf), } } + fn buf_to_frame( + &self, + buf: &'static mut [u8], + len: usize, + ) -> Result { + // Error check input for compliance with max 15.4 buffer size and + // that the provided len is compatibile with the provided buffer. + if buf.len() < radio::MAX_BUF_SIZE || len > buf.len() { + return Err((ErrorCode::INVAL, buf)); + } + + Ok(Frame { + buf: buf, + info: FrameInfoWrap::Raw(len), + }) + } + fn transmit(&self, frame: Frame) -> Result<(), (ErrorCode, &'static mut [u8])> { let Frame { buf, info } = frame; let state = match self.tx_state.take() { diff --git a/capsules/extra/src/ieee802154/virtual_mac.rs b/capsules/extra/src/ieee802154/virtual_mac.rs index efc499d375..3d669892f2 100644 --- a/capsules/extra/src/ieee802154/virtual_mac.rs +++ b/capsules/extra/src/ieee802154/virtual_mac.rs @@ -44,13 +44,13 @@ use kernel::ErrorCode; /// IEE 802.15.4 MAC device muxer that keeps a list of MAC users and sequences /// any pending transmission requests. Any received frames from the underlying /// MAC device are sent to all users. -pub struct MuxMac<'a> { - mac: &'a dyn device::MacDevice<'a>, - users: List<'a, MacUser<'a>>, - inflight: OptionalCell<&'a MacUser<'a>>, +pub struct MuxMac<'a, M: device::MacDevice<'a>> { + mac: &'a M, + users: List<'a, MacUser<'a, M>>, + inflight: OptionalCell<&'a MacUser<'a, M>>, } -impl device::TxClient for MuxMac<'_> { +impl<'a, M: device::MacDevice<'a>> device::TxClient for MuxMac<'a, M> { fn send_done(&self, spi_buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>) { self.inflight.take().map(move |user| { user.send_done(spi_buf, acked, result); @@ -59,7 +59,7 @@ impl device::TxClient for MuxMac<'_> { } } -impl device::RxClient for MuxMac<'_> { +impl<'a, M: device::MacDevice<'a>> device::RxClient for MuxMac<'a, M> { fn receive<'b>(&self, buf: &'b [u8], header: Header<'b>, data_offset: usize, data_len: usize) { for user in self.users.iter() { user.receive(buf, header, data_offset, data_len); @@ -67,8 +67,8 @@ impl device::RxClient for MuxMac<'_> { } } -impl<'a> MuxMac<'a> { - pub const fn new(mac: &'a dyn device::MacDevice<'a>) -> MuxMac<'a> { +impl<'a, M: device::MacDevice<'a>> MuxMac<'a, M> { + pub const fn new(mac: &'a M) -> MuxMac<'a, M> { MuxMac { mac: mac, users: List::new(), @@ -78,13 +78,13 @@ impl<'a> MuxMac<'a> { /// Registers a MAC user with this MAC mux device. Each MAC user should only /// be registered once. - pub fn add_user(&self, user: &'a MacUser<'a>) { + pub fn add_user(&self, user: &'a MacUser<'a, M>) { self.users.push_head(user); } /// Gets the next `MacUser` and operation to perform if an operation is not /// already underway. - fn get_next_op_if_idle(&self) -> Option<(&'a MacUser<'a>, Op)> { + fn get_next_op_if_idle(&self) -> Option<(&'a MacUser<'a, M>, Op)> { if self.inflight.is_some() { return None; } @@ -107,7 +107,7 @@ impl<'a> MuxMac<'a> { /// Performs a non-idle operation on a `MacUser` asynchronously: that is, if the /// transmission operation results in immediate failure, then return the /// buffer to the `MacUser` via its transmit client. - fn perform_op_async(&self, node: &'a MacUser<'a>, op: Op) { + fn perform_op_async(&self, node: &'a MacUser<'a, M>, op: Op) { if let Op::Transmit(frame) = op { match self.mac.transmit(frame) { // If Err, the transmission failed, @@ -126,7 +126,7 @@ impl<'a> MuxMac<'a> { /// the error code and the buffer immediately. fn perform_op_sync( &self, - node: &'a MacUser<'a>, + node: &'a MacUser<'a, M>, op: Op, ) -> Option> { if let Op::Transmit(frame) = op { @@ -162,7 +162,7 @@ impl<'a> MuxMac<'a> { /// device but fails immediately, return the buffer synchronously. fn do_next_op_sync( &self, - new_node: &MacUser<'a>, + new_node: &MacUser<'a, M>, ) -> Option> { self.get_next_op_if_idle().and_then(|(node, op)| { if core::ptr::eq(node, new_node) { @@ -192,17 +192,17 @@ enum Op { /// all MacUsers because there is only one MAC device. For example, the MAC /// device address is shared, so calling `set_address` on one `MacUser` sets the /// MAC address for all `MacUser`s. -pub struct MacUser<'a> { - mux: &'a MuxMac<'a>, +pub struct MacUser<'a, M: device::MacDevice<'a>> { + mux: &'a MuxMac<'a, M>, operation: MapCell, - next: ListLink<'a, MacUser<'a>>, + next: ListLink<'a, MacUser<'a, M>>, tx_client: Cell>, rx_client: Cell>, } -impl<'a> MacUser<'a> { - pub const fn new(mux: &'a MuxMac<'a>) -> MacUser<'a> { - MacUser { +impl<'a, M: device::MacDevice<'a>> MacUser<'a, M> { + pub const fn new(mux: &'a MuxMac<'a, M>) -> Self { + Self { mux: mux, operation: MapCell::new(Op::Idle), next: ListLink::empty(), @@ -212,7 +212,7 @@ impl<'a> MacUser<'a> { } } -impl MacUser<'_> { +impl<'a, M: device::MacDevice<'a>> MacUser<'a, M> { fn send_done(&self, spi_buf: &'static mut [u8], acked: bool, result: Result<(), ErrorCode>) { self.tx_client .get() @@ -226,13 +226,13 @@ impl MacUser<'_> { } } -impl<'a> ListNode<'a, MacUser<'a>> for MacUser<'a> { - fn next(&'a self) -> &'a ListLink<'a, MacUser<'a>> { +impl<'a, M: device::MacDevice<'a>> ListNode<'a, MacUser<'a, M>> for MacUser<'a, M> { + fn next(&'a self) -> &'a ListLink<'a, MacUser<'a, M>> { &self.next } } -impl<'a> device::MacDevice<'a> for MacUser<'a> { +impl<'a, M: device::MacDevice<'a>> device::MacDevice<'a> for MacUser<'a, M> { fn set_transmit_client(&self, client: &'a dyn device::TxClient) { self.tx_client.set(Some(client)); } @@ -287,6 +287,14 @@ impl<'a> device::MacDevice<'a> for MacUser<'a> { .prepare_data_frame(buf, dst_pan, dst_addr, src_pan, src_addr, security_needed) } + fn buf_to_frame( + &self, + buf: &'static mut [u8], + len: usize, + ) -> Result { + self.mux.mac.buf_to_frame(buf, len) + } + fn transmit(&self, frame: framer::Frame) -> Result<(), (ErrorCode, &'static mut [u8])> { // If the muxer is idle, immediately transmit the frame, otherwise // attempt to queue the transmission request. However, each MAC user can diff --git a/capsules/extra/src/lib.rs b/capsules/extra/src/lib.rs index 240db15598..102347e44f 100644 --- a/capsules/extra/src/lib.rs +++ b/capsules/extra/src/lib.rs @@ -75,6 +75,7 @@ pub mod read_only_state; pub mod rf233; pub mod rf233_const; pub mod screen; +pub mod screen_shared; pub mod sdcard; pub mod segger_rtt; pub mod seven_segment; @@ -85,6 +86,7 @@ pub mod sht4x; pub mod si7021; pub mod sip_hash; pub mod sound_pressure; +pub mod ssd1306; pub mod st77xx; pub mod symmetric_encryption; pub mod temperature; diff --git a/capsules/extra/src/log.rs b/capsules/extra/src/log.rs index 640fad006e..f6056cebf6 100644 --- a/capsules/extra/src/log.rs +++ b/capsules/extra/src/log.rs @@ -63,7 +63,6 @@ //! ``` use core::cell::Cell; -use core::convert::TryFrom; use core::mem::size_of; use core::unreachable; diff --git a/capsules/extra/src/net/sixlowpan/sixlowpan_compression.rs b/capsules/extra/src/net/sixlowpan/sixlowpan_compression.rs index a0509efa4d..23329030a0 100644 --- a/capsules/extra/src/net/sixlowpan/sixlowpan_compression.rs +++ b/capsules/extra/src/net/sixlowpan/sixlowpan_compression.rs @@ -11,7 +11,6 @@ use crate::net::util::{network_slice_to_u16, u16_to_network_slice}; /// Implements the 6LoWPAN specification for sending IPv6 datagrams over /// 802.15.4 packets efficiently, as detailed in RFC 6282. use core::mem; -use core::result::Result; /// Contains bit masks and constants related to the two-byte header of the /// LoWPAN_IPHC encoding format. diff --git a/capsules/extra/src/net/udp/driver.rs b/capsules/extra/src/net/udp/driver.rs index d19f93112a..df905f15d0 100644 --- a/capsules/extra/src/net/udp/driver.rs +++ b/capsules/extra/src/net/udp/driver.rs @@ -21,8 +21,6 @@ use crate::net::udp::udp_send::{UDPSendClient, UDPSender}; use crate::net::util::host_slice_to_u16; use core::cell::Cell; -use core::convert::TryFrom; -use core::convert::TryInto; use core::mem::size_of; use core::{cmp, mem}; diff --git a/capsules/extra/src/screen.rs b/capsules/extra/src/screen.rs index a5ad3bc96f..f63e6d5634 100644 --- a/capsules/extra/src/screen.rs +++ b/capsules/extra/src/screen.rs @@ -15,7 +15,6 @@ //! ``` use core::cell::Cell; -use core::convert::From; use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; use kernel::hil; diff --git a/capsules/extra/src/screen_shared.rs b/capsules/extra/src/screen_shared.rs new file mode 100644 index 0000000000..cb98b30884 --- /dev/null +++ b/capsules/extra/src/screen_shared.rs @@ -0,0 +1,459 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2024. + +//! Shares a screen among multiple userspace processes. +//! +//! The screen can be split into multiple regions, and regions are assigned to +//! processes by AppID. +//! +//! Boards should create an array of `AppScreenRegion` objects that assign apps +//! to specific regions (frames) within the screen. +//! +//! ``` +//! AppScreenRegion { +//! app_id: kernel::process:ShortID::new(id), +//! frame: Frame { +//! x: 0, +//! y: 0, +//! width: 8, +//! height: 16, +//! } +//! } +//! ``` +//! +//! This driver uses a subset of the API from `Screen`. It does not support any +//! screen config settings (brightness, invert) as those operations affect the +//! entire screen. + +use core::convert::From; + +use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; +use kernel::hil; +use kernel::processbuffer::ReadableProcessBuffer; +use kernel::syscall::{CommandReturn, SyscallDriver}; +use kernel::utilities::cells::{OptionalCell, TakeCell}; +use kernel::utilities::leasable_buffer::SubSliceMut; +use kernel::{ErrorCode, ProcessId}; + +/// Syscall driver number. +use capsules_core::driver; +pub const DRIVER_NUM: usize = driver::NUM::Screen as usize; + +/// Ids for read-only allow buffers +mod ro_allow { + pub const SHARED: usize = 0; + /// The number of allow buffers the kernel stores for this grant + pub const COUNT: u8 = 1; +} + +#[derive(Clone, Copy, PartialEq)] +enum ScreenCommand { + WriteSetFrame, + WriteBuffer, +} + +fn pixels_in_bytes(pixels: usize, bits_per_pixel: usize) -> usize { + let bytes = pixels * bits_per_pixel / 8; + if pixels * bits_per_pixel % 8 != 0 { + bytes + 1 + } else { + bytes + } +} + +/// Rectangular region of a screen. +#[derive(Default, Clone, Copy, PartialEq)] +pub struct Frame { + /// X coordinate of the upper left corner of the frame. + x: usize, + /// Y coordinate of the upper left corner of the frame. + y: usize, + /// Width of the frame. + width: usize, + /// Height of the frame. + height: usize, +} + +pub struct AppScreenRegion { + app_id: kernel::process::ShortID, + frame: Frame, +} + +impl AppScreenRegion { + pub fn new( + app_id: kernel::process::ShortID, + x: usize, + y: usize, + width: usize, + height: usize, + ) -> Self { + Self { + app_id, + frame: Frame { + x, + y, + width, + height, + }, + } + } +} + +#[derive(Default)] +pub struct App { + /// The app has requested some screen operation, or `None()` if idle. + command: Option, + /// The current frame the app is using. + frame: Frame, +} + +/// A userspace driver that allows multiple apps to use the same screen. +/// +/// Each app is given a pre-set rectangular region of the screen to use. +pub struct ScreenShared<'a, S: hil::screen::Screen<'a>> { + /// Underlying screen driver to use. + screen: &'a S, + + /// Grant region for apps using the screen. + apps: Grant, AllowRoCount<{ ro_allow::COUNT }>, AllowRwCount<0>>, + + /// Static allocations of screen regions for each app. + apps_regions: &'a [AppScreenRegion], + + /// The process currently executing a command on the screen. + current_process: OptionalCell, + + /// Internal buffer for write commands. + buffer: TakeCell<'static, [u8]>, +} + +impl<'a, S: hil::screen::Screen<'a>> ScreenShared<'a, S> { + pub fn new( + screen: &'a S, + grant: Grant, AllowRoCount<{ ro_allow::COUNT }>, AllowRwCount<0>>, + buffer: &'static mut [u8], + apps_regions: &'a [AppScreenRegion], + ) -> ScreenShared<'a, S> { + ScreenShared { + screen: screen, + apps: grant, + current_process: OptionalCell::empty(), + buffer: TakeCell::new(buffer), + apps_regions, + } + } + + // Enqueue a command for the given app. + fn enqueue_command(&self, command: ScreenCommand, process_id: ProcessId) -> CommandReturn { + let ret = self + .apps + .enter(process_id, |app, _| { + if app.command.is_some() { + Err(ErrorCode::BUSY) + } else { + app.command = Some(command); + Ok(()) + } + }) + .map_err(ErrorCode::from) + .and_then(|r| r) + .into(); + + if self.current_process.is_none() { + self.run_next_command(); + } + + ret + } + + /// Calculate the frame within the entire screen that the app is currently + /// trying to use. This is the `app_frame` within the app's allocated + /// `app_screen_region`. + fn calculate_absolute_frame(&self, app_screen_region_frame: Frame, app_frame: Frame) -> Frame { + // x and y are sums + let mut absolute_x = app_screen_region_frame.x + app_frame.x; + let mut absolute_y = app_screen_region_frame.y + app_frame.y; + // width and height are simply the app_frame width and height. + let mut absolute_w = app_frame.width; + let mut absolute_h = app_frame.height; + + // Make sure that the calculate frame is within the allocated region. + absolute_x = core::cmp::min( + app_screen_region_frame.x + app_screen_region_frame.width, + absolute_x, + ); + absolute_y = core::cmp::min( + app_screen_region_frame.y + app_screen_region_frame.height, + absolute_y, + ); + absolute_w = core::cmp::min( + app_screen_region_frame.x + app_screen_region_frame.width - absolute_x, + absolute_w, + ); + absolute_h = core::cmp::min( + app_screen_region_frame.y + app_screen_region_frame.height - absolute_y, + absolute_h, + ); + + Frame { + x: absolute_x, + y: absolute_y, + width: absolute_w, + height: absolute_h, + } + } + + fn call_screen( + &self, + process_id: ProcessId, + app_screen_region_frame: Frame, + ) -> Result<(), ErrorCode> { + self.apps + .enter(process_id, |app, kernel_data| { + match app.command { + Some(ScreenCommand::WriteSetFrame) => { + let absolute_frame = + self.calculate_absolute_frame(app_screen_region_frame, app.frame); + + app.command = Some(ScreenCommand::WriteBuffer); + self.screen + .set_write_frame( + absolute_frame.x, + absolute_frame.y, + absolute_frame.width, + absolute_frame.height, + ) + .map_err(|e| { + app.command = None; + e + }) + } + Some(ScreenCommand::WriteBuffer) => { + app.command = None; + kernel_data + .get_readonly_processbuffer(ro_allow::SHARED) + .map(|allow_buf| { + let len = allow_buf.len(); + + if len == 0 { + Err(ErrorCode::NOMEM) + } else if !self.is_len_multiple_color_depth(len) { + Err(ErrorCode::INVAL) + } else { + // All good, copy buffer. + + self.buffer.take().map_or(Err(ErrorCode::FAIL), |buffer| { + let copy_len = + core::cmp::min(buffer.len(), allow_buf.len()); + allow_buf.enter(|ab| { + // buffer[..copy_len].copy_from_slice(ab[..copy_len]); + ab[..copy_len].copy_to_slice(&mut buffer[..copy_len]) + })?; + + // Send to screen. + let mut data = SubSliceMut::new(buffer); + data.slice(..copy_len); + self.screen.write(data, false) + }) + } + }) + .map_err(ErrorCode::from) + .and_then(|r| r) + } + _ => Err(ErrorCode::NOSUPPORT), + } + }) + .map_err(ErrorCode::from) + .and_then(|r| r) + } + + fn schedule_callback(&self, process_id: ProcessId, data1: usize, data2: usize, data3: usize) { + let _ = self.apps.enter(process_id, |_app, kernel_data| { + kernel_data.schedule_upcall(0, (data1, data2, data3)).ok(); + }); + } + + fn get_app_screen_region_frame(&self, process_id: ProcessId) -> Option { + let short_id = process_id.short_app_id(); + + for app_screen_region in self.apps_regions { + if short_id == app_screen_region.app_id { + return Some(app_screen_region.frame); + } + } + None + } + + fn run_next_command(&self) { + let ran_cmd = self.current_process.map_or(false, |process_id| { + let app_region_frame = self.get_app_screen_region_frame(process_id); + + app_region_frame.map_or(false, |frame| { + let r = self.call_screen(process_id, frame); + if r.is_err() { + // We were unable to run the screen operation meaning we + // will not get a callback and we need to report the error. + self.current_process.take().map(|process_id| { + self.schedule_callback( + process_id, + kernel::errorcode::into_statuscode(r), + 0, + 0, + ); + }); + false + } else { + true + } + }) + }); + + if !ran_cmd { + // Check if there are any pending events. + for app in self.apps.iter() { + let process_id = app.processid(); + + // Check if this process has both a pending command and is + // allocated a region on the screen. + let frame_maybe = app.enter(|app, _| { + if app.command.is_some() { + self.get_app_screen_region_frame(process_id) + } else { + None + } + }); + + // If we have a candidate, try to execute the screen operation. + if frame_maybe.is_some() { + match frame_maybe { + Some(frame) => { + // Reserve the screen for this process and execute + // the operation. + self.current_process.set(process_id); + match self.call_screen(process_id, frame) { + Ok(()) => { + // Everything is good, stop looking for apps + // to execute. + break; + } + Err(err) => { + // Could not run the screen command. + // Un-reserve the screen and do an upcall + // with the bad news. + self.current_process.clear(); + self.schedule_callback( + process_id, + kernel::errorcode::into_statuscode(Err(err)), + 0, + 0, + ); + } + } + } + None => {} + } + } + } + } + } + + fn is_len_multiple_color_depth(&self, len: usize) -> bool { + let depth = pixels_in_bytes(1, self.screen.get_pixel_format().get_bits_per_pixel()); + (len % depth) == 0 + } +} + +impl<'a, S: hil::screen::Screen<'a>> hil::screen::ScreenClient for ScreenShared<'a, S> { + fn command_complete(&self, r: Result<(), ErrorCode>) { + if r.is_err() { + self.current_process.take().map(|process_id| { + self.schedule_callback(process_id, kernel::errorcode::into_statuscode(r), 0, 0); + }); + } + + self.run_next_command(); + } + + fn write_complete(&self, data: SubSliceMut<'static, u8>, r: Result<(), ErrorCode>) { + self.buffer.replace(data.take()); + + // Notify that the write is finished. + self.current_process.take().map(|process_id| { + self.schedule_callback(process_id, kernel::errorcode::into_statuscode(r), 0, 0); + }); + + self.run_next_command(); + } + + fn screen_is_ready(&self) { + self.run_next_command(); + } +} + +impl<'a, S: hil::screen::Screen<'a>> SyscallDriver for ScreenShared<'a, S> { + fn command( + &self, + command_num: usize, + data1: usize, + data2: usize, + process_id: ProcessId, + ) -> CommandReturn { + match command_num { + // Driver existence check + 0 => CommandReturn::success(), + + // Get Rotation + 21 => CommandReturn::success_u32(self.screen.get_rotation() as u32), + + // Get Resolution + 23 => match self.get_app_screen_region_frame(process_id) { + Some(frame) => { + CommandReturn::success_u32_u32(frame.width as u32, frame.height as u32) + } + None => CommandReturn::failure(ErrorCode::NOSUPPORT), + }, + + // Get pixel format + 25 => CommandReturn::success_u32(self.screen.get_pixel_format() as u32), + + // Set Write Frame + 100 => { + let frame = Frame { + x: (data1 >> 16) & 0xFFFF, + y: data1 & 0xFFFF, + width: (data2 >> 16) & 0xFFFF, + height: data2 & 0xFFFF, + }; + + self.apps + .enter(process_id, |app, kernel_data| { + app.frame = frame; + + // Just issue upcall. + let _ = kernel_data + .schedule_upcall(0, (kernel::errorcode::into_statuscode(Ok(())), 0, 0)); + }) + .map_err(ErrorCode::from) + .into() + } + + // Write + 200 => { + // First check if this app has any screen real estate allocated. + // If not, return error. + if self.get_app_screen_region_frame(process_id).is_none() { + CommandReturn::failure(ErrorCode::NOSUPPORT) + } else { + self.enqueue_command(ScreenCommand::WriteSetFrame, process_id) + } + } + + _ => CommandReturn::failure(ErrorCode::NOSUPPORT), + } + } + + fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> { + self.apps.enter(processid, |_, _| {}) + } +} diff --git a/capsules/extra/src/sip_hash.rs b/capsules/extra/src/sip_hash.rs index b6f2271bea..8d35b11194 100644 --- a/capsules/extra/src/sip_hash.rs +++ b/capsules/extra/src/sip_hash.rs @@ -27,7 +27,6 @@ //! option. use core::cell::Cell; -use core::convert::TryInto; use core::{cmp, mem}; use kernel::deferred_call::{DeferredCall, DeferredCallClient}; use kernel::hil::hasher::{Client, Hasher, SipHash}; diff --git a/capsules/extra/src/sound_pressure.rs b/capsules/extra/src/sound_pressure.rs index b349d10d49..93a6f759f6 100644 --- a/capsules/extra/src/sound_pressure.rs +++ b/capsules/extra/src/sound_pressure.rs @@ -57,7 +57,6 @@ //! ``` use core::cell::Cell; -use core::convert::TryFrom; use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; use kernel::hil; use kernel::syscall::{CommandReturn, SyscallDriver}; diff --git a/capsules/extra/src/ssd1306.rs b/capsules/extra/src/ssd1306.rs new file mode 100644 index 0000000000..ea6f0b81ee --- /dev/null +++ b/capsules/extra/src/ssd1306.rs @@ -0,0 +1,564 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2023. + +//! SSD1306/SSD1315 OLED Screen + +use core::cell::Cell; +use kernel::hil; +use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell}; +use kernel::utilities::leasable_buffer::SubSliceMut; +use kernel::ErrorCode; + +pub const BUFFER_SIZE: usize = 1032; + +const WIDTH: usize = 128; +const HEIGHT: usize = 64; + +#[derive(Copy, Clone, PartialEq)] +#[repr(usize)] +pub enum Command { + // Charge Pump Commands + /// Charge Pump Setting. + SetChargePump { enable: bool }, + + // Fundamental Commands + /// SetContrastControl. Double byte command to select 1 out of 256 contrast + /// steps. Contrast increases as the value increases. + SetContrast { contrast: u8 }, + /// Entire Display On. + EntireDisplayOn { ignore_ram: bool }, + /// Set Normal Display. + SetDisplayInvert { inverse: bool }, + /// Set Display Off. + SetDisplayOnOff { on: bool }, + + // Scrolling Commands + /// Continuous Horizontal Scroll. Right or Left Horizontal Scroll. + ContinuousHorizontalScroll { + left: bool, + page_start: u8, + interval: u8, + page_end: u8, + }, + /// Continuous Vertical and Horizontal Scroll. Vertical and Right Horizontal + /// Scroll. + ContinuousVerticalHorizontalScroll { + left: bool, + page_start: u8, + interval: u8, + page_end: u8, + vertical_offset: u8, + }, + /// Deactivate Scroll. Stop scrolling that is configured by scroll commands. + DeactivateScroll = 0x2e, + /// Activate Scroll. Start scrolling that is configured by scroll commands. + ActivateScroll = 0x2f, + /// Set Vertical Scroll Area. Set number of rows in top fixed area. The + /// number of rows in top fixed area is referenced to the top of the GDDRAM + /// (i.e. row 0). + SetVerticalScrollArea { rows_fixed: u8, rows_scroll: u8 }, + + // Addressing Setting Commands + /// Set Lower Column Start Address for Page Addressing Mode. + /// + /// Set the lower nibble of the column start address register for Page + /// Addressing Mode using `X[3:0]` as data bits. The initial display line + /// register is reset to 0000b after RESET. + SetLowerColumnStartAddress { address: u8 }, + /// Set Higher Column Start Address for Page Addressing Mode. + /// + /// Set the higher nibble of the column start address register for Page + /// Addressing Mode using `X[3:0]` as data bits. The initial display line + /// register is reset to 0000b after RESET. + SetHigherColumnStartAddress { address: u8 }, + /// Set Memory Addressing Mode. + SetMemoryAddressingMode { mode: u8 }, + /// Set Column Address. Setup column start and end address. + SetColumnAddress { column_start: u8, column_end: u8 }, + /// Set Page Address. Setup page start and end address. + SetPageAddress { page_start: u8, page_end: u8 }, + /// Set Page Start Address for Page Addressing Mode. Set GDDRAM Page Start + /// Address (PAGE0~PAGE7) for Page Addressing Mode using `X[2:0]`. + SetPageStartAddress { address: u8 }, + + // Hardware Configuration Commands + /// Set Display Start Line. Set display RAM display start line register from + /// 0-63 using `X[5:0]`. + SetDisplayStartLine { line: u8 }, + /// Set Segment Remap. + SetSegmentRemap { reverse: bool }, + /// Set Multiplex Ratio. + SetMultiplexRatio { ratio: u8 }, + /// Set COM Output Scan Direction. + SetComScanDirection { decrement: bool }, + /// Set Display Offset. Set vertical shift by COM from 0-63. + SetDisplayOffset { vertical_shift: u8 } = 0xd3, + /// Set COM Pins Hardware Configuration + SetComPins { alternative: bool, enable_com: bool }, + + // Timing & Driving Scheme Setting Commands. + /// Set Display Clock Divide Ratio/Oscillator Frequency. + SetDisplayClockDivide { + divide_ratio: u8, + oscillator_frequency: u8, + }, + /// Set Pre-charge Period. + SetPrechargePeriod { phase1: u8, phase2: u8 }, + /// Set VCOMH Deselect Level. + SetVcomDeselect { level: u8 }, +} + +impl Command { + fn encode(self, buffer: &mut SubSliceMut<'static, u8>) { + let take = match self { + Self::SetChargePump { enable } => { + buffer[0] = 0x8D; + buffer[1] = 0x10 | ((enable as u8) << 2); + 2 + } + Self::SetContrast { contrast } => { + buffer[0] = 0x81; + buffer[1] = contrast; + 2 + } + Self::EntireDisplayOn { ignore_ram } => { + buffer[0] = 0xa4 | (ignore_ram as u8); + 1 + } + Self::SetDisplayInvert { inverse } => { + buffer[0] = 0xa6 | (inverse as u8); + 1 + } + Self::SetDisplayOnOff { on } => { + buffer[0] = 0xae | (on as u8); + 1 + } + Self::ContinuousHorizontalScroll { + left, + page_start, + interval, + page_end, + } => { + buffer[0] = 0x26 | (left as u8); + buffer[1] = 0; + buffer[2] = page_start; + buffer[3] = interval; + buffer[4] = page_end; + buffer[5] = 0; + buffer[6] = 0xff; + 7 + } + Self::ContinuousVerticalHorizontalScroll { + left, + page_start, + interval, + page_end, + vertical_offset, + } => { + buffer[0] = 0x29 | (left as u8); + buffer[1] = 0; + buffer[2] = page_start; + buffer[3] = interval; + buffer[4] = page_end; + buffer[5] = vertical_offset; + 6 + } + Self::DeactivateScroll => { + buffer[0] = 0x2e; + 1 + } + Self::ActivateScroll => { + buffer[0] = 0x2f; + 1 + } + Self::SetVerticalScrollArea { + rows_fixed, + rows_scroll, + } => { + buffer[0] = 0xa3; + buffer[1] = rows_fixed; + buffer[2] = rows_scroll; + 3 + } + Self::SetLowerColumnStartAddress { address } => { + buffer[0] = 0x00 | (address & 0xF); + 1 + } + Self::SetHigherColumnStartAddress { address } => { + buffer[0] = 0x10 | (address & 0xF); + 1 + } + Self::SetMemoryAddressingMode { mode } => { + buffer[0] = 0x20; + buffer[1] = mode; + 2 + } + Self::SetColumnAddress { + column_start, + column_end, + } => { + buffer[0] = 0x21; + buffer[1] = column_start; + buffer[2] = column_end; + 3 + } + Self::SetPageAddress { + page_start, + page_end, + } => { + buffer[0] = 0x22; + buffer[1] = page_start; + buffer[2] = page_end; + 3 + } + Self::SetPageStartAddress { address } => { + buffer[0] = 0xb0 | (address & 0x7); + 1 + } + Self::SetDisplayStartLine { line } => { + buffer[0] = 0x40 | (line & 0x3F); + 1 + } + Self::SetSegmentRemap { reverse } => { + buffer[0] = 0xa0 | (reverse as u8); + 1 + } + Self::SetMultiplexRatio { ratio } => { + buffer[0] = 0xa8; + buffer[1] = ratio; + 2 + } + Self::SetComScanDirection { decrement } => { + buffer[0] = 0xc0 | ((decrement as u8) << 3); + 1 + } + Self::SetDisplayOffset { vertical_shift } => { + buffer[0] = 0xd3; + buffer[1] = vertical_shift; + 2 + } + Self::SetComPins { + alternative, + enable_com, + } => { + buffer[0] = 0xda; + buffer[1] = ((alternative as u8) << 4) | ((enable_com as u8) << 5) | 0x2; + 2 + } + Self::SetDisplayClockDivide { + divide_ratio, + oscillator_frequency, + } => { + buffer[0] = 0xd5; + buffer[1] = ((oscillator_frequency & 0xF) << 4) | (divide_ratio & 0xf); + 2 + } + Self::SetPrechargePeriod { phase1, phase2 } => { + buffer[0] = 0xd9; + buffer[1] = ((phase2 & 0xF) << 4) | (phase1 & 0xf); + 2 + } + Self::SetVcomDeselect { level } => { + buffer[0] = 0xdb; + buffer[1] = (level & 0xF) << 4; + 2 + } + }; + + // Move the available region of the buffer to what is remaining after + // this command was encoded. + buffer.slice(take..); + } +} + +// #[derive(Copy, Clone, PartialEq)] +#[derive(Clone, Copy, PartialEq)] +enum State { + Idle, + Init, + SimpleCommand, + Write, +} + +pub struct Ssd1306<'a, I: hil::i2c::I2CDevice> { + i2c: &'a I, + state: Cell, + client: OptionalCell<&'a dyn hil::screen::ScreenClient>, + setup_client: OptionalCell<&'a dyn hil::screen::ScreenSetupClient>, + buffer: TakeCell<'static, [u8]>, + write_buffer: MapCell>, + enable_charge_pump: bool, +} + +impl<'a, I: hil::i2c::I2CDevice> Ssd1306<'a, I> { + pub fn new(i2c: &'a I, buffer: &'static mut [u8], enable_charge_pump: bool) -> Ssd1306<'a, I> { + Ssd1306 { + i2c, + state: Cell::new(State::Idle), + client: OptionalCell::empty(), + setup_client: OptionalCell::empty(), + buffer: TakeCell::new(buffer), + write_buffer: MapCell::empty(), + enable_charge_pump, + } + } + + pub fn init_screen(&self) { + let commands = [ + Command::SetDisplayOnOff { on: false }, + Command::SetDisplayClockDivide { + divide_ratio: 0, + oscillator_frequency: 0x8, + }, + Command::SetMultiplexRatio { + ratio: HEIGHT as u8 - 1, + }, + Command::SetDisplayOffset { vertical_shift: 0 }, + Command::SetDisplayStartLine { line: 0 }, + Command::SetChargePump { + enable: self.enable_charge_pump, + }, + Command::SetMemoryAddressingMode { mode: 0 }, //horizontal + Command::SetSegmentRemap { reverse: true }, + Command::SetComScanDirection { decrement: true }, + Command::SetComPins { + alternative: true, + enable_com: false, + }, + Command::SetContrast { contrast: 0xcf }, + Command::SetPrechargePeriod { + phase1: 0x1, + phase2: 0xf, + }, + Command::SetVcomDeselect { level: 2 }, + Command::EntireDisplayOn { ignore_ram: false }, + Command::SetDisplayInvert { inverse: false }, + Command::DeactivateScroll, + Command::SetDisplayOnOff { on: true }, + ]; + + match self.send_sequence(&commands) { + Ok(()) => { + self.state.set(State::Init); + } + Err(_e) => {} + } + } + + fn send_sequence(&self, sequence: &[Command]) -> Result<(), ErrorCode> { + if self.state.get() == State::Idle { + self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buffer| { + let mut buf_slice = SubSliceMut::new(buffer); + + // Specify this is a series of command bytes. + buf_slice[0] = 0; // Co = 0, D/CÌ… = 0 + + // Move the window of the subslice after the command byte header. + buf_slice.slice(1..); + + for cmd in sequence.iter() { + cmd.encode(&mut buf_slice); + } + + // We need the amount of data that has been sliced away + // at the start of the subslice. + let remaining_len = buf_slice.len(); + buf_slice.reset(); + let tx_len = buf_slice.len() - remaining_len; + + self.i2c.enable(); + match self.i2c.write(buf_slice.take(), tx_len) { + Ok(()) => Ok(()), + Err((_e, buf)) => { + self.buffer.replace(buf); + self.i2c.disable(); + Err(ErrorCode::INVAL) + } + } + }) + } else { + Err(ErrorCode::BUSY) + } + } +} + +impl<'a, I: hil::i2c::I2CDevice> hil::screen::ScreenSetup<'a> for Ssd1306<'a, I> { + fn set_client(&self, client: &'a dyn hil::screen::ScreenSetupClient) { + self.setup_client.set(client); + } + + fn set_resolution(&self, _resolution: (usize, usize)) -> Result<(), ErrorCode> { + Err(ErrorCode::NOSUPPORT) + } + + fn set_pixel_format(&self, _depth: hil::screen::ScreenPixelFormat) -> Result<(), ErrorCode> { + Err(ErrorCode::NOSUPPORT) + } + + fn set_rotation(&self, _rotation: hil::screen::ScreenRotation) -> Result<(), ErrorCode> { + Err(ErrorCode::NOSUPPORT) + } + + fn get_num_supported_resolutions(&self) -> usize { + 1 + } + + fn get_supported_resolution(&self, index: usize) -> Option<(usize, usize)> { + match index { + 0 => Some((WIDTH, HEIGHT)), + _ => None, + } + } + + fn get_num_supported_pixel_formats(&self) -> usize { + 1 + } + + fn get_supported_pixel_format(&self, index: usize) -> Option { + match index { + 0 => Some(hil::screen::ScreenPixelFormat::Mono), + _ => None, + } + } +} + +impl<'a, I: hil::i2c::I2CDevice> hil::screen::Screen<'a> for Ssd1306<'a, I> { + fn set_client(&self, client: &'a dyn hil::screen::ScreenClient) { + self.client.set(client); + } + + fn get_resolution(&self) -> (usize, usize) { + (WIDTH, HEIGHT) + } + + fn get_pixel_format(&self) -> hil::screen::ScreenPixelFormat { + hil::screen::ScreenPixelFormat::Mono + } + + fn get_rotation(&self) -> hil::screen::ScreenRotation { + hil::screen::ScreenRotation::Normal + } + + fn set_write_frame( + &self, + x: usize, + y: usize, + width: usize, + height: usize, + ) -> Result<(), ErrorCode> { + let commands = [ + Command::SetPageAddress { + page_start: (y / 8) as u8, + page_end: ((y / 8) + (height / 8) - 1) as u8, + }, + Command::SetColumnAddress { + column_start: x as u8, + column_end: (x + width - 1) as u8, + }, + ]; + match self.send_sequence(&commands) { + Ok(()) => { + self.state.set(State::SimpleCommand); + Ok(()) + } + Err(e) => Err(e), + } + } + + fn write(&self, data: SubSliceMut<'static, u8>, _continue: bool) -> Result<(), ErrorCode> { + self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buffer| { + let mut buf_slice = SubSliceMut::new(buffer); + + // Specify this is data. + buf_slice[0] = 0x40; // Co = 0, D/CÌ… = 1 + + // Move the window of the subslice after the command byte header. + buf_slice.slice(1..); + + // Figure out how much we can send. + let copy_len = core::cmp::min(buf_slice.len(), data.len()); + + for i in 0..copy_len { + buf_slice[i] = data[i]; + } + + let tx_len = copy_len + 1; + + self.i2c.enable(); + match self.i2c.write(buf_slice.take(), tx_len) { + Ok(()) => { + self.state.set(State::Write); + self.write_buffer.replace(data); + Ok(()) + } + Err((_e, buf)) => { + self.buffer.replace(buf); + Err(ErrorCode::INVAL) + } + } + }) + } + + fn set_brightness(&self, brightness: u16) -> Result<(), ErrorCode> { + let commands = [Command::SetContrast { + contrast: (brightness >> 8) as u8, + }]; + match self.send_sequence(&commands) { + Ok(()) => { + self.state.set(State::SimpleCommand); + Ok(()) + } + Err(e) => Err(e), + } + } + + fn set_power(&self, enabled: bool) -> Result<(), ErrorCode> { + let commands = [Command::SetDisplayOnOff { on: enabled }]; + match self.send_sequence(&commands) { + Ok(()) => { + self.state.set(State::SimpleCommand); + Ok(()) + } + Err(e) => Err(e), + } + } + + fn set_invert(&self, enabled: bool) -> Result<(), ErrorCode> { + let commands = [Command::SetDisplayInvert { inverse: enabled }]; + match self.send_sequence(&commands) { + Ok(()) => { + self.state.set(State::SimpleCommand); + Ok(()) + } + Err(e) => Err(e), + } + } +} + +impl<'a, I: hil::i2c::I2CDevice> hil::i2c::I2CClient for Ssd1306<'a, I> { + fn command_complete(&self, buffer: &'static mut [u8], _status: Result<(), hil::i2c::Error>) { + self.buffer.replace(buffer); + self.i2c.disable(); + + match self.state.get() { + State::Init => { + self.state.set(State::Idle); + self.client.map(|client| client.screen_is_ready()); + } + + State::SimpleCommand => { + self.state.set(State::Idle); + self.client.map(|client| client.command_complete(Ok(()))); + } + + State::Write => { + self.state.set(State::Idle); + self.write_buffer.take().map(|buf| { + self.client.map(|client| client.write_complete(buf, Ok(()))); + }); + } + _ => {} + } + } +} diff --git a/capsules/extra/src/test/hmac_sha256.rs b/capsules/extra/src/test/hmac_sha256.rs index a9d0ce3dd7..e249e0d080 100644 --- a/capsules/extra/src/test/hmac_sha256.rs +++ b/capsules/extra/src/test/hmac_sha256.rs @@ -127,3 +127,8 @@ impl CapsuleTest for TestHmacSha256 { self.client.set(client); } } + +impl digest::ClientVerify<32> for TestHmacSha256 { + fn verification_done(&self, _result: Result, _compare: &'static mut [u8; 32]) { + } +} diff --git a/capsules/extra/src/text_screen.rs b/capsules/extra/src/text_screen.rs index f435f9f447..ef166ef73a 100644 --- a/capsules/extra/src/text_screen.rs +++ b/capsules/extra/src/text_screen.rs @@ -16,7 +16,6 @@ //! ``` use core::cmp; -use core::convert::From; use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; use kernel::hil; diff --git a/capsules/extra/src/tickv.rs b/capsules/extra/src/tickv.rs index 6cb2640bfa..3fc63c9fb3 100644 --- a/capsules/extra/src/tickv.rs +++ b/capsules/extra/src/tickv.rs @@ -39,7 +39,7 @@ use kernel::hil::hasher::{self, Hasher}; use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell}; use kernel::utilities::leasable_buffer::{SubSlice, SubSliceMut}; use kernel::ErrorCode; -use tickv::{self, AsyncTicKV}; +use tickv::AsyncTicKV; /// The type of keys, this should define the output size of the digest /// operations. diff --git a/capsules/extra/src/usb/descriptors.rs b/capsules/extra/src/usb/descriptors.rs index 1a38501de3..effcb997d8 100644 --- a/capsules/extra/src/usb/descriptors.rs +++ b/capsules/extra/src/usb/descriptors.rs @@ -8,7 +8,6 @@ use core::cell::Cell; use core::cmp::min; -use core::convert::From; use core::fmt; use kernel::hil::usb::TransferType; diff --git a/chips/apollo3/src/chip.rs b/chips/apollo3/src/chip.rs index 0de6cd7474..94b7df6dba 100644 --- a/chips/apollo3/src/chip.rs +++ b/chips/apollo3/src/chip.rs @@ -5,7 +5,7 @@ //! Chip trait setup. use core::fmt::Write; -use cortexm4::{self, CortexM4, CortexMVariant}; +use cortexm4::{CortexM4, CortexMVariant}; use kernel::platform::chip::Chip; use kernel::platform::chip::InterruptService; diff --git a/chips/apollo3/src/lib.rs b/chips/apollo3/src/lib.rs index ab93461f41..b8744db126 100644 --- a/chips/apollo3/src/lib.rs +++ b/chips/apollo3/src/lib.rs @@ -104,7 +104,7 @@ pub unsafe fn init() { } // Mock implementation for tests -#[cfg(not(any(target_arch = "arm", target_os = "none")))] +#[cfg(not(all(target_arch = "arm", target_os = "none")))] pub unsafe fn init() { // Prevent unused code warning. scb::disable_fpca(); diff --git a/chips/arty_e21_chip/src/chip.rs b/chips/arty_e21_chip/src/chip.rs index a85f14ae98..4f8abdefe3 100644 --- a/chips/arty_e21_chip/src/chip.rs +++ b/chips/arty_e21_chip/src/chip.rs @@ -3,12 +3,10 @@ // Copyright Tock Contributors 2022. use core::fmt::Write; -use kernel; use kernel::debug; use kernel::hil::time::Freq32KHz; use kernel::platform::chip::InterruptService; use kernel::utilities::registers::interfaces::Readable; -use rv32i; use crate::clint; use crate::interrupts; @@ -134,7 +132,7 @@ impl<'a, I: InterruptService + 'a> ArtyExx<'a, I> { } // Mock implementation for tests on Travis-CI. - #[cfg(not(any(target_arch = "riscv32", target_os = "none")))] + #[cfg(not(all(target_arch = "riscv32", target_os = "none")))] pub unsafe fn configure_trap_handler(&self) { unimplemented!() } diff --git a/chips/e310x/src/chip.rs b/chips/e310x/src/chip.rs index 063be0ceb1..f86e10db7f 100644 --- a/chips/e310x/src/chip.rs +++ b/chips/e310x/src/chip.rs @@ -5,11 +5,9 @@ //! High-level setup and interrupt mapping for the chip. use core::fmt::Write; -use kernel; use kernel::debug; use kernel::platform::chip::Chip; use kernel::utilities::registers::interfaces::{ReadWriteable, Readable}; -use rv32i; use rv32i::csr; use rv32i::csr::{mcause, mie::mie, mip::mip, CSR}; use rv32i::pmp::{simple::SimplePMP, PMPUserMPU}; diff --git a/chips/earlgrey/src/chip.rs b/chips/earlgrey/src/chip.rs index 6bcf409ded..7211e243bc 100644 --- a/chips/earlgrey/src/chip.rs +++ b/chips/earlgrey/src/chip.rs @@ -6,7 +6,6 @@ use core::fmt::{Display, Write}; use core::marker::PhantomData; -use kernel; use kernel::platform::chip::{Chip, InterruptService}; use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable}; use rv32i::csr::{mcause, mie::mie, mtvec::mtvec, CSR}; @@ -436,7 +435,7 @@ pub unsafe fn configure_trap_handler() { // Mock implementation for crate tests that does not include the section // specifier, as the test will not use our linker script, and the host // compilation environment may not allow the section name. -#[cfg(not(any(target_arch = "riscv32", target_os = "none")))] +#[cfg(not(all(target_arch = "riscv32", target_os = "none")))] pub extern "C" fn _start_trap_vectored() { use core::hint::unreachable_unchecked; unsafe { diff --git a/chips/earlgrey/src/registers/top_earlgrey.rs b/chips/earlgrey/src/registers/top_earlgrey.rs index df5efdbd85..4ec1a25bc1 100644 --- a/chips/earlgrey/src/registers/top_earlgrey.rs +++ b/chips/earlgrey/src/registers/top_earlgrey.rs @@ -24,8 +24,6 @@ //! - Pinmux Pin/Select Names //! - Power Manager Wakeups -use core::convert::TryFrom; - /// Peripheral base address for uart0 in top earlgrey. /// /// This should be used with #mmio_region_from_addr to access the memory-mapped diff --git a/chips/esp32-c3/src/chip.rs b/chips/esp32-c3/src/chip.rs index a5eee9dc9f..c8aea1d0b7 100644 --- a/chips/esp32-c3/src/chip.rs +++ b/chips/esp32-c3/src/chip.rs @@ -6,7 +6,6 @@ use core::fmt::Write; -use kernel; use kernel::platform::chip::{Chip, InterruptService}; use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable}; use kernel::utilities::StaticRef; @@ -288,7 +287,7 @@ pub unsafe fn configure_trap_handler() { // Mock implementation for crate tests that does not include the section // specifier, as the test will not use our linker script, and the host // compilation environment may not allow the section name. -#[cfg(not(any(target_arch = "riscv32", target_os = "none")))] +#[cfg(not(all(target_arch = "riscv32", target_os = "none")))] pub extern "C" fn _start_trap_vectored() { use core::hint::unreachable_unchecked; unsafe { diff --git a/chips/imxrt10xx/src/chip.rs b/chips/imxrt10xx/src/chip.rs index 7fc3f91338..2c300cb301 100644 --- a/chips/imxrt10xx/src/chip.rs +++ b/chips/imxrt10xx/src/chip.rs @@ -5,7 +5,7 @@ //! Chip trait setup. use core::fmt::Write; -use cortexm7::{self, CortexM7, CortexMVariant}; +use cortexm7::{CortexM7, CortexMVariant}; use kernel::debug; use kernel::platform::chip::{Chip, InterruptService}; diff --git a/chips/imxrt10xx/src/gpt.rs b/chips/imxrt10xx/src/gpt.rs index 8473742617..1587b82072 100644 --- a/chips/imxrt10xx/src/gpt.rs +++ b/chips/imxrt10xx/src/gpt.rs @@ -3,7 +3,6 @@ // Copyright Tock Contributors 2022. use core::sync::atomic::{AtomicU32, Ordering}; -use cortexm7; use cortexm7::support::atomic; use kernel::hil; use kernel::hil::time::{Ticks, Ticks32, Time}; diff --git a/chips/imxrt10xx/src/lib.rs b/chips/imxrt10xx/src/lib.rs index df0d55d27f..e4fb850181 100644 --- a/chips/imxrt10xx/src/lib.rs +++ b/chips/imxrt10xx/src/lib.rs @@ -229,9 +229,7 @@ pub unsafe fn init() { cortexm7::nvic::disable_all(); cortexm7::nvic::clear_all_pending(); - cortexm7::scb::set_vector_table_offset( - &BASE_VECTORS as *const [unsafe extern "C" fn(); 16] as *const (), - ); + cortexm7::scb::set_vector_table_offset(core::ptr::addr_of!(BASE_VECTORS) as *const ()); cortexm7::nvic::enable_all(); } diff --git a/chips/imxrt10xx/src/lpuart.rs b/chips/imxrt10xx/src/lpuart.rs index 39bfb2279a..57a8daa722 100644 --- a/chips/imxrt10xx/src/lpuart.rs +++ b/chips/imxrt10xx/src/lpuart.rs @@ -395,7 +395,7 @@ impl<'a> Lpuart<'a> { dma_channel.set_client(self, self.tx_dma_source); unsafe { // Safety: pointing to static memory - dma_channel.set_destination(&self.registers.data as *const _ as *const u8); + dma_channel.set_destination(core::ptr::addr_of!(self.registers.data) as *const u8); } dma_channel.set_interrupt_on_completion(true); dma_channel.set_disable_on_completion(true); @@ -407,7 +407,7 @@ impl<'a> Lpuart<'a> { dma_channel.set_client(self, self.rx_dma_source); unsafe { // Safety: pointing to static memory - dma_channel.set_source(&self.registers.data as *const _ as *const u8); + dma_channel.set_source(core::ptr::addr_of!(self.registers.data) as *const u8); } dma_channel.set_interrupt_on_completion(true); dma_channel.set_disable_on_completion(true); diff --git a/chips/litex_vexriscv/src/chip.rs b/chips/litex_vexriscv/src/chip.rs index c30f7f62f6..7f066a0164 100644 --- a/chips/litex_vexriscv/src/chip.rs +++ b/chips/litex_vexriscv/src/chip.rs @@ -5,7 +5,6 @@ //! High-level setup and interrupt mapping for the chip. use core::fmt::Write; -use kernel; use kernel::debug; use kernel::platform::chip::InterruptService; use kernel::utilities::registers::interfaces::{ReadWriteable, Readable}; diff --git a/chips/litex_vexriscv/src/interrupt_controller.rs b/chips/litex_vexriscv/src/interrupt_controller.rs index ecff09f86a..4abc24d50a 100644 --- a/chips/litex_vexriscv/src/interrupt_controller.rs +++ b/chips/litex_vexriscv/src/interrupt_controller.rs @@ -102,7 +102,7 @@ mod vexriscv_irq_raw { /// defined in litex/soc/cores/cpu/vexriscv/csr-defs.h const CSR_IRQ_PENDING: usize = 0xFC0; - #[cfg(not(any(target_arch = "riscv32", target_os = "none")))] + #[cfg(not(all(target_arch = "riscv32", target_os = "none")))] pub unsafe fn irq_getmask() -> usize { 0 } @@ -117,7 +117,7 @@ mod vexriscv_irq_raw { mask } - #[cfg(not(any(target_arch = "riscv32", target_os = "none")))] + #[cfg(not(all(target_arch = "riscv32", target_os = "none")))] pub unsafe fn irq_setmask(_mask: usize) {} #[cfg(all(target_arch = "riscv32", target_os = "none"))] @@ -128,7 +128,7 @@ mod vexriscv_irq_raw { asm!("csrw 0xBC0, {mask}", mask = in(reg) mask); } - #[cfg(not(any(target_arch = "riscv32", target_os = "none")))] + #[cfg(not(all(target_arch = "riscv32", target_os = "none")))] pub unsafe fn irq_pending() -> usize { 0 } diff --git a/chips/msp432/src/chip.rs b/chips/msp432/src/chip.rs index 615989a09f..80a6ca893e 100644 --- a/chips/msp432/src/chip.rs +++ b/chips/msp432/src/chip.rs @@ -3,7 +3,7 @@ // Copyright Tock Contributors 2022. use core::fmt::Write; -use cortexm4::{self, CortexM4, CortexMVariant}; +use cortexm4::{CortexM4, CortexMVariant}; use kernel::platform::chip::Chip; use crate::nvic; diff --git a/chips/msp432/src/uart.rs b/chips/msp432/src/uart.rs index 448b1c06b2..8a24bb6c44 100644 --- a/chips/msp432/src/uart.rs +++ b/chips/msp432/src/uart.rs @@ -10,7 +10,6 @@ use core::cell::Cell; use kernel::hil; use kernel::utilities::cells::OptionalCell; use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable}; -use kernel::utilities::registers::{ReadOnly, ReadWrite}; use kernel::utilities::StaticRef; use kernel::ErrorCode; @@ -257,7 +256,7 @@ impl<'a> hil::uart::Transmit<'a> for Uart<'a> { Err((ErrorCode::BUSY, tx_buffer)) } else { self.tx_busy.set(true); - let tx_reg = (&self.registers.txbuf as *const ReadWrite).cast::<()>(); + let tx_reg = core::ptr::addr_of!(self.registers.txbuf).cast::<()>(); self.tx_dma .map(move |dma| dma.transfer_mem_to_periph(tx_reg, tx_buffer, tx_len)); Ok(()) @@ -305,7 +304,7 @@ impl<'a> hil::uart::Receive<'a> for Uart<'a> { Err((ErrorCode::BUSY, rx_buffer)) } else { self.rx_busy.set(true); - let rx_reg = (&self.registers.rxbuf as *const ReadOnly).cast::<()>(); + let rx_reg = core::ptr::addr_of!(self.registers.rxbuf).cast::<()>(); self.rx_dma .map(move |dma| dma.transfer_periph_to_mem(rx_reg, rx_buffer, rx_len)); Ok(()) diff --git a/chips/nrf52/src/ble_radio.rs b/chips/nrf52/src/ble_radio.rs index 03e889dbb4..104bdc79db 100644 --- a/chips/nrf52/src/ble_radio.rs +++ b/chips/nrf52/src/ble_radio.rs @@ -38,7 +38,6 @@ //! * CRC - 3 bytes use core::cell::Cell; -use core::convert::TryFrom; use kernel::hil::ble_advertising; use kernel::hil::ble_advertising::RadioChannel; use kernel::utilities::cells::OptionalCell; diff --git a/chips/nrf52/src/chip.rs b/chips/nrf52/src/chip.rs index 95eb4d9401..3a4b8b6d74 100644 --- a/chips/nrf52/src/chip.rs +++ b/chips/nrf52/src/chip.rs @@ -3,7 +3,7 @@ // Copyright Tock Contributors 2022. use core::fmt::Write; -use cortexm4::{self, nvic, CortexM4, CortexMVariant}; +use cortexm4::{nvic, CortexM4, CortexMVariant}; use kernel::platform::chip::InterruptService; pub struct NRF52<'a, I: InterruptService + 'a> { diff --git a/chips/nrf52/src/pwm.rs b/chips/nrf52/src/pwm.rs index c3d8206d0a..afb619bb49 100644 --- a/chips/nrf52/src/pwm.rs +++ b/chips/nrf52/src/pwm.rs @@ -10,7 +10,6 @@ use kernel::utilities::registers::interfaces::Writeable; use kernel::utilities::registers::{register_bitfields, ReadWrite, WriteOnly}; use kernel::utilities::StaticRef; use kernel::ErrorCode; -use nrf5x; #[repr(C)] struct PwmRegisters { @@ -233,7 +232,10 @@ impl Pwm { // Setup the duty cycles unsafe { DUTY_CYCLES[0] = dc_out as u16; - self.registers.seq0.seq_ptr.set(&DUTY_CYCLES as *const u16); + self.registers + .seq0 + .seq_ptr + .set(core::ptr::addr_of!(DUTY_CYCLES) as *const u16); } self.registers.seq0.seq_cnt.write(SEQ_CNT::CNT.val(1)); self.registers diff --git a/chips/nrf52/src/uart.rs b/chips/nrf52/src/uart.rs index 3e4d98f518..99fcf22eac 100644 --- a/chips/nrf52/src/uart.rs +++ b/chips/nrf52/src/uart.rs @@ -10,7 +10,6 @@ //! * Author: Niklas Adolfsson //! * Date: March 10 2018 -use core; use core::cell::Cell; use core::cmp::min; use kernel::hil::uart; @@ -392,7 +391,7 @@ impl<'a> Uarte<'a> { self.registers.event_endtx.write(Event::READY::CLEAR); // precaution: copy value into variable with static lifetime BYTE = byte; - self.registers.txd_ptr.set((&BYTE as *const u8) as u32); + self.registers.txd_ptr.set(core::ptr::addr_of!(BYTE) as u32); self.registers.txd_maxcnt.write(Counter::COUNTER.val(1)); self.registers.task_starttx.write(Task::ENABLE::SET); } diff --git a/chips/nrf52840/src/ieee802154_radio.rs b/chips/nrf52840/src/ieee802154_radio.rs index a6206900ed..740cce7da7 100644 --- a/chips/nrf52840/src/ieee802154_radio.rs +++ b/chips/nrf52840/src/ieee802154_radio.rs @@ -6,8 +6,6 @@ use crate::timer::TimerAlarm; use core::cell::Cell; -use core::convert::TryFrom; -use kernel; use kernel::hil::radio::{self, PowerClient, RadioData}; use kernel::hil::time::{Alarm, AlarmClient, Time}; use kernel::utilities::cells::{OptionalCell, TakeCell}; @@ -16,7 +14,6 @@ use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, Writ use kernel::utilities::StaticRef; use kernel::ErrorCode; -use nrf52; use nrf52::constants::TxPower; // This driver implements a subset of 802.15.4 sending and receiving for the diff --git a/chips/nrf5x/src/constants.rs b/chips/nrf5x/src/constants.rs index 463a8072ce..d16846f11e 100644 --- a/chips/nrf5x/src/constants.rs +++ b/chips/nrf5x/src/constants.rs @@ -2,8 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT // Copyright Tock Contributors 2022. -use core::convert::TryFrom; - // PCNF0 pub const RADIO_PCNF0_LFLEN_POS: u32 = 0; pub const RADIO_PCNF0_S0LEN_POS: u32 = 8; diff --git a/chips/nrf5x/src/gpio.rs b/chips/nrf5x/src/gpio.rs index 3488bad690..18a60c25e3 100644 --- a/chips/nrf5x/src/gpio.rs +++ b/chips/nrf5x/src/gpio.rs @@ -24,7 +24,7 @@ const NUM_GPIOTE: usize = 4; const NUM_GPIOTE: usize = 8; // Dummy value for testing on Travis-CI. #[cfg(all( - not(any(target_arch = "arm", target_os = "none")), + not(all(target_arch = "arm", target_os = "none")), not(feature = "nrf51"), not(feature = "nrf52"), ))] diff --git a/chips/qemu_rv32_virt_chip/src/chip.rs b/chips/qemu_rv32_virt_chip/src/chip.rs index 95e92df557..58e98696b8 100644 --- a/chips/qemu_rv32_virt_chip/src/chip.rs +++ b/chips/qemu_rv32_virt_chip/src/chip.rs @@ -6,14 +6,12 @@ use core::fmt::Write; -use kernel; use kernel::debug; use kernel::hil::time::Freq10MHz; use kernel::platform::chip::{Chip, InterruptService}; use kernel::utilities::registers::interfaces::{ReadWriteable, Readable}; -use rv32i; use rv32i::csr::{mcause, mie::mie, mip::mip, CSR}; use crate::plic::PLIC; diff --git a/chips/rp2040/src/clocks.rs b/chips/rp2040/src/clocks.rs index 1ebc75e01b..6967be34ef 100644 --- a/chips/rp2040/src/clocks.rs +++ b/chips/rp2040/src/clocks.rs @@ -1059,7 +1059,7 @@ impl Clocks { } } - #[cfg(not(any(target_arch = "arm", target_os = "none")))] + #[cfg(not(all(target_arch = "arm", target_os = "none")))] fn loop_3_cycles(&self, _clock: Clock) { unimplemented!() } diff --git a/chips/rp2040/src/deferred_calls.rs b/chips/rp2040/src/deferred_calls.rs index c2fe383800..9a7c4281d4 100644 --- a/chips/rp2040/src/deferred_calls.rs +++ b/chips/rp2040/src/deferred_calls.rs @@ -7,9 +7,6 @@ //! Deferred calls also peripheral drivers to register pseudo interrupts. //! These are the definitions of which deferred calls this chip needs. -use core::convert::Into; -use core::convert::TryFrom; - /// A type of task to defer a call for #[derive(Copy, Clone)] pub enum DeferredCallTask { diff --git a/chips/rp2040/src/lib.rs b/chips/rp2040/src/lib.rs index 8536e202a6..7ed5a0924f 100644 --- a/chips/rp2040/src/lib.rs +++ b/chips/rp2040/src/lib.rs @@ -23,9 +23,7 @@ pub mod usb; pub mod watchdog; pub mod xosc; -use cortexm0p::{ - self, initialize_ram_jump_to_main, unhandled_interrupt, CortexM0P, CortexMVariant, -}; +use cortexm0p::{initialize_ram_jump_to_main, unhandled_interrupt, CortexM0P, CortexMVariant}; extern "C" { // _estack is not really a function, but it makes the types work diff --git a/chips/rp2040/src/timer.rs b/chips/rp2040/src/timer.rs index 73fbe3e1ac..ff4f44aeaf 100644 --- a/chips/rp2040/src/timer.rs +++ b/chips/rp2040/src/timer.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT // Copyright Tock Contributors 2022. -use cortexm0p; use cortexm0p::support::atomic; use kernel::hil; use kernel::hil::time::{Alarm, Ticks, Ticks32, Time}; diff --git a/chips/sam4l/src/chip.rs b/chips/sam4l/src/chip.rs index e0ad6de312..b650b2a381 100644 --- a/chips/sam4l/src/chip.rs +++ b/chips/sam4l/src/chip.rs @@ -7,7 +7,7 @@ use crate::pm; use core::fmt::Write; -use cortexm4::{self, CortexM4, CortexMVariant}; +use cortexm4::{CortexM4, CortexMVariant}; use kernel::platform::chip::{Chip, InterruptService}; pub struct Sam4l { diff --git a/chips/sam4l/src/crccu.rs b/chips/sam4l/src/crccu.rs index 03a5c7af14..0271de9993 100644 --- a/chips/sam4l/src/crccu.rs +++ b/chips/sam4l/src/crccu.rs @@ -511,7 +511,7 @@ impl<'a> Crc<'a> for Crccu<'a> { // Set the descriptor memory address accordingly self.registers .dscr - .set(&self.descriptor as *const Descriptor as u32); + .set(core::ptr::addr_of!(self.descriptor) as u32); // Configure the unit to compute a checksum self.registers.mr.write( diff --git a/chips/sam4l/src/usbc/mod.rs b/chips/sam4l/src/usbc/mod.rs index e585dda3bf..f2dcc7d883 100644 --- a/chips/sam4l/src/usbc/mod.rs +++ b/chips/sam4l/src/usbc/mod.rs @@ -520,7 +520,9 @@ impl<'a> Usbc<'a> { usbc_regs().usbcon.modify(Control::USBE::SET); // Set the pointer to the endpoint descriptors - usbc_regs().udesc.set(&self.descriptors as *const _ as u32); + usbc_regs() + .udesc + .set(core::ptr::addr_of!(self.descriptors) as u32); // Clear pending device global interrupts usbc_regs().udintclr.write( @@ -1396,7 +1398,7 @@ impl<'a> Usbc<'a> { \n {:?}\ \n {:?}\ \n {:?}", - bi, // (&b.addr as *const _), b.addr.get(), + bi, // core::ptr::addr_of!(b.addr), b.addr.get(), b.packet_size.get(), b.control_status.get(), _buf.map(HexBuf) diff --git a/chips/stm32f303xc/src/tim2.rs b/chips/stm32f303xc/src/tim2.rs index b7f3ab83b4..8e00e2fa3c 100644 --- a/chips/stm32f303xc/src/tim2.rs +++ b/chips/stm32f303xc/src/tim2.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT // Copyright Tock Contributors 2022. -use cortexm4; use cortexm4::support::atomic; use kernel::hil::time::{ Alarm, AlarmClient, Counter, Freq16KHz, OverflowClient, Ticks, Ticks32, Time, diff --git a/chips/stm32f4xx/src/chip.rs b/chips/stm32f4xx/src/chip.rs index 678bb807b0..d69c1cec3f 100644 --- a/chips/stm32f4xx/src/chip.rs +++ b/chips/stm32f4xx/src/chip.rs @@ -5,7 +5,7 @@ //! Chip trait setup. use core::fmt::Write; -use cortexm4::{self, CortexM4, CortexMVariant}; +use cortexm4::{CortexM4, CortexMVariant}; use kernel::platform::chip::Chip; use kernel::platform::chip::InterruptService; diff --git a/chips/stm32f4xx/src/fsmc.rs b/chips/stm32f4xx/src/fsmc.rs index 49ae8f66aa..08d98361a4 100644 --- a/chips/stm32f4xx/src/fsmc.rs +++ b/chips/stm32f4xx/src/fsmc.rs @@ -266,12 +266,12 @@ impl<'a> Fsmc<'a> { } } - #[cfg(not(any(target_arch = "arm", target_os = "none")))] + #[cfg(not(all(target_arch = "arm", target_os = "none")))] fn write_reg(&self, _bank: FsmcBanks, _addr: u16) { unimplemented!() } - #[cfg(not(any(target_arch = "arm", target_os = "none")))] + #[cfg(not(all(target_arch = "arm", target_os = "none")))] fn write_data(&self, _bank: FsmcBanks, _data: u16) { unimplemented!() } diff --git a/chips/stm32f4xx/src/gpio.rs b/chips/stm32f4xx/src/gpio.rs index 66b8de09fd..69800996de 100644 --- a/chips/stm32f4xx/src/gpio.rs +++ b/chips/stm32f4xx/src/gpio.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT // Copyright Tock Contributors 2022. -use cortexm4; use cortexm4::support::atomic; use enum_primitive::cast::FromPrimitive; use enum_primitive::enum_from_primitive; diff --git a/chips/stm32f4xx/src/spi.rs b/chips/stm32f4xx/src/spi.rs index 80ed219145..fcc8008bbc 100644 --- a/chips/stm32f4xx/src/spi.rs +++ b/chips/stm32f4xx/src/spi.rs @@ -143,7 +143,7 @@ register_bitfields![u32, // for use by dma1 pub(crate) fn get_address_dr(regs: StaticRef) -> u32 { - ®s.dr as *const ReadWrite as u32 + core::ptr::addr_of!(regs.dr) as u32 } pub const SPI3_BASE: StaticRef = diff --git a/chips/stm32f4xx/src/tim2.rs b/chips/stm32f4xx/src/tim2.rs index 1d42ed10e9..c090572cd0 100644 --- a/chips/stm32f4xx/src/tim2.rs +++ b/chips/stm32f4xx/src/tim2.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT // Copyright Tock Contributors 2022. -use cortexm4; use cortexm4::support::atomic; use kernel::hil::time::{ Alarm, AlarmClient, Counter, Freq16KHz, OverflowClient, Ticks, Ticks32, Time, diff --git a/chips/stm32f4xx/src/usart.rs b/chips/stm32f4xx/src/usart.rs index df4de2db8e..6ff7a5ad88 100644 --- a/chips/stm32f4xx/src/usart.rs +++ b/chips/stm32f4xx/src/usart.rs @@ -160,7 +160,7 @@ pub const USART3_BASE: StaticRef = // for use by dma1 pub(crate) fn get_address_dr(regs: StaticRef) -> u32 { - ®s.dr as *const ReadWrite as u32 + core::ptr::addr_of!(regs.dr) as u32 } #[allow(non_camel_case_types)] diff --git a/chips/swervolf-eh1/src/chip.rs b/chips/swervolf-eh1/src/chip.rs index bef4173a9c..1ab6f799ff 100644 --- a/chips/swervolf-eh1/src/chip.rs +++ b/chips/swervolf-eh1/src/chip.rs @@ -5,7 +5,6 @@ //! High-level setup and interrupt mapping for the chip. use core::fmt::Write; -use kernel; use kernel::platform::chip::{Chip, InterruptService}; use kernel::utilities::cells::VolatileCell; use kernel::utilities::registers::interfaces::{ReadWriteable, Readable}; diff --git a/doc/syscalls/README.md b/doc/syscalls/README.md index 7146d31111..72cd43fe7a 100644 --- a/doc/syscalls/README.md +++ b/doc/syscalls/README.md @@ -15,12 +15,13 @@ provided syscalls, and the driver specific interfaces (using `allow`, * [Base](#base) * [Kernel](#kernel) * [Hardware Access](#hardware-access) - * [Radio](#radio) + * [Networking](#networking) * [Cryptography](#cryptography) * [Storage](#storage) * [Sensors](#sensors) * [Sensor ICs](#sensor-ics) * [Other ICs](#other-ics) + * [Display](#display) * [Miscellaneous](#miscellaneous) @@ -47,17 +48,13 @@ stabilized or not (a "✓" indicates stability) in the Tock 2.0 release. | ✓ | 0x00001 | [Console](00001_console.md) | UART console | | ✓ | 0x00002 | [LED](00002_leds.md) | Control LEDs on board | | ✓ | 0x00003 | [Button](00003_buttons.md) | Get interrupts from buttons on the board | -| ✓ | 0x00005 | [ADC](00005_adc.md) | Sample analog-to-digital converter pins | -| | 0x00006 | DAC | Digital to analog converter | -| | 0x00007 | [AnalogComparator](00007_analog_comparator.md) | Analog Comparator | | | 0x00008 | [Low-Level Debug](00008_low_level_debug.md) | Low-level debugging tools | -| | 0x00009 | [ROS](00009_ros.md) | Read Only State, access system information | -| | 0x00010 | [PWM](00010_pwm.md) | Control PWM pins | ### Kernel |2.0| Driver Number | Driver | Description | |---|---------------|------------------|--------------------------------------------| +| | 0x00009 | [ROS](00009_ros.md) | Read Only State, access system information | | | 0x10000 | IPC | Inter-process communication | ### Hardware Access @@ -65,6 +62,10 @@ stabilized or not (a "✓" indicates stability) in the Tock 2.0 release. |2.0| Driver Number | Driver | Description | |---|---------------|------------------|--------------------------------------------| | | 0x00004 | [GPIO](00004_gpio.md) | Set and read GPIO pins | +| ✓ | 0x00005 | [ADC](00005_adc.md)| Sample analog-to-digital converter pins | +| | 0x00006 | DAC | Digital to analog converter | +| | 0x00007 | [AnalogComparator](00007_analog_comparator.md) | Analog Comparator | +| | 0x00010 | [PWM](00010_pwm.md)| Control PWM pins | | | 0x20000 | UART | UART | | | 0x20001 | SPI | Raw SPI Master interface | | | 0x20002 | SPI Slave | Raw SPI slave interface | @@ -75,7 +76,7 @@ stabilized or not (a "✓" indicates stability) in the Tock 2.0 release. _Note:_ GPIO is slated for re-numbering in Tock 2.0. -### Radio +### Networking |2.0| Driver Number | Driver | Description | |---|---------------|------------------|--------------------------------------------| @@ -107,10 +108,11 @@ _Note:_ GPIO is slated for re-numbering in Tock 2.0. | ✓ | 0x60000 | [Ambient Temp.](60000_ambient_temperature.md) | Ambient temperature (centigrate) | | ✓ | 0x60001 | [Humidity](60001_humidity.md) | Humidity Sensor (percent) | | ✓ | 0x60002 | [Luminance](60002_luminance.md) | Ambient Light Sensor (lumens) | -| | 0x60003 | Pressure | Pressure sensor | -| | 0x60004 | Ninedof | Virtualized accelerometer/magnetometer/gyroscope | -| | 0x60005 | Proximity | Proximity Sensor | -| | 0x60006 | SoundPressure | Sound Pressure Sensor | +| | 0x60003 | Pressure | Pressure sensor | +| | 0x60004 | Ninedof | Virtualized accelerometer/magnetometer/gyroscope | +| | 0x60005 | Proximity | Proximity Sensor | +| | 0x60006 | SoundPressure | Sound Pressure Sensor | +| | 0x90002 | [Touch](90002_touch.md) | Multi Touch Panel | ### Sensor ICs @@ -132,11 +134,15 @@ _Note:_ GPIO is slated for re-numbering in Tock 2.0. | | 0x80003 | GPIO Async | Asynchronous GPIO pins | | | 0x80004 | nRF51822 | nRF serialization link to nRF51822 BLE SoC | -### Miscellaneous +### Display |2.0| Driver Number | Driver | Description | |---|---------------|-----------------------------------------|--------------------------------------------| -| | 0x90000 | Buzzer | Buzzer | | | 0x90001 | [Screen](90001_screen.md) | Graphic Screen | -| | 0x90002 | [Touch](90002_touch.md) | Multi Touch Panel | | | 0x90003 | [Text Screen](90003_text_screen.md) | Text Screen | + +### Miscellaneous + +|2.0| Driver Number | Driver | Description | +|---|---------------|-----------------------------------------|--------------------------------------------| +| | 0x90000 | Buzzer | Buzzer | diff --git a/doc/wg/core/README.md b/doc/wg/core/README.md index 2095a007ce..224c9fc94f 100644 --- a/doc/wg/core/README.md +++ b/doc/wg/core/README.md @@ -26,6 +26,7 @@ are to: - Philip Levis, [phil-levis](https://github.com/phil-levis), Stanford - Amit Levy (chair), [alevy](https://github.com/alevy), Princeton University - Pat Pannuto, [ppannuto](https://github.com/ppannuto), UCSD +- Alexandru Radovici [alexandruradovici](https://github.com/alexandruradovici), Politehnica Bucharest & OxidOS - Leon Schuermann, [lschuermann](https://github.com/lschuermann), Princeton University - Johnathan Van Why, [jrvanwhy](https://github.com/jrvanwhy), Google diff --git a/doc/wg/core/notes/core-notes-2024-02-09.md b/doc/wg/core/notes/core-notes-2024-02-09.md new file mode 100644 index 0000000000..6acb6ff886 --- /dev/null +++ b/doc/wg/core/notes/core-notes-2024-02-09.md @@ -0,0 +1,124 @@ +# Tock Meeting Notes 02/09/24 + +## Attendees + +- Branden Ghena +- Amit Levy +- Leon Schuermann +- Brad Campbell +- Alex Radovici +- Jonathan Van Why +- Alyssa Haroldson +- Tyler Potyondy +- Pat Pannuto + + +## Updates +### Display Support +* Brad: OLED screen work is in a good state in libtock-c. Support for the monochrome display is good +* Amit: Where does the display driver live? +* Brad: It's in the kernel +* Amit: And the C library just does like fonts and stuff +* Brad: Yes. The C library layers on top of the syscall interface we already had + +### Hardware CI +* Leon: Update on Tock CI development. System I present a few weeks ago, is now being used for a CW310 OpenTitan board. You can start jobs and get access to a Linux container that has access to the board. So it's a good solution for boards we don't have many of, and in the future for automatically running jobs. +* Amit: Remote, reservation-based build environment. On the path towards building a CI system +* Brad: Would CI be essentially the same as a person using it? +* Leon: The base for this can talk github API, so whenever a github workload is created we get a webhook request to the server along with which type of job. The job is scheduled with a parameter of the workflow ID. So the environment would run a github action runner in "ephemeral" mode. Then that can run the job and reports back. The only difference is that we won't have to pretend to be a user and send SSH commands. We'll start a workflow that actually just runs some tasks + +### Tockworld +* Amit: Tockworld update. Thanks to Pat we're moving forward with securing space at UCSD + + +## Mutable static references +* https://github.com/tock/tock/issues/3841 +* Alex: We have a problem with the new version of Rust. It won't compile mutable static references in the future. It's a warning right now. We get 25 warnings on the Microbit right now, which will become errors soon. +* Brad: CI is checking this warning here: https://github.com/tock/tock/pull/3842 +* Alex: Leon incidentally fixed one of these issues in the boards file, with the `ptr_address_of` change Alyssa proposed +* Leon: Yes, I still need to rebase that, but the change is mostly good. +* Alex: Deferred calls and several other places use static mut references too +* Amit: So that'll be important to address +* Alyssa: We might have to change to unsafe cell with a helper that gives a reference. Would have a .get_mut() function +* Amit: Unsafe cell has a const constructor, so that's probably fine. Just extra wrapping code +* Johnathan: `static mut` is stabilized as part of the 2021 edition. So the stable compiler can't deny that anytime soon at least. I feel like they can't just switch it off like that with Rust's stability promises +* Amit: Yeah. So it might not be urgent. +* Branden: Maybe this is real because we're on a nightly? The warning seems to promise that it will be an error +* Amit: It's an edition thing. The Rust 2024 edition will break it, even if the Rust 2021 edition allows it. +* Alyssa: Dependencies can stay on 2021, even if you're on 2024 +* Amit: We should still fix. Especially if it's as simple as Alyssa suggests +* Alyssa: You could do `&mut* ptr_address_of()` still. That overcomes the lint +* Johnathan: That's fine for now. But it would be good to move towards what they want at some point. They're trying to get us to avoid this for a reason, so we'll likely eventually have a Tock cell that wraps unsafe cell in some way. +* Alyssa: Ti50 has a version like this. It acts differently on chip than on host for testing purposes. Unsafe sell or a checked, sync cell of some type + +## Removing naked functions +* https://github.com/tock/tock/pull/3802 +* Amit: This would get us to stable, I believe +* Brad: Yes. We've handled the last few other things. So that means we can merge this to remove the last nightly feature on ARM, and the Hail board compiles on stable! +* Branden: What's the nightly feature on RISC-V? +* Brad: ASM-const for the CSR library. It's more difficult. +* Jonathan: I see a rewrite coming when we update Tock registers +* Brad: The point is, if we're going to compile 99% of our boards on nightly, because we still like our nightly features, this is just a proof-of-concept that we _can_ compile on stable and will test roughly half of our code on stable. Importantly the capsules and kernel crates +* Alyssa: I see progress towards stable as unambiguously good +* Leon: I do think this is a great idea. What has made me skittish is that while we were making these changes, we had problems with the linker placing assembly code and not being able to branch between them. So I'm worried that the linker won't be able to make some optimizations now. The benchmarks CI run doesn't show any massive memory increases (or decreases) so we're probably okay, but I want awareness +* Amit: How did we fix it? +* Leon: I think we jump to a constant now, instead of a relative jump +* Amit: This is now on the merge queue +* Branden: Why do we want to be on nightly at all? +* Brad: Two makefile-level things that boards can opt into. Compiling our own Core library with optimizations, and a testing framework. +* Leon: I think we can use macro_rules to hack around the RISC-V CSR stuff. We could have an expansion which builds the actual CSR assembly strings from a macro +* Pat: I think we had the macro version before, and left it because it was ugly. So we could certainly go back +* Brad: So overview, we could go back to that. If there's someone who's motivated to see RISC-V on stable we wouldn't preclude that. I don't personally care though, because I think one example on stable is good enough. +* Brad: Our plan for stable, is that once the Tock registers update that will affect the CSR stuff, and then we'll chip away at that feature too. +* Branden: And it is nice to have some things on nightly and some things on stable, so we're testing both +* Johnathan: We also want to test stuff with MIRI, and that'll require nightly. +* Alyssa: Unfortunately MIRI won't be stabilized until the Rust memory model is stabilized, so it's going to be a _while_. More than 3-5 years out +* Amit: Comparatively, naked functions are basically dead though + +## Process Checking +* https://github.com/tock/tock/pull/3772 +* Amit: Phil isn't here to discuss unfortunately +* Brad: I do want to handle this, but I agree we could push it + +## Libtock-C Refresh +* Amit: High-level, Libtock-C could use some love. Tyler brought part of this up +* Brad: Yeah, Tyler brought up how clumsy libtock-c is to use. It's been cobbled together at low-effort for testing kernel features. Then I realized I wasn't sure what it meant to "fix" it or how to start. So, I want to crowdsource ideas on how to improve it +* Branden: A trivial answer is documentation, which is quite lacking +* Tyler: An example, there's an assumption listed in one of the alarm files that may or may not be valid anymore. It would be great to know "what are the assumptions" about how you use APIs. For example, requirements based on the frequencies they're running at. Probably falls under documentation +* Amit: Aside from documentation, two things. First, we could consider the build infrastructure. Even with the best C tools, stuff is hard. But things like CMake are more ergonomic for relying on libraries. That could be a big deal. It's a chicken-and-egg thing where people aren't asking for this, partially because it's not easy to use right now. +* Leon: It would be great to pull libtock-c into an out-of-tree library too +* Leon: Also, we have pretty inconsistent APIs in libtock-c. I'm not sure even all kernel changes ever made it into userspace. It would be great to version individual subsystems. We basically don't have any stability guarantees for libtock-c right now +* Tyler: As part of the CI tests for libtock-c, we build things, but I don't think we actually have unit tests for anything. +* Leon: There's one very limited one. The Tock CI tests an ancient version of libtock-c for the litex board +* Amit: The second one, was that it could be worth separating the libtock-c which we currently have which is a useful proving ground and isn't particularly good for real applications from an alternative userspace. We could have a new one designed from the top down. Although there's a question for who would do that +* Brad: Where do those interfaces come from? +* Amit: There _are_ users that are building C apps. They don't currently contribute upstream. I'm not sure what their libtock-c stuff looks like or how it works. I just know that they are building applications in C for Tock. +* Amit: In general, the interface would come from applications. We might need to talk with groups who do make applications +* Amit: There is this IoT application thing now that Tyler is revisiting. C seems important in that domain. +* Amit: We could replicate some similar API from an existing system. Proton-style for example. It would be much more constrained, but that enables better documentation since there's less stuff +* Brad: So how much would be exposed and where are the pain points is the question. If a more-documented smaller API would be helpful, that's one answer +* Brad: One idea I had was just reorganizing things. Making a folder-structure here for categories of drivers seems useful +* Branden: The examples folder is a mess too. And there's a tests folder in there where it's unclear what goes where +* Pat: Could we match the syscall numbers which are in tables in the kernel by types. We could use those same types for our folders +* Brad: Yes. I'll look at that +* Brad: Does any of this seem like the thing that would move the needle Tyler? +* Tyler: I think it would help. As someone who came into the project recently, and I'm working with two undergrads on the open-thread abstractions, there are function prototypes where we're connecting OpenThread to Libtock-C. The biggest pain-points are the documentation, but specifically and worse the inconsistencies in APIs and places where the kernel has changed and we just get some generic error when making a call. +* Tyler: I'm not sure if a simpler redesign would be good. It would help. But I can't decide on restart versus repair +* Brad: I think the consistency thing is a clear issue. Part of what I would hope to do with a reorganization is separate the testing stuff from interfaces that are more preferable. It's fine to have an interface to a specific IC, but we really want a Temperature interface. So we could guide people to more general, well-made APIs +* Brad: One question, are you saying some things just don't work on Master for kernel and userspace? +* Tyler: There are syscalls that are deprecated and just do nothing in the Thread stuff for example. You do get an appropriate error back at least +* Brad: That's a bug in my mind. Someone should have "fixed" libtock-c +* Tyler: I don't know if there's a way to automate this, but it would be neat to tag things in the kernel with what they associate with in userspace, so making changes in one would flag a required change in the other. The same issue will otherwise occur in a few years even if we fix everything now, as long as nothing is checking that we keep the two in alignment. +* Leon: I don't fully agree with classifying them all as bugs. One of my conclusions is that in the kernel the development of kernel stuff that guides releases goes mostly independently of capsules. We don't use capsules to inform kernel releases often. So they change and get out-of-sync. Having some relation of which capsule API we want and whatever libtock-c currently expects would be good +* Brad: Anyone is free to stabilize a capsule syscall interface, although we do so rarely. Then userspace wouldn't have to change because it's stable +* Leon: I guess. I'm concerned that's not realistic though. For example, was the alarm stuff a part of the release? +* Brad: I think we deprecated the old stuff, but left it there. I am aggressive about not breaking userspace after we agreed on stability +* Brad: Users do expect functions to work. So some way to check that the functions work would be useful. Possibly CI testing which could block PRs for kernel or userspace. I think fixing a lot of entry-level stuff would help a lot. But then we still do need to decide on what our interfaces _should_ be. I'm not sure +* Tyler: Depends on who's using it. They might define usability differently +* Amit: Hopefully we could talk to some of the users and ask questions about their use +* Tyler: One more thought, speaking to the alarm infrastructure, there's a surprising and troubling amount of bugs in the implementation. The time-as-tick PR but also I think the queue of alarms has some issues with sorting. I'm not sure it's actually a real-world issue but it could be an edge case. So I think we should be thinking about unit tests too +* Branden: I think that's a rare case though. Most drivers just rely on the kernel syscalls to do almost all work +* Tyler: The alarm has a lot of logic. Maybe there are others with a lot of logic and we should have testing for them. It is a shame if the kernel does all this hard work, and libtock-c ruins it. +* Amit: I suspect there's not much logic, primarily because libtock-c was for testing the kernel. A redesign could have more logic though +* Tyler: So moving forward, documentation push first, and I'll help there. Then we could kick-off the process of talking to stakeholders. Would be useful + diff --git a/doc/wg/core/notes/core-notes-2024-02-16.md b/doc/wg/core/notes/core-notes-2024-02-16.md new file mode 100644 index 0000000000..3d77030785 --- /dev/null +++ b/doc/wg/core/notes/core-notes-2024-02-16.md @@ -0,0 +1,96 @@ +# Tock Meeting Notes 02/16/24 + +## Attendees + +- Branden Ghena +- Hudson Ayers +- Leon Schuermann +- Jonathan Van Why +- Andrew Imwalle +- Tyler Potyondy +- Brad Campbell +- Philip Levis +- Pat Pannuto +- Alex Radovici + + +## Updates +### Certification and Unit Tests +* Alex: Started writing unit tests for Tock (in the process of certifying). We're not sure how to do this, and posted an issue looking for help/advice: https://github.com/tock/tock/issues/3854 +### Board with Display +* Brad: PR on makepython-nrf52840 board with screen drivers needs reviews. Board isn't very interesting, but the capsules matter: https://github.com/tock/tock/pull/3817 + + +## Async Process Loading +* https://github.com/tock/tock/pull/3849 +* Brad: This is a refactor on process loading/checking to make it all asynchronous. It's been tricky to handle the synchronous code that exists with the rest of the asynchronous Tock stuff, specifically you don't get errors along the way, just one error for the whole thing. So the PR spells out some details on why this refactor helps +* Brad: The major change is that we currently load anything that looks like a valid TBF into a full process object, then decide if it's valid. So we committed a bunch of resources to something that might not be credentialed. So by splitting the tasks of checking and creating, we can stop it short and skip over things that are never going to be valid. This is particularly helpful on the path towards dynamic process loading, for loading new processes at runtime +* Phil: One point you made there, is the idea that you have a process that's parsed and syntactically valid from a TBF perspective, but we haven't loaded it so we don't know if it has a proper ID. If I want to check a signature, do I just check once, or each time I want to run it? +* Brad: Just once. Between parsing the binary and creating a process standard object in the processes array. +* Phil: What happens if I have two images, 1 and 2, and both of them have TBFs checked. I want to load version 1, then later want to stop it and load version 2 into that slot. Then later want to go back to version 1. Do I have to check the signature every time? Or just once? It's probably not a show-stopper, I'm just trying to understand. +* Brad: The primitive that's in the PR right now is that once a process is in the processes array, it has a valid credential. If you modify the binary, that would not be true. Other than that, the credential should still pass. +* Phil: So, three steps, checking loading and running. The credentials are part of the loading step. So if you have a shortage of process array elements, then re-checking signatures when swapping could be an issue. Although that's very hypothetical. +* Brad: There are two ways to think about that. Yes, you could end up having to recheck. But part of the implementation adds a process binary array, and that holds the object after parsed, but before loading into a full process. +* Phil: So you'd have unloaded, but parsed, binaries. +* Brad: Yes, you could do that +* Phil: So there are 4 levels: exists, parsed, loaded, running. That makes sense +* Brad: I had hoped that we could get away without parsed, but then I don't know how to do version checking. You need to hold everything you might want to run, so you can choose the best one to run. +* Phil: Something to think about for async is what are the operations that are async. It sounds like parsing is now async. Really, what's the granularity of async operations in the new approach? +* Brad: It's really just the credentials checker. Then the entire loading process happens as an async thing. You could a bunch of deferred calls, but you don't have to. There is one though, so we start on an async and can do callbacks. So a drop-in replacement could read from an external chip. +* Phil: That makes sense to me. This is a good idea. It was something I struggled with and was trying to figure out how to make it async, but the PR was so big already +* Brad: Definitely +* Brad: The other change that falls out of this: the core kernel loop treats the processes array like it did before credentials checking. Anything in that array is totally valid to execute. So all of the checking happens before the array is populated. +* Phil: That cleans up the loop. That's very nice +* Brad: Yes. That removes overhead if you don't want to do checking +* Phil: My one comment: now that process loading/checking is complicated with a four-stage state machine. It would be good to write a document describing it, as it will be totally non-obvious. What are the states, how do they transition, etc. +* Brad: Yes, good point +* Brad: Last thing, which will maybe be in this PR. What does happen if you want to dynamically swap processes. The idea that everything in the processes array is valid would no longer be true, and we'd need some way to check for uniqueness at that point. I'm still figuring that out. +* Brad: If you did a process update while the system is running, you have a new binary and would like to stop the old and load the new. But we need to make sure the uniqueness doesn't ever get violated. +* Phil: I thought you checked that it's unique before making a new process? +* Brad: Right. That was easy, but is hard in this PR. Because the kernel no longer has the checking mechanism to do that check. No reference to a checker. +* Phil: It'll probably need a reference. Whatever handles a call to transition a process will need that. +* Brad: Right now, if you only consider the boot case, you can do this once. But if there's a way to add a new process you need to do it again. And how that should work is a bit tricky. +* Phil: It just needs a reference, right? Or something else can mark a process as "has clearance to run". Which must be something that can assert uniqueness. +* Brad: Yup. I got to this stage yesterday or so. Still considering it. +* Phil: If you don't want the main loop to have a reference to the checker, you could add a new process state about whether a process is cleared as unique. And the kernel will only start those that are cleared. +* Phil: I am happy to continue to be a sounding board for this. I'm not good at tracking the github stream though. Send me an email about it please and that'll go faster. + +## Signed Processes +* https://github.com/tock/tock/pull/3772 +* Brad: It makes sense to have a trait per hash so we can keep track? +* Phil: Not per hash. Per signature algorithm. So you know which kind was used. And those types should define the size of the data and the contents +* Brad: Doing that elegantly doesn't seem possible right now. I might have a less elegant way to do it with a rust feature. +* Phil: Is the issue having two types? +* Brad: You can have the trait, and in theory there's just a constant attached to the trait which is the size. That's a nightly feature. +* Phil: Can't you associate a type with it? +* Brad: Yes, but not a constant one + +## Libtock-C Revamp +* https://github.com/tock/libtock-c/pull/370 +* Brad: I wrote a guide about how we could arrange the libtock C library to be usable but more predictable. Looking for comments there +* Hudson: I'll look into this +* Branden: I really strongly like this. I think it's a big step forward for libtock-c +* Leon: So this is mostly the status quo, but with a synchronous namespace? +* Brad: Two other things too. Requires wrappers for low-level syscalls. Second it is very prescriptive on what those names look like. + + +## Unit tests for Tock +* https://github.com/tock/tock/issues/3854 +* Alex: We want a certified version of Tock. Needs unit tests for every single line +* Alex: But it's difficult to test free-standing functions. For example, the TBF library. When doing unit tests, we have to mock up various other functions. The only way we found to do this is configurations for testing/not testing. I'd love some thoughts on how to do this +* Alex: We want, long term, these tests to get back into Tock. I know Tock doesn't like conditional compilation +* Pat: We do have some of this already. Conditional compilation for testing was the one type we really were okay with. I think it's just in arch right now? +* Alex: We'll need it in the kernel too though. And it can't just go in the test suite, it's got to go in the main code because when we compile it for testing we have to pull in a different mocked-up crate. Something I know is giving correct or incorrect answers so I can do unit tests on a function-by-function basis. +* Hudson: Yeah, but every dependency in the kernel having a config for testing or not testing will be really ugly, right? +* Alex: That's the issue. For anything that has a trait or a generic works fine. But everything, like the kernel, that doesn't do this is not fine. We would either need to modify the kernel to take the tock TBF as a trait, which wouldn't be a code size increase at least. Or we need configure +* Hudson: Yeah, that would have it's own problem. It would add generics everywhere and explode a bit. +* Leon: Doesn't Rust support default arguments for generics? That would potentially mean we could add a limited set of generic parameters but other things wouldn't need to care? +* Alex: So we could add it to kernel resources, add a default associated type, and in testing we'd override the kernel resources? +* Leon: Yes? It's still not "nice", but at least there's an interface contract that you explicitly write out in the code. I'm still not sure this is the right solution. But it could be useful. +* Alex: We're willing to try some things and see if it works well +* Alex: Generally, we'll need to do this everywhere we use libraries. Particularly, everywhere we use Cells. +* Johnathan: That seems like a weird line. Cells seems like something that doesn't need to be stubbed. Not sure if it's a requirement. +* Alex: It's a might right now. We'll argue it's a low-level primitive, but certification may still require it +* Alex: Long-term if anyone wants to use Tock in safety-critical environments, or even IoT in EU soon, certification will be a must +* Leon: We'll take a look at Leon's suggestion though, and see how it goes + diff --git a/kernel/src/errorcode.rs b/kernel/src/errorcode.rs index b99a40f034..7fc84b221e 100644 --- a/kernel/src/errorcode.rs +++ b/kernel/src/errorcode.rs @@ -4,8 +4,6 @@ //! Standard errors in Tock. -use core::convert::TryFrom; - /// Standard errors in Tock. /// /// In contrast to [`Result<(), ErrorCode>`](crate::Result<(), ErrorCode>) this diff --git a/kernel/src/hil/i2c.rs b/kernel/src/hil/i2c.rs index a1ee90883f..b4e748ca00 100644 --- a/kernel/src/hil/i2c.rs +++ b/kernel/src/hil/i2c.rs @@ -6,7 +6,6 @@ use crate::ErrorCode; -use core::convert::Into; use core::fmt; use core::fmt::{Display, Formatter}; diff --git a/kernel/src/hil/public_key_crypto/mod.rs b/kernel/src/hil/public_key_crypto/mod.rs index 66b074ffc9..f9c86d537a 100644 --- a/kernel/src/hil/public_key_crypto/mod.rs +++ b/kernel/src/hil/public_key_crypto/mod.rs @@ -6,3 +6,4 @@ pub mod keys; pub mod rsa_math; +pub mod signature; diff --git a/kernel/src/hil/public_key_crypto/signature.rs b/kernel/src/hil/public_key_crypto/signature.rs new file mode 100644 index 0000000000..2a2f6c4b79 --- /dev/null +++ b/kernel/src/hil/public_key_crypto/signature.rs @@ -0,0 +1,59 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2024. + +//! Interface for verifying signatures. + +use crate::ErrorCode; + +/// This trait provides callbacks for when the verification has completed. +pub trait ClientVerify { + /// Called when the verification is complete. + /// + /// If the verification operation encounters an error, result will be a + /// `Result::Err()` specifying the ErrorCode. Otherwise, result will be a + /// `Result::Ok` set to `Ok(true)` if the signature was correctly verified + /// and `Ok(false)` otherwise. + /// + /// If verification operation did encounter errors `result` will be `Err()` + /// with an appropriate `ErrorCode`. Valid `ErrorCode`s include: + /// + /// - `CANCEL`: the operation was cancelled. + /// - `FAIL`: an internal failure. + fn verification_done( + &self, + result: Result, + hash: &'static mut [u8; HL], + signature: &'static mut [u8; SL], + ); +} + +/// Verify a signature. +/// +/// This is a generic interface, and it is up to the implementation as to the +/// signature verification algorithm being used. +/// +/// - `HL`: The length in bytes of the hash. +/// - `SL`: The length in bytes of the signature. +pub trait SignatureVerify<'a, const HL: usize, const SL: usize> { + /// Set the client instance which will receive the `verification_done()` + /// callback. + fn set_verify_client(&self, client: &'a dyn ClientVerify); + + /// Verify the signature matches the given hash. + /// + /// If this returns `Ok(())`, then the `verification_done()` callback will + /// be called. If this returns `Err()`, no callback will be called. + /// + /// The valid `ErrorCode`s that can occur are: + /// + /// - `OFF`: the underlying digest engine is powered down and cannot be + /// used. + /// - `BUSY`: there is an outstanding operation already in process, and the + /// verification engine cannot accept another request. + fn verify( + &self, + hash: &'static mut [u8; HL], + signature: &'static mut [u8; SL], + ) -> Result<(), (ErrorCode, &'static mut [u8; HL], &'static mut [u8; SL])>; +} diff --git a/kernel/src/hil/spi.rs b/kernel/src/hil/spi.rs index 6cefbe248a..9731ebbc17 100644 --- a/kernel/src/hil/spi.rs +++ b/kernel/src/hil/spi.rs @@ -14,7 +14,6 @@ // Author: Amit Aryeh Levy use crate::ErrorCode; -use core::option::Option; /// Data order defines the order of bits sent over the wire: most /// significant first, or least significant first. diff --git a/kernel/src/hil/time.rs b/kernel/src/hil/time.rs index dc62b58457..4f0b5eccfe 100644 --- a/kernel/src/hil/time.rs +++ b/kernel/src/hil/time.rs @@ -16,7 +16,7 @@ //! into these more general ones. use crate::ErrorCode; -use core::cmp::{Eq, Ord, Ordering, PartialOrd}; +use core::cmp::Ordering; use core::fmt; /// An integer type defining the width of a time value, which allows diff --git a/kernel/src/process_checker.rs b/kernel/src/process_checker.rs index e52a7aae9a..a3cebdc6e1 100644 --- a/kernel/src/process_checker.rs +++ b/kernel/src/process_checker.rs @@ -8,6 +8,7 @@ //! See the [AppID TRD](../../doc/reference/trd-appid.md). pub mod basic; +pub mod signature; use crate::config; use crate::debug; diff --git a/kernel/src/process_checker/signature.rs b/kernel/src/process_checker/signature.rs new file mode 100644 index 0000000000..55225fae5b --- /dev/null +++ b/kernel/src/process_checker/signature.rs @@ -0,0 +1,302 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2024. + +//! Signature credential checker for checking process credentials. + +use crate::hil; +use crate::process::{Process, ShortID}; +use crate::process_checker::{AppCredentialsChecker, AppUniqueness}; +use crate::process_checker::{CheckResult, Client, Compress}; +use crate::utilities::cells::MapCell; +use crate::utilities::cells::OptionalCell; +use crate::utilities::leasable_buffer::{SubSlice, SubSliceMut}; +use crate::ErrorCode; +use tock_tbf::types::TbfFooterV2Credentials; +use tock_tbf::types::TbfFooterV2CredentialsType; + +/// Checker that validates a correct signature credential. +/// +/// This checker provides the scaffolding on top of a hasher (`&H`) and a +/// verifier (`&S`) for a given `TbfFooterV2CredentialsType`. +/// +/// This assumes the `TbfFooterV2CredentialsType` data format only contains the +/// signature (i.e. the data length of the credential in the TBF footer is the +/// same as `SL`). +pub struct AppCheckerSignature< + 'a, + S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>, + H: hil::digest::DigestDataHash<'a, HL>, + const HL: usize, + const SL: usize, +> { + hasher: &'a H, + verifier: &'a S, + hash: MapCell<&'static mut [u8; HL]>, + signature: MapCell<&'static mut [u8; SL]>, + client: OptionalCell<&'static dyn Client<'static>>, + credential_type: TbfFooterV2CredentialsType, + credentials: OptionalCell, + binary: OptionalCell<&'static [u8]>, +} + +impl< + 'a, + S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>, + H: hil::digest::DigestDataHash<'a, HL>, + const HL: usize, + const SL: usize, + > AppCheckerSignature<'a, S, H, HL, SL> +{ + pub fn new( + hasher: &'a H, + verifier: &'a S, + hash_buffer: &'static mut [u8; HL], + signature_buffer: &'static mut [u8; SL], + credential_type: TbfFooterV2CredentialsType, + ) -> AppCheckerSignature<'a, S, H, HL, SL> { + Self { + hasher, + verifier, + hash: MapCell::new(hash_buffer), + signature: MapCell::new(signature_buffer), + client: OptionalCell::empty(), + credential_type, + credentials: OptionalCell::empty(), + binary: OptionalCell::empty(), + } + } +} + +impl< + 'a, + S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>, + H: hil::digest::DigestDataHash<'a, HL>, + const HL: usize, + const SL: usize, + > hil::digest::ClientData for AppCheckerSignature<'a, S, H, HL, SL> +{ + fn add_mut_data_done(&self, _result: Result<(), ErrorCode>, _data: SubSliceMut<'static, u8>) {} + + fn add_data_done(&self, result: Result<(), ErrorCode>, data: SubSlice<'static, u8>) { + self.binary.set(data.take()); + + // We added the binary data to the hasher, now we can compute the hash. + match result { + Err(e) => { + self.client.map(|c| { + let binary = self.binary.take().unwrap(); + let cred = self.credentials.take().unwrap(); + c.check_done(Err(e), cred, binary) + }); + } + Ok(()) => { + self.hash.take().map(|h| match self.hasher.run(h) { + Err((e, _)) => { + self.client.map(|c| { + let binary = self.binary.take().unwrap(); + let cred = self.credentials.take().unwrap(); + c.check_done(Err(e), cred, binary) + }); + } + Ok(()) => {} + }); + } + } + } +} + +impl< + 'a, + S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>, + H: hil::digest::DigestDataHash<'a, HL>, + const HL: usize, + const SL: usize, + > hil::digest::ClientHash for AppCheckerSignature<'a, S, H, HL, SL> +{ + fn hash_done(&self, result: Result<(), ErrorCode>, digest: &'static mut [u8; HL]) { + match result { + Err(e) => { + self.hash.replace(digest); + self.client.map(|c| { + let binary = self.binary.take().unwrap(); + let cred = self.credentials.take().unwrap(); + c.check_done(Err(e), cred, binary) + }); + } + Ok(()) => match self.signature.take() { + Some(sig) => match self.verifier.verify(digest, sig) { + Err((e, d, s)) => { + self.hash.replace(d); + self.signature.replace(s); + self.client.map(|c| { + let binary = self.binary.take().unwrap(); + let cred = self.credentials.take().unwrap(); + c.check_done(Err(e), cred, binary) + }); + } + Ok(()) => {} + }, + None => { + self.hash.replace(digest); + self.client.map(|c| { + let binary = self.binary.take().unwrap(); + let cred = self.credentials.take().unwrap(); + c.check_done(Err(ErrorCode::FAIL), cred, binary) + }); + } + }, + } + } +} + +impl< + 'a, + S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>, + H: hil::digest::DigestDataHash<'a, HL>, + const HL: usize, + const SL: usize, + > hil::digest::ClientVerify for AppCheckerSignature<'a, S, H, HL, SL> +{ + fn verification_done(&self, _result: Result, _compare: &'static mut [u8; HL]) { + // Unused for this checker. + // Needed to make the sha256 client work. + } +} + +impl< + 'a, + S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>, + H: hil::digest::DigestDataHash<'a, HL>, + const HL: usize, + const SL: usize, + > hil::public_key_crypto::signature::ClientVerify + for AppCheckerSignature<'a, S, H, HL, SL> +{ + fn verification_done( + &self, + result: Result, + hash: &'static mut [u8; HL], + signature: &'static mut [u8; SL], + ) { + self.hash.replace(hash); + self.signature.replace(signature); + + self.client.map(|c| { + let binary = self.binary.take().unwrap(); + let cred = self.credentials.take().unwrap(); + let check_result = if result.unwrap_or(false) { + Ok(CheckResult::Accept) + } else { + Ok(CheckResult::Pass) + }; + + c.check_done(check_result, cred, binary) + }); + } +} + +impl< + 'a, + S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>, + H: hil::digest::DigestDataHash<'a, HL>, + const HL: usize, + const SL: usize, + > AppCredentialsChecker<'static> for AppCheckerSignature<'a, S, H, HL, SL> +{ + fn require_credentials(&self) -> bool { + true + } + + fn check_credentials( + &self, + credentials: TbfFooterV2Credentials, + binary: &'static [u8], + ) -> Result<(), (ErrorCode, TbfFooterV2Credentials, &'static [u8])> { + self.credentials.set(credentials); + + if credentials.format() == self.credential_type { + // Save the signature we are trying to compare with. + self.signature.map(|b| { + b.as_mut_slice()[..SL].copy_from_slice(&credentials.data()[..SL]); + }); + + // Add the process binary to compute the hash. + self.hasher.clear_data(); + match self.hasher.add_data(SubSlice::new(binary)) { + Ok(()) => Ok(()), + Err((e, b)) => Err((e, credentials, b.take())), + } + } else { + Err((ErrorCode::NOSUPPORT, credentials, binary)) + } + } + + fn set_client(&self, client: &'static dyn Client<'static>) { + self.client.replace(client); + } +} + +impl< + 'a, + S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>, + H: hil::digest::DigestDataHash<'a, HL>, + const HL: usize, + const SL: usize, + > AppUniqueness for AppCheckerSignature<'a, S, H, HL, SL> +{ + fn different_identifier(&self, process_a: &dyn Process, process_b: &dyn Process) -> bool { + let cred_a = process_a.get_credentials(); + let cred_b = process_b.get_credentials(); + + // If it doesn't have credentials, it is by definition + // different. It should not be runnable (this checker requires + // credentials), but if this returned false it could block + // runnable processes from running. + cred_a.map_or(true, |a| { + cred_b.map_or(true, |b| { + // Two IDs are different if they have a different format, + // different length (should not happen, but worth checking for + // the next test), or any byte of them differs. + if a.format() != b.format() { + true + } else if a.data().len() != b.data().len() { + true + } else { + for (aval, bval) in a.data().iter().zip(b.data().iter()) { + if aval != bval { + return true; + } + } + false + } + }) + }) + } +} + +impl< + 'a, + S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>, + H: hil::digest::DigestDataHash<'a, HL>, + const HL: usize, + const SL: usize, + > Compress for AppCheckerSignature<'a, S, H, HL, SL> +{ + fn to_short_id(&self, _process: &dyn Process, credentials: &TbfFooterV2Credentials) -> ShortID { + let data = credentials.data(); + if data.len() < 4 { + // Should never trigger, as we only approve signature credentials. + return ShortID::LocallyUnique; + } + let id: u32 = 0x8000000_u32 + | (data[0] as u32) << 24 + | (data[1] as u32) << 16 + | (data[2] as u32) << 8 + | (data[3] as u32); + match core::num::NonZeroU32::new(id) { + Some(nzid) => ShortID::Fixed(nzid), + None => ShortID::LocallyUnique, // Should never be generated + } + } +} diff --git a/kernel/src/process_loading.rs b/kernel/src/process_loading.rs index af6993cf83..42985b5c93 100644 --- a/kernel/src/process_loading.rs +++ b/kernel/src/process_loading.rs @@ -8,7 +8,6 @@ //! checking whether they are allowed to be loaded, and if so initializing a process //! structure to run it. -use core::convert::TryInto; use core::fmt; use crate::capabilities::{ProcessApprovalCapability, ProcessManagementCapability}; diff --git a/kernel/src/process_printer.rs b/kernel/src/process_printer.rs index 6211a5af58..a9478c3612 100644 --- a/kernel/src/process_printer.rs +++ b/kernel/src/process_printer.rs @@ -145,7 +145,7 @@ impl ProcessPrinter for ProcessPrinterText { let _ = match process.get_completion_code() { Some(opt_cc) => match opt_cc { - Some(cc) => bww.write_fmt(format_args!(" Completion Code: {}\r\n", cc)), + Some(cc) => bww.write_fmt(format_args!(" Completion Code: {}\r\n", cc as isize)), None => bww.write_str(" Completion Code: Faulted\r\n"), }, None => bww.write_str(" Completion Code: None\r\n"), diff --git a/kernel/src/scheduler/round_robin.rs b/kernel/src/scheduler/round_robin.rs index d9d226d1fc..464c3f7382 100644 --- a/kernel/src/scheduler/round_robin.rs +++ b/kernel/src/scheduler/round_robin.rs @@ -104,6 +104,15 @@ impl<'a, C: Chip> Scheduler for RoundRobinSched<'a> { } } } + + let next = match next { + Some(p) => p, + None => { + // No processes on the system + return SchedulingDecision::TrySleep; + } + }; + let timeslice = if self.last_rescheduled.get() { self.time_remaining.get() } else { @@ -113,9 +122,7 @@ impl<'a, C: Chip> Scheduler for RoundRobinSched<'a> { }; assert!(timeslice != 0); - // next will not be None, because if we make a full iteration and nothing - // is ready we return early - SchedulingDecision::RunProcess((next.unwrap(), Some(timeslice))) + SchedulingDecision::RunProcess((next, Some(timeslice))) } fn result(&self, result: StoppedExecutingReason, execution_time_us: Option) { diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 71488a75e4..bdcc993b4e 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -9,7 +9,6 @@ //! - error types //! - interface trait for context switches -use core::convert::TryFrom; use core::fmt::Write; use crate::errorcode::ErrorCode; diff --git a/kernel/src/syscall_driver.rs b/kernel/src/syscall_driver.rs index c9b13e71f7..758da28ea1 100644 --- a/kernel/src/syscall_driver.rs +++ b/kernel/src/syscall_driver.rs @@ -77,8 +77,6 @@ //! kernel (the scheduler and syscall dispatcher) is responsible for //! encoding these types into the Tock system call ABI specification. -use core::convert::TryFrom; - use crate::errorcode::ErrorCode; use crate::process; use crate::process::ProcessId; diff --git a/kernel/src/utilities/leasable_buffer.rs b/kernel/src/utilities/leasable_buffer.rs index d2fb1db432..3a74a536bc 100644 --- a/kernel/src/utilities/leasable_buffer.rs +++ b/kernel/src/utilities/leasable_buffer.rs @@ -429,7 +429,7 @@ impl<'a, T> SubSlice<'a, T> { /// /// ```rust,ignore /// let buffer = unsafe { - /// core::slice::from_raw_parts(&_ptr_in_flash as *const u8, 1500) + /// core::slice::from_raw_parts(core::ptr::addr_of!(_ptr_in_flash), 1500) /// }; /// let s = SubSlice::new(buffer); /// s.slice(0..250); diff --git a/kernel/src/utilities/math.rs b/kernel/src/utilities/math.rs index aed2edf5be..041aef07cb 100644 --- a/kernel/src/utilities/math.rs +++ b/kernel/src/utilities/math.rs @@ -4,7 +4,6 @@ //! Helper functions for common mathematical operations. -use core::convert::{From, Into}; use core::f32; /// Get closest power of two greater than the given number. diff --git a/libraries/riscv-csr/src/csr.rs b/libraries/riscv-csr/src/csr.rs index b050f817b4..3b583c7f24 100644 --- a/libraries/riscv-csr/src/csr.rs +++ b/libraries/riscv-csr/src/csr.rs @@ -171,7 +171,10 @@ impl ReadWriteRiscvCsr { /// instruction where `rs1 = in(reg) value_to_set` and `rd = /// out(reg) `. // Mock implementations for tests on Travis-CI. - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_os = "none")))] + #[cfg(not(all( + any(target_arch = "riscv32", target_arch = "riscv64"), + target_os = "none" + )))] pub fn atomic_replace(&self, _value_to_set: usize) -> usize { unimplemented!("RISC-V CSR {} Atomic Read/Write", V) } @@ -204,7 +207,10 @@ impl ReadWriteRiscvCsr { /// instruction where `rs1 = in(reg) bitmask` and `rd = out(reg) /// `. // Mock implementations for tests on Travis-CI. - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_os = "none")))] + #[cfg(not(all( + any(target_arch = "riscv32", target_arch = "riscv64"), + target_os = "none" + )))] pub fn read_and_set_bits(&self, bitmask: usize) -> usize { unimplemented!( "RISC-V CSR {} Atomic Read and Set Bits, bitmask {:04x}", @@ -241,7 +247,10 @@ impl ReadWriteRiscvCsr { /// instruction where `rs1 = in(reg) bitmask` and `rd = out(reg) /// `. // Mock implementations for tests on Travis-CI. - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_os = "none")))] + #[cfg(not(all( + any(target_arch = "riscv32", target_arch = "riscv64"), + target_os = "none" + )))] pub fn read_and_clear_bits(&self, bitmask: usize) -> usize { unimplemented!( "RISC-V CSR {} Atomic Read and Clear Bits, bitmask {:04x}", @@ -294,7 +303,10 @@ impl Readable for ReadWriteRiscvCsr usize { unimplemented!("reading RISC-V CSR {}", V) } @@ -316,7 +328,10 @@ impl Writeable for ReadWriteRiscvCsr diff --git a/libraries/tock-tbf/src/parse.rs b/libraries/tock-tbf/src/parse.rs index 1a022119ab..ccbc45fafd 100644 --- a/libraries/tock-tbf/src/parse.rs +++ b/libraries/tock-tbf/src/parse.rs @@ -4,8 +4,6 @@ //! Tock Binary Format parsing code. -use core::convert::TryInto; -use core::iter::Iterator; use core::{mem, str}; use crate::types; diff --git a/libraries/tock-tbf/src/types.rs b/libraries/tock-tbf/src/types.rs index f3d889a8a7..b495861f61 100644 --- a/libraries/tock-tbf/src/types.rs +++ b/libraries/tock-tbf/src/types.rs @@ -4,7 +4,6 @@ //! Types and Data Structures for TBFs. -use core::convert::TryInto; use core::fmt; use core::mem::size_of; diff --git a/tools/check_process_console.py b/tools/check_process_console.py index a2ab37c090..f0826552f0 100755 --- a/tools/check_process_console.py +++ b/tools/check_process_console.py @@ -37,6 +37,7 @@ "deleting": (-1, "not_executed"), "cariage_return": (-1, "not_executed"), "newline_return": (-1, "not_executed"), + "command_history_edit": (-1, "not_executed"), } colors = ["\033[92m", "\033[91m", "\033[00m"] @@ -479,6 +480,91 @@ def test_newline_return(port: SerialPort): pass_test("newline_return") +def test_command_history_edit(port: SerialPort): + ''' Tests basic editing of commands in history ''' + print_title("Testing basic command history editing:") + fail_test("command_history_edit") + + def test_inserting(): + print("Inserting 'FooBar'") + port.send_input("FooBar\r\n") + port.clear_input() + + print("Moving up in history 1 time") + port.send_input(commands["up"]) + + print("Moving to the start of the command") + port.send_input(commands["home"]) + + print("Insert to the start 'Dummy'") + port.send_input("Dummy") + + print("Moving to the end of the command") + port.send_input(commands["end"]) + + print("Insert to the end 'Dummy'") + port.send_input("Dummy") + + print("Moving to the beginning of the middle 'Dummy'") + port.send_input(commands["left"] * 8) + + print("Insert in the middle 'Dummy'") + port.send_input("Dummy") + + print("Moving down in history 1 time") + port.send_input(commands["down"]) + + out = port.recv_output() + + exit_if_condition(out != "DummyFooDummyBarDummy", + "[ERROR] Command does not match") + + + def test_deleting_with(delete_char: str): + print("Moving up in history 1 time") + port.send_input(commands["up"]) + + print("Moving to the start of the command") + port.send_input(commands["home"]) + + print("Delete first 'Dummy'") + port.send_input(delete_char * 5) + + print("Moving to the end of the command") + port.send_input(commands["end"]) + + print("Delete last 'Dummy'") + port.send_input(commands["backspace"] * 5) + + print("Moving to the begining of the middle 'Dummy'") + port.send_input(commands["left"] * 8) + + print("Delete middle 'Dummy'") + port.send_input(delete_char * 5) + + print("Moving down in history 1 time") + port.send_input(commands["down"]) + + out = port.recv_output() + + exit_if_condition(out != "FooBar", + "[ERROR] Command does not match") + + test_inserting() + out = port.send_input("\r\n") + port.clear_input() + + print("Testing with ANSI Escpae Sequence...") + test_deleting_with(commands["delete"]) + port.clear_input() + + print("Testing with ASCII character...") + test_deleting_with(commands["delete-ascii"]) + + out = port.send_input("\r\n") + port.clear_input() + pass_test("command_history_edit") + def read_serial_port_name(): ''' Fetches the serial port name from the user ''' @@ -503,6 +589,7 @@ def main(): test_deleting(port) test_cariage_return(port) test_newline_return(port) + test_command_history_edit(port) port.finish() diff --git a/tools/license-checker/Cargo.toml b/tools/license-checker/Cargo.toml index 13f5d37394..3d7c1d6f04 100644 --- a/tools/license-checker/Cargo.toml +++ b/tools/license-checker/Cargo.toml @@ -18,4 +18,4 @@ thiserror = "1.0.44" [dependencies.syntect] default-features = false features = ["default-syntaxes", "regex-onig", "yaml-load"] -version = "5.0.0" +version = "5.2.0" diff --git a/tools/license-checker/src/parser.rs b/tools/license-checker/src/parser.rs index 7d64da3400..c9cf7e0c3b 100644 --- a/tools/license-checker/src/parser.rs +++ b/tools/license-checker/src/parser.rs @@ -29,6 +29,12 @@ const FALLBACK_NAME: &str = "fallback"; pub struct Cache { is_comment: ScopeSelector, is_punctuation: ScopeSelector, + // Syntect's plain text syntax does not mark anything as comments, which + // causes the license check to fail. Instead, plain text files should use + // the fallback parser. This stores the name of the plain text syntax, so + // that Parser can detect when syntect has returned the plain text syntax + // for a file. + plain_text_name: String, syntax_set: SyntaxSet, } @@ -42,10 +48,12 @@ impl Default for Cache { SyntaxDefinition::load_from_str(FALLBACK_SYNTAX, true, Some(FALLBACK_NAME)) .expect("Failed to parse fallback syntax"), ); + let syntax_set = builder.build(); Self { is_comment: ScopeSelector::from_str(COMMENT_SELECTOR).unwrap(), is_punctuation: ScopeSelector::from_str("punctuation.definition.comment").unwrap(), - syntax_set: builder.build(), + plain_text_name: syntax_set.find_syntax_plain_text().name.clone(), + syntax_set, } } } @@ -104,8 +112,8 @@ impl<'cache> Parser<'cache> { let syntax = match cache.syntax_set.find_syntax_for_file(path) { Err(error) if error.kind() == ErrorKind::InvalidData => return Err(ParseError::Binary), Err(error) => return Err(error.into()), - Ok(Some(syntax)) => syntax, - Ok(None) => cache.syntax_set.find_syntax_by_name(FALLBACK_NAME).unwrap(), + Ok(Some(syntax)) if syntax.name != cache.plain_text_name => syntax, + Ok(_) => cache.syntax_set.find_syntax_by_name(FALLBACK_NAME).unwrap(), }; Ok(Self { @@ -341,7 +349,7 @@ mod tests { } #[test] - fn plain_text() { + fn plain_text_no_extension() { const EXPECTED: &[LineContents] = &[ Comment("Licensed under the Apache License, Version 2.0 or the MIT License."), Comment("SPDX-License-Identifier: Apache-2.0 OR MIT"), @@ -351,7 +359,23 @@ mod tests { Comment("This is a plain text file; the license checker should recognize that it does"), Comment("# not use a common comment syntax."), ]; - let path = Path::new("testdata/plain_text"); + let path = Path::new("testdata/plain_text_no_extension"); + assert_produces(Parser::new(&Cache::default(), path), EXPECTED); + } + + #[test] + fn plain_text_txt() { + const EXPECTED: &[LineContents] = &[ + Comment("Licensed under the Apache License, Version 2.0 or the MIT License."), + Comment("SPDX-License-Identifier: Apache-2.0 OR MIT"), + Comment("Copyright Tock Contributors 2024."), + Comment("Copyright Google LLC 2024."), + Comment(""), + Comment("This is a plain text file with the .txt extension. The license checker"), + Comment("should use the fallback parser, even though syntect may recognize it as a"), + Comment("plain text file."), + ]; + let path = Path::new("testdata/plain_text.txt"); assert_produces(Parser::new(&Cache::default(), path), EXPECTED); } diff --git a/tools/license-checker/testdata/plain_text.txt b/tools/license-checker/testdata/plain_text.txt new file mode 100644 index 0000000000..12561e8d46 --- /dev/null +++ b/tools/license-checker/testdata/plain_text.txt @@ -0,0 +1,8 @@ +Licensed under the Apache License, Version 2.0 or the MIT License. +SPDX-License-Identifier: Apache-2.0 OR MIT +Copyright Tock Contributors 2024. +Copyright Google LLC 2024. + +This is a plain text file with the .txt extension. The license checker +should use the fallback parser, even though syntect may recognize it as a +plain text file. diff --git a/tools/license-checker/testdata/plain_text b/tools/license-checker/testdata/plain_text_no_extension similarity index 100% rename from tools/license-checker/testdata/plain_text rename to tools/license-checker/testdata/plain_text_no_extension diff --git a/tools/tockbot/maint_nightly.yaml b/tools/tockbot/maint_nightly.yaml new file mode 100644 index 0000000000..4a7da79b55 --- /dev/null +++ b/tools/tockbot/maint_nightly.yaml @@ -0,0 +1,54 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2024. + +_anchors: + core_wg_users: &core_wg_users + - hudson-ayers + - bradjc + - brghena + - phil-levis + - alevy + - ppannuto + - lschuermann + - jrvanwhy + + active_reviewers: &active_reviewers + - alexandruradovici + - hudson-ayers + - bradjc + - brghena + - alevy + - lschuermann + - jrvanwhy + +repo: + owner: tock + name: tock + +# Ignore all PRs and issues that have the tockbot-ignore label: +ignored_labels: + - tockbot-ignore + +tasks: + - type: stale_pr_assign + label: Assign Active Reviewers to Stale PRs + + # For how long the PR must have not received any comments: + staleness_time: 259200 # 60 * 60 * 24 * 3 days + + # Any such PRs must not already have a review by a core team + # member (i.e., have been triaged) + no_reviews_by: *core_wg_users + + # Assign one active reviewer at random: + assignee_cnt: 1 + assignee_candidates: *active_reviewers + + # Ignore PRs that are marked as "blocked" or "blocked-upstream". Those + # should not necessarily be assigned a reviewer, but be staged for + # "check-in" in a core-WG call after being stale for some time (e.g., a + # month). + ignored_labels: + - blocked + - blocked-upstream diff --git a/tools/tockbot/requirements.txt b/tools/tockbot/requirements.txt new file mode 100644 index 0000000000..402cfe8907 --- /dev/null +++ b/tools/tockbot/requirements.txt @@ -0,0 +1,26 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2024. + +attrs==23.2.0 +cattrs==23.2.3 +certifi==2023.11.17 +cffi==1.16.0 +charset-normalizer==3.3.2 +cryptography==42.0.4 +Deprecated==1.2.14 +idna==3.6 +platformdirs==4.2.0 +pycparser==2.21 +PyGithub==2.1.1 +PyJWT==2.8.0 +PyNaCl==1.5.0 +python-dateutil==2.8.2 +PyYAML==6.0.1 +requests==2.31.0 +requests-cache==1.2.0 +six==1.16.0 +typing_extensions==4.9.0 +url-normalize==1.4.3 +urllib3==2.1.0 +wrapt==1.16.0 diff --git a/tools/tockbot/shell.nix b/tools/tockbot/shell.nix new file mode 100644 index 0000000000..f4c4cafa8a --- /dev/null +++ b/tools/tockbot/shell.nix @@ -0,0 +1,15 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2024. + +with import {}; + +mkShell { + name = "mirrorcheck-shell"; + buildInputs = [ + (python3.withPackages (pypkgs: with pypkgs; [ + requests-cache pygithub pyyaml + ])) + ]; +} + diff --git a/tools/tockbot/tockbot.py b/tools/tockbot/tockbot.py new file mode 100755 index 0000000000..169f2664c4 --- /dev/null +++ b/tools/tockbot/tockbot.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python3 + +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2024. + +import os, sys +import random +import argparse +import logging +from datetime import datetime, timedelta, timezone +import yaml +from github import Github, Auth + +# Cache GitHub API requests aggressively: +from requests_cache import NEVER_EXPIRE, DO_NOT_CACHE, get_cache, install_cache +install_cache( + cache_control=True, + urls_expire_after={ + '*.github.com': NEVER_EXPIRE, + '*': DO_NOT_CACHE, + }, +) + +class CallbackFilter: + def __init__(self, function, filtered_cb, sequence): + self.function = function + self.sequence = sequence + self.filtered_cb = filtered_cb + + def __iter__(self): + return self + + def __next__(self): + # Let any StopIteration exception bubble up the call stack + while True: + item = next(self.sequence) + if self.function(item): + return item + else: + self.filtered_cb(item) + +def ignore_prs_filter(config, task_config, prs, logger): + filtered = prs + + # Build a chain of filters over each of the labels: + for ignored_label in ( + config.get("ignored_labels", []) + + task_config.get("ignored_labels", []) + ): + filtered = CallbackFilter( + lambda pr: not any(map( + lambda l: l.name == ignored_label, + pr.get_labels() + )), + lambda ignored: logger.debug( + f"-> Filtered #{filtered.number}, is ignored by label " + + f"\"{ignored_label}\"." + ), + filtered + ) + + return filtered + +def verbose_pr_stream(prs, log): + def verbose_pr_stream_log(pr, log): + log.debug(f"Processing PR #{pr.number} (\"{pr.title}\")") + return pr + return map(lambda pr: verbose_pr_stream_log(pr, log), prs) + +# Assign maintainers to stale PRs when they haven't seen any review / +# reviewer activity after a given amount of time: +def task_stale_pr_assign(config, task_config, gh, repo, rand, log, dry_run): + # Get the list of open PRs: + prs = verbose_pr_stream(repo.get_pulls(state="open"), log) + + # Ignore all draft PRs: + prs = CallbackFilter( + lambda pr: pr.draft == False, + lambda filtered: log.debug( + f"-> Filtered #{filtered.number}, is a draft PR."), + prs, + ) + + # Filter out PRs that are marked as ignored by this tool: + prs = ignore_prs_filter(config, task_config, prs, log) + + # Filter out PRs that are assigned to one or more users: + prs = CallbackFilter( + lambda pr: len(pr.assignees) == 0, + lambda filtered: log.debug( + f"-> Filtered #{filtered.number}, has assignees."), + prs, + ) + + # Filter out PRs which have received reviews that are not dismissed + # (optionally filted by a designated group of people, if the config is not + # an empty list): + no_reviews_cond = task_config.get("no_reviews_by", None) + if no_reviews_cond is not None: + prs = CallbackFilter( + lambda pr: not any(map( + lambda review: ( + # Only keep PRs that do not have any review where the + # reviewer is in the `no_reviews_cond` list, ... + review.user.login in no_reviews_cond \ + # ... not counting dismissed reviews: + and review.state != "DISMISSED" \ + # ... and not comment reviews (won't be dismissed): + and review.state != "COMMENTED" + ), + pr.get_reviews(), + )), + lambda filtered: log.debug( + f"-> Filtered #{filtered.number}, has current reviews."), + prs + ) + + # Filter our PRs that have seen a comment be updated in the last + # task_config["staleness_time"] seconds: + if task_config.get("staleness_time", None) is not None: + comments_since = datetime.now(timezone.utc) \ + - timedelta(seconds=task_config["staleness_time"]) + + prs = CallbackFilter( + lambda pr: ( + ( + # Keep PRs that do _not_ have at least one review comment or + # at least one issue comment since `comments_since`, + pr.get_review_comments(since=comments_since).totalCount == 0 and \ + pr.as_issue().get_comments(since=comments_since).totalCount == 0 + ) and ( + # ... except if the PR is less than `staleness_time` old: + pr.created_at < comments_since + ) + ), + lambda filtered: log.debug( + f"-> Filtered #{filtered.number}, not stale."), + prs + ) + + # Now, add an assignee to all remaining PRs randomly: + assignee_cnt = task_config.get("assignee_cnt", 1) + for pr in prs: + assignees = list(map( + lambda login: gh.get_user(login), + rand.sample( + list(filter( + # Avoid assigning the PR creator: + lambda login: pr.user.login != login, + task_config["assignee_candidates"])), + assignee_cnt + ) + )) + + log.info(( + "Would assign user(s) {} to PR #{} (\"{}\")" + if dry_run else + "Assigning user(s) {} to PR #{} (\"{}\")" + ).format( + ", ".join(map(lambda a: a.login, assignees)), + pr.number, + pr.title, + )) + + if not dry_run: + pr.add_to_assignees(*assignees) + + +def cmd_maint_nightly(config, log, dry_run, gh_token = None): + rand = random.SystemRandom() + + # Instantiate the GitHub client library: + if gh_token is not None: + auth_args = { "auth": Auth.Token(gh_token) } + else: + log.warning("Running without GitHub auth token.") + auth_args = {} + + gh = Github(**auth_args) + + repo = gh.get_repo("{}/{}".format( + config["repo"]["owner"], + config["repo"]["name"])) + + # Perform the various maintenance tasks + task_handlers = { + "stale_pr_assign": task_stale_pr_assign, + } + + for task in config["tasks"]: + if task["type"] not in task_handlers: + log.error("Unknown task type \"{}\", skipping!".format(task["type"])) + continue + + log.info("Running task \"{}\" (type \"{}\")...".format( + task.get("label", ""), task["type"])) + log.debug(f"Starting task with rate limits: {str(gh.get_rate_limit())}") + + handler = task_handlers[task["type"]] + handler( + config = config, + task_config = task, + gh = gh, + repo = repo, + rand = rand, + log = log, + dry_run = dry_run, + ) + + log.debug(f"Finished all tasks with rate limits: {str(gh.get_rate_limit())}") + +def main(): + parser = argparse.ArgumentParser(prog = "tockbot") + + # Global options: + parser.add_argument("-n", "--dry-run", action="store_true") + parser.add_argument("-v", "--verbose", action="store_true") + + # Subcommands: + subparsers = parser.add_subparsers(dest="subcommand", required=True) + + # Nightly project maintenance command: + maint_nightly_parser = subparsers.add_parser("maint-nightly") + maint_nightly_parser.add_argument( + "-c", "--config", required=True, + help="YAML configuration for nightly maintenance job") + + args = parser.parse_args() + + # Initialize the logging facility: + ch = logging.StreamHandler() + fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + ch.setFormatter(fmt) + log = logging.getLogger('tockbot') + log.addHandler(ch) + if args.verbose: + log.setLevel(logging.DEBUG) + else: + log.setLevel(logging.INFO) + + # Load the YAML configuration for commands that require it: + if args.subcommand in ["maint-nightly"]: + with open(args.config, "r") as f: + config = yaml.safe_load(f) + + # Check if we're being passed a GitHub access token in an environment var: + gh_token = os.environ.get("GITHUB_TOKEN", None) + gh_token = gh_token if gh_token != "" else None + + if args.subcommand == "maint-nightly": + return cmd_maint_nightly( + config, log, dry_run=args.dry_run, gh_token=gh_token) + else: + log.critical(f"Unhandled subcommand: {args.subcommand}") + return 1 + +if __name__ == "__main__": + sys.exit(main())