Open Instrument Project 이번세미나에서는 I. SD/SDHC 카드사용방법분석 II. OI 응용모듈 : SD Card / MP3 모듈 III. FAT 파일시스템분석 IV. OI 플랫폼라이브러리 : Drive, FileSystem V. MP3 코덱 : VS1053 VI. Example : SD Card 에저장된 MP3 파일재생하기 Open Instrument Project 2011. 6. 15 이상진 ICbanq 연구원
I. SD/SDHC 카드사용방법분석 1
I. SD/SDHC 카드사용방법분석 SD/SDHC 카드의핀매핑 SPI Mo ode SD Mode SPI Mode 1 DAT3 CS 2 CMD DI 3 GND 4 VCC 5 CLK SCLK 6 GND 7 DAT0 DO 8 DAT1 9 DAT2 2
I. SD/SDHC 카드사용방법분석 SD/SDHC 카드의동작모드 SD Mode 4 Bit 씩데이터전송 보다고속의데이터전송이가능하나특수한인터페이스가필요함 SPI Mode 1 Bit 씩데이터전송 SD 모드에비해상대적으로전송속도가느리지만 MCU 에기본내장된 SPI 인터페이스만으로사용가능 3
I. SD/SDHC 카드사용방법분석 SD vs SDHC 주소지정방식 최대용량 SD Byte 단위주소 (32-bit) typ. ~2GB (FAT16) 이론상 4GB (FAT32) SDHC 블록 ( 섹터 ) 단위주소 (512 Byte 고정 ) ~ 32GB 권장파일시스템 FAT16 FAT32 / exfat 속도표기방법 배속 (e.g. x133, x150 등 ) Class 2, 4, 6, 10 등 보다최신의 SDXC 규격도존재함 4
I. SD/SDHC 카드사용방법분석 SD Card 의초기화과정 5
I. SD/SDHC 카드사용방법분석 SD_CS_HIGH(); for(int i=0; i<10; i++) { _SPI1.Write(0xFF); } do { SD_CS_LOW(); SendCommand(SD_CMD0, (uint32_t)0); ReceiveResponse_R1(result); SD_CS_HIGH(); timeout++; if(timeout >= 100) { return SD_CARD_NOT_DETECTED; } }while(result!= 1); card_type = SDCardTypes::SD_Unknown; 6
I. SD/SDHC 카드사용방법분석 SDHC 혹은 SD(v2) 카드인경우 SendCommand(SD_CMD8, (uint32_t)0x000001aa); uint32_t cmd8_response; ReceiveResponse_R3(result, cmd8_response); if(result == 0x01) { if(acmd41(0x40000000)!= 0) return SD_CARD_INITIALIZE_FAILED; SendCommand(SD_CMD58, (uint32_t)0); uint32_t cmd58_response; ReceiveResponse_R3(result, cmd58_response); } if((cmd58_response & (1<<30)) == 0) { card_type = SDCardTypes::SD_V2; } else { card_type = SDCardTypes::SDHC; } 7
I. SD/SDHC 카드사용방법분석 SD 혹은 MMC 카드인경우 SendCommand(SD_CMD8, (uint32_t)0x000001aa); uint32_t cmd8_response; ReceiveResponse_R3(result, cmd8_response); if(result == 0x01) { 생략 } else if(result == 0x05) { if(acmd41(0x00000000)!= 0) { if(cmd1()!= 0) return SD_CARD_INITIALIZE_FAILED; else card_type = SDCardTypes::SD_V1; } else card_type = SDCardTypes::SD_V1; } 8
I. SD/SDHC 카드사용방법분석 생략 SendCommand(SD_CMD16, 512); ReceiveResponse_R1(result); if(result == 0x00) return SD_CARD_INIT_OK; else return SD_CARD_INITIALIZE_FAILED; SD_CS_HIGH(); 9
I. SD/SDHC 카드사용방법분석 SD vs SDHC int SDCard::ReadSector(uint8_t* buffer, uint32_t sector) { uint32_t addr; int retry_count = 3; while(retry_count > 0) { SD_CS_HIGH(); SD 카드는 byte 단위의 linear address 를사용 (memory 와유사 ) SDHC 카드는 512 바이트단위의블록 ( 섹터 ) 번호를사용 (block 디바이스와유사 - CF Card, HDD 등 ) if(_cardtype!= SDCardTypes::SDHC) { addr = sector * 512; SendCommand(SD_CMD17, addr); // CMD17(READ_SINGLE_BLOCK) } else { SendCommand(SD_CMD17, sector); // CMD17(READ_SINGLE_BLOCK) } uint32_t timeout; for(timeout = 0; timeout < 10000; timeout++) { uint8_t token = _SPI1.Read(); if(token == 0xfe) // 카드로부터의데이터전송을기다림 break; } 생략 10
I. SD/SDHC 카드사용방법분석 풀소스코드보기 http://oi.icbanq.com/view topic.php?f=1 3&t=39 참조사이트 http://elmchan.org/docs/mmc/mmc_e.html 11
II. OI 응용모듈 : SD Card / MP3 모듈 12
II. OI 응용모듈 : SD Card / MP3 모듈 VCC_3.3V R11 R12 R13 R16 R17 R18 R14 R15 C23 10uF 10 0K 10 0K 10 0K 10 0K 10 0K 10 0K 10 0K 10 0K R20 R19 DO NOT POPULATE VCC_3.3V P0.16 0R 10K BSH201/SOT23 Q1 1 2 3 4 5 6 7 8 9 10 11 12 P0.11 P1.10 P1.9 P1.11 P0.1 P0.2 SD_CHIP_SELECT SPI_MOSI SPI_SCK SPI_MISO SD_CARD_DETECT SD_WRITE_PROTECT J5 SD_SOCKET/DM1AA-SF-PEJ(HIROSE) 13
III. FAT 파일시스템분석 M icrosoft 사가개발, FAT12/16 은 M S-DOS 에채용, FAT32 는 Window s 98 부터사용됨 최근에는 FAT 의여러한계를개선한 exfat 방식도나와있음. PC 와의높은호환성 Linked-list 구조로적은메모리만으로사용가능함 비교적구조가간단하여구현이용이함 MP3 Player, 디지털카메라등에서널리사용됨 14
III. FAT 파일시스템분석 MBR : Master Boot Record 미디어의 0번섹터에위치 부트코드 (446 Byte) 미디어내의파티션정보수록 ( 파티션당 16 바이트 ) 15
III. FAT 파일시스템분석 16
III. FAT 파일시스템분석 이름오프셋값 시작섹터번호 0x1C6 0x00002000 섹터수 0x1CA 0x007AD400 (=8049664 개 ) 17
III. FAT 파일시스템분석 18
III. FAT 파일시스템분석 BPB 예약섹터공간 FAT1 FAT2 클러스터 19
III. FAT 파일시스템분석 BPB (BIOS Parameter Block) 각파티션의첫번째섹터에위치 섹터크기 / 클러스터크기정보 루트디렉터리엔트리정보 FAT 테이블정보 20
III. FAT 파일시스템분석 BPB Example 0 1 2 3 4 5 6 7 8 9 A B C D E F 00000000 EB 58 90 4D 53 44 4F 53 35 2E 30 00 02 02 24 00 00000010 02 00 00 00 00 F8 00 00 3F 00 FF 00 00 00 00 00 00000020 9F CD 03 00 C6 03 00 00 00 00 00 00 02 00 00 00 00000030 01 00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 Name Offset Size Value BPB_BytsPerSec 0x0B 16Bits 0x0200 (512) BPB_SecPerClus 0x0D 8Bits 0x02 BPB_RsvdSecCnt 0x0E 16Bits 0x0024 (36) BPB_NumFATs 0x10 8Bits 0x02 BPB_FATSz32 0x24 32Bits 0x000003C6 (966) BPB_RootClus 0x2C 32Bits 0x00000002 21
III. FAT 파일시스템분석 클러스터번호로섹터번호구하기 - ((cluster 번호 2) * 클러스터당섹터수 ) + ( 첫데이터섹터 ) Example (Cluster 번호가 2 번인경우 ) 클러스터당섹터수 : 2 첫데이터섹터 : 파티션의시작섹터 + 예약된섹터 + (FAT 개수 * FAT 섹터수 ) ((2 2) * 2) + (0x61 + 0x24 + (2 * 0x3C6)) = 2065 즉실제섹터는 2065 번섹터 22
III. FAT 파일시스템분석 파일 디렉터리엔트리 파일명, 시작클러스터, 파일크기, 날짜등의정보 FAT 클러스터체인 Linked-list 구조 다음에읽어야할클러스터번호가나열되어있음 23
III. FAT 파일시스템분석 Directory Entry 루트클러스터및하위디렉터리의시작클러스터에위치함 8.3 DOS 포맷으로파일명보관 파일의크기, 시작클러스터, 생성 / 억세스날짜보관 이름 오프셋 크기 (byte) 설명 DIR_name 0x00 11 파일이름 DIR_attr 0x0B 1 속성 DIR_FstClusHI 0x14 2 시작클러스터 ( 상위 ) DIR_FstClusLO 0x1A 2 시작클러스터 ( 하위 ) DIR_FileSize 0x1C 4 파일크기 ( 바이트 ) 24
III. FAT 파일시스템분석 Directory Entry Example Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00102220 30 30 30 32 30 30 30 30 4D 50 33 20 10 6D 4F 76 00020000MP3.mOv 00102230 37 35 37 35 01 00 DB 93 48 33 33 33 2A C8 30 00 7575..?H333*?. 파일이름 : 00020000.MP3 속성 : 0x20 ( 일반 ) 시작클러스터 : 78643 (0x00013333) 파일크기 : 3196970 byte (0x0030C82A) 25
III. FAT 파일시스템분석 FAT 테이블 각파일의클러스터연결정보보관 현재클러스터에해당하는 FAT 테이블위치에는다음클러스터번호가저장되어있음 마지막클러스터의경우 0XFFFFFFFF8~0xFFFFFFFF 의값이저장되어있음 26
III. FAT 파일시스템분석 FAT 테이블 Example 0 1 2 3 00 FFFFFFFF FFFFFFFF 00000003 00000005 04 00000007 00000006 FFFFFFFF 00000009 08 0000000A 00000008 0000000B 0000000C 0C FFFFFFFF 00000000 00000000 00000000 10 00000000 00000012 00000014 00000000 14 00000015 00000016 FFFFFFFF 00000000 18 00000000 00000000 00000000 00000000 1C 00000000 00000000 00000000 00000000 : 예약 : 사용되지않음 Root Directory : 00000002 00000003 00000005 00000006 File A : 00000004 00000007 00000009-00000008 0000000A 0000000B 0000000C File B : 00000011 00000012 00000014 00000015 00000016 27
III. FAT 파일시스템분석 28
III. FAT 파일시스템분석 추천유틸리티 WinHex http://w w w.w inhex.com/w inhex/ 개인은제한된기능으로무료사용가능 29
IV. OI 플랫폼라이브러리 : Drive, FileSystem Drive Class 미디어 (SD 카드, 플래시메모리등 ) 을실제로억세스하는작업을정의하는추상클래스 장치초기화, 섹터단위 Read / Write FileSystem Class 현재는 elm-chan.org 에서공개하고있는 fatfs 라이브러리를사용 C 로구성된라이브러리의 C++ Wrapper Drive Class 를상속하는어떤장치라도사용가능 30
IV. OI 플랫폼라이브러리 : Drive, FileSystem -_Drive: Drive -_Fatfs: FATFS FileSystem <<create>>-filesystem() <<destroy>>-filesystem() +Mount(drive: Drive): int +Exists(path: char): bool +Exists(path: TCHAR): bool +Remove(path: char): int +Remove(path: TCHAR): int +Rename(path: char): int +Rename(path: TCHAR): int +Move(src_path: char, dst_path: char): int +Move(src_path: TCHAR, dst_path: TCHAR): int +Copy(src_path: char, dst_path: char): int +Copy(src_path: TCHAR, dst_path: TCHAR): int +Touch(path: char): int +Touch(path: TCHAR): int +GetFreeSize(: void): uint64_t +ChangeDirectory(path: char): int +ChangeDirectory(path: TCHAR): int +GetCurrentDirectory(path: char): int +GetCurrentDirectory(path: TCHAR): int +GetFileCount(: void): int +GetFileCount(path: char): int +GetFileCount(path: TCHAR): int +GetFileName(SFN: uint8_t, index: int): int +GetFileName(LFN: TCHAR, index: int): int +GetFileName(SFN: uint8_t, LFN: TCHAR): int +GetFileName(LFN: TCHAR, SFN: uint8_t): int #_DriveType: DriveType #_SectorCount: uint32_t #_SectorSize: uint32_t #_WriteProtected: bool #_MediaInserted: bool #_Initialized: bool #_DriveIndex: int Drive <<create>>-drive() <<destroy>>-drive() +GetDriveIndex(): int +Init(): int +Format(): int +SectorCount(): uint32_t +DriveSize(): uint64_t +ReadSector(buffer: uint8_t, sector: uint32_t, count: int): int +ReadSector(buffer: uint8_t, sector: uint32_t): int +WriteSector(buffer: uint8_t, sector: uint32_t, count: int): int +WriteSector(buffer: uint8_t, sector: uint32_t): int SDCard -_CardType: SDCardTypes -_EventCardInserted: EventHandlerBase -_EventCardRemoved: EventHandlerBase SerialFlash 31
IV. OI 플랫폼라이브러리 : Drive, FileSystem class Drive : PlatformLibraryBase { protected: DriveType::DriveType _DriveType; uint32_t _SectorCount; uint32_t _SectorSize; bool _WriteProtected; bool _MediaInserted; bool _Initialized; int _DriveIndex; 다음페이지에 32
IV. OI 플랫폼라이브러리 : Drive, FileSystem public: Drive(); ~Drive(); int GetDriveIndex() { return _DriveIndex; } virtual int Init() = 0; virtual int Format() = 0; virtual uint32_t SectorCount() = 0; virtual uint64_t DriveSize() { return _SectorSize * _SectorCount; } virtual int ReadSector (uint8_t* buffer, uint32_t sector, int count) = 0; virtual int ReadSector (uint8_t* buffer, uint32_t sector) = 0; }; virtual int WriteSector (uint8_t* buffer, uint32_t sector, int count) = 0; virtual int WriteSector(uint8_t* buffer, uint32_t sector) = 0; 33
IV. OI 플랫폼라이브러리 : Drive, FileSystem class SDCard : Drive { public: SDCard(); ~SDCard(); 생략 int Init(); bool isinitialized() { return _Initialized; } bool iswriteprotected() { return _WriteProtected; } bool ismediainserted() { return _MediaInserted; } int GetCardInfo(SDCardInfo& info); int SendCommand(int command, uint32_t arg); int SendCommand(int command, uint8_t arg[4], uint8_t CRC); int ReceiveResponse_R1(uint8_t& result); int ReceiveResponse_R3(uint8_t& result, uint32_t& data); int ReadSector(uint8_t* buffer, uint32_t sector, int count); int ReadSector(uint8_t* buffer, uint32_t sector); int WriteSector(uint8_t* buffer, uint32_t sector, int count); int WriteSector(uint8_t* buffer, uint32_t sector); 생략 }; 34
IV. OI 플랫폼라이브러리 : Drive, FileSystem 예 ) 파일시스템초기화 _FileSystem.Mount((Drive*)(&_SDCard)); 예 ) 파일열기 int Open(const char* path, int mode, int access = FileAccessModes::ReadWrite); int Open(const TCHAR* path, int mode, int access = FileAccessModes::ReadWrite); FileTest.Open( 1234.txt", FileOpenModes::Open); FileTest.Open( 1234.txt", FileOpenModes::OpenOrCreate); FileTest.Open( 1234.txt", FileOpenModes::Append); 예 ) 파일읽기 int Read(uint8_t& data); int Read(uint8_t* buffer, uint32_t len_to_read, uint32_t& len_read); int Read(uint8_t* buffer, uint32_t len_to_read); int ReadLine(uint8_t* buffer, int max_len); FileTest.Read(buffer, 32, len_read); 35
V. MP3 코덱 : VS1053 36
V. MP3 코덱 : VS1053 재생가능포맷 MP3 = MPEG 1 & 2 audio layer III (CBR+VBR+ABR) MP1 & MP2 = MPEG 1 & 2 audio layers I & II WMA 4.0/4.1/7/8/9 all profiles (5-384 kbps) Ogg Vorbis FLAC lossless audio (up to 24 bits, 48 khz) AAC-LC(+PNS), HE-AAC v2 (Level 3) (SBR + PS) WAV (PCM + IMA ADPCM) General MIDI 1 / SP-MIDI format 0 녹음 ( 인코딩 ) 가능포맷 Ogg Vorbis with software plugin IMA ADPCM 16-bit PCM 37
V. MP3 코덱 : VS1053 음장효과 EarSpeaker Spatial Processing Bass and treble controls High-quality on-chip stereo DAC Zero-cross detection for smooth volume change Stereo earphone driver capable of driving a 30 ohm load Quiet power-on and power-off I2S interface for external DAC 38
V. MP3 코덱 : VS1053 VS1033 vs VS1053 Ogg Vorbis 지원추가 ( 재생및녹음 ) 음질이더강화된내장 DAC VS1033: THD 0.4%, SND 85dB VS1053: THD 0.07%, SNR 94dB 1.8V 전원사용으로보다더저전력 VS1033: 2.5V Next Version VS1063 : MP3 인코딩이가능 양방향모드 ( 재생및녹음을동시에수행, ADPCM 만 ) 5 채널 Equalizer (2011 년후반기출시예정 ) 39
V. MP3 코덱 : VS1053 U1 R1 10K Y1 R3 1M SPI_MISO SPI_MOSI SPI_SCK 12.288Mhz 18pFC1 18pFC2 P1.11 P1.10 P1.9 P0.15 P0.9 P1.5 P0.10 EINT1 VCC_3.3V R8 100K 30 29 28 23 3 8 13 18 17 15 32 33 34 9 10 36 25 11 12 4 16 20 21 22 SO SI SCLK CS# RESET# DREQ xdcs#/bsync XTAL1 XTAL2 VCO TEST GPIO0/I2S_SCLK GPIO1/I2S_DATA GPIO2/DCLK GPIO3/SDATA GPIO4/I2S_LROUT GPIO5/I2C_MCLK GPIO6 GPIO7 DGND DGND DGND DGND DGND DVDD 6 DVDD 14 DVDD 19 CVDD 5 CVDD 7 CVDD 24 CVDD 31 AVDD 38 AVDD 43 AVDD 45 LEFT RIGHT GBUF RX 26 TX 27 46 39 42 MCP 1 MCN 2 LINE_IN 48 RCAP 44 AGND 37 AGND 40 AGND 41 AGND 47 VCC_3.3V VCC_1.8V AVCC_3.3V HP_LEFT HP_RIGHT HP_GBUF VCC_3.3V LINE_IN_LEFT MIC_N R2 10K LINE_IN_RIGHT C3 1uF VS1053B 40
V. MP3 코덱 : VS1053 J6 HP_LEFT HP_RIGHT HP_GBUF 6 5 7 4 3 HEADPHONE OUT R4 R5 R6 328B J11 C4 20R C5 20R C6 10R 1 2 3 CON3 LINE_IN_LEFT R9 470R C7 1uF + 6 5 7 4 3 J7 LINE INPUT 10nF 10nF 47nF LINE_IN_RIGHT R10 470R C8 + 328B C9 C10 1uF 10nF 10nF J1 VCC_3.3V J2 1 2 3 4 5 6 7 8 9 10 P1.5 EINT1 P0.15 J121 2 P1.9 SPI_SCK P1.10 SPI_MOSI P1.11 SPI_MISO P0.1 P0.2 JUMPER P0.16 J9 1 2 J101 2 P0.9 P0.10 P0.11 JUMPER JUMPER 1 2 3 4 5 6 7 8 9 10 CON10 CON10 41
V. MP3 코덱 : VS1053 int Init(void); int SoftReset(); int Reset(); bool isdatarequired(void); void WaitForDataRequest(void); int SendData(uint8_t* buffer, int size); void SetVolume(int volume); void SetBassEnhancer(int frequency, int step); void SetTrebleEnhancer(int frequency, int step); void SetEarSpeakerSpatialEffect(int step); int GetBitrate(void); int GetSampleRate(void); int GetStreamInfo(void); int GetDecodeTime(void); void GetVUmeterValue(int& left, int& right); 42
VI. Example : SD Card 에저장된 MP3 파일재생하기 43
VI. Example : SD Card 에저장된 MP3 파일재생하기 44
VI. Example : SD Card 에저장된 MP3 파일재생하기 LibrarySetup.cpp ( 자동생성되는코드 ) 45
VI. Example : SD Card 에저장된 MP3 파일재생하기 int App::ApplcationMain(void) { // 응용프로그램의시작지점입니다. File FileMP3; _FileSystem.Mount((Drive*)(&_SDCard)); uint8_t play_buffer[64]; _VS1053_MP3.Init(); // 파일열기 FileMP3.Open("01.MP3", FileOpenModes::Open); printf("start PLAYING...\n"); // 파일이끝날때까지재생 while(filemp3.isend() == false) { while(_vs1053_mp3.isdatarequired() == true) } { uint32_t len_read; FileMP3.Read(play_buffer, 32, len_read); _VS1053_MP3.SendData(&play_buffer[0], len_read); } } printf("end!\n"); 46
VI. Example : SD Card 에저장된 MP3 파일재생하기 CMD0 (GO_IDLE_STATE) OK. CMD8 (SEND_IF_COND) - R3 Response: 0x1AA ACMD41 (APP_SEND_OP_COND) OK. Card type identified - SDHC Card CMD16 (SET_BLOCKLEN) OK. Size is 4.1GB, total 8057856 sectors File System mounted. type : FAT32 Cluster size = 32768 bytes Firmware patch and FLAC decoder successfully downloaded. START PLAYING... 47
감사합니다 OI Project에참여해주세요. http://oi.icbanq.com