| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | //*---------------------------------------------------------------------------- |
| 2 | //* ATMEL Microcontroller Software Support - ROUSSET - |
| 3 | //*---------------------------------------------------------------------------- |
| 4 | //* The software is delivered "AS IS" without warranty or condition of any |
| 5 | //* kind, either express, implied or statutory. This includes without |
| 6 | //* limitation any warranty or condition with respect to merchantability or |
| 7 | //* fitness for any particular purpose, or against the infringements of |
| 8 | //* intellectual property rights of others. |
| 9 | //*---------------------------------------------------------------------------- |
| 10 | //* File Name : mci_device.c |
| 11 | //* Object : TEST DataFlash Functions |
| 12 | //* Creation : FB 26/11/2002 |
| 13 | //* |
| 14 | //*---------------------------------------------------------------------------- |
| 15 | |
| 16 | #include <AT91C_MCI_Device.h> |
| 17 | #include "stdio.h" |
| 18 | |
| 19 | #define AT91C_MCI_TIMEOUT 1000000 /* For AT91F_MCIDeviceWaitReady */ |
| 20 | #define BUFFER_SIZE_MCI_DEVICE 512 |
| 21 | #define MASTER_CLOCK 60000000 |
| 22 | #define FALSE 0 |
| 23 | #define TRUE 1 |
| 24 | |
| 25 | //* External Functions |
| 26 | extern void AT91F_ASM_MCI_Handler(void); |
| 27 | //* Global Variables |
| 28 | AT91S_MciDeviceFeatures MCI_Device_Features; |
| 29 | AT91S_MciDeviceDesc MCI_Device_Desc; |
| 30 | AT91S_MciDevice MCI_Device; |
| 31 | |
| 32 | #undef ENABLE_WRITE |
| 33 | #undef MMC |
| 34 | |
| 35 | //*---------------------------------------------------------------------------- |
| 36 | //* \fn AT91F_MCI_SendCommand |
| 37 | //* \brief Generic function to send a command to the MMC or SDCard |
| 38 | //*---------------------------------------------------------------------------- |
| 39 | int AT91F_MCI_SendCommand ( |
| 40 | AT91PS_MciDevice pMCI_Device, |
| 41 | unsigned int Cmd, |
| 42 | unsigned int Arg) |
| 43 | { |
| 44 | unsigned int error,status; |
| 45 | //unsigned int tick=0; |
| 46 | |
| 47 | // Send the command |
| 48 | AT91C_BASE_MCI->MCI_ARGR = Arg; |
| 49 | AT91C_BASE_MCI->MCI_CMDR = Cmd; |
| 50 | |
| 51 | // wait for CMDRDY Status flag to read the response |
| 52 | do |
| 53 | { |
| 54 | status = AT91C_BASE_MCI->MCI_SR; |
| 55 | //tick++; |
| 56 | } |
| 57 | while( !(status & AT91C_MCI_CMDRDY) );//&& (tick<100) ); |
| 58 | |
| 59 | // Test error ==> if crc error and response R3 ==> don't check error |
| 60 | error = (AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR; |
| 61 | if(error != 0 ) |
| 62 | { |
| 63 | // if the command is SEND_OP_COND the CRC error flag is always present (cf : R3 response) |
| 64 | if ( (Cmd != AT91C_SDCARD_APP_OP_COND_CMD) && (Cmd != AT91C_MMC_SEND_OP_COND_CMD) ) |
| 65 | return ((AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR); |
| 66 | else |
| 67 | { |
| 68 | if (error != AT91C_MCI_RCRCE) |
| 69 | return ((AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR); |
| 70 | } |
| 71 | } |
| 72 | return AT91C_CMD_SEND_OK; |
| 73 | } |
| 74 | |
| 75 | //*---------------------------------------------------------------------------- |
| 76 | //* \fn AT91F_MCI_SDCard_SendAppCommand |
| 77 | //* \brief Specific function to send a specific command to the SDCard |
| 78 | //*---------------------------------------------------------------------------- |
| 79 | int AT91F_MCI_SDCard_SendAppCommand ( |
| 80 | AT91PS_MciDevice pMCI_Device, |
| 81 | unsigned int Cmd_App, |
| 82 | unsigned int Arg ) |
| 83 | { |
| 84 | unsigned int status; |
| 85 | //unsigned int tick=0; |
| 86 | |
| 87 | // Send the CMD55 for application specific command |
| 88 | AT91C_BASE_MCI->MCI_ARGR = (pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address << 16 ); |
| 89 | AT91C_BASE_MCI->MCI_CMDR = AT91C_APP_CMD; |
| 90 | |
| 91 | // wait for CMDRDY Status flag to read the response |
| 92 | do |
| 93 | { |
| 94 | status = AT91C_BASE_MCI->MCI_SR; |
| 95 | //tick++; |
| 96 | } |
| 97 | while( !(status & AT91C_MCI_CMDRDY) );//&& (tick<100) ); |
| 98 | |
| 99 | // if an error occurs |
| 100 | if (((AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR) != 0 ) |
| 101 | return ((AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR); |
| 102 | |
| 103 | // check if it is a specific command and then send the command |
| 104 | if ( (Cmd_App && AT91C_SDCARD_APP_ALL_CMD) == 0) |
| 105 | return AT91C_CMD_SEND_ERROR; |
| 106 | |
| 107 | return( AT91F_MCI_SendCommand(pMCI_Device,Cmd_App,Arg) ); |
| 108 | } |
| 109 | |
| 110 | //*---------------------------------------------------------------------------- |
| 111 | //* \fn AT91F_MCI_GetStatus |
| 112 | //* \brief Addressed card sends its status register |
| 113 | //*---------------------------------------------------------------------------- |
| 114 | int AT91F_MCI_GetStatus(AT91PS_MciDevice pMCI_Device,unsigned int relative_card_address) |
| 115 | { |
| 116 | if (AT91F_MCI_SendCommand(pMCI_Device, |
| 117 | AT91C_SEND_STATUS_CMD, |
| 118 | relative_card_address <<16) == AT91C_CMD_SEND_OK) |
| 119 | return (AT91C_BASE_MCI->MCI_RSPR[0]); |
| 120 | |
| 121 | return AT91C_CMD_SEND_ERROR; |
| 122 | } |
| 123 | |
| 124 | //*---------------------------------------------------------------------------- |
| 125 | //* \fn AT91F_MCI_Device_Handler |
| 126 | //* \brief MCI C interrupt handler |
| 127 | //*---------------------------------------------------------------------------- |
| 128 | void AT91F_MCI_Device_Handler( |
| 129 | AT91PS_MciDevice pMCI_Device, |
| 130 | unsigned int status) |
| 131 | { |
| 132 | // If End of Tx Buffer Empty interrupt occurred |
| 133 | if ( status & AT91C_MCI_TXBUFE ) |
| 134 | { |
| 135 | AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_TXBUFE; |
| 136 | AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTDIS; |
| 137 | |
| 138 | pMCI_Device->pMCI_DeviceDesc->state = AT91C_MCI_IDLE; |
| 139 | } // End of if AT91C_MCI_TXBUFF |
| 140 | |
| 141 | // If End of Rx Buffer Full interrupt occurred |
| 142 | if ( status & AT91C_MCI_RXBUFF ) |
| 143 | { |
| 144 | AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_RXBUFF; |
| 145 | AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTDIS; |
| 146 | |
| 147 | pMCI_Device->pMCI_DeviceDesc->state = AT91C_MCI_IDLE; |
| 148 | } // End of if AT91C_MCI_RXBUFF |
| 149 | |
| 150 | } |
| 151 | |
| 152 | //*---------------------------------------------------------------------------- |
| 153 | //* \fn AT91F_MCI_Handler |
| 154 | //* \brief MCI Handler |
| 155 | //*---------------------------------------------------------------------------- |
| 156 | void AT91F_MCI_Handler(void) |
| 157 | { |
| 158 | int status; |
| 159 | |
| 160 | status = ( AT91C_BASE_MCI->MCI_SR & AT91C_BASE_MCI->MCI_IMR ); |
| 161 | |
| 162 | AT91F_MCI_Device_Handler(&MCI_Device,status); |
| 163 | } |
| 164 | |
| 165 | //*---------------------------------------------------------------------------- |
| 166 | //* \fn AT91F_MCI_ReadBlock |
| 167 | //* \brief Read an ENTIRE block or PARTIAL block |
| 168 | //*---------------------------------------------------------------------------- |
| 169 | int AT91F_MCI_ReadBlock( |
| 170 | AT91PS_MciDevice pMCI_Device, |
| 171 | int src, |
| 172 | unsigned int *dataBuffer, |
| 173 | int sizeToRead ) |
| 174 | { |
| 175 | //////////////////////////////////////////////////////////////////////////////////////////// |
| 176 | if(pMCI_Device->pMCI_DeviceDesc->state != AT91C_MCI_IDLE) |
| 177 | return AT91C_READ_ERROR; |
| 178 | |
| 179 | if( (AT91F_MCI_GetStatus(pMCI_Device,pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address) & AT91C_SR_READY_FOR_DATA) != AT91C_SR_READY_FOR_DATA) |
| 180 | return AT91C_READ_ERROR; |
| 181 | |
| 182 | if ( (src + sizeToRead) > pMCI_Device->pMCI_DeviceFeatures->Memory_Capacity ) |
| 183 | return AT91C_READ_ERROR; |
| 184 | |
| 185 | // If source does not fit a begin of a block |
| 186 | if ( (src % pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length) != 0 ) |
| 187 | return AT91C_READ_ERROR; |
| 188 | |
| 189 | // Test if the MMC supports Partial Read Block |
| 190 | // ALWAYS SUPPORTED IN SD Memory Card |
| 191 | if( (sizeToRead < pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length) |
| 192 | && (pMCI_Device->pMCI_DeviceFeatures->Read_Partial == 0x00) ) |
| 193 | return AT91C_READ_ERROR; |
| 194 | |
| 195 | if( sizeToRead > pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length) |
| 196 | return AT91C_READ_ERROR; |
| 197 | //////////////////////////////////////////////////////////////////////////////////////////// |
| 198 | |
| 199 | // Init Mode Register |
| 200 | AT91C_BASE_MCI->MCI_MR |= ((pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length << 16) | AT91C_MCI_PDCMODE); |
| 201 | |
| 202 | if (sizeToRead %4) |
| 203 | sizeToRead = (sizeToRead /4)+1; |
| 204 | else |
| 205 | sizeToRead = sizeToRead/4; |
| 206 | |
| 207 | AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS); |
| 208 | AT91C_BASE_PDC_MCI->PDC_RPR = (unsigned int)dataBuffer; |
| 209 | AT91C_BASE_PDC_MCI->PDC_RCR = sizeToRead; |
| 210 | |
| 211 | // Send the Read single block command |
| 212 | if ( AT91F_MCI_SendCommand(pMCI_Device, AT91C_READ_SINGLE_BLOCK_CMD, src) != AT91C_CMD_SEND_OK ) |
| 213 | return AT91C_READ_ERROR; |
| 214 | |
| 215 | pMCI_Device->pMCI_DeviceDesc->state = AT91C_MCI_RX_SINGLE_BLOCK; |
| 216 | |
| 217 | // Enable AT91C_MCI_RXBUFF Interrupt |
| 218 | AT91C_BASE_MCI->MCI_IER = AT91C_MCI_RXBUFF; |
| 219 | |
| 220 | // (PDC) Receiver Transfer Enable |
| 221 | AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN; |
| 222 | |
| 223 | return AT91C_READ_OK; |
| 224 | } |
| 225 | |
| 226 | |
| 227 | #ifdef ENABLE_WRITE |
| 228 | //*---------------------------------------------------------------------------- |
| 229 | //* \fn AT91F_MCI_WriteBlock |
| 230 | //* \brief Write an ENTIRE block but not always PARTIAL block !!! |
| 231 | //*---------------------------------------------------------------------------- |
| 232 | int AT91F_MCI_WriteBlock( |
| 233 | AT91PS_MciDevice pMCI_Device, |
| 234 | int dest, |
| 235 | unsigned int *dataBuffer, |
| 236 | int sizeToWrite ) |
| 237 | { |
| 238 | //////////////////////////////////////////////////////////////////////////////////////////// |
| 239 | if( pMCI_Device->pMCI_DeviceDesc->state != AT91C_MCI_IDLE) |
| 240 | return AT91C_WRITE_ERROR; |
| 241 | |
| 242 | if( (AT91F_MCI_GetStatus(pMCI_Device,pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address) & AT91C_SR_READY_FOR_DATA) != AT91C_SR_READY_FOR_DATA) |
| 243 | return AT91C_WRITE_ERROR; |
| 244 | |
| 245 | if ( (dest + sizeToWrite) > pMCI_Device->pMCI_DeviceFeatures->Memory_Capacity ) |
| 246 | return AT91C_WRITE_ERROR; |
| 247 | |
| 248 | // If source does not fit a begin of a block |
| 249 | if ( (dest % pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length) != 0 ) |
| 250 | return AT91C_WRITE_ERROR; |
| 251 | |
| 252 | // Test if the MMC supports Partial Write Block |
| 253 | if( (sizeToWrite < pMCI_Device->pMCI_DeviceFeatures->Max_Write_DataBlock_Length) |
| 254 | && (pMCI_Device->pMCI_DeviceFeatures->Write_Partial == 0x00) ) |
| 255 | return AT91C_WRITE_ERROR; |
| 256 | |
| 257 | if( sizeToWrite > pMCI_Device->pMCI_DeviceFeatures->Max_Write_DataBlock_Length ) |
| 258 | return AT91C_WRITE_ERROR; |
| 259 | //////////////////////////////////////////////////////////////////////////////////////////// |
| 260 | |
| 261 | // Init Mode Register |
| 262 | AT91C_BASE_MCI->MCI_MR |= ((pMCI_Device->pMCI_DeviceFeatures->Max_Write_DataBlock_Length << 16) | AT91C_MCI_PDCMODE); |
| 263 | |
| 264 | if (sizeToWrite %4) |
| 265 | sizeToWrite = (sizeToWrite /4)+1; |
| 266 | else |
| 267 | sizeToWrite = sizeToWrite/4; |
| 268 | |
| 269 | // Init PDC for write sequence |
| 270 | AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS); |
| 271 | AT91C_BASE_PDC_MCI->PDC_TPR = (unsigned int) dataBuffer; |
| 272 | AT91C_BASE_PDC_MCI->PDC_TCR = sizeToWrite; |
| 273 | |
| 274 | // Send the write single block command |
| 275 | if ( AT91F_MCI_SendCommand(pMCI_Device, AT91C_WRITE_BLOCK_CMD, dest) != AT91C_CMD_SEND_OK) |
| 276 | return AT91C_WRITE_ERROR; |
| 277 | |
| 278 | pMCI_Device->pMCI_DeviceDesc->state = AT91C_MCI_TX_SINGLE_BLOCK; |
| 279 | |
| 280 | // Enable AT91C_MCI_TXBUFE Interrupt |
| 281 | AT91C_BASE_MCI->MCI_IER = AT91C_MCI_TXBUFE; |
| 282 | |
| 283 | // Enables TX for PDC transfert requests |
| 284 | AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTEN; |
| 285 | |
| 286 | return AT91C_WRITE_OK; |
| 287 | } |
| 288 | #endif |
| 289 | |
| 290 | #ifdef MMC |
| 291 | //*------------------------------------------------------------------------------------------------------------ |
| 292 | //* \fn AT91F_MCI_MMC_SelectCard |
| 293 | //* \brief Toggles a card between the Stand_by and Transfer states or between Programming and Disconnect states |
| 294 | //*------------------------------------------------------------------------------------------------------------ |
| 295 | int AT91F_MCI_MMC_SelectCard(AT91PS_MciDevice pMCI_Device, unsigned int relative_card_address) |
| 296 | { |
| 297 | int status; |
| 298 | |
| 299 | //* Check if the MMC card chosen is already the selected one |
| 300 | status = AT91F_MCI_GetStatus(pMCI_Device,relative_card_address); |
| 301 | |
| 302 | if (status < 0) |
| 303 | return AT91C_CARD_SELECTED_ERROR; |
| 304 | |
| 305 | if ((status & AT91C_SR_CARD_SELECTED) == AT91C_SR_CARD_SELECTED) |
| 306 | return AT91C_CARD_SELECTED_OK; |
| 307 | |
| 308 | //* Search for the MMC Card to be selected, status = the Corresponding Device Number |
| 309 | status = 0; |
| 310 | while( (pMCI_Device->pMCI_DeviceFeatures[status].Relative_Card_Address != relative_card_address) |
| 311 | && (status < AT91C_MAX_MCI_CARDS) ) |
| 312 | status++; |
| 313 | |
| 314 | if (status > AT91C_MAX_MCI_CARDS) |
| 315 | return AT91C_CARD_SELECTED_ERROR; |
| 316 | |
| 317 | if (AT91F_MCI_SendCommand( pMCI_Device, |
| 318 | AT91C_SEL_DESEL_CARD_CMD, |
| 319 | pMCI_Device->pMCI_DeviceFeatures[status].Relative_Card_Address << 16) == AT91C_CMD_SEND_OK) |
| 320 | return AT91C_CARD_SELECTED_OK; |
| 321 | return AT91C_CARD_SELECTED_ERROR; |
| 322 | } |
| 323 | #endif |
| 324 | |
| 325 | //*---------------------------------------------------------------------------- |
| 326 | //* \fn AT91F_MCI_GetCSD |
| 327 | //* \brief Asks to the specified card to send its CSD |
| 328 | //*---------------------------------------------------------------------------- |
| 329 | int AT91F_MCI_GetCSD (AT91PS_MciDevice pMCI_Device, unsigned int relative_card_address , unsigned int * response) |
| 330 | { |
| 331 | |
| 332 | if(AT91F_MCI_SendCommand(pMCI_Device, |
| 333 | AT91C_SEND_CSD_CMD, |
| 334 | (relative_card_address << 16)) != AT91C_CMD_SEND_OK) |
| 335 | return AT91C_CMD_SEND_ERROR; |
| 336 | |
| 337 | response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; |
| 338 | response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; |
| 339 | response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; |
| 340 | response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; |
| 341 | |
| 342 | return AT91C_CMD_SEND_OK; |
| 343 | } |
| 344 | |
| 345 | //*---------------------------------------------------------------------------- |
| 346 | //* \fn AT91F_MCI_SetBlocklength |
| 347 | //* \brief Select a block length for all following block commands (R/W) |
| 348 | //*---------------------------------------------------------------------------- |
| 349 | int AT91F_MCI_SetBlocklength(AT91PS_MciDevice pMCI_Device,unsigned int length) |
| 350 | { |
| 351 | return( AT91F_MCI_SendCommand(pMCI_Device, AT91C_SET_BLOCKLEN_CMD, length) ); |
| 352 | } |
| 353 | |
| 354 | #ifdef MMC |
| 355 | //*---------------------------------------------------------------------------- |
| 356 | //* \fn AT91F_MCI_MMC_GetAllOCR |
| 357 | //* \brief Asks to all cards to send their operations conditions |
| 358 | //*---------------------------------------------------------------------------- |
| 359 | int AT91F_MCI_MMC_GetAllOCR (AT91PS_MciDevice pMCI_Device) |
| 360 | { |
| 361 | unsigned int response =0x0; |
| 362 | |
| 363 | while(1) |
| 364 | { |
| 365 | response = AT91F_MCI_SendCommand(pMCI_Device, |
| 366 | AT91C_MMC_SEND_OP_COND_CMD, |
| 367 | AT91C_MMC_HOST_VOLTAGE_RANGE); |
| 368 | if (response != AT91C_CMD_SEND_OK) |
| 369 | return AT91C_INIT_ERROR; |
| 370 | |
| 371 | response = AT91C_BASE_MCI->MCI_RSPR[0]; |
| 372 | |
| 373 | if ( (response & AT91C_CARD_POWER_UP_BUSY) == AT91C_CARD_POWER_UP_BUSY) |
| 374 | return(response); |
| 375 | } |
| 376 | } |
| 377 | #endif |
| 378 | |
| 379 | #ifdef MMC |
| 380 | //*---------------------------------------------------------------------------- |
| 381 | //* \fn AT91F_MCI_MMC_GetAllCID |
| 382 | //* \brief Asks to the MMC on the chosen slot to send its CID |
| 383 | //*---------------------------------------------------------------------------- |
| 384 | int AT91F_MCI_MMC_GetAllCID (AT91PS_MciDevice pMCI_Device, unsigned int *response) |
| 385 | { |
| 386 | int Nb_Cards_Found=-1; |
| 387 | |
| 388 | while(1) |
| 389 | { |
| 390 | if(AT91F_MCI_SendCommand(pMCI_Device, |
| 391 | AT91C_MMC_ALL_SEND_CID_CMD, |
| 392 | AT91C_NO_ARGUMENT) != AT91C_CMD_SEND_OK) |
| 393 | return Nb_Cards_Found; |
| 394 | else |
| 395 | { |
| 396 | Nb_Cards_Found = 0; |
| 397 | //* Assignation of the relative address to the MMC CARD |
| 398 | pMCI_Device->pMCI_DeviceFeatures[Nb_Cards_Found].Relative_Card_Address = Nb_Cards_Found + AT91C_FIRST_RCA; |
| 399 | //* Set the insert flag |
| 400 | pMCI_Device->pMCI_DeviceFeatures[Nb_Cards_Found].Card_Inserted = AT91C_MMC_CARD_INSERTED; |
| 401 | |
| 402 | if (AT91F_MCI_SendCommand(pMCI_Device, |
| 403 | AT91C_MMC_SET_RELATIVE_ADDR_CMD, |
| 404 | (Nb_Cards_Found + AT91C_FIRST_RCA) << 16) != AT91C_CMD_SEND_OK) |
| 405 | return AT91C_CMD_SEND_ERROR; |
| 406 | |
| 407 | //* If no error during assignation address ==> Increment Nb_cards_Found |
| 408 | Nb_Cards_Found++ ; |
| 409 | } |
| 410 | } |
| 411 | } |
| 412 | #endif |
| 413 | #ifdef MMC |
| 414 | //*---------------------------------------------------------------------------- |
| 415 | //* \fn AT91F_MCI_MMC_Init |
| 416 | //* \brief Return the MMC initialisation status |
| 417 | //*---------------------------------------------------------------------------- |
| 418 | int AT91F_MCI_MMC_Init (AT91PS_MciDevice pMCI_Device) |
| 419 | { |
| 420 | unsigned int tab_response[4]; |
| 421 | unsigned int mult,blocknr; |
| 422 | unsigned int i,Nb_Cards_Found=0; |
| 423 | |
| 424 | //* Resets all MMC Cards in Idle state |
| 425 | AT91F_MCI_SendCommand(pMCI_Device, AT91C_MMC_GO_IDLE_STATE_CMD, AT91C_NO_ARGUMENT); |
| 426 | |
| 427 | if(AT91F_MCI_MMC_GetAllOCR(pMCI_Device) == AT91C_INIT_ERROR) |
| 428 | return AT91C_INIT_ERROR; |
| 429 | |
| 430 | Nb_Cards_Found = AT91F_MCI_MMC_GetAllCID(pMCI_Device,tab_response); |
| 431 | if (Nb_Cards_Found != AT91C_CMD_SEND_ERROR) |
| 432 | { |
| 433 | //* Set the Mode Register |
| 434 | AT91C_BASE_MCI->MCI_MR = AT91C_MCI_MR_PDCMODE; |
| 435 | |
| 436 | for(i = 0; i < Nb_Cards_Found; i++) |
| 437 | { |
| 438 | if (AT91F_MCI_GetCSD(pMCI_Device, |
| 439 | pMCI_Device->pMCI_DeviceFeatures[i].Relative_Card_Address, |
| 440 | tab_response) != AT91C_CMD_SEND_OK) |
| 441 | pMCI_Device->pMCI_DeviceFeatures[i].Relative_Card_Address = 0; |
| 442 | else |
| 443 | { |
| 444 | pMCI_Device->pMCI_DeviceFeatures[i].Max_Read_DataBlock_Length = 1 << ((tab_response[1] >> AT91C_CSD_RD_B_LEN_S) & AT91C_CSD_RD_B_LEN_M ); |
| 445 | pMCI_Device->pMCI_DeviceFeatures[i].Max_Write_DataBlock_Length = 1 << ((tab_response[3] >> AT91C_CSD_WBLEN_S) & AT91C_CSD_WBLEN_M ); |
| 446 | pMCI_Device->pMCI_DeviceFeatures[i].Sector_Size = 1 + ((tab_response[2] >> AT91C_CSD_v22_SECT_SIZE_S) & AT91C_CSD_v22_SECT_SIZE_M ); |
| 447 | pMCI_Device->pMCI_DeviceFeatures[i].Read_Partial = (tab_response[1] >> AT91C_CSD_RD_B_PAR_S) & AT91C_CSD_RD_B_PAR_M; |
| 448 | pMCI_Device->pMCI_DeviceFeatures[i].Write_Partial = (tab_response[3] >> AT91C_CSD_WBLOCK_P_S) & AT91C_CSD_WBLOCK_P_M; |
| 449 | |
| 450 | // None in MMC specification version 2.2 |
| 451 | pMCI_Device->pMCI_DeviceFeatures[i].Erase_Block_Enable = 0; |
| 452 | |
| 453 | pMCI_Device->pMCI_DeviceFeatures[i].Read_Block_Misalignment = (tab_response[1] >> AT91C_CSD_RD_B_MIS_S) & AT91C_CSD_RD_B_MIS_M; |
| 454 | pMCI_Device->pMCI_DeviceFeatures[i].Write_Block_Misalignment = (tab_response[1] >> AT91C_CSD_WR_B_MIS_S) & AT91C_CSD_WR_B_MIS_M; |
| 455 | |
| 456 | //// Compute Memory Capacity |
| 457 | // compute MULT |
| 458 | mult = 1 << ( ((tab_response[2] >> AT91C_CSD_C_SIZE_M_S) & AT91C_CSD_C_SIZE_M_M) + 2 ); |
| 459 | // compute MSB of C_SIZE |
| 460 | blocknr = ((tab_response[1] >> AT91C_CSD_CSIZE_H_S) & AT91C_CSD_CSIZE_H_M) << 2; |
| 461 | // compute MULT * (LSB of C-SIZE + MSB already computed + 1) = BLOCKNR |
| 462 | blocknr = mult * ( ( blocknr + ( (tab_response[2] >> AT91C_CSD_CSIZE_L_S) & AT91C_CSD_CSIZE_L_M) ) + 1 ); |
| 463 | |
| 464 | pMCI_Device->pMCI_DeviceFeatures[i].Memory_Capacity = pMCI_Device->pMCI_DeviceFeatures[i].Max_Read_DataBlock_Length * blocknr; |
| 465 | //// End of Compute Memory Capacity |
| 466 | |
| 467 | } // end of else |
| 468 | } // end of for |
| 469 | |
| 470 | return AT91C_INIT_OK; |
| 471 | } // end of if |
| 472 | |
| 473 | return AT91C_INIT_ERROR; |
| 474 | } |
| 475 | #endif |
| 476 | |
| 477 | //*---------------------------------------------------------------------------- |
| 478 | //* \fn AT91F_MCI_SDCard_GetOCR |
| 479 | //* \brief Asks to all cards to send their operations conditions |
| 480 | //*---------------------------------------------------------------------------- |
| 481 | int AT91F_MCI_SDCard_GetOCR (AT91PS_MciDevice pMCI_Device) |
| 482 | { |
| 483 | unsigned int response =0x0; |
| 484 | |
| 485 | // The RCA to be used for CMD55 in Idle state shall be the card's default RCA=0x0000. |
| 486 | pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address = 0x0; |
| 487 | |
| 488 | while( (response & AT91C_CARD_POWER_UP_BUSY) != AT91C_CARD_POWER_UP_BUSY ) |
| 489 | { |
| 490 | response = AT91F_MCI_SDCard_SendAppCommand(pMCI_Device, |
| 491 | AT91C_SDCARD_APP_OP_COND_CMD, |
| 492 | AT91C_MMC_HOST_VOLTAGE_RANGE); |
| 493 | if (response != AT91C_CMD_SEND_OK) |
| 494 | return AT91C_INIT_ERROR; |
| 495 | |
| 496 | response = AT91C_BASE_MCI->MCI_RSPR[0]; |
| 497 | } |
| 498 | |
| 499 | return(AT91C_BASE_MCI->MCI_RSPR[0]); |
| 500 | } |
| 501 | |
| 502 | //*---------------------------------------------------------------------------- |
| 503 | //* \fn AT91F_MCI_SDCard_GetCID |
| 504 | //* \brief Asks to the SDCard on the chosen slot to send its CID |
| 505 | //*---------------------------------------------------------------------------- |
| 506 | int AT91F_MCI_SDCard_GetCID (AT91PS_MciDevice pMCI_Device, unsigned int *response) |
| 507 | { |
| 508 | if(AT91F_MCI_SendCommand(pMCI_Device, |
| 509 | AT91C_ALL_SEND_CID_CMD, |
| 510 | AT91C_NO_ARGUMENT) != AT91C_CMD_SEND_OK) |
| 511 | return AT91C_CMD_SEND_ERROR; |
| 512 | |
| 513 | response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; |
| 514 | response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; |
| 515 | response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; |
| 516 | response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; |
| 517 | |
| 518 | return AT91C_CMD_SEND_OK; |
| 519 | } |
| 520 | |
| 521 | //*---------------------------------------------------------------------------- |
| 522 | //* \fn AT91F_MCI_SDCard_SetBusWidth |
| 523 | //* \brief Set bus width for SDCard |
| 524 | //*---------------------------------------------------------------------------- |
| 525 | int AT91F_MCI_SDCard_SetBusWidth(AT91PS_MciDevice pMCI_Device) |
| 526 | { |
| 527 | volatile int ret_value; |
| 528 | char bus_width; |
| 529 | |
| 530 | do |
| 531 | { |
| 532 | ret_value =AT91F_MCI_GetStatus(pMCI_Device,pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address); |
| 533 | } |
| 534 | while((ret_value > 0) && ((ret_value & AT91C_SR_READY_FOR_DATA) == 0)); |
| 535 | |
| 536 | // Select Card |
| 537 | AT91F_MCI_SendCommand(pMCI_Device, |
| 538 | AT91C_SEL_DESEL_CARD_CMD, |
| 539 | (pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address)<<16); |
| 540 | |
| 541 | // Set bus width for Sdcard |
| 542 | if(pMCI_Device->pMCI_DeviceDesc->SDCard_bus_width == AT91C_MCI_SCDBUS) |
| 543 | bus_width = AT91C_BUS_WIDTH_4BITS; |
| 544 | else bus_width = AT91C_BUS_WIDTH_1BIT; |
| 545 | |
| 546 | if (AT91F_MCI_SDCard_SendAppCommand(pMCI_Device,AT91C_SDCARD_SET_BUS_WIDTH_CMD,bus_width) != AT91C_CMD_SEND_OK) |
| 547 | return AT91C_CMD_SEND_ERROR; |
| 548 | |
| 549 | return AT91C_CMD_SEND_OK; |
| 550 | } |
| 551 | |
| 552 | //*---------------------------------------------------------------------------- |
| 553 | //* \fn AT91F_MCI_SDCard_Init |
| 554 | //* \brief Return the SDCard initialisation status |
| 555 | //*---------------------------------------------------------------------------- |
| 556 | int AT91F_MCI_SDCard_Init (AT91PS_MciDevice pMCI_Device) |
| 557 | { |
| 558 | unsigned int tab_response[4]; |
| 559 | unsigned int mult,blocknr; |
| 560 | |
| 561 | AT91F_MCI_SendCommand(pMCI_Device, AT91C_GO_IDLE_STATE_CMD, AT91C_NO_ARGUMENT); |
| 562 | |
| 563 | if(AT91F_MCI_SDCard_GetOCR(pMCI_Device) == AT91C_INIT_ERROR) |
| 564 | return AT91C_INIT_ERROR; |
| 565 | |
| 566 | if (AT91F_MCI_SDCard_GetCID(pMCI_Device,tab_response) == AT91C_CMD_SEND_OK) |
| 567 | { |
| 568 | pMCI_Device->pMCI_DeviceFeatures->Card_Inserted = AT91C_SD_CARD_INSERTED; |
| 569 | |
| 570 | if (AT91F_MCI_SendCommand(pMCI_Device, AT91C_SET_RELATIVE_ADDR_CMD, 0) == AT91C_CMD_SEND_OK) |
| 571 | { |
| 572 | pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address = (AT91C_BASE_MCI->MCI_RSPR[0] >> 16); |
| 573 | if (AT91F_MCI_GetCSD(pMCI_Device,pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address,tab_response) == AT91C_CMD_SEND_OK) |
| 574 | { |
| 575 | pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length = 1 << ((tab_response[1] >> AT91C_CSD_RD_B_LEN_S) & AT91C_CSD_RD_B_LEN_M ); |
| 576 | pMCI_Device->pMCI_DeviceFeatures->Max_Write_DataBlock_Length = 1 << ((tab_response[3] >> AT91C_CSD_WBLEN_S) & AT91C_CSD_WBLEN_M ); |
| 577 | pMCI_Device->pMCI_DeviceFeatures->Sector_Size = 1 + ((tab_response[2] >> AT91C_CSD_v21_SECT_SIZE_S) & AT91C_CSD_v21_SECT_SIZE_M ); |
| 578 | pMCI_Device->pMCI_DeviceFeatures->Read_Partial = (tab_response[1] >> AT91C_CSD_RD_B_PAR_S) & AT91C_CSD_RD_B_PAR_M; |
| 579 | pMCI_Device->pMCI_DeviceFeatures->Write_Partial = (tab_response[3] >> AT91C_CSD_WBLOCK_P_S) & AT91C_CSD_WBLOCK_P_M; |
| 580 | pMCI_Device->pMCI_DeviceFeatures->Erase_Block_Enable = (tab_response[3] >> AT91C_CSD_v21_ER_BLEN_EN_S) & AT91C_CSD_v21_ER_BLEN_EN_M; |
| 581 | pMCI_Device->pMCI_DeviceFeatures->Read_Block_Misalignment = (tab_response[1] >> AT91C_CSD_RD_B_MIS_S) & AT91C_CSD_RD_B_MIS_M; |
| 582 | pMCI_Device->pMCI_DeviceFeatures->Write_Block_Misalignment = (tab_response[1] >> AT91C_CSD_WR_B_MIS_S) & AT91C_CSD_WR_B_MIS_M; |
| 583 | |
| 584 | //// Compute Memory Capacity |
| 585 | // compute MULT |
| 586 | mult = 1 << ( ((tab_response[2] >> AT91C_CSD_C_SIZE_M_S) & AT91C_CSD_C_SIZE_M_M) + 2 ); |
| 587 | // compute MSB of C_SIZE |
| 588 | blocknr = ((tab_response[1] >> AT91C_CSD_CSIZE_H_S) & AT91C_CSD_CSIZE_H_M) << 2; |
| 589 | // compute MULT * (LSB of C-SIZE + MSB already computed + 1) = BLOCKNR |
| 590 | blocknr = mult * ( ( blocknr + ( (tab_response[2] >> AT91C_CSD_CSIZE_L_S) & AT91C_CSD_CSIZE_L_M) ) + 1 ); |
| 591 | |
| 592 | pMCI_Device->pMCI_DeviceFeatures->Memory_Capacity = pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length * blocknr; |
| 593 | //// End of Compute Memory Capacity |
| 594 | printf("SD-Card: %d Bytes\n\r", pMCI_Device->pMCI_DeviceFeatures->Memory_Capacity); |
| 595 | |
| 596 | if( AT91F_MCI_SDCard_SetBusWidth(pMCI_Device) == AT91C_CMD_SEND_OK ) |
| 597 | { |
| 598 | if (AT91F_MCI_SetBlocklength(pMCI_Device,pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length) == AT91C_CMD_SEND_OK) |
| 599 | return AT91C_INIT_OK; |
| 600 | } |
| 601 | } |
| 602 | } |
| 603 | } |
| 604 | return AT91C_INIT_ERROR; |
| 605 | } |
| 606 | |
| 607 | //*---------------------------------------------------------------------------- |
| 608 | //* \fn AT91F_CfgDevice |
| 609 | //* \brief This function is used to initialise MMC or SDCard Features |
| 610 | //*---------------------------------------------------------------------------- |
| 611 | void AT91F_CfgDevice(void) |
| 612 | { |
| 613 | // Init Device Structure |
| 614 | |
| 615 | MCI_Device_Features.Relative_Card_Address = 0; |
| 616 | MCI_Device_Features.Card_Inserted = AT91C_CARD_REMOVED; |
| 617 | MCI_Device_Features.Max_Read_DataBlock_Length = 0; |
| 618 | MCI_Device_Features.Max_Write_DataBlock_Length = 0; |
| 619 | MCI_Device_Features.Read_Partial = 0; |
| 620 | MCI_Device_Features.Write_Partial = 0; |
| 621 | MCI_Device_Features.Erase_Block_Enable = 0; |
| 622 | MCI_Device_Features.Sector_Size = 0; |
| 623 | MCI_Device_Features.Memory_Capacity = 0; |
| 624 | |
| 625 | MCI_Device_Desc.state = AT91C_MCI_IDLE; |
| 626 | MCI_Device_Desc.SDCard_bus_width = AT91C_MCI_SCDBUS; |
| 627 | |
| 628 | // Init AT91S_DataFlash Global Structure, by default AT45DB choosen !!! |
| 629 | MCI_Device.pMCI_DeviceDesc = &MCI_Device_Desc; |
| 630 | MCI_Device.pMCI_DeviceFeatures = &MCI_Device_Features; |
| 631 | |
| 632 | } |
| 633 | |
| 634 | //*---------------------------------------------------------------------------- |
| 635 | //* \fn AT91F_MCI_Init |
| 636 | //* \brief Initialsise Card |
| 637 | //*---------------------------------------------------------------------------- |
| 638 | int AT91F_MCI_Init(void) |
| 639 | { |
| 640 | |
| 641 | /////////////////////////////////////////////////////////////////////////////////////////// |
| 642 | // MCI Init : common to MMC and SDCard |
| 643 | /////////////////////////////////////////////////////////////////////////////////////////// |
| 644 | |
| 645 | // Set up PIO SDC_TYPE to switch on MMC/SDCard and not DataFlash Card |
| 646 | AT91F_PIO_CfgOutput(AT91C_BASE_PIOB,AT91C_PIO_PB7); |
| 647 | AT91F_PIO_SetOutput(AT91C_BASE_PIOB,AT91C_PIO_PB7); |
| 648 | |
| 649 | // Init MCI for MMC and SDCard interface |
| 650 | AT91F_MCI_CfgPIO(); |
| 651 | AT91F_MCI_CfgPMC(); |
| 652 | AT91F_PDC_Open(AT91C_BASE_PDC_MCI); |
| 653 | |
| 654 | // Disable all the interrupts |
| 655 | AT91C_BASE_MCI->MCI_IDR = 0xFFFFFFFF; |
| 656 | |
| 657 | // Init MCI Device Structures |
| 658 | AT91F_CfgDevice(); |
| 659 | |
| 660 | // Configure MCI interrupt |
| 661 | AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, |
| 662 | AT91C_ID_MCI, |
| 663 | AT91C_AIC_PRIOR_HIGHEST, |
| 664 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, |
| 665 | AT91F_ASM_MCI_Handler); |
| 666 | |
| 667 | // Enable MCI interrupt |
| 668 | AT91F_AIC_EnableIt(AT91C_BASE_AIC,AT91C_ID_MCI); |
| 669 | |
| 670 | // Enable Receiver |
| 671 | AT91F_US_EnableRx((AT91PS_USART) AT91C_BASE_DBGU); |
| 672 | |
| 673 | AT91F_MCI_Configure(AT91C_BASE_MCI, |
| 674 | AT91C_MCI_DTOR_1MEGA_CYCLES, |
| 675 | AT91C_MCI_MR_PDCMODE, // 15MHz for MCK = 60MHz (CLKDIV = 1) |
| 676 | AT91C_MCI_SDCARD_4BITS_SLOTA); |
| 677 | |
| 678 | if(AT91F_MCI_SDCard_Init(&MCI_Device) != AT91C_INIT_OK) |
| 679 | return FALSE; |
| 680 | else |
| 681 | return TRUE; |
| 682 | |
| 683 | } |
| 684 | |
| 685 | //*---------------------------------------------------------------------------- |
| 686 | //* \fn AT91F_MCIDeviceWaitReady |
| 687 | //* \brief Wait for MCI Device ready |
| 688 | //*---------------------------------------------------------------------------- |
| 689 | void AT91F_MCIDeviceWaitReady(unsigned int timeout) |
| 690 | { |
| 691 | volatile int status; |
| 692 | |
| 693 | do |
| 694 | { |
| 695 | status = AT91C_BASE_MCI->MCI_SR; |
| 696 | timeout--; |
| 697 | } |
| 698 | while( !(status & AT91C_MCI_NOTBUSY) && (timeout>0) ); |
| 699 | } |
| 700 | |
| 701 | unsigned int swab32(unsigned int data) |
| 702 | { |
| 703 | unsigned int res = 0; |
| 704 | |
| 705 | res = (data & 0x000000ff) << 24 | |
| 706 | (data & 0x0000ff00) << 8 | |
| 707 | (data & 0x00ff0000) >> 8 | |
| 708 | (data & 0xff000000) >> 24; |
| 709 | |
| 710 | return res; |
| 711 | } |
| 712 | |
| 713 | //*-------------------------------------------------------------------- |
| 714 | //* \fn AT91F_MCI_ReadBlockSwab |
| 715 | //* \brief Read Block and swap byte order |
| 716 | //*-------------------------------------------------------------------- |
| 717 | int AT91F_MCI_ReadBlockSwab( |
| 718 | AT91PS_MciDevice pMCI_Device, |
| 719 | int src, |
| 720 | unsigned int *databuffer, |
| 721 | int sizeToRead) |
| 722 | { |
| 723 | int i; |
| 724 | unsigned char *buf = (unsigned char *)databuffer; |
| 725 | |
| 726 | //* Read Block 1 |
| 727 | for(i=0;i<BUFFER_SIZE_MCI_DEVICE;i++) |
| 728 | *buf++ = 0x00; |
| 729 | AT91F_MCI_ReadBlock(&MCI_Device,src,databuffer,sizeToRead); |
| 730 | |
| 731 | //* Wait end of Read |
| 732 | AT91F_MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); |
| 733 | |
| 734 | { |
| 735 | int index; |
| 736 | unsigned int *uiBuffer = databuffer; |
| 737 | |
| 738 | for(index = 0; index < 512/4; index++) |
| 739 | uiBuffer[index] = swab32(uiBuffer[index]); |
| 740 | } |
| 741 | return(1); |
| 742 | } |
| 743 | |