How to co-exist SD/MMC and I2C module SCK/SCL SDI/SDA SDO SD/MMC CE MCU I2C Device Typ 65mA GPS Module Soft UART SPI SD PIC 18F2550 Soft I2C 2X AA Cell Boost DC/DC VCC(3.3V) LCD Tips to handle SD card Initialize at PWON Cs=clk=di high Entering SPI mode Raw I/O DO B6 B7 B7 DI B6 CLK GetResponse Ret0xff Do retry{ send 0xff if(!(res&0xfe) break; } Return ret; /CShigh Send dummy 80 clocks (Send 0xff x 10) /CSLow Send 0x40,0x00,0x00,0x00,0x00,0x95 Ret=GetResponse(); While(ret==0x0){ cshigh send 0xff cslow send 0x40,0x00,0x00,0x00,0x00,0x00,0x95 ret=GetResponse(); } /cshigh Send 0xff Status = Tips to handle SD card address’d read /write DI A3 0x40|17 Command 17 A2 A1 A0 Least command list 6Bytes command Start Command Argument CRC Stop “01” 6bit 32bit 7bit “1” CRC Required at CMD0 before changing SPI mode. Ignored at SPI mode. Response R1 (1Byte) Fixed Invalid argument Invalid address Erase err CRC Err Invalid CMD ? Idling “0” 1/0 1/0 1/0 1/0 1/0 1/0 1/0 Command Arg Response Operation / affects CMD0 none R1 Reset card CMD1 None R1 Ask if card reset has done? CMD16 Length R1 Change block length used in CMD 17 and CMD24.Default is 512.Up to 2024 bytes.Some restrictions depend on the card. Does not apply on write operation. CMD17 Address R1 Single block read. CMD24 Address R1 Single block write Single block read sequence /CS TX CMD16 A3 A2 A1 A0 FF RX R1 D0 D1 ~ D511 CRC1 CRC2 Single block write sequence /CS TX CMD24 D0 D1 ~ D511 A3 A2 A1 A0 FF R1 CRC1 CRC2 Single block read sequence Regular task 1s Timer invocation. Read SW. Read and Parse GPS Msg. Read Batt. Volt. Write data to SD. Exec command Update LCD. FAT16 Filesystem Software I2C Driver Software UART Driver Software I2C Interrupt Timer Value Consider benefits between Direct execution and ISR interruption. NOP SCL SDA NOP blank START state ST b7 b6 ACK SM PAYLOAD ACK MAX clk freq : 400kHz … 2.5us Exec step @ 8MHz … 0.5us @40MHz ... 0.1us Interrupt latency … several clks data clk Timer assignment TMR0 Software serial TMR1 Software I2C TMR2 TMR3 Software serial (receive only) top level interface Underlying i/o func in ISR char ser_getchar(void) if RXING { process RX until done; } else if HAS_TX process TX until done; } else { wait for RX; } RX buff State diagram INIT TXSTBY waiting for start bit TMR0L 0xff //TMR0 full count T0IF0 // Clear TMR0 flag T0IE1 // Set TMR0 INT RXWAITING ser_getchar() TXBUSY RXBUSY Tx not implimented RXREADY RXERR b 1.5b LSB FIRST ST RXWAITING RXBUSY 0 1 2 3 4 5 6 7 SP RXREADY Software serial timing consideration interrupt read bit prepare for next Counter value for Start BIT: 1.5bit = 1.563E-4s ... 195.38 256 – 195 = 61 Other BIT: 1bit = 1.042E-4s ... 124.8 256 – 125 = 131 1/9600 = 1.042E-4s ST 1.5bit 8MHz 40MHz 1/4 2MHz 10MHz Prescaler 1/8 1/2 1us 1MHz 1.25MHz 0.8us 8bit Timer (1/256) 1/104 1/130 104.17us SPI raw level I/O MBR 0 boot 446 P.tbl1 P.tbl2 P.tbl3 P.tbl4 signature struct { Byte bootDescriptor; /* 0x80: bootable device, 0x00: non-bootable */ Byte firstPartitionSector[3]; /* 1st sector number */ Byte fileSystemDescriptor; /* 1:FAT12, 4:FAT16(less than 32MB), 5:拡張 DOS パーティション, 6:FAT16(more 32MB), 0xb:FAT32(more 2GB), 0xc:FAT32 Int32h 拡張, 0xe:FAT16 Int32h 拡張, 0xf:拡張 DOS パーティションの Int32h 拡張 */ Byte lastPartitionSector[3]; Byte firstSectorNumbers[4]; /* first sector number (link to BPB sector) */ Byte numberOfSectors[4]; } partitionTable; firstSectorNumbers(454~457) holds offset to logical sector 0 in little endian ex 3E 00 00 00 3E * 512 = 7C00 PBR 7C00 JMP INST(3) OEM NAME (8) BIOS Param Blk(25) Ext BIOS Param Blk(26) Boot (448) signature(2) struct { Byte bytesPerSector[2]; /* bytes/sector */ Byte sectorsPerCluster; /* sectors/cluster */ Byte reservedSectors[2]; /* reserved sector, beginning with sector 0 */ Byte numberOfFATs; /* file allocation table */ Byte rootEntries[2]; /* root entry (512) */ Byte totalSectors[2]; /* partion total secter */ Byte mediaDescriptor; /* 0xf8: Hard Disk */ Byte sectorsPerFAT[2]; /* sector/FAT (FAT32 always zero: see bigSectorsPerFAT) */ Byte sectorsPerTrack[2]; /* sector/track (not use) */ Byte heads[2]; /* heads number (not use) */ Byte hiddenSectors[4]; /* hidden sector number */ Byte bigTotalSectors[4]; /* total sector number */ } FAT16BPB; PBR + ReservedSectors x 512 ex 7C00h + 6x512 = 8800h 8800 FAT1 27200 45C00 FAT2 Root directory entry 49C00 User Data Area SectorsPerFat ex F5h x 512=1EA00h 8800h+1EA00h = 27200h ex 27200h+1EA00h = 45C00h sizeof(Direntey) x rootEntries ex 32 x 512 = 16384 45C00h + 16384(dec) = typedef struct DirEntry_t { Byte name[8]; /* file name */ Byte extension[3]; /* file name extension */ Byte attribute; /* file attribute bit 4 directory flag bit 3 volume flag bit 2 hidden flag bit 1 system flag bit 0 read only flag */ Byte reserved; /* use NT or same OS */ Byte createTimeMs; /* VFAT で使用するファイル作成時刻の10ミリ秒 (0 ~ 199) */ Byte createTime[2]; /* VFAT で使用するファイル作成時間 */ Byte createDate[2]; /* VFAT で使用するファイル作成日付 */ Byte accessDate[2]; /* VFAT で使用するファイル・アクセス日付 */ Byte clusterHighWord[2]; /* FAT32 で使用するクラスタ番号の上位 16 bits */ Byte updateTime[2]; Byte updateDate[2]; Byte cluster[2]; /* start cluster number */ Byte fileSize[4]; /* file size in bytes (directory is always zero) */ }; Filesystem initialization Read MBR •Retrieve firstSectorNumbers •Determine head of PBR1 firstSectorNumbers x 512 •Note We does not handle other than No.1 Partition. Read PBR1 •Retrieve ReservedSectors, SectorsPerFAT, SectorsPerCluster, rootEntries, bigTotalSectors •Determine head address of FAT1 PBR1 + ReservedSectors x 512 FAT2 FAT1 + SectorsPerFAT x 512 RDE FAT2 + SectorsPerFAT x 512 UDA RDE + 32 x rootEntries NumSectorsOfUDA bigTotalSectors – ReservedSectors – (UDA – FAT1)/512 UDAClusters NumSecdtorsOfUDA / SectorsPerCluster •Holds following information FAT1 FAT2 SectorsPerFAT RDE rootEntries UDA UDAClusters SectorsPerCluster Create and write a file on filesystem Create() FAT1 FAT2 UDA R Look for unused RDE Look for unused cluster RDE R W W Mark 0xFF to found cluster W Update corresponding RDE Write() W Write Data to allocated cluster W Update length of RDE Update linked list of FAT (if data occupies beyond current cluster) close() Flush unwritten data Update length of RDE Mark 0xFF to last used cluster W W Interface layer ser_init() ser_isr() gps_init() buff ser_getchr() buff GPS status register gps_parse() coord i2c_init() i2c_write() LCD Display time info V.Batt SW adc_read() V.BATT fopen() fclose() fwrite() fprintf() FAT mm_init() mm_read_block() spi_init() mm_write_block() spi_trx() MM SPI SD Card write(data, length) buff_len buffer[512] sector uda cluster •current_cluster •index of sector in the curr. cluster address uda + (curr.cluster -2) * sector_per_cluster * 512 + index_of_sector * 512 •buff_len GPS Data format of GGA NNorth Altitude SSouth where: dd deg mm.mmmm min(resolution 1E-4) Time in UTC where: hhhour mmmin ss.ssssec Longitude where: ddd deg mm.mmmm min(resolution 1E-4) $GPGGA,hhmmss.sss,ddmm.mmmm,N,dddmm.mmmm,E, 0 2 38 40 48 13 56 23 25 36 v,ss,dd.d,hhhhh.h,M,gggg.g,M,XXX.X,0000*hh<CR><LF> Latitude Num of STAs used range: 00 - 12 State of measuring where: 0Not working 1Working Latitude unit in meter WWest EEast
© Copyright 2024 ExpyDoc