티스토리 뷰
이번 글에서는 SD 메모리 카드 안에 저장 되어 있는 데이터를 읽어 오는 방법에 대해서 설명하도록 하겠다.
SD 메모리 카드에서 데이터를 읽어 올때는 block 단위로 읽어 올 수 있는데, 한번에 하나의 블럭을 읽어 오는 방법과 하나의 명령으로 여러 블럭의 데이터를 읽어 오는 방법이 있다.
위의 표에서 볼 수 있듯이, 하나의 블럭단위로 읽어 오기 위한 명령어는 CMD17이고, 여러 블럭을 한꺼번에 읽어 오기 위한 명령은 CMD18이다.
명령어를 수행할 때에는 데이터를 어디에서 읽어 올지 그 주소를 알려주어야 하는데, 메모리 용량에 따라 주소의 의미가 달라진다.
위의 그림에서 보는것처럼 SDHC나 SDXC type의 메모리의 경우 block address를 의미하는것이지만, SDSC의 경우에는 byte address를 의미하고 있기 때문에 read 명령을 수행할 때에는 주의하여야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | static void read_mem( int argc, char **argv) { uint32_t num_blk = 0; uint32_t blk_count = 1; if (argc>1) num_blk = strtoul (argv[1], NULL, 0); if (argc>2) blk_count = strtoul (argv[2], NULL, 0); if (blk_count == 0) blk_count = 1; if (blk_count > 1) { if (blk_count > 4) blk_count = 4; read_mem_multi(num_blk, blk_count); } else read_mem_single(num_blk); } CLI_CMD(read, "Read SD Memory data" , read_mem); |
SD 메모리에서 데이터를 읽어 오기 위한 코드를 위와 같이 만들어 보았다.
3,4번줄은 몇번째 메모리 block에서 읽어 올 것인지, 몇개의 block을 읽을 것인지 저장해 두기 위하여 변수를 선언하였다. 초기 값으로 0번 블럭 하나를 읽어 오는것으로 설정해 두었다.
사용자가 argument 없이 "read" 명령만 입력하였을 경우에 사용하기 위한 초기값인 것이다.
만약 특정 block을 읽고 싶다면 read 명령 다음에 위치 시키면 된다. 이를 처리하기 위한 부분이 6~7번 줄이다.
한번에 여러 블럭을 읽어오기 위해서는 몇개의 블럭을 읽을 것인지 알려 주어야 하는데 두번째 argument 위치에 알려 주면 된다. 블럭 개수를 읽기 위한 코드는 9~10번줄에 해당한다.
읽기 위한 블럭 개수는 최소 1개는 되어야 하기 때문에 혹시 실수로 블럭 개수를 0으로 입력하였을 때에는 이런 오류를 수정하기 위하여 블럭 개수를 1로 설정해 주어야 한다. 12~13번 줄이 블럭 개수가 0인 경우 1로 변경하는 코드이다.
블럭 개수가 1보다 큰 경우에는 multi-read 동작을 수행하도록 하기 위하여 15~20번 줄에 해당하는 코드를 실행 시키고, 하나의 블럭 데이터만 읽기 위해서는 single-read 동작을 하면 된다.
17~18번 줄에 있는 코드는 RAM 메모리 크기가 충분하면 불 필요한 코드이지만, MCU와 같이 RAM 메모리 크기가 작은 경우 SD 메모리에서 읽어 온 데이터를 저장할 수 있는 공간이 제한적이므로 적당한 크기만큼만 읽어 오도록 해 주어야 한다.
이 글에서는 최대 4개 블럭크기만큼 한번에 읽어 오도록 하였다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | static void read_mem_single(uint32_t num_blk) { struct sd_cmd cmd; struct sd_data data; uint8_t buf[SD_MEM_BUF_SZ]; printf ( "Read Single Block [0x%X]\n" , num_blk); cmd.cmd_idx = SD_CMD_READ_SINGLE_BLOCK; if (high_capacity) cmd.arg = num_blk; else cmd.arg = num_blk * SD_MEM_BUF_SZ; cmd.resp_type = SD_RSP_R1; data.dst = ( void *)buf; data.blocks = 1; data.block_size = SD_MEM_BUF_SZ; data.flags = SD_DATA_READ; if (sd_cmd_request(&cmd, &data)) { printf ( "Read Block error\n" ); return ; } dump_mem(buf, SD_MEM_BUF_SZ); } |
한개의 블럭 크기만큼만 읽기 동작을 수행하기 위한 read_mem_single() 함수는 위와 같이 만들 수 있다.
9번 줄에서 READ_SINGLE_BLOCK 명령어를 사용한 것을 볼 수 있고, 10~13번 줄은 메모리 용량 차이에 따른 주소 설정을 다르게 하는것을 볼 수 있다.
정상적으로 메모리 데이터를 읽어 왔으면, 어떤 값을 읽어 왔는지 확인해 보기 위하여 27번 줄에 보이는 것처럼 dump_mem() 함수를 이용하여 화면에 출력해 본다.
위의 그림은 "read"라는 명령만 수행하였을 경우의 결과 화면이다. 0번 블럭 하나를 정상적으로 읽어 온 것을 확인할 수 있다. 일반적으로 0번 블럭에는 MBR(Master Boot Record) 데이터가 들어있는데, 읽어 온 데이터를 보면 제대로 읽어 왔음을 짐작할 수 있다.
위의 그림은 특정 블럭 하나를 지정하여 읽어 온 결과 화면이다. MBR에 있는 데이터중에서 첫번째 boot record를 읽어 온 것이다. FAT32로 된 파일 시스템인것을 알 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | static void read_mem_multi(uint32_t num_blk, uint32_t blk_count) { struct sd_cmd cmd; struct sd_data data; uint8_t *multi_buf = calloc (blk_count, SD_MEM_BUF_SZ); if (multi_buf == NULL) { printf ( "MEM Buffer Alloc Fail\n" ); return ; } printf ( "Read Multi Block [0x%X:%u]\n" , num_blk, blk_count); cmd.cmd_idx = SD_CMD_READ_MULTIPLE_BLOCK; if (high_capacity) cmd.arg = num_blk; else cmd.arg = num_blk * SD_MEM_BUF_SZ; cmd.resp_type = SD_RSP_R1; data.dst = ( void *)multi_buf; data.blocks = blk_count; data.block_size = SD_MEM_BUF_SZ; data.flags = SD_DATA_READ; if (sd_cmd_request(&cmd, &data)) { printf ( "Read Block error\n" ); goto done; } cmd.cmd_idx = SD_CMD_STOP_TRANSMISSION; cmd.arg = 0; cmd.resp_type = SD_RSP_R1b; if (sd_cmd_request(&cmd, NULL)) { printf ( "Stop Read Block error\n" ); goto done; } dump_mem(multi_buf, blk_count*SD_MEM_BUF_SZ); done: free (multi_buf); } |
한번에 여러 블럭의 데이터를 읽어 오기 위한 read_mem_multi() 함수는 위와 같이 만들수 있다.
읽어 온 메모리 데이터를 저장하기 위하여 5번 줄에 나오는것처럼 calloc()을 이용하여 heap 메모리에서 필요한 크기만큼 할당 받는다.
15번 줄에서 READ_MULTIPLE_BLOCK 명령을 사용한것을 볼 수 있다. 그 뒤로 SD 메모리 용량에 따른 주소값을 설정하는 코드가 있다.
원하는 블럭에 대하여 읽기 동작을 완료 하였으면, SD 메모리에 STOP 명령을 보내 주어야 한다. 이 부분은 33~41번 줄에 들어 있다.
역시 제대로 읽어 왔는지 결과를 확인해 본다.
위의 그림은 0x2000부터 10개의 블럭을 읽어 오도록 수행한 결과 화면이다. 비록 10개의 블럭을 읽기 위한 명령을 사용하였지만, 실제로는 4개의 블럭만 읽어 오도록 만든것을 확인할 수 있다.
위의 그림은 나머지 부분이 잘려져 있지만, 실제 읽어 온 데이터는 다음과 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | [Just4Fun]$ Micro SD Memory. Jul 26 2017 - 21:39:38 Micro SD Memory. Jul 26 2017 - 21:39:38 SD Memory Card Version: 2.0 SD Memory Card Capacity : SDHC or SDXC [Just4Fun]$ read 0x2000 10 Read Multi Block [0x2000:4] 0000: EB58904D 53444F53 352E3000 02403411 | .X.MSDOS5.0..@4. 0010: 02000000 00F80000 3F00FF00 00200000 | ........?.... .. 0020: 00C0EC00 66070000 00000000 02000000 | ....f........... 0030: 01000600 00000000 00000000 00000000 | ................ 0040: 80002989 4B87AA4E 4F204E41 4D452020 | ..).K..NO NAME 0050: 20204641 54333220 202033C9 8ED1BCF4 | FAT32 3..... 0060: 7B8EC18E D9BD007C 88564088 4E028A56 | {......|.V@.N..V 0070: 40B441BB AA55CD13 721081FB 55AA750A | @.A..U..r...U.u. 0080: F6C10174 05FE4602 EB2D8A56 40B408CD | ...t..F..-.V@... 0090: 137305B9 FFFF8AF1 660FB6C6 40660FB6 | .s......f...@f.. 00A0: D180E23F F7E286CD C0ED0641 660FB7C9 | ...?.......Af... 00B0: 66F7E166 8946F883 7E160075 39837E2A | f..f.F..~..u9.~* 00C0: 00773366 8B461C66 83C00CBB 0080B901 | .w3f.F.f........ 00D0: 00E82C00 E9A803A1 F87D80C4 7C8BF0AC | ..,......}..|... 00E0: 84C07417 3CFF7409 B40EBB07 00CD10EB | ..t.<.t......... 00F0: EEA1FA7D EBE4A17D 80EBDF98 CD16CD19 | ...}...}........ 0100: 6660807E 02000F84 2000666A 00665006 | f`.~.... .fj.fP. 0110: 53666810 000100B4 428A5640 8BF4CD13 | Sfh.....B.V@.... 0120: 66586658 66586658 EB33663B 46F87203 | fXfXfXfX.3f;F.r. 0130: F9EB2A66 33D2660F B74E1866 F7F1FEC2 | ..*f3.f..N.f.... 0140: 8ACA668B D066C1EA 10F7761A 86D68A56 | ..f..f....v....V 0150: 408AE8C0 E4060ACC B80102CD 1366610F | @............fa. 0160: 8274FF81 C3000266 40497594 C3424F4F | .t.....f@Iu..BOO 0170: 544D4752 20202020 00000000 00000000 | TMGR ........ 0180: 00000000 00000000 00000000 00000000 | ................ 0190: 00000000 00000000 00000000 00000000 | ................ 01A0: 00000000 00000000 00000000 0D0A4469 | ..............Di 01B0: 736B2065 72726F72 FF0D0A50 72657373 | sk error...Press 01C0: 20616E79 206B6579 20746F20 72657374 | any key to rest 01D0: 6172740D 0A000000 00000000 00000000 | art............. 01E0: 00000000 00000000 00000000 00000000 | ................ 01F0: 00000000 00000000 AC01B901 000055AA | ..............U. 0200: 52526141 00000000 00000000 00000000 | RRaA............ 0210: 00000000 00000000 00000000 00000000 | ................ 0220: 00000000 00000000 00000000 00000000 | ................ 0230: 00000000 00000000 00000000 00000000 | ................ 0240: 00000000 00000000 00000000 00000000 | ................ 0250: 00000000 00000000 00000000 00000000 | ................ 0260: 00000000 00000000 00000000 00000000 | ................ 0270: 00000000 00000000 00000000 00000000 | ................ 0280: 00000000 00000000 00000000 00000000 | ................ 0290: 00000000 00000000 00000000 00000000 | ................ 02A0: 00000000 00000000 00000000 00000000 | ................ 02B0: 00000000 00000000 00000000 00000000 | ................ 02C0: 00000000 00000000 00000000 00000000 | ................ 02D0: 00000000 00000000 00000000 00000000 | ................ 02E0: 00000000 00000000 00000000 00000000 | ................ 02F0: 00000000 00000000 00000000 00000000 | ................ 0300: 00000000 00000000 00000000 00000000 | ................ 0310: 00000000 00000000 00000000 00000000 | ................ 0320: 00000000 00000000 00000000 00000000 | ................ 0330: 00000000 00000000 00000000 00000000 | ................ 0340: 00000000 00000000 00000000 00000000 | ................ 0350: 00000000 00000000 00000000 00000000 | ................ 0360: 00000000 00000000 00000000 00000000 | ................ 0370: 00000000 00000000 00000000 00000000 | ................ 0380: 00000000 00000000 00000000 00000000 | ................ 0390: 00000000 00000000 00000000 00000000 | ................ 03A0: 00000000 00000000 00000000 00000000 | ................ 03B0: 00000000 00000000 00000000 00000000 | ................ 03C0: 00000000 00000000 00000000 00000000 | ................ 03D0: 00000000 00000000 00000000 00000000 | ................ 03E0: 00000000 72724161 0FA60300 730C0000 | ....rrAa....s... 03F0: 00000000 00000000 00000000 000055AA | ..............U. 0400: 00000000 00000000 00000000 00000000 | ................ 0410: 00000000 00000000 00000000 00000000 | ................ 0420: 00000000 00000000 00000000 00000000 | ................ 0430: 00000000 00000000 00000000 00000000 | ................ 0440: 00000000 00000000 00000000 00000000 | ................ 0450: 00000000 00000000 00000000 00000000 | ................ 0460: 00000000 00000000 00000000 00000000 | ................ 0470: 00000000 00000000 00000000 00000000 | ................ 0480: 00000000 00000000 00000000 00000000 | ................ 0490: 00000000 00000000 00000000 00000000 | ................ 04A0: 00000000 00000000 00000000 00000000 | ................ 04B0: 00000000 00000000 00000000 00000000 | ................ 04C0: 00000000 00000000 00000000 00000000 | ................ 04D0: 00000000 00000000 00000000 00000000 | ................ 04E0: 00000000 00000000 00000000 00000000 | ................ 04F0: 00000000 00000000 00000000 00000000 | ................ 0500: 00000000 00000000 00000000 00000000 | ................ 0510: 00000000 00000000 00000000 00000000 | ................ 0520: 00000000 00000000 00000000 00000000 | ................ 0530: 00000000 00000000 00000000 00000000 | ................ 0540: 00000000 00000000 00000000 00000000 | ................ 0550: 00000000 00000000 00000000 00000000 | ................ 0560: 00000000 00000000 00000000 00000000 | ................ 0570: 00000000 00000000 00000000 00000000 | ................ 0580: 00000000 00000000 00000000 00000000 | ................ 0590: 00000000 00000000 00000000 00000000 | ................ 05A0: 00000000 00000000 00000000 00000000 | ................ 05B0: 00000000 00000000 00000000 00000000 | ................ 05C0: 00000000 00000000 00000000 00000000 | ................ 05D0: 00000000 00000000 00000000 00000000 | ................ 05E0: 00000000 00000000 00000000 00000000 | ................ 05F0: 00000000 00000000 00000000 000055AA | ..............U. 0600: 00000000 00000000 00000000 00000000 | ................ 0610: 00000000 00000000 00000000 00000000 | ................ 0620: 00000000 00000000 00000000 00000000 | ................ 0630: 00000000 00000000 00000000 00000000 | ................ 0640: 00000000 00000000 00000000 00000000 | ................ 0650: 00000000 00000000 00000000 00000000 | ................ 0660: 00000000 00000000 00000000 00000000 | ................ 0670: 00000000 00000000 00000000 00000000 | ................ 0680: 00000000 00000000 00000000 00000000 | ................ 0690: 00000000 00000000 00000000 00000000 | ................ 06A0: 00000000 00000000 00000000 00000000 | ................ 06B0: 00000000 00000000 00000000 00000000 | ................ 06C0: 00000000 00000000 00000000 00000000 | ................ 06D0: 00000000 00000000 00000000 00000000 | ................ 06E0: 00000000 00000000 00000000 00000000 | ................ 06F0: 00000000 00000000 00000000 00000000 | ................ 0700: 00000000 00000000 00000000 00000000 | ................ 0710: 00000000 00000000 00000000 00000000 | ................ 0720: 00000000 00000000 00000000 00000000 | ................ 0730: 00000000 00000000 00000000 00000000 | ................ 0740: 00000000 00000000 00000000 00000000 | ................ 0750: 00000000 00000000 00000000 00000000 | ................ 0760: 00000000 00000000 00000000 00000000 | ................ 0770: 00000000 00000000 00000000 00000000 | ................ 0780: 00000000 00000000 00000000 00000000 | ................ 0790: 00000000 00000000 00000000 00000000 | ................ 07A0: 00000000 00000000 00000000 00000000 | ................ 07B0: 00000000 00000000 00000000 00000000 | ................ 07C0: 00000000 00000000 00000000 00000000 | ................ 07D0: 00000000 00000000 00000000 00000000 | ................ 07E0: 00000000 00000000 00000000 00000000 | ................ 07F0: 00000000 00000000 00000000 00000000 | ................ [Just4Fun]$ |
에러 없이 4개 블럭에 있는 데이터를 한번에 읽어 왔음을 확인할 수 있다.
'프로젝트 > microSD' 카테고리의 다른 글
SD memory card - Write (3) | 2017.07.29 |
---|---|
SD memory card - CSD (0) | 2017.07.25 |
SD memory card - CID (0) | 2017.07.17 |
SD memory card - 초기화 (16) | 2017.07.14 |
SD memory card - 준비 (0) | 2017.07.14 |