Skip to content

Commit

Permalink
Made it possible to share the ADC (#49)
Browse files Browse the repository at this point in the history
* feat: added heapless as dependency and example
added the heapless crate as a dependency for allocating and sharing the
adc between multiple structs, and also created an example on how this
can be done.

* feat: enable adc sharing in the bsc
now the adc is allocated in the bsc inside of an arc, which allows it to
be cloned and shared between multiple structs, so that both the light
sensor array and the future battery sensor will be able to use it.

* fix: fixed the no_bsc_arc example
fixed the example for the usage of `Arc`, the problem was that we didn't
create the memory block for the allocation before doing it, so the
program had a runtime error

* fix: fixed arc allocation in the bsc
same fix as in the arc example, the memory block for the adc wasn't
being defined and so, the alloc function failed, solved that.

* fix: add the allow static mut refs flag
in rust 2024 this will be disallowed due to causing undefined behaviour,
in this case we're using rust 2021 and also the `heapless` crate does it
this way, so i added a flag to prevent the compiler from giving an
error/warning
  • Loading branch information
JatoMixo authored Jul 31, 2024
1 parent db730e9 commit 77a7c29
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 18 deletions.
1 change: 1 addition & 0 deletions mightybuga_bsc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] }
cortex-m-semihosting = "0.5.0"
panic-halt = "0.2.0"
panic-semihosting = "0.6.0"
heapless = { version = "0.8.0", features = ["portable-atomic"] }

fugit = "0.3.7"

Expand Down
83 changes: 83 additions & 0 deletions mightybuga_bsc/examples/no_bsc_arc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//! This is an example on how to use the `Arc` type from the `heapless` crate to allocate something
//! in the memory and then create pointers to that location in order to use it in a memory
//! safe way (except for the part in which we define the block of memory, that requires using unsafe)
#![no_std]
#![cfg_attr(not(doc), no_main)]
#![allow(static_mut_refs)]
use core::cell::RefCell;

use stm32f1xx_hal::{
pac::ADC1,
adc::Adc,
};

use panic_halt as _;

use mightybuga_bsc as board;

use cortex_m_rt::entry;
use board::hal::{pac, prelude::*};

use heapless::{
arc_pool,
pool::arc::ArcBlock,
};

#[entry]
fn main() -> ! {
// Get access to the core peripherals from the cortex-m crate
let _cp = cortex_m::Peripherals::take().unwrap();
// Get access to the device specific peripherals from the peripheral access crate
let dp = pac::Peripherals::take().unwrap();

// Take ownership over the raw flash and rcc devices and convert them into the corresponding
// HAL structs
let mut flash = dp.FLASH.constrain();
let rcc = dp.RCC.constrain();

// Freeze the configuration of all the clocks in the system and store the frozen frequencies in
// `clocks`
let clocks = rcc.cfgr.freeze(&mut flash.acr);

// Acquire the GPIOC peripheral
let _gpioc = dp.GPIOC.split();
let mut gpioa = dp.GPIOA.split();

// This macro generates all the necessary code implementations to allocate a refcell containing
// the adc1 into a block in the memory
arc_pool!(P: RefCell<Adc<ADC1>>);

// Generate the memory block in which the refcell<adc1> will be allocated, we need to do
// this in an unsafe way
let arc_block: &'static mut ArcBlock<RefCell<Adc<ADC1>>> = unsafe {
static mut B: ArcBlock<RefCell<Adc<ADC1>>> = ArcBlock::new();
&mut B
};

// Tell the singleton to use this block in the memory for managing the refcell<adc1>
P.manage(arc_block);

// Allocate the adc1 inside of a refcell in the memory block we created earlier, the `alloc`
// method doesn't have an unwrap for its Result, so we use a simple match statement to do that.
let arc = match P.alloc(RefCell::new(Adc::adc1(dp.ADC1, clocks))) {
Ok(adc_arc) => adc_arc,
Err(_) => {
panic!("Couldn't get the Arc");
},
};

// Clone the pointer to the refcell<adc1>
let arc2 = arc.clone();

// Use any of those pointers to read using the adc
let _x: u16 = arc2.borrow_mut().read(&mut gpioa.pa0.into_analog(&mut gpioa.crl)).unwrap();
let _y: u16 = arc.borrow_mut().read(&mut gpioa.pa2.into_analog(&mut gpioa.crl)).unwrap();

// Drop the pointers and the original instance of the refcell<adc1>
drop(arc2);
drop(arc);

loop {

}
}
26 changes: 23 additions & 3 deletions mightybuga_bsc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![no_std]
#![allow(non_camel_case_types)]
#![allow(static_mut_refs)]

