Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

KinetisSDHC.c 30KB

6 lat temu
7 lat temu
7 lat temu
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. // adapted for Arduino SD library by Paul Stoffregen
  2. // following code is modified by Walter Zimmer from
  3. // from version provided by
  4. // Petr Gargulak (NXP Employee)
  5. //https://community.nxp.com/servlet/JiveServlet/download/339474-1-263510/SDHC_K60_Baremetal.ZIP
  6. //see also
  7. //https://community.nxp.com/thread/99202
  8. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  9. #include "kinetis.h"
  10. //#include "core_pins.h" // testing only
  11. //#include "HardwareSerial.h" // testing only
  12. // Missing in Teensyduino 1.30
  13. #ifndef MPU_CESR_VLD_MASK
  14. #define MPU_CESR_VLD_MASK 0x1u
  15. #endif
  16. /******************************************************************************
  17. * Constants
  18. ******************************************************************************/
  19. enum {
  20. SDHC_RESULT_OK = 0, /* 0: Successful */
  21. SDHC_RESULT_ERROR, /* 1: R/W Error */
  22. SDHC_RESULT_WRPRT, /* 2: Write Protected */
  23. SDHC_RESULT_NOT_READY, /* 3: Not Ready */
  24. SDHC_RESULT_PARERR, /* 4: Invalid Parameter */
  25. SDHC_RESULT_NO_RESPONSE /* 5: No Response */ // from old diskio.h
  26. };
  27. /*void print_result(int n)
  28. {
  29. switch (n) {
  30. case SDHC_RESULT_OK: serial_print("OK\n"); break;
  31. case SDHC_RESULT_ERROR: serial_print("R/W Error\n"); break;
  32. case SDHC_RESULT_WRPRT: serial_print("Write Protect\n"); break;
  33. case SDHC_RESULT_NOT_READY: serial_print("Not Ready\n"); break;
  34. case SDHC_RESULT_PARERR: serial_print("Invalid Param\n"); break;
  35. case SDHC_RESULT_NO_RESPONSE: serial_print("No Response\n"); break;
  36. default: serial_print("Unknown result\n");
  37. }
  38. }*/
  39. #define SDHC_STATUS_NOINIT 0x01 /* Drive not initialized */
  40. #define SDHC_STATUS_NODISK 0x02 /* No medium in the drive */
  41. #define SDHC_STATUS_PROTECT 0x04 /* Write protected */
  42. #define IO_SDHC_ATTRIBS (IO_DEV_ATTR_READ | IO_DEV_ATTR_REMOVE | IO_DEV_ATTR_SEEK | IO_DEV_ATTR_WRITE | IO_DEV_ATTR_BLOCK_MODE)
  43. #define SDHC_XFERTYP_RSPTYP_NO (0x00)
  44. #define SDHC_XFERTYP_RSPTYP_136 (0x01)
  45. #define SDHC_XFERTYP_RSPTYP_48 (0x02)
  46. #define SDHC_XFERTYP_RSPTYP_48BUSY (0x03)
  47. #define SDHC_XFERTYP_CMDTYP_ABORT (0x03)
  48. #define SDHC_PROCTL_EMODE_INVARIANT (0x02)
  49. #define SDHC_PROCTL_DTW_1BIT (0x00)
  50. #define SDHC_PROCTL_DTW_4BIT (0x01)
  51. #define SDHC_PROCTL_DTW_8BIT (0x10)
  52. #define SDHC_INITIALIZATION_MAX_CNT 100000
  53. /* SDHC commands */
  54. #define SDHC_CMD0 (0)
  55. #define SDHC_CMD1 (1)
  56. #define SDHC_CMD2 (2)
  57. #define SDHC_CMD3 (3)
  58. #define SDHC_CMD4 (4)
  59. #define SDHC_CMD5 (5)
  60. #define SDHC_CMD6 (6)
  61. #define SDHC_CMD7 (7)
  62. #define SDHC_CMD8 (8)
  63. #define SDHC_CMD9 (9)
  64. #define SDHC_CMD10 (10)
  65. #define SDHC_CMD11 (11)
  66. #define SDHC_CMD12 (12)
  67. #define SDHC_CMD13 (13)
  68. #define SDHC_CMD15 (15)
  69. #define SDHC_CMD16 (16)
  70. #define SDHC_CMD17 (17)
  71. #define SDHC_CMD18 (18)
  72. #define SDHC_CMD20 (20)
  73. #define SDHC_CMD24 (24)
  74. #define SDHC_CMD25 (25)
  75. #define SDHC_CMD26 (26)
  76. #define SDHC_CMD27 (27)
  77. #define SDHC_CMD28 (28)
  78. #define SDHC_CMD29 (29)
  79. #define SDHC_CMD30 (30)
  80. #define SDHC_CMD32 (32)
  81. #define SDHC_CMD33 (33)
  82. #define SDHC_CMD34 (34)
  83. #define SDHC_CMD35 (35)
  84. #define SDHC_CMD36 (36)
  85. #define SDHC_CMD37 (37)
  86. #define SDHC_CMD38 (38)
  87. #define SDHC_CMD39 (39)
  88. #define SDHC_CMD40 (40)
  89. #define SDHC_CMD42 (42)
  90. #define SDHC_CMD52 (52)
  91. #define SDHC_CMD53 (53)
  92. #define SDHC_CMD55 (55)
  93. #define SDHC_CMD56 (56)
  94. #define SDHC_CMD60 (60)
  95. #define SDHC_CMD61 (61)
  96. #define SDHC_ACMD6 (0x40 + 6)
  97. #define SDHC_ACMD13 (0x40 + 13)
  98. #define SDHC_ACMD22 (0x40 + 22)
  99. #define SDHC_ACMD23 (0x40 + 23)
  100. #define SDHC_ACMD41 (0x40 + 41)
  101. #define SDHC_ACMD42 (0x40 + 42)
  102. #define SDHC_ACMD51 (0x40 + 51)
  103. #define SDHC_FIFO_BUFFER_SIZE 16
  104. #define SDHC_BLOCK_SIZE 512
  105. /******************************************************************************
  106. * Macros
  107. ******************************************************************************/
  108. // prescale can be 2, 4, 8, 16, 32, 64, 128, 256
  109. // divisor can be 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
  110. #define SDHC_SYSCTL_DIVISOR(prescale, divisor) \
  111. (SDHC_SYSCTL_SDCLKFS((prescale)>>1)|SDHC_SYSCTL_DVS((divisor)-1))
  112. #if (F_CPU == 256000000)
  113. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(64, 10) // 400 kHz
  114. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 6) // 21.3 MHz
  115. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 3) // 42.6 MHz
  116. #elif (F_CPU == 240000000)
  117. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(64, 10) // 375 kHz
  118. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 5) // 24 MHz
  119. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 3) // 40 MHz
  120. #elif (F_CPU == 216000000)
  121. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(64, 9) // 375 kHz
  122. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 5) // 21.6 MHz
  123. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 3) // 36 MHz
  124. #elif (F_CPU == 192000000)
  125. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(32, 15) // 400 kHz
  126. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 4) // 24 MHz
  127. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 2) // 48 MHz
  128. #elif (F_CPU == 180000000)
  129. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(32, 15) // 351 kHz
  130. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 4) // 22.5 MHz
  131. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 2) // 45 MHz
  132. #elif (F_CPU == 168000000)
  133. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(32, 14) // 375 kHz
  134. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 4) // 21 MHz
  135. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 2) // 42 MHz
  136. #elif (F_CPU == 144000000)
  137. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(32, 12) // 375 kHz
  138. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 3) // 24 MHz
  139. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 2) // 36 MHz
  140. #elif (F_CPU == 120000000)
  141. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(32, 10) // 375 kHz
  142. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 3) // 20 MHz
  143. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 2) // 30 MHz
  144. #elif (F_CPU == 96000000)
  145. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(16, 15) // 400 kHz
  146. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 2) // 24 MHz
  147. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 48 MHz
  148. #elif (F_CPU == 72000000)
  149. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(16, 12) // 375 kHz
  150. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 2) // 18 MHz
  151. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 36 MHz
  152. #elif (F_CPU == 48000000)
  153. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(8, 15) // 400 kHz
  154. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 24 MHz
  155. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 24 MHz
  156. #elif (F_CPU == 24000000)
  157. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(4, 15) // 500 kHz
  158. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 12 MHz
  159. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 12 MHz
  160. #elif (F_CPU == 16000000)
  161. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(4, 10) // 400 kHz
  162. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 8 MHz
  163. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 8 MHz
  164. #elif (F_CPU == 8000000)
  165. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(2, 10) // 400 kHz
  166. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 4 MHz
  167. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 4 MHz
  168. #elif (F_CPU == 4000000)
  169. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(2, 5) // 400 kHz
  170. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 2 MHz
  171. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 2 MHz
  172. #elif (F_CPU == 2000000)
  173. #define SDHC_SYSCTL_400KHZ SDHC_SYSCTL_DIVISOR(2, 3) // 333 kHz
  174. #define SDHC_SYSCTL_25MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 1 MHz
  175. #define SDHC_SYSCTL_50MHZ SDHC_SYSCTL_DIVISOR(2, 1) // 1 MHz
  176. #endif
  177. /******************************************************************************
  178. * Types
  179. ******************************************************************************/
  180. typedef struct {
  181. uint8_t status;
  182. uint8_t highCapacity;
  183. uint8_t version2;
  184. uint8_t tranSpeed;
  185. uint32_t address;
  186. uint32_t numBlocks;
  187. uint32_t lastCardStatus;
  188. } SD_CARD_DESCRIPTOR;
  189. /******************************************************************************
  190. * Global functions
  191. ******************************************************************************/
  192. uint8_t SDHC_InitCard(void);
  193. uint8_t SDHC_GetStatus(void);
  194. uint32_t SDHC_GetBlockCnt(void);
  195. int SDHC_ReadBlocks(void * buff, uint32_t sector);
  196. int SDHC_WriteBlocks(const void * buff, uint32_t sector);
  197. /******************************************************************************
  198. * Private variables
  199. ******************************************************************************/
  200. static SD_CARD_DESCRIPTOR sdCardDesc;
  201. /******************************************************************************
  202. * Private functions
  203. ******************************************************************************/
  204. static uint8_t SDHC_Init(void);
  205. static void SDHC_InitGPIO(void);
  206. static void SDHC_ReleaseGPIO(void);
  207. static void SDHC_SetClock(uint32_t sysctl);
  208. static uint32_t SDHC_WaitStatus(uint32_t mask);
  209. static int SDHC_ReadBlock(uint32_t* pData);
  210. static int SDHC_WriteBlock(const uint32_t* pData);
  211. static int SDHC_CMD_Do(uint32_t xfertyp);
  212. static int SDHC_CMD0_GoToIdle(void);
  213. static int SDHC_CMD2_Identify(void);
  214. static int SDHC_CMD3_GetAddress(void);
  215. static int SDHC_ACMD6_SetBusWidth(uint32_t address, uint32_t width);
  216. static int SDHC_CMD7_SelectCard(uint32_t address);
  217. static int SDHC_CMD8_SetInterface(uint32_t cond);
  218. static int SDHC_CMD9_GetParameters(uint32_t address);
  219. static int SDHC_CMD12_StopTransfer(void);
  220. static int SDHC_CMD12_StopTransferWaitForBusy(void);
  221. static int SDHC_CMD16_SetBlockSize(uint32_t block_size);
  222. static int SDHC_CMD17_ReadBlock(uint32_t sector);
  223. static int SDHC_CMD24_WriteBlock(uint32_t sector);
  224. static int SDHC_ACMD41_SendOperationCond(uint32_t cond);
  225. /******************************************************************************
  226. *
  227. * Public functions
  228. *
  229. ******************************************************************************/
  230. // initialize the SDHC Controller
  231. // returns status of initialization(OK, nonInit, noCard, CardProtected)
  232. static uint8_t SDHC_Init(void)
  233. {
  234. int i;
  235. // Enable clock to SDHC peripheral
  236. SIM_SCGC3 |= SIM_SCGC3_SDHC;
  237. // Enable clock to PORT E peripheral (all SDHC BUS signals)
  238. SIM_SCGC5 |= SIM_SCGC5_PORTE;
  239. SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
  240. SIM_SCGC7 |= SIM_SCGC7_DMA;
  241. // Enable DMA access via MPU (not currently used)
  242. MPU_CESR &= ~MPU_CESR_VLD_MASK;
  243. // De-init GPIO - to prevent unwanted clocks on bus
  244. SDHC_ReleaseGPIO();
  245. /* Reset SDHC */
  246. SDHC_SYSCTL = SDHC_SYSCTL_RSTA | SDHC_SYSCTL_SDCLKFS(0x80);
  247. while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) ; // wait
  248. /* Initial values */ // to do - Check values
  249. SDHC_VENDOR = 0;
  250. SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(SDHC_BLOCK_SIZE);
  251. SDHC_PROCTL = SDHC_PROCTL_EMODE(SDHC_PROCTL_EMODE_INVARIANT) | SDHC_PROCTL_D3CD;
  252. SDHC_WML = SDHC_WML_RDWML(SDHC_FIFO_BUFFER_SIZE) | SDHC_WML_WRWML(SDHC_FIFO_BUFFER_SIZE);
  253. /* Set the SDHC initial baud rate divider and start */
  254. //SDHC_SetBaudrate(400);
  255. SDHC_SetClock(SDHC_SYSCTL_400KHZ);
  256. /* Poll inhibit bits */
  257. while (SDHC_PRSSTAT & (SDHC_PRSSTAT_CIHB | SDHC_PRSSTAT_CDIHB)) { };
  258. /* Init GPIO again */
  259. SDHC_InitGPIO();
  260. /* Enable requests */
  261. SDHC_IRQSTAT = 0xFFFF;
  262. SDHC_IRQSTATEN = SDHC_IRQSTATEN_DMAESEN | SDHC_IRQSTATEN_AC12ESEN | SDHC_IRQSTATEN_DEBESEN |
  263. SDHC_IRQSTATEN_DCESEN | SDHC_IRQSTATEN_DTOESEN | SDHC_IRQSTATEN_CIESEN |
  264. SDHC_IRQSTATEN_CEBESEN | SDHC_IRQSTATEN_CCESEN | SDHC_IRQSTATEN_CTOESEN |
  265. SDHC_IRQSTATEN_BRRSEN | SDHC_IRQSTATEN_BWRSEN | SDHC_IRQSTATEN_DINTSEN |
  266. SDHC_IRQSTATEN_CRMSEN | SDHC_IRQSTATEN_TCSEN | SDHC_IRQSTATEN_CCSEN;
  267. // initial clocks... SD spec says only 74 clocks are needed, but if Teensy rebooted
  268. // while the card was in middle of an operation, thousands of clock cycles can be
  269. // needed to get the card to complete a prior command and return to a usable state.
  270. for (i=0; i < 500; i++) {
  271. SDHC_SYSCTL |= SDHC_SYSCTL_INITA;
  272. while (SDHC_SYSCTL & SDHC_SYSCTL_INITA) { };
  273. }
  274. // to do - check if this needed
  275. SDHC_IRQSTAT |= SDHC_IRQSTAT_CRM;
  276. // Check card
  277. if (SDHC_PRSSTAT & SDHC_PRSSTAT_CINS) {
  278. return 0;
  279. } else {
  280. return SDHC_STATUS_NODISK;
  281. }
  282. }
  283. uint8_t KinetisSDHC_GetCardType(void)
  284. {
  285. if (sdCardDesc.status) return 0;
  286. if (sdCardDesc.version2 == 0) return 1; // SD_CARD_TYPE_SD1
  287. if (sdCardDesc.highCapacity == 0) return 2; // SD_CARD_TYPE_SD2
  288. return 3; // SD_CARD_TYPE_SDHC
  289. }
  290. // initialize the SDHC Controller and SD Card
  291. // returns status of initialization(OK, nonInit, noCard, CardProtected)
  292. uint8_t KinetisSDHC_InitCard(void)
  293. {
  294. uint8_t resS;
  295. int resR;
  296. uint32_t i;
  297. resS = SDHC_Init();
  298. sdCardDesc.status = resS;
  299. sdCardDesc.address = 0;
  300. sdCardDesc.highCapacity = 0;
  301. sdCardDesc.version2 = 0;
  302. sdCardDesc.numBlocks = 0;
  303. if (resS)
  304. return resS;
  305. resR = SDHC_CMD0_GoToIdle();
  306. if (resR) {
  307. sdCardDesc.status = SDHC_STATUS_NOINIT;
  308. return SDHC_STATUS_NOINIT;
  309. }
  310. resR = SDHC_CMD8_SetInterface(0x000001AA); // 3.3V and AA check pattern
  311. if (resR == SDHC_RESULT_OK) {
  312. if (SDHC_CMDRSP0 != 0x000001AA) {
  313. sdCardDesc.status = SDHC_STATUS_NOINIT;
  314. return SDHC_STATUS_NOINIT;
  315. }
  316. sdCardDesc.highCapacity = 1;
  317. } else if (resR == SDHC_RESULT_NO_RESPONSE) {
  318. // version 1 cards do not respond to CMD8
  319. } else {
  320. sdCardDesc.status = SDHC_STATUS_NOINIT;
  321. return SDHC_STATUS_NOINIT;
  322. }
  323. if (SDHC_ACMD41_SendOperationCond(0)) {
  324. sdCardDesc.status = SDHC_STATUS_NOINIT;
  325. return SDHC_STATUS_NOINIT;
  326. }
  327. if (SDHC_CMDRSP0 & 0x300000) {
  328. uint32_t condition = 0x00300000;
  329. if (sdCardDesc.highCapacity)
  330. condition |= 0x40000000;
  331. i = 0;
  332. do {
  333. i++;
  334. if (SDHC_ACMD41_SendOperationCond(condition)) {
  335. resS = SDHC_STATUS_NOINIT;
  336. break;
  337. }
  338. } while ((!(SDHC_CMDRSP0 & 0x80000000)) && (i < SDHC_INITIALIZATION_MAX_CNT));
  339. if (resS)
  340. return resS;
  341. if ((i >= SDHC_INITIALIZATION_MAX_CNT) || (!(SDHC_CMDRSP0 & 0x40000000)))
  342. sdCardDesc.highCapacity = 0;
  343. }
  344. // Card identify
  345. if(SDHC_CMD2_Identify()) {
  346. sdCardDesc.status = SDHC_STATUS_NOINIT;
  347. return SDHC_STATUS_NOINIT;
  348. }
  349. // Get card address
  350. if(SDHC_CMD3_GetAddress()) {
  351. sdCardDesc.status = SDHC_STATUS_NOINIT;
  352. return SDHC_STATUS_NOINIT;
  353. }
  354. sdCardDesc.address = SDHC_CMDRSP0 & 0xFFFF0000;
  355. // Get card parameters
  356. if(SDHC_CMD9_GetParameters(sdCardDesc.address)) {
  357. sdCardDesc.status = SDHC_STATUS_NOINIT;
  358. return SDHC_STATUS_NOINIT;
  359. }
  360. if (!(SDHC_CMDRSP3 & 0x00C00000)) {
  361. uint32_t read_bl_len, c_size, c_size_mult;
  362. read_bl_len = (SDHC_CMDRSP2 >> 8) & 0x0F;
  363. c_size = SDHC_CMDRSP2 & 0x03;
  364. c_size = (c_size << 10) | (SDHC_CMDRSP1 >> 22);
  365. c_size_mult = (SDHC_CMDRSP1 >> 7) & 0x07;
  366. sdCardDesc.numBlocks = (c_size + 1) * (1 << (c_size_mult + 2)) * (1 << (read_bl_len - 9));
  367. } else {
  368. uint32_t c_size;
  369. sdCardDesc.version2 = 1;
  370. c_size = (SDHC_CMDRSP1 >> 8) & 0x003FFFFF;
  371. sdCardDesc.numBlocks = (c_size + 1) << 10;
  372. }
  373. // Select card
  374. if (SDHC_CMD7_SelectCard(sdCardDesc.address)) {
  375. sdCardDesc.status = SDHC_STATUS_NOINIT;
  376. return SDHC_STATUS_NOINIT;
  377. }
  378. // Set Block Size to 512
  379. // Block Size in SDHC Controller is already set to 512 by SDHC_Init();
  380. // Set 512 Block size in SD card
  381. if (SDHC_CMD16_SetBlockSize(SDHC_BLOCK_SIZE)) {
  382. sdCardDesc.status = SDHC_STATUS_NOINIT;
  383. return SDHC_STATUS_NOINIT;
  384. }
  385. // Set 4 bit data bus width
  386. if (SDHC_ACMD6_SetBusWidth(sdCardDesc.address, 2)) {
  387. sdCardDesc.status = SDHC_STATUS_NOINIT;
  388. return SDHC_STATUS_NOINIT;
  389. }
  390. // Set Data bus width also in SDHC controller
  391. SDHC_PROCTL &= (~ SDHC_PROCTL_DTW_MASK);
  392. SDHC_PROCTL |= SDHC_PROCTL_DTW(SDHC_PROCTL_DTW_4BIT);
  393. // De-Init GPIO
  394. SDHC_ReleaseGPIO();
  395. // Set the SDHC default baud rate
  396. SDHC_SetClock(SDHC_SYSCTL_25MHZ);
  397. // TODO: use CMD6 and CMD9 to detect if card supports 50 MHz
  398. // then use CMD4 to configure card to high speed mode,
  399. // and SDHC_SetClock() for 50 MHz config
  400. // Init GPIO
  401. SDHC_InitGPIO();
  402. return sdCardDesc.status;
  403. }
  404. // read a block from disk
  405. // buff - pointer on buffer where read data should be stored
  406. // sector - index of start sector
  407. int KinetisSDHC_ReadBlock(void * buff, uint32_t sector)
  408. {
  409. int result;
  410. uint32_t* pData = (uint32_t*)buff;
  411. // Check if this is ready
  412. if (sdCardDesc.status != 0)
  413. return SDHC_RESULT_NOT_READY;
  414. // Convert LBA to uint8_t address if needed
  415. if (!sdCardDesc.highCapacity)
  416. sector *= 512;
  417. SDHC_IRQSTAT = 0xffff;
  418. // Just single block mode is needed
  419. result = SDHC_CMD17_ReadBlock(sector);
  420. if(result != SDHC_RESULT_OK) return result;
  421. result = SDHC_ReadBlock(pData);
  422. // finish up
  423. while (!(SDHC_IRQSTAT & SDHC_IRQSTAT_TC)) { } // wait for transfer to complete
  424. SDHC_IRQSTAT = (SDHC_IRQSTAT_TC | SDHC_IRQSTAT_BRR | SDHC_IRQSTAT_AC12E);
  425. return result;
  426. }
  427. //-----------------------------------------------------------------------------
  428. // FUNCTION: disk_write
  429. // SCOPE: SDHC public related function
  430. // DESCRIPTION: Function write block/blocks to disk
  431. //
  432. // PARAMETERS: buff - pointer on buffer where is stored data
  433. // sector - index of start sector
  434. // count - count of sector to write
  435. //
  436. // RETURNS: result of operation
  437. //-----------------------------------------------------------------------------
  438. int KinetisSDHC_WriteBlock(const void * buff, uint32_t sector)
  439. {
  440. int result;
  441. const uint32_t *pData = (const uint32_t *)buff;
  442. // Check if this is ready
  443. if (sdCardDesc.status != 0) return SDHC_RESULT_NOT_READY;
  444. // Convert LBA to uint8_t address if needed
  445. if(!sdCardDesc.highCapacity)
  446. sector *= 512;
  447. SDHC_IRQSTAT = 0xffff;
  448. // Just single block mode is needed
  449. result = SDHC_CMD24_WriteBlock(sector);
  450. if (result != SDHC_RESULT_OK) return result;
  451. result = SDHC_WriteBlock(pData);
  452. // finish up
  453. while (!(SDHC_IRQSTAT & SDHC_IRQSTAT_TC)) { } // wait for transfer to complete
  454. SDHC_IRQSTAT = (SDHC_IRQSTAT_TC | SDHC_IRQSTAT_BWR | SDHC_IRQSTAT_AC12E);
  455. return result;
  456. }
  457. /******************************************************************************
  458. *
  459. * Private functions
  460. *
  461. ******************************************************************************/
  462. // initialize the SDHC Controller signals
  463. static void SDHC_InitGPIO(void)
  464. {
  465. PORTE_PCR0 = PORT_PCR_MUX(4) | PORT_PCR_PS | PORT_PCR_PE | PORT_PCR_DSE; /* SDHC.D1 */
  466. PORTE_PCR1 = PORT_PCR_MUX(4) | PORT_PCR_PS | PORT_PCR_PE | PORT_PCR_DSE; /* SDHC.D0 */
  467. PORTE_PCR2 = PORT_PCR_MUX(4) | PORT_PCR_DSE; /* SDHC.CLK */
  468. PORTE_PCR3 = PORT_PCR_MUX(4) | PORT_PCR_PS | PORT_PCR_PE | PORT_PCR_DSE; /* SDHC.CMD */
  469. PORTE_PCR4 = PORT_PCR_MUX(4) | PORT_PCR_PS | PORT_PCR_PE | PORT_PCR_DSE; /* SDHC.D3 */
  470. PORTE_PCR5 = PORT_PCR_MUX(4) | PORT_PCR_PS | PORT_PCR_PE | PORT_PCR_DSE; /* SDHC.D2 */
  471. }
  472. // release the SDHC Controller signals
  473. static void SDHC_ReleaseGPIO(void)
  474. {
  475. PORTE_PCR0 = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; /* PULLUP SDHC.D1 */
  476. PORTE_PCR1 = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; /* PULLUP SDHC.D0 */
  477. PORTE_PCR2 = 0; /* SDHC.CLK */
  478. PORTE_PCR3 = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; /* PULLUP SDHC.CMD */
  479. PORTE_PCR4 = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; /* PULLUP SDHC.D3 */
  480. PORTE_PCR5 = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; /* PULLUP SDHC.D2 */
  481. }
  482. static void SDHC_SetClock(uint32_t sysctl)
  483. {
  484. uint32_t n, timeout;
  485. n = SDHC_SYSCTL;
  486. // Disable SDHC clocks
  487. n &= ~SDHC_SYSCTL_SDCLKEN;
  488. SDHC_SYSCTL = n;
  489. // Change dividers
  490. n &= ~(SDHC_SYSCTL_DTOCV_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DVS_MASK);
  491. n |= sysctl | SDHC_SYSCTL_DTOCV(0x0E);
  492. SDHC_SYSCTL = n;
  493. /* Wait for stable clock */
  494. timeout = 0xFFFFF;
  495. while ((!(SDHC_PRSSTAT & SDHC_PRSSTAT_SDSTB)) && timeout) {
  496. timeout--;
  497. }
  498. /* Enable SDHC clocks */
  499. SDHC_SYSCTL = n | SDHC_SYSCTL_SDCLKEN;
  500. SDHC_IRQSTAT |= SDHC_IRQSTAT_DTOE;
  501. }
  502. // waits for status bits sets
  503. static uint32_t SDHC_WaitStatus(uint32_t mask)
  504. {
  505. uint32_t result;
  506. uint32_t timeout = 1<<24;
  507. do {
  508. result = SDHC_IRQSTAT & mask;
  509. timeout--;
  510. }
  511. while(!result && (timeout));
  512. if (timeout)
  513. return result;
  514. return 0;
  515. }
  516. // reads one block
  517. static int SDHC_ReadBlock(uint32_t* pData)
  518. {
  519. uint32_t i, irqstat;
  520. const uint32_t i_max = ((SDHC_BLOCK_SIZE) / (4 * SDHC_FIFO_BUFFER_SIZE));
  521. for (i = 0; i < i_max; i++) {
  522. irqstat = SDHC_IRQSTAT;
  523. SDHC_IRQSTAT = irqstat | SDHC_IRQSTAT_BRR;
  524. if (irqstat & (SDHC_IRQSTAT_DEBE | SDHC_IRQSTAT_DCE | SDHC_IRQSTAT_DTOE)) {
  525. SDHC_IRQSTAT = irqstat | SDHC_IRQSTAT_BRR |
  526. SDHC_IRQSTAT_DEBE | SDHC_IRQSTAT_DCE | SDHC_IRQSTAT_DTOE;
  527. SDHC_CMD12_StopTransferWaitForBusy();
  528. return SDHC_RESULT_ERROR;
  529. }
  530. while (!(SDHC_PRSSTAT & SDHC_PRSSTAT_BREN)) { };
  531. *pData++ = SDHC_DATPORT;
  532. *pData++ = SDHC_DATPORT;
  533. *pData++ = SDHC_DATPORT;
  534. *pData++ = SDHC_DATPORT;
  535. *pData++ = SDHC_DATPORT;
  536. *pData++ = SDHC_DATPORT;
  537. *pData++ = SDHC_DATPORT;
  538. *pData++ = SDHC_DATPORT;
  539. *pData++ = SDHC_DATPORT;
  540. *pData++ = SDHC_DATPORT;
  541. *pData++ = SDHC_DATPORT;
  542. *pData++ = SDHC_DATPORT;
  543. *pData++ = SDHC_DATPORT;
  544. *pData++ = SDHC_DATPORT;
  545. *pData++ = SDHC_DATPORT;
  546. *pData++ = SDHC_DATPORT;
  547. }
  548. return SDHC_RESULT_OK;
  549. }
  550. // writes one block
  551. static int SDHC_WriteBlock(const uint32_t* pData)
  552. {
  553. uint32_t i, i_max, j;
  554. i_max = ((SDHC_BLOCK_SIZE) / (4 * SDHC_FIFO_BUFFER_SIZE));
  555. for(i = 0; i < i_max; i++) {
  556. while (!(SDHC_IRQSTAT & SDHC_IRQSTAT_BWR)) ; // wait
  557. if (SDHC_IRQSTAT & (SDHC_IRQSTAT_DEBE | SDHC_IRQSTAT_DCE | SDHC_IRQSTAT_DTOE)) {
  558. SDHC_IRQSTAT |= SDHC_IRQSTAT_DEBE | SDHC_IRQSTAT_DCE |
  559. SDHC_IRQSTAT_DTOE | SDHC_IRQSTAT_BWR;
  560. (void)SDHC_CMD12_StopTransferWaitForBusy();
  561. return SDHC_RESULT_ERROR;
  562. }
  563. for(j=0; j<SDHC_FIFO_BUFFER_SIZE; j++) {
  564. SDHC_DATPORT = *pData++;
  565. }
  566. SDHC_IRQSTAT |= SDHC_IRQSTAT_BWR;
  567. if (SDHC_IRQSTAT & (SDHC_IRQSTAT_DEBE | SDHC_IRQSTAT_DCE | SDHC_IRQSTAT_DTOE)) {
  568. SDHC_IRQSTAT |= SDHC_IRQSTAT_DEBE | SDHC_IRQSTAT_DCE |
  569. SDHC_IRQSTAT_DTOE | SDHC_IRQSTAT_BWR;
  570. (void)SDHC_CMD12_StopTransferWaitForBusy();
  571. return SDHC_RESULT_ERROR;
  572. }
  573. }
  574. return SDHC_RESULT_OK;
  575. }
  576. // sends the command to SDcard
  577. static int SDHC_CMD_Do(uint32_t xfertyp)
  578. {
  579. // Card removal check preparation
  580. SDHC_IRQSTAT |= SDHC_IRQSTAT_CRM;
  581. // Wait for cmd line idle // to do timeout PRSSTAT[CDIHB] and the PRSSTAT[CIHB]
  582. while ((SDHC_PRSSTAT & SDHC_PRSSTAT_CIHB) || (SDHC_PRSSTAT & SDHC_PRSSTAT_CDIHB))
  583. { };
  584. SDHC_XFERTYP = xfertyp;
  585. /* Wait for response */
  586. if (SDHC_WaitStatus(SDHC_IRQSTAT_CIE | SDHC_IRQSTAT_CEBE | SDHC_IRQSTAT_CCE | SDHC_IRQSTAT_CC) != SDHC_IRQSTAT_CC) {
  587. SDHC_IRQSTAT |= SDHC_IRQSTAT_CTOE | SDHC_IRQSTAT_CIE | SDHC_IRQSTAT_CEBE |
  588. SDHC_IRQSTAT_CCE | SDHC_IRQSTAT_CC;
  589. return SDHC_RESULT_ERROR;
  590. }
  591. /* Check card removal */
  592. if (SDHC_IRQSTAT & SDHC_IRQSTAT_CRM) {
  593. SDHC_IRQSTAT |= SDHC_IRQSTAT_CTOE | SDHC_IRQSTAT_CC;
  594. return SDHC_RESULT_NOT_READY;
  595. }
  596. /* Get response, if available */
  597. if (SDHC_IRQSTAT & SDHC_IRQSTAT_CTOE) {
  598. SDHC_IRQSTAT |= SDHC_IRQSTAT_CTOE | SDHC_IRQSTAT_CC;
  599. return SDHC_RESULT_NO_RESPONSE;
  600. }
  601. SDHC_IRQSTAT |= SDHC_IRQSTAT_CC;
  602. return SDHC_RESULT_OK;
  603. }
  604. // sends CMD0 to put SDCARD to idle
  605. static int SDHC_CMD0_GoToIdle(void)
  606. {
  607. uint32_t xfertyp;
  608. int result;
  609. SDHC_CMDARG = 0;
  610. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD0) | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_NO));
  611. result = SDHC_CMD_Do(xfertyp);
  612. if(result == SDHC_RESULT_OK) {
  613. (void)SDHC_CMDRSP0;
  614. }
  615. return result;
  616. }
  617. // sends CMD2 to identify card
  618. static int SDHC_CMD2_Identify(void)
  619. {
  620. uint32_t xfertyp;
  621. int result;
  622. SDHC_CMDARG = 0;
  623. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD2) | SDHC_XFERTYP_CCCEN |
  624. SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_136));
  625. result = SDHC_CMD_Do(xfertyp);
  626. if(result == SDHC_RESULT_OK) {
  627. (void)SDHC_CMDRSP0;
  628. }
  629. return result;
  630. }
  631. // sends CMD 3 to get address
  632. static int SDHC_CMD3_GetAddress(void)
  633. {
  634. uint32_t xfertyp;
  635. int result;
  636. SDHC_CMDARG = 0;
  637. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD3) | SDHC_XFERTYP_CICEN |
  638. SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48));
  639. result = SDHC_CMD_Do(xfertyp);
  640. if (result == SDHC_RESULT_OK) {
  641. (void)SDHC_CMDRSP0;
  642. }
  643. return result;
  644. }
  645. // sends ACMD6 to set bus width
  646. static int SDHC_ACMD6_SetBusWidth(uint32_t address, uint32_t width)
  647. {
  648. uint32_t xfertyp;
  649. int result;
  650. SDHC_CMDARG = address;
  651. // first send CMD 55 Application specific command
  652. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD55) | SDHC_XFERTYP_CICEN |
  653. SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48));
  654. result = SDHC_CMD_Do(xfertyp);
  655. if(result == SDHC_RESULT_OK) {
  656. (void)SDHC_CMDRSP0;
  657. } else {
  658. return result;
  659. }
  660. SDHC_CMDARG = width;
  661. // Send 6CMD
  662. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD6) | SDHC_XFERTYP_CICEN |
  663. SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48));
  664. result = SDHC_CMD_Do(xfertyp);
  665. if(result == SDHC_RESULT_OK) {
  666. (void)SDHC_CMDRSP0;
  667. }
  668. return result;
  669. }
  670. // sends CMD 7 to select card
  671. static int SDHC_CMD7_SelectCard(uint32_t address)
  672. {
  673. uint32_t xfertyp;
  674. int result;
  675. SDHC_CMDARG = address;
  676. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD7) | SDHC_XFERTYP_CICEN |
  677. SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48BUSY));
  678. result = SDHC_CMD_Do(xfertyp);
  679. if(result == SDHC_RESULT_OK) {
  680. (void)SDHC_CMDRSP0;
  681. }
  682. return result;
  683. }
  684. // CMD8 to send interface condition
  685. static int SDHC_CMD8_SetInterface(uint32_t cond)
  686. {
  687. uint32_t xfertyp;
  688. int result;
  689. SDHC_CMDARG = cond;
  690. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD8) | SDHC_XFERTYP_CICEN |
  691. SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48));
  692. result = SDHC_CMD_Do(xfertyp);
  693. if(result == SDHC_RESULT_OK) {
  694. (void)SDHC_CMDRSP0;
  695. }
  696. return result;
  697. }
  698. // sends CMD 8 to send interface condition
  699. static int SDHC_CMD9_GetParameters(uint32_t address)
  700. {
  701. uint32_t xfertyp;
  702. int result;
  703. SDHC_CMDARG = address;
  704. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD9) | SDHC_XFERTYP_CCCEN |
  705. SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_136));
  706. result = SDHC_CMD_Do(xfertyp);
  707. if (result == SDHC_RESULT_OK) {
  708. //(void)SDHC_CMDRSP0;
  709. sdCardDesc.tranSpeed = SDHC_CMDRSP2 >> 24;
  710. }
  711. return result;
  712. }
  713. // sends CMD12 to stop transfer
  714. static int SDHC_CMD12_StopTransfer(void)
  715. {
  716. uint32_t xfertyp;
  717. int result;
  718. SDHC_CMDARG = 0;
  719. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD12) | SDHC_XFERTYP_CMDTYP(SDHC_XFERTYP_CMDTYP_ABORT) |
  720. SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48BUSY));
  721. result = SDHC_CMD_Do(xfertyp);
  722. if (result == SDHC_RESULT_OK) {
  723. }
  724. return result;
  725. }
  726. // sends CMD12 to stop transfer and first waits to ready SDCArd
  727. static int SDHC_CMD12_StopTransferWaitForBusy(void)
  728. {
  729. uint32_t timeOut = 100;
  730. int result;
  731. do {
  732. result = SDHC_CMD12_StopTransfer();
  733. timeOut--;
  734. } while(timeOut && (SDHC_PRSSTAT & SDHC_PRSSTAT_DLA) && result == SDHC_RESULT_OK);
  735. if (result != SDHC_RESULT_OK)
  736. return result;
  737. if(!timeOut)
  738. return SDHC_RESULT_NO_RESPONSE;
  739. return SDHC_RESULT_OK;
  740. }
  741. // sends CMD8 to set block size
  742. static int SDHC_CMD16_SetBlockSize(uint32_t block_size)
  743. {
  744. uint32_t xfertyp;
  745. int result;
  746. SDHC_CMDARG = block_size;
  747. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD16) | SDHC_XFERTYP_CICEN |
  748. SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48));
  749. result = SDHC_CMD_Do(xfertyp);
  750. if (result == SDHC_RESULT_OK) {
  751. (void)SDHC_CMDRSP0;
  752. }
  753. return result;
  754. }
  755. // sends CMD17 to read one block
  756. static int SDHC_CMD17_ReadBlock(uint32_t sector)
  757. {
  758. uint32_t xfertyp;
  759. int result;
  760. SDHC_CMDARG = sector;
  761. SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | 512;
  762. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD17) | SDHC_XFERTYP_CICEN |
  763. SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48) |
  764. SDHC_XFERTYP_DTDSEL | SDHC_XFERTYP_DPSEL);
  765. result = SDHC_CMD_Do(xfertyp);
  766. if (result == SDHC_RESULT_OK) {
  767. (void)SDHC_CMDRSP0;
  768. }
  769. return result;
  770. }
  771. // sends CMD24 to write one block
  772. static int SDHC_CMD24_WriteBlock(uint32_t sector)
  773. {
  774. uint32_t xfertyp;
  775. int result;
  776. SDHC_CMDARG = sector;
  777. SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | 512;
  778. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD24) | SDHC_XFERTYP_CICEN |
  779. SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48) |
  780. SDHC_XFERTYP_DPSEL);
  781. result = SDHC_CMD_Do(xfertyp);
  782. if (result == SDHC_RESULT_OK) {
  783. (void)SDHC_CMDRSP0;
  784. }
  785. return result;
  786. }
  787. // ACMD 41 to send operation condition
  788. static int SDHC_ACMD41_SendOperationCond(uint32_t cond)
  789. {
  790. uint32_t xfertyp;
  791. int result;
  792. SDHC_CMDARG = 0;
  793. // first send CMD 55 Application specific command
  794. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_CMD55) | SDHC_XFERTYP_CICEN |
  795. SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48));
  796. result = SDHC_CMD_Do(xfertyp);
  797. if (result == SDHC_RESULT_OK) {
  798. (void)SDHC_CMDRSP0;
  799. } else {
  800. return result;
  801. }
  802. SDHC_CMDARG = cond;
  803. // Send 41CMD
  804. xfertyp = (SDHC_XFERTYP_CMDINX(SDHC_ACMD41) | SDHC_XFERTYP_RSPTYP(SDHC_XFERTYP_RSPTYP_48));
  805. result = SDHC_CMD_Do(xfertyp);
  806. if (result == SDHC_RESULT_OK) {
  807. (void)SDHC_CMDRSP0;
  808. }
  809. return result;
  810. }
  811. #endif // __MK64FX512__ or __MK66FX1M0__