mirror of
https://github.com/laanwj/k210-sdk-stuff.git
synced 2024-11-22 09:26:21 +04:00
rust: sdcard read/write sectors using DMA
This commit is contained in:
parent
ed91b43e2a
commit
0dcbeda646
@ -1,5 +1,4 @@
|
|||||||
//! SD card slot access (in SPI mode) on Maix Go
|
//! SD card slot access (in SPI mode) on Maix Go
|
||||||
// TODO: actually use the DMA channel that is claimed…
|
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
|
|
||||||
use crate::soc::dmac::{dma_channel, DMAC};
|
use crate::soc::dmac::{dma_channel, DMAC};
|
||||||
@ -189,6 +188,22 @@ impl<'a, X: SPI> SDCard<'a, X> {
|
|||||||
self.spi.send_data(self.spi_cs, data);
|
self.spi.send_data(self.spi_cs, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_data_dma(&self, data: &[u32]) {
|
||||||
|
self.spi.configure(
|
||||||
|
work_mode::MODE0,
|
||||||
|
frame_format::STANDARD,
|
||||||
|
8, /* data bits */
|
||||||
|
0, /* endian */
|
||||||
|
0, /*instruction length*/
|
||||||
|
0, /*address length*/
|
||||||
|
0, /*wait cycles*/
|
||||||
|
aitm::STANDARD,
|
||||||
|
tmod::TRANS,
|
||||||
|
);
|
||||||
|
self.spi
|
||||||
|
.send_data_dma(self.dmac, self.channel, self.spi_cs, data);
|
||||||
|
}
|
||||||
|
|
||||||
fn read_data(&self, data: &mut [u8]) {
|
fn read_data(&self, data: &mut [u8]) {
|
||||||
self.spi.configure(
|
self.spi.configure(
|
||||||
work_mode::MODE0,
|
work_mode::MODE0,
|
||||||
@ -204,6 +219,22 @@ impl<'a, X: SPI> SDCard<'a, X> {
|
|||||||
self.spi.recv_data(self.spi_cs, data);
|
self.spi.recv_data(self.spi_cs, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_data_dma(&self, data: &mut [u32]) {
|
||||||
|
self.spi.configure(
|
||||||
|
work_mode::MODE0,
|
||||||
|
frame_format::STANDARD,
|
||||||
|
8, /* data bits */
|
||||||
|
0, /* endian */
|
||||||
|
0, /*instruction length*/
|
||||||
|
0, /*address length*/
|
||||||
|
0, /*wait cycles*/
|
||||||
|
aitm::STANDARD,
|
||||||
|
tmod::RECV,
|
||||||
|
);
|
||||||
|
self.spi
|
||||||
|
.recv_data_dma(self.dmac, self.channel, self.spi_cs, data);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send 5 bytes command to the SD card.
|
* Send 5 bytes command to the SD card.
|
||||||
* @param cmd: The user expected command to send to SD card.
|
* @param cmd: The user expected command to send to SD card.
|
||||||
@ -554,13 +585,18 @@ impl<'a, X: SPI> SDCard<'a, X> {
|
|||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
let mut error = false;
|
let mut error = false;
|
||||||
|
let mut dma_chunk = [0u32; SEC_LEN];
|
||||||
for chunk in data_buf.chunks_mut(SEC_LEN) {
|
for chunk in data_buf.chunks_mut(SEC_LEN) {
|
||||||
if self.get_response() != SD_START_DATA_SINGLE_BLOCK_READ {
|
if self.get_response() != SD_START_DATA_SINGLE_BLOCK_READ {
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Read the SD block data : read NumByteToRead data */
|
/* Read the SD block data : read NumByteToRead data */
|
||||||
self.read_data(chunk);
|
self.read_data_dma(&mut dma_chunk);
|
||||||
|
/* Place the data received as u32 units from DMA into the u8 target buffer */
|
||||||
|
for (a, b) in chunk.iter_mut().zip(dma_chunk.iter()) {
|
||||||
|
*a = (b & 0xff) as u8;
|
||||||
|
}
|
||||||
/* Get CRC bytes (not really needed by us, but required by SD) */
|
/* Get CRC bytes (not really needed by us, but required by SD) */
|
||||||
let mut frame = [0u8; 2];
|
let mut frame = [0u8; 2];
|
||||||
self.read_data(&mut frame);
|
self.read_data(&mut frame);
|
||||||
@ -610,11 +646,15 @@ impl<'a, X: SPI> SDCard<'a, X> {
|
|||||||
self.end_cmd();
|
self.end_cmd();
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
let mut dma_chunk = [0u32; SEC_LEN];
|
||||||
for chunk in data_buf.chunks(SEC_LEN) {
|
for chunk in data_buf.chunks(SEC_LEN) {
|
||||||
/* Send the data token to signify the start of the data */
|
/* Send the data token to signify the start of the data */
|
||||||
self.write_data(&frame);
|
self.write_data(&frame);
|
||||||
/* Write the block data to SD : write count data by block */
|
/* Write the block data to SD : write count data by block */
|
||||||
self.write_data(chunk);
|
for (a, &b) in dma_chunk.iter_mut().zip(chunk.iter()) {
|
||||||
|
*a = b.into();
|
||||||
|
}
|
||||||
|
self.write_data_dma(&mut dma_chunk);
|
||||||
/* Put dummy CRC bytes */
|
/* Put dummy CRC bytes */
|
||||||
self.write_data(&[0xff, 0xff]);
|
self.write_data(&[0xff, 0xff]);
|
||||||
/* Read data response */
|
/* Read data response */
|
||||||
|
@ -75,6 +75,7 @@ pub trait SPI {
|
|||||||
);
|
);
|
||||||
fn set_clk_rate(&self, spi_clk: u32) -> u32;
|
fn set_clk_rate(&self, spi_clk: u32) -> u32;
|
||||||
fn recv_data<X: TruncU32>(&self, chip_select: u32, rx: &mut [X]);
|
fn recv_data<X: TruncU32>(&self, chip_select: u32, rx: &mut [X]);
|
||||||
|
fn recv_data_dma(&self, dmac: &DMAC, channel_num: dma_channel, chip_select: u32, rx: &mut [u32]);
|
||||||
fn send_data<X: Into<u32> + Copy>(&self, chip_select: u32, tx: &[X]);
|
fn send_data<X: Into<u32> + Copy>(&self, chip_select: u32, tx: &[X]);
|
||||||
fn send_data_dma(&self, dmac: &DMAC, channel_num: dma_channel, chip_select: u32, tx: &[u32]);
|
fn send_data_dma(&self, dmac: &DMAC, channel_num: dma_channel, chip_select: u32, tx: &[u32]);
|
||||||
fn fill_data(&self, chip_select: u32, value: u32, tx_len: usize);
|
fn fill_data(&self, chip_select: u32, value: u32, tx_len: usize);
|
||||||
@ -193,6 +194,30 @@ impl<IF: SPI01> SPI for SPIImpl<IF> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Receive 32-bit data using DMA.
|
||||||
|
// make sure to set tmod to tmod::RECV
|
||||||
|
fn recv_data_dma(&self, dmac: &DMAC, channel_num: dma_channel, chip_select: u32, rx: &mut [u32]) {
|
||||||
|
if rx.len() == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
self.spi.ctrlr1.write(|w| w.bits((rx.len() - 1).try_into().unwrap()));
|
||||||
|
self.spi.ssienr.write(|w| w.bits(0x01));
|
||||||
|
self.spi.dmacr.write(|w| w.bits(0x3)); /*enable dma receive */
|
||||||
|
|
||||||
|
sysctl::dma_select(channel_num, IF::DMA_RX);
|
||||||
|
dmac.set_single_mode(channel_num, self.spi.dr.as_ptr() as u64, rx.as_ptr() as u64,
|
||||||
|
address_increment::NOCHANGE, address_increment::INCREMENT,
|
||||||
|
burst_length::LENGTH_1, transfer_width::WIDTH_32, rx.len() as u32);
|
||||||
|
self.spi.dr[0].write(|w| w.bits(0xffffffff));
|
||||||
|
self.spi.ser.write(|w| w.bits(1 << chip_select));
|
||||||
|
dmac.wait_done(channel_num);
|
||||||
|
|
||||||
|
self.spi.ser.write(|w| w.bits(0x00));
|
||||||
|
self.spi.ssienr.write(|w| w.bits(0x00));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Send arbitrary data
|
/// Send arbitrary data
|
||||||
fn send_data<X: Into<u32> + Copy>(&self, chip_select: u32, tx: &[X]) {
|
fn send_data<X: Into<u32> + Copy>(&self, chip_select: u32, tx: &[X]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
Loading…
Reference in New Issue
Block a user