Skip to content

Commit

Permalink
Merge pull request #14 from braun-embedded/aes-dma2
Browse files Browse the repository at this point in the history
Add DMA support to AES module
  • Loading branch information
arkorobotics authored Jul 27, 2019
2 parents 12aed40 + 25f33a9 commit b1fdd33
Show file tree
Hide file tree
Showing 5 changed files with 688 additions and 4 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ version = "0.1.7"
features = ["stm32l0x1", "stm32l0x2", "rt"]

[dependencies]
as-slice = "0.1.0"
embedded-hal = { version = "0.2.3", features = ["unproven"] }
cortex-m = {version = "0.5.8", features = ["const-fn"] }
cortex-m-rt = "0.6.8"
Expand Down Expand Up @@ -85,6 +86,10 @@ opt-level = "s"
name = "aes"
required-features = ["stm32l082"]

[[example]]
name = "aes-dma"
required-features = ["stm32l082"]

[[example]]
name = "button_irq"
required-features = ["rt"]
Expand Down
114 changes: 114 additions & 0 deletions examples/aes-dma.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//! Encryption/decryption using the AES peripheral


#![no_main]
#![no_std]


extern crate panic_semihosting;


use core::pin::Pin;

use cortex_m_rt::entry;
use stm32l0xx_hal::{
prelude::*,
aes::AES,
dma::DMA,
pac,
rcc::Config,
};


#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();

let mut rcc = dp.RCC.freeze(Config::hsi16());
let mut aes = AES::new(dp.AES, &mut rcc);
let mut dma = DMA::new(dp.DMA1, &mut rcc);

let key = [0x01234567, 0x89abcdef, 0x01234567, 0x89abcdef];
let ivr = [0xfedcba98, 0x76543210, 0xfedcba98];

const DATA: [u32; 8] = [
0x00112233,
0x44556677,
0x8899aabb,
0xccddeeff,

0x00112233,
0x44556677,
0x8899aabb,
0xccddeeff,
];
let data = Pin::new(&DATA);

static mut ENCRYPTED: [u32; 8] = [0; 8];
static mut DECRYPTED: [u32; 8] = [0; 8];

// Prepare DMA buffers. This is safe, as this is the `main` function, and no
// other functions have access to these statics.
let mut encrypted = Pin::new(unsafe { &mut ENCRYPTED });
let mut decrypted = Pin::new(unsafe { &mut DECRYPTED });

loop {
let mut ctr_stream = aes.start_ctr_stream(key, ivr);
let tx_transfer = ctr_stream.tx
.write_all(
&mut dma.handle,
data,
dma.channels.channel1,
)
.start();
let rx_transfer = ctr_stream.rx
.read_all(
&mut dma.handle,
encrypted,
dma.channels.channel2,
)
.start();

let tx_res = tx_transfer.wait().unwrap();
let rx_res = rx_transfer.wait().unwrap();

ctr_stream.tx = tx_res.target;
ctr_stream.rx = rx_res.target;
dma.channels.channel1 = tx_res.channel;
dma.channels.channel2 = rx_res.channel;
encrypted = rx_res.buffer;
aes = ctr_stream.finish();

assert_ne!(encrypted, Pin::new(&mut [0; 8]));
assert_ne!(encrypted, data);

let mut ctr_stream = aes.start_ctr_stream(key, ivr);
let tx_transfer = ctr_stream.tx
.write_all(
&mut dma.handle,
encrypted,
dma.channels.channel1,
)
.start();
let rx_transfer = ctr_stream.rx
.read_all(
&mut dma.handle,
decrypted,
dma.channels.channel2,
)
.start();

let tx_res = tx_transfer.wait().unwrap();
let rx_res = rx_transfer.wait().unwrap();

ctr_stream.tx = tx_res.target;
ctr_stream.rx = rx_res.target;
dma.channels.channel1 = tx_res.channel;
dma.channels.channel2 = rx_res.channel;
encrypted = tx_res.buffer;
decrypted = rx_res.buffer;
aes = ctr_stream.finish();

assert_eq!(decrypted, data);
}
}
82 changes: 78 additions & 4 deletions src/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,24 @@
//! See STM32L0x2 reference manual, chapter 18.


use core::convert::TryInto;
use core::{
convert::TryInto,
ops::{
Deref,
DerefMut,
},
pin::Pin,
};

use as_slice::{
AsMutSlice,
AsSlice,
};
use nb::block;
use void::Void;

use crate::{
dma,
pac,
rcc::Rcc,
};
Expand All @@ -32,9 +44,9 @@ impl AES {
// Configure peripheral
aes.cr.write(|w| {
w
// Disable DMA
.dmaouten().clear_bit()
.dmainen().clear_bit()
// Enable DMA
.dmaouten().set_bit()
.dmainen().set_bit()
// Disable interrupts
.errie().clear_bit()
.ccfie().clear_bit()
Expand Down Expand Up @@ -176,6 +188,37 @@ impl Tx {

Ok(())
}

/// Writes the provided buffer to the AES peripheral using DMA
///
/// Returns a DMA transfer that is ready to be started. It needs to be
/// started for anything to happen.
///
/// # Panics
///
/// Panics, if the buffer length is larger than `u16::max_value()`.
///
/// The AES peripheral works with 128-bit blocks, which means the buffer
/// length must be a multiple of 4. Panics, if this is not the case.
pub fn write_all<Buffer, Channel>(self,
dma: &mut dma::Handle,
buffer: Pin<Buffer>,
channel: Channel,
)
-> dma::Transfer<Self, Channel, Buffer, dma::Ready>
where
Self: dma::Target<Channel>,
Buffer: Deref + 'static,
Buffer::Target: AsSlice<Element=u32>,
Channel: dma::Channel,
{
assert!(buffer.as_slice().len() % 4 == 0);

// Safe, because we're only taking the address of a register.
let address = &unsafe { &*pac::AES::ptr() }.dinr as *const _ as u32;

dma::Transfer::memory_to_peripheral(dma, self, channel, buffer, address)
}
}


Expand Down Expand Up @@ -218,6 +261,37 @@ impl Rx {

Ok(block)
}

/// Reads data from the AES peripheral into the provided buffer using DMA
///
/// Returns a DMA transfer that is ready to be started. It needs to be
/// started for anything to happen.
///
/// # Panics
///
/// Panics, if the buffer length is larger than `u16::max_value()`.
///
/// The AES peripheral works with 128-bit blocks, which means the buffer
/// length must be a multiple of 4. Panics, if this is not the case.
pub fn read_all<Buffer, Channel>(self,
dma: &mut dma::Handle,
buffer: Pin<Buffer>,
channel: Channel,
)
-> dma::Transfer<Self, Channel, Buffer, dma::Ready>
where
Self: dma::Target<Channel>,
Buffer: DerefMut + 'static,
Buffer::Target: AsMutSlice<Element=u32>,
Channel: dma::Channel,
{
assert!(buffer.as_slice().len() % 4 == 0);

// Safe, because we're only taking the address of a register.
let address = &unsafe { &*pac::AES::ptr() }.doutr as *const _ as u32;

dma::Transfer::peripheral_to_memory(dma, self, channel, buffer, address)
}
}


Expand Down
Loading

0 comments on commit b1fdd33

Please sign in to comment.