Read a micro SD card using MMC / SPI
Posted: Sat Jun 09, 2012 1:25 am
Main module: Readcard.mod
MMC.def
Code: Select all
MODULE ReadCard;
(* =========================================================================
Example ARM Oberon Program
Description:
Display the letters and numbers found in the first four blocks of an
SD Card that appear to contain text information.
Target:
LPC17xx systems with an SD Card connected to the SPI1 bus
Tested on:
Olimex LPC1766-STK Development Prototype Board
Refs:
Oberon for Cortex-M3 Microcontrollers
(c) 2009-2012 CFB Software
http://www.astrobe.com
========================================================================= *)
IMPORT SPI, Main, MCU, MMC, Out, SYSTEM;
CONST
MaxBlocks = 4;
MaxBlockNo = 4096;
PROCEDURE ShowProgress(s: ARRAY OF CHAR);
BEGIN
Out.String(s); Out.Ln
END ShowProgress;
PROCEDURE IsLetter(ch: CHAR): BOOLEAN;
BEGIN
RETURN ((ch >= "a") & (ch <= "z")) OR ((ch >= "A") & (ch <= "Z"))
END IsLetter;
PROCEDURE IsDigit(ch: CHAR): BOOLEAN;
BEGIN
RETURN (ch >= "0") & (ch <= "9")
END IsDigit;
PROCEDURE DisplayChar(ch: CHAR);
BEGIN
Out.Char(" ");
Out.Char(ch);
END DisplayChar;
PROCEDURE DisplayHex(ch: CHAR);
BEGIN
Out.Hex(ORD(ch), 4);
END DisplayHex;
PROCEDURE DisplayBlock(blockNo: INTEGER; data: MMC.DataBlock);
VAR
i: INTEGER;
ch: CHAR;
BEGIN
Out.String("BlockNumber: ");
Out.Int(blockNo, 0);
Out.Ln;
FOR i := 0 TO LEN(data) - 1 DO
ch := data[i];
IF IsLetter(ch) OR IsDigit(ch) THEN DisplayChar(ch) ELSE DisplayChar(".") END;
IF (i + 1) MOD 32 = 0 THEN Out.Ln() END
END;
Out.Ln()
END DisplayBlock;
PROCEDURE IsTextBlock(block: ARRAY OF CHAR): BOOLEAN;
(* If the first four characters are letters it is assumed to be
a text block
*)
VAR
i: INTEGER;
text: BOOLEAN;
BEGIN
text := TRUE;
i := 0;
WHILE (i < 4) & text DO
text := IsLetter(block[i]);
INC(i)
END;
RETURN text
END IsTextBlock;
PROCEDURE SDPowerOn(on: BOOLEAN);
VAR
s: SET;
BEGIN
(* P0.21 *)
SYSTEM.GET(MCU.PINSEL1, s);
SYSTEM.PUT(MCU.PINSEL1, s - {10, 11});
SYSTEM.GET(MCU.FIO0DIR, s);
SYSTEM.PUT(MCU.FIO0DIR, s + {21});
IF on THEN
SYSTEM.PUT(MCU.FIO0CLR, {21})
ELSE
SYSTEM.PUT(MCU.FIO0SET, {21})
END
END SDPowerOn;
PROCEDURE Run();
CONST
SPIBus = 1;
nBits = 8;
useSSEL = TRUE;
VAR
blockNo, blockCount, status: INTEGER;
rdData: MMC.DataBlock;
BEGIN
ShowProgress("Initialise SPI");
SPI.Init(SPIBus, nBits, useSSEL);
SDPowerOn(TRUE);
ShowProgress("Initialise MMC");
status := MMC.Init();
ASSERT(status = MMC.NoError, 101);
ShowProgress("Reading ...");
blockCount := 0;
blockNo := 0;
WHILE (blockCount < MaxBlocks) & (blockNo < MaxBlockNo) DO
status := MMC.ReadBlock(blockNo, rdData);
ASSERT(status = MMC.NoError, 102);
IF IsTextBlock(rdData) THEN
DisplayBlock(blockNo, rdData);
INC(blockCount)
END;
INC(blockNo)
END;
SDPowerOn(FALSE);
ShowProgress("Finished")
END Run;
BEGIN
Run()
END ReadCard.
Code: Select all
DEFINITION MODULE MMC;
(* =========================================================================
Astrobe Library Functions for MultiMedia / SD Cards using SPI
REF: NXP Application Note AN10406.
"Accessing SD/MMC Card using SPI on LPC2000, V3 (Jan 3, 2007)"
Oberon Version (c) 2009-2012 CFB Software
http://www.astrobe.com
========================================================================= *)
IMPORT SPI;
CONST
NoError* = 0;
IdleStateTimeout* = 1;
OpCondTimeout* = 2;
SetBlockLenTimeout* = 3;
WriteBlockTimeout* = 4;
WriteBlockFail* = 5;
ReadBlockTimeout* = 6;
ReadBlockDataTokenMissing* = 7;
DataTokenTimeout* = 8;
SelectCardTimeout* = 9;
SetRelativeAddrTimeout* = 10;
PROCEDURE Init*(): INTEGER;
PROCEDURE WriteBlock*(blockNumber: INTEGER; data: DataBlock): INTEGER;
PROCEDURE ReadBlock*(blockNumber: INTEGER; VAR data: DataBlock): INTEGER;
END MMC.