rust: sdlcd improvements

- Init error reporting
- Put 16-bit halves of display output correctly
- Better comments
This commit is contained in:
Wladimir J. van der Laan 2019-08-12 07:34:04 +00:00
parent a46b314c6d
commit ed91b43e2a
2 changed files with 42 additions and 28 deletions

View File

@ -1,4 +1,4 @@
//! SD card slot access on Maix Go //! SD card slot access (in SPI mode) on Maix Go
// TODO: actually use the DMA channel that is claimed… // TODO: actually use the DMA channel that is claimed…
use core::convert::TryInto; use core::convert::TryInto;
@ -34,7 +34,7 @@ pub const SEC_LEN: usize = 512;
/** SD commands */ /** SD commands */
#[repr(u8)] #[repr(u8)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
enum CMD { pub enum CMD {
/** Software reset */ /** Software reset */
CMD0 = 0, CMD0 = 0,
/** Check voltage range (SDC V2) */ /** Check voltage range (SDC V2) */
@ -67,6 +67,13 @@ enum CMD {
CMD59 = 59, CMD59 = 59,
} }
#[derive(Debug, Copy, Clone)]
pub enum InitError {
CMDFailed(CMD, u8),
CardCapacityStatusNotSet([u8; 4]),
CannotGetCardInfo,
}
/** /**
* Card Specific Data: CSD Register * Card Specific Data: CSD Register
*/ */
@ -441,15 +448,18 @@ impl<'a, X: SPI> SDCard<'a, X> {
} }
/* /*
* Initializes the SD/SD communication. * Initializes the SD/SD communication in SPI mode.
* @param None * @param None
* @retval The SD Response info if succeeeded, otherwise Err * @retval The SD Response info if succeeeded, otherwise Err
*/ */
pub fn init(&self) -> Result<SD_CardInfo, ()> { pub fn init(&self) -> Result<SD_CardInfo, InitError> {
/* Initialize SD_SPI */ /* Initialize SD_SPI */
self.lowlevel_init(); self.lowlevel_init();
/* SD chip select high */ /* SD chip select high */
self.CS_HIGH(); self.CS_HIGH();
/* NOTE: this reset doesn't always seem to work if the SD access was broken off in the
* middle of an operation: CMDFailed(CMD0, 127). */
/* Send dummy byte 0xFF, 10 times with CS high */ /* Send dummy byte 0xFF, 10 times with CS high */
/* Rise CS and MOSI for 80 clocks cycles */ /* Rise CS and MOSI for 80 clocks cycles */
/* Send dummy byte 0xFF */ /* Send dummy byte 0xFF */
@ -457,15 +467,15 @@ impl<'a, X: SPI> SDCard<'a, X> {
/*------------Put SD in SPI mode--------------*/ /*------------Put SD in SPI mode--------------*/
/* SD initialized and set to SPI mode properly */ /* SD initialized and set to SPI mode properly */
/* Send software reset */
self.send_cmd(CMD::CMD0, 0, 0x95); self.send_cmd(CMD::CMD0, 0, 0x95);
let result = self.get_response(); let result = self.get_response();
self.end_cmd(); self.end_cmd();
if result != 0x01 { if result != 0x01 {
// printf("SD_CMD0 is %X\n", result); return Err(InitError::CMDFailed(CMD::CMD0, result));
// TODO: better erroring
return Err(());
} }
/* Check voltage range */
self.send_cmd(CMD::CMD8, 0x01AA, 0x87); self.send_cmd(CMD::CMD8, 0x01AA, 0x87);
/* 0x01 or 0x05 */ /* 0x01 or 0x05 */
let result = self.get_response(); let result = self.get_response();
@ -473,17 +483,18 @@ impl<'a, X: SPI> SDCard<'a, X> {
self.read_data(&mut frame); self.read_data(&mut frame);
self.end_cmd(); self.end_cmd();
if result != 0x01 { if result != 0x01 {
//printf("SD_CMD8 is %X\n", result); return Err(InitError::CMDFailed(CMD::CMD8, result));
return Err(());
} }
let mut index = 255; let mut index = 255;
while index != 0 { while index != 0 {
/* <ACMD> */
self.send_cmd(CMD::CMD55, 0, 0); self.send_cmd(CMD::CMD55, 0, 0);
let result = self.get_response(); let result = self.get_response();
self.end_cmd(); self.end_cmd();
if result != 0x01 { if result != 0x01 {
return Err(()); return Err(InitError::CMDFailed(CMD::CMD55, result));
} }
/* Initiate SDC initialization process */
self.send_cmd(CMD::ACMD41, 0x40000000, 0); self.send_cmd(CMD::ACMD41, 0x40000000, 0);
let result = self.get_response(); let result = self.get_response();
self.end_cmd(); self.end_cmd();
@ -493,12 +504,12 @@ impl<'a, X: SPI> SDCard<'a, X> {
index -= 1; index -= 1;
} }
if index == 0 { if index == 0 {
//printf("SD_CMD55 is %X\n", result); return Err(InitError::CMDFailed(CMD::ACMD41, result));
return Err(());
} }
index = 255; index = 255;
let mut frame = [0u8; 4]; let mut frame = [0u8; 4];
while index != 0 { while index != 0 {
/* Read OCR */
self.send_cmd(CMD::CMD58, 0, 1); self.send_cmd(CMD::CMD58, 0, 1);
let result = self.get_response(); let result = self.get_response();
self.read_data(&mut frame); self.read_data(&mut frame);
@ -509,20 +520,19 @@ impl<'a, X: SPI> SDCard<'a, X> {
index -= 1; index -= 1;
} }
if index == 0 { if index == 0 {
// printf("SD_CMD58 is %X\n", result); return Err(InitError::CMDFailed(CMD::CMD58, result));
return Err(());
} }
if (frame[0] & 0x40) == 0 { if (frame[0] & 0x40) == 0 {
return Err(()); return Err(InitError::CardCapacityStatusNotSet(frame));
} }
self.HIGH_SPEED_ENABLE(); self.HIGH_SPEED_ENABLE();
self.get_cardinfo() self.get_cardinfo()
.map_err(|_| InitError::CannotGetCardInfo)
} }
/* /*
* Reads a block of data from the SD. * Reads a block of data from the SD.
* @param data_buf: pointer to the buffer that receives the data read from the * @param data_buf: slice that receives the data read from the SD.
* SD.
* @param sector: SD's internal address to read from. * @param sector: SD's internal address to read from.
* @retval The SD Response: * @retval The SD Response:
* - `Err(())`: Sequence failed * - `Err(())`: Sequence failed
@ -572,8 +582,7 @@ impl<'a, X: SPI> SDCard<'a, X> {
/* /*
* Writes a block to the SD * Writes a block to the SD
* @param data_buf: pointer to the buffer containing the data to be written on * @param data_buf: slice containing the data to be written to the SD.
* the SD.
* @param sector: address to write on. * @param sector: address to write on.
* @retval The SD Response: * @retval The SD Response:
* - `Err(())`: Sequence failed * - `Err(())`: Sequence failed

View File

@ -1,4 +1,6 @@
/*! Stream raw data from SD card to LCD, bascially a test for using both SPI0 and SPI1 */ /*! Stream raw data from SD card to LCD, bascially a test for using both SPI0 and SPI1
* at the same time
*/
#![allow(dead_code)] #![allow(dead_code)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
@ -9,8 +11,8 @@ use core::convert::TryInto;
use k210_hal::prelude::*; use k210_hal::prelude::*;
use k210_hal::stdout::Stdout; use k210_hal::stdout::Stdout;
use k210_hal::Peripherals; use k210_hal::Peripherals;
use k210_shared::board::def::{io,DISP_WIDTH,DISP_HEIGHT,DISP_PIXELS}; use k210_shared::board::def::{io, DISP_HEIGHT, DISP_PIXELS, DISP_WIDTH};
use k210_shared::board::lcd::{LCD,LCDHL,self}; use k210_shared::board::lcd::{self, LCD, LCDHL};
use k210_shared::board::lcd_colors; use k210_shared::board::lcd_colors;
use k210_shared::board::sdcard; use k210_shared::board::sdcard;
use k210_shared::soc::dmac::{dma_channel, DMACExt}; use k210_shared::soc::dmac::{dma_channel, DMACExt};
@ -22,7 +24,7 @@ use riscv_rt::entry;
/** GPIOHS GPIO number to use for controlling the SD card CS pin */ /** GPIOHS GPIO number to use for controlling the SD card CS pin */
const SD_CS_GPIONUM: u8 = 7; const SD_CS_GPIONUM: u8 = 7;
/** CS value passed to SPI controller, this is a dummy value as SPI0_CS3 is not mapping to anything /** CS value passed to SPI controller, this is a dummy value as SPI0_CS3 is not mapped to anything
* in the FPIOA */ * in the FPIOA */
const SD_CS: u32 = 3; const SD_CS: u32 = 3;
@ -90,14 +92,17 @@ fn main() -> ! {
let mut image: ScreenImage = [0; DISP_PIXELS / 2]; let mut image: ScreenImage = [0; DISP_PIXELS / 2];
let mut buffer = [0u8; DISP_PIXELS * 2]; let mut buffer = [0u8; DISP_PIXELS * 2];
while sector < num_sectors { while sector < num_sectors {
sd.read_sector(&mut buffer, sector.try_into().unwrap()).unwrap(); /* Read raw image */
sd.read_sector(&mut buffer, sector.try_into().unwrap())
.unwrap();
writeln!(stdout, "sector {} succesfully read", sector).unwrap(); writeln!(stdout, "sector {} succesfully read", sector).unwrap();
let mut i = buffer.iter(); let mut i = buffer.iter();
/* Combine into u32s, reordering 16-bit halves */
for x in image.iter_mut() { for x in image.iter_mut() {
*x = (u32::from(*i.next().unwrap()) << 0) | *x = (u32::from(*i.next().unwrap()) << 16)
(u32::from(*i.next().unwrap()) << 8) | | (u32::from(*i.next().unwrap()) << 24)
(u32::from(*i.next().unwrap()) << 16) | | (u32::from(*i.next().unwrap()) << 0)
(u32::from(*i.next().unwrap()) << 24); | (u32::from(*i.next().unwrap()) << 8);
} }
lcd.draw_picture(0, 0, DISP_WIDTH, DISP_HEIGHT, &image); lcd.draw_picture(0, 0, DISP_WIDTH, DISP_HEIGHT, &image);