// reexport hal crates to allow users to directly refer to them
// like in https://github.com/therealprof/nucleo-f103rb/blob/master/src/lib.rs
Expand All @@ -13,6 +14,11 @@ use hal::serial::*;
use hal::timer::SysDelay;

use core::cell::RefCell;

use heapless::{
arc_pool,
pool::arc::ArcBlock,
};
use core::ops::Deref;

use engine::engine::Engine;
Expand All @@ -36,6 +42,9 @@ pub mod prelude {
};
}

// Implement ArcPool for the ADC1
arc_pool!(ADC_POOL: RefCell<Adc<ADC1>>);

pub struct Mightybuga_BSC {
// LEDs
pub led_d1: gpio::Pin<'C', 13, gpio::Output>,
Expand Down Expand Up @@ -185,8 +194,19 @@ impl Mightybuga_BSC {
EncoderPolarity::PolarityBA,
);

// Initialize the line sensor array
let adc1 = Adc::adc1(dp.ADC1, clocks);
// Generate the memory block in which the adc will be allocated
let adc_arc_block: &'static mut ArcBlock<RefCell<Adc<ADC1>>> = unsafe {
static mut B: ArcBlock<RefCell<Adc<ADC1>>> = ArcBlock::new();
&mut B
};
ADC_POOL.manage(adc_arc_block);

// Allocate the Adc in an Arc to share it
let adc_arc = match ADC_POOL.alloc(RefCell::new(Adc::adc1(dp.ADC1, clocks))) {
Ok(adc_arc) => adc_arc,
Err(_) => panic!("Couldn't get the adc arc"),
};

let light_sensor_array = LightSensorArray {
led: gpiob.pb1.into_push_pull_output(&mut gpiob.crl),
sensor_0: gpioa.pa0.into_analog(&mut gpioa.crl),
Expand All @@ -197,7 +217,7 @@ impl Mightybuga_BSC {
sensor_5: gpioa.pa5.into_analog(&mut gpioa.crl),
sensor_6: gpioa.pa6.into_analog(&mut gpioa.crl),
sensor_7: gpioa.pa7.into_analog(&mut gpioa.crl),
adc: RefCell::new(adc1),
adc: adc_arc.clone(),
};

// Return the initialized struct
Expand Down
34 changes: 19 additions & 15 deletions mightybuga_bsc/src/light_sensor_array.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use core::cell::RefCell;
use crate::hal::{
adc::Adc,
gpio::{Analog, Output, Pin},
pac::ADC1,
prelude::_embedded_hal_adc_OneShot,
use heapless::pool::arc::Arc;
use crate::{
hal::{
gpio::{Analog, Output, Pin},
prelude::_embedded_hal_adc_OneShot,
},
ADC_POOL,
};

/// The LineSensor used to detect the place where the line is located.
Expand All @@ -23,20 +24,23 @@ pub struct LightSensorArray {
pub sensor_6: Pin<'A', 6, Analog>,
pub sensor_7: Pin<'A', 7, Analog>,

pub adc: RefCell<Adc<ADC1>>,
pub adc: Arc<ADC_POOL>,
}

impl light_sensor_array_controller::LightSensorArrayController for LightSensorArray {
fn get_light_map(&mut self) -> [u16; 8] {

let mut adc = self.adc.borrow_mut();

let light_map = [
self.adc.get_mut().read(&mut self.sensor_0).unwrap(),
self.adc.get_mut().read(&mut self.sensor_1).unwrap(),
self.adc.get_mut().read(&mut self.sensor_2).unwrap(),
self.adc.get_mut().read(&mut self.sensor_3).unwrap(),
self.adc.get_mut().read(&mut self.sensor_4).unwrap(),
self.adc.get_mut().read(&mut self.sensor_5).unwrap(),
self.adc.get_mut().read(&mut self.sensor_6).unwrap(),
self.adc.get_mut().read(&mut self.sensor_7).unwrap(),
adc.read(&mut self.sensor_0).unwrap(),
adc.read(&mut self.sensor_1).unwrap(),
adc.read(&mut self.sensor_2).unwrap(),
adc.read(&mut self.sensor_3).unwrap(),
adc.read(&mut self.sensor_4).unwrap(),
adc.read(&mut self.sensor_5).unwrap(),
adc.read(&mut self.sensor_6).unwrap(),
adc.read(&mut self.sensor_7).unwrap(),
];

light_map
Expand Down

0 comments on commit 77a7c29

Please sign in to comment.