use core::ffi::c_void;
use crate::csdk;
use crate::csdk::interrupts::interrupt;
const DMA_CHANNEL_COUNT: usize = 16;
static mut DMA_CHANNELS: [Option<*mut csdk::DMA_HandleTypeDef>; DMA_CHANNEL_COUNT] = [None; DMA_CHANNEL_COUNT];
pub struct DmaChannel {
pub handle: csdk::DMA_HandleTypeDef,
}
pub struct Config {
init: csdk::DMA_InitTypeDef,
}
impl Config {
pub fn new() -> Self {
Self {
init: csdk::DMA_InitTypeDef{
Direction: csdk::DMA_PERIPH_TO_MEMORY,
PeriphInc: csdk::DMA_PINC_DISABLE,
MemInc: csdk::DMA_MINC_DISABLE,
PeriphDataAlignment: csdk::DMA_PDATAALIGN_HALFWORD,
MemDataAlignment: csdk::DMA_MDATAALIGN_HALFWORD,
Mode: csdk::DMA_CIRCULAR,
Priority: csdk::DMA_PRIORITY_VERY_HIGH,
}
}
}
pub fn new_peri_to_mem() -> Self {
let mut conf = Self::new();
conf.init.Direction = csdk::DMA_PERIPH_TO_MEMORY;
conf
}
pub fn new_mem_to_peri() -> Self {
let mut conf = Self::new();
conf.init.Direction = csdk::DMA_MEMORY_TO_PERIPH;
conf
}
}
impl DmaChannel {
pub fn new(config: Config, channel: u8, map_value: u8) -> Result<Self, crate::Error> {
let mut handle = csdk::DMA_HandleTypeDef {
Instance: csdk::DMA1_Channel1,
Init: config.init,
Lock: 0,
State: 0,
Parent: core::ptr::null_mut(),
XferCpltCallback: None,
XferHalfCpltCallback: None,
XferErrorCallback: None,
XferAbortCallback: None,
ErrorCode: 0,
DmaBaseAddress: core::ptr::null_mut(),
ChannelIndex: 0,
};
unsafe {
csdk::HAL_RCC_DMA_CLK_ENABLE();
handle.Instance = match channel {
1 => {
(*csdk::SYSCFG).CFGR3 &= !(0b11111);
(*csdk::SYSCFG).CFGR3 |= map_value as u32;
csdk::DMA1_Channel1
},
2 => {
(*csdk::SYSCFG).CFGR3 &= !(0b11111 << 8);
(*csdk::SYSCFG).CFGR3 |= (map_value as u32) << 8;
csdk::DMA1_Channel2
},
3 => {
(*csdk::SYSCFG).CFGR3 &= !(0b11111 << 16);
(*csdk::SYSCFG).CFGR3 |= (map_value as u32) << 16;
csdk::DMA1_Channel3
},
_ => panic!(),
};
handle.State = csdk::HAL_DMA_StateTypeDef_HAL_DMA_STATE_READY;
defmt::println!("dma state 1 {} {} {}", handle.State, 1, handle.ErrorCode);
let result = csdk::HAL_DMA_Init(&mut handle);
defmt::println!("dma state 2 {} {} {}", handle.State, result, handle.ErrorCode);
}
Ok(Self { handle })
}
pub fn link(&mut self, handle: &mut impl HasDmaField){
handle.set_dma_field(self);
self.handle.Parent = handle.get_handle_ptr();
}
}
pub trait HasDmaField {
fn set_dma_field(&mut self, dma_handle: &mut DmaChannel);
fn get_handle_ptr(&mut self) -> *mut c_void;
}
#[interrupt]
unsafe fn DMA1_CHANNEL1() {
on_irq();
}
#[interrupt]
unsafe fn DMA1_CHANNEL2_3() {
on_irq();
}
unsafe fn on_irq() {
let isr = (*csdk::DMA1).ISR;
let channel_id = if (isr & 1 ) != 0 {
Some(0)
} else if ( isr & (1 << 4) ) != 0 {
Some(1)
} else if ( isr & (1 << 8) ) != 0 {
Some(2)
} else {
None
};
defmt::println!("channel_id: {}", channel_id);
match channel_id {
Some(id) => match DMA_CHANNELS[id] {
Some(ptr) => csdk::HAL_DMA_IRQHandler(ptr),
None => (),
},
None => (),
}
}