' Program: MMC.BAS written using Bascom-AVR ver 1.11.6.2 ' Basic program to interface with a Sandisk ' MMC module using the SPI protocol. ' ' ALPHA CODE ' **** NOT FOR COMMERCIAL USE ***** ' Ver. 0.0.9 Aug, 2001 ' ' Project Reference: MMC-AT103L ' MCU: Atmel AT103L ' Software: Bascom-AVR ver 1.11.6.2 ' Atmel Programmer: STK300 development board set at 3.3v. ' ISP and terminal output ' ' Initial Date: July 23, 2001 ' Projected Completion Date: Unknown ' ' Author: Ranjit Diol ' rsdiol@compsys1.com ' http://www.compsys1.com/workbench ' '*************************************************************** ' (c) COMPSys, 2001 ' All Rights Reserved '*************************************************************** ' ' DISCLAIMER: This file is being released as non-commericial ' software. It is being provided "AS IS", neither the author, ' nor COMPSys shall be held liable for any damages caused ' by its use either directly or indirectly in any form or manner. ' '=============================================================== ' 'Brief: The MMC is a 3volt part therefore all data lines ' must be conditioned if interfacing with a 5v mcu. ' Or, a 3.3v MCU can be used such as the AT103L or the AT90LS8535 ' 'IMPORTANT NOTE: ' In SPI mode the MMC's minimum block size is 512 bytes ' therefore data has to be accumulated first either in an eeprom ' or in memory before sending it out as a chunk of 512 bytes. ' ' MMC pins in SPI mode: ' Pin1:ChipSelect(SS),Pin2:MMC input(MOSI),Pin3:GND,Pin4:3V+, ' Pin5:Clock(SCK), Pin6:GND, Pin7:MMC output(MISO) ' AT103L pins: ' Portb.0 SS,Portb.1 SCK,Portb.2 MOSI, Portb.3 MISO ' ' '============================================================== $regfile = "M103def.dat" 'AT103L mcu 'Constants Const Msbl = 0 Const Msbh = 1 Const Dly = 2 Const Bits8 = 8 Const Bits16 = 16 Const Bits32 = 32 'Variables Dim Res(16) As Byte Dim Indat(512) As Byte 'Memory buffer for temp storage. Dim Dat As Byte Dim Resp As Byte Dim Resp2 As Word Dim I As Word Dim J As Word Dim X As Byte Dim Y As Byte Dim K As Byte Dim Bout As Byte Dim Addr1 As Byte Dim Addr2 As Byte Dim Addr3 As Byte Dim Addr4 As Byte Dim Addr As Long Dim Saddr As Long Dim Eaddr As Long 'Aliases Cs Alias Portb.0 Clk Alias Portb.1 Miso Alias Pinb.3 'inp Mosi Alias Portb.2 'out 'Declarations Declare Sub Mprint Declare Sub Minit Declare Sub Mstatus Declare Sub Mwrite(byval Bout As Byte , Byval Addr As Long ) Declare Sub Mread(byval Addr As Long ) Declare Sub Merase(byval Saddr As Long , Byval Eaddr As Long) 'AT103 HW SPI Portb0=SS to MMC 1, Portb1=clock to MMC 5, MISO=Portb3 to MMC 7, MOSI=Portb2 to MMC 2 Config Pinb.0 = Output Config Pinb.1 = Output Config Pinb.2 = Output Config Pinb.3 = Input Waitms 300 Config Spi = Soft , Din = Pinb.3 , Dout = Portb.2 , Ss = Portb.0 , Clock = Portb.1 Spiinit '******** MAIN PROGRAM ************* Main: 'Initialize the MMCC Minit 'If you want to use the ERASE routine 'Uncomment and enter the start/end 32bit address values 'Call erase subroutine enter StartAddr , EndAddr 'Merase &H00000000 , &H00001000 'call write subroutine as: BYTE-TO-WRITE, 32BIT_ADDRESS Mwrite &HBE , &H00000000 'Call read sub from 512 from address are put in array INDAT Mread &H00000000 'Call print sub print 512 bytes stored in INDAT array Mprint Xloop: Set Cs Shiftout Mosi , Clk , Dat , Msbl Endloop: Goto Endloop End 'end program '************ END OF PROGRAM ************** '======= SUB ROUTINES AND FUNCTIONS ======= '*** INITIALIZATION OF MMC *** Sub Minit Set Cs Dat = &HFF For I = 1 To 10 Shiftout Mosi , Clk , Dat , Msbl Next I Resp = 255 Reset Cs Cmd0: Dat = &H40 Shiftout Mosi , Clk , Dat , Msbl Addr = &H00000000 Shiftout Mosi , Clk , Addr , Msbl Dat = &H95 Shiftout Mosi , Clk , Dat , Msbl While Resp <> &H01 Shiftin Miso , Clk , Resp , Msbl Wend Lcd "C0:" ; Hex(resp) 'Initialized Set Cs Waitms 50 Reset Cs Dat = &HFF Cmd1: While Resp <> &H00 Set Cs Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl Reset Cs Dat = &H41 Shiftout Mosi , Clk , Dat , Msbl Addr = 0 Shiftout Mosi , Clk , Addr , Msbl Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl Wend Dat = &HFF Set Cs Lcd "C1:" ; Hex(resp) End Sub '**** READ routine assumes ADDR uses Status subroutine ***** Sub Mread(byval Addr As Long) Set Cs Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl Reset Cs Dat = &H51 Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Addr , Msbl Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl While Resp <> 0 Shiftin Miso , Clk , Resp , Msbl Wend While Resp <> &HFE Shiftin Miso , Clk , Resp , Msbl Wend 'Lcd Hex(resp) For I = 1 To 512 Shiftin Miso , Clk , Resp , Msbl Indat(i) = Resp 'Print Hex(resp); Next I Shiftin Miso , Clk , Resp , Msbl Shiftin Miso , Clk , Resp , Msbl Set Cs Mstatus 'Return End Sub '****Block Start Tag / End Tag and ERASE **** Sub Merase(byval Saddr As Long , Byval Eaddr As Long) 'erase first 1024 bytes 'Block START TAG Cmd32: Set Cs Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl Reset Cs Dat = &H60 Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Saddr , Msbl Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl While Resp <> &H00 Shiftin Miso , Clk , Resp , Msbl Wend 'Block END TAG Cmd33: Set Cs Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl Reset Cs Dat = &H61 Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Eaddr , Msbl Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl While Resp <> &H00 Shiftin Miso , Clk , Resp , Msbl Wend 'ERASE SELECTED BLOCK Cmd38: Set Cs Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl Reset Cs Dat = &H66 Shiftout Mosi , Clk , Dat , Msbl Addr = 0 Shiftout Mosi , Clk , Addr , Msbl Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl While Resp = 0 Shiftin Miso , Clk , Resp , Msbl Wend Mstatus End Sub '** WRITE Routine assumes ADDR, BOUT uses Status subroutine ** Sub Mwrite(byval Bout As Byte , Byval Addr As Long) Cmd24: Set Cs Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl Reset Cs Dat = &H58 Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Addr , Msbl Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl While Resp <> 0 Shiftin Miso , Clk , Resp , Msbl Wend Lcd "C24:" ; Hex(resp) Dat = &HFE Shiftout Mosi , Clk , Dat , Msbl For I = 1 To 512 Shiftout Mosi , Clk , Bout , Msbl Next I Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl 'If Y = &H05 write is a success Y = Resp And &H0F 'If Resp = 0 the MMC is busy Shiftin Miso , Clk , Resp , Msbl While Resp = 0 Shiftin Miso , Clk , Resp , Msbl Wend Lowerline Lcd "Wr:" ; Hex(y) Set Cs Mstatus End Sub 'Get MMC Status Sub Mstatus Cmd13: Set Cs Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp , Msbl Reset Cs Dat = &H4D Shiftout Mosi , Clk , Dat , Msbl Addr = 0 Shiftout Mosi , Clk , Addr , Msbl Dat = &HFF Shiftout Mosi , Clk , Dat , Msbl Shiftout Mosi , Clk , Dat , Msbl Shiftin Miso , Clk , Resp2 , Msbl Print "Status:" ; Hex(resp2) Set Cs 'Return End Sub Sub Mprint For I = 1 To 512 Print Hex(indat(i)); Next Mstatus End Sub