1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174 |
- #include "sdk_config.h"
- #if APP_SDCARD_ENABLED
- #include "app_sdcard.h"
- #include "nrf_gpio.h"
- #include "nrf_drv_spi.h"
- #include "app_error.h"
- #include "nrf_assert.h"
- #include "nrf_pt.h"
- #define CMD_MASK 0x40
- #define ACMD_MASK 0x80
- #define CMD0 (CMD_MASK | 0)
- #define CMD1 (CMD_MASK | 1)
- #define CMD8 (CMD_MASK | 8)
- #define CMD9 (CMD_MASK | 9)
- #define CMD10 (CMD_MASK | 10)
- #define CMD12 (CMD_MASK | 12)
- #define CMD16 (CMD_MASK | 16)
- #define CMD17 (CMD_MASK | 17)
- #define CMD18 (CMD_MASK | 18)
- #define CMD23 (CMD_MASK | 23)
- #define CMD24 (CMD_MASK | 24)
- #define CMD25 (CMD_MASK | 25)
- #define CMD32 (CMD_MASK | 32)
- #define CMD33 (CMD_MASK | 33)
- #define CMD38 (CMD_MASK | 38)
- #define CMD55 (CMD_MASK | 55)
- #define CMD58 (CMD_MASK | 58)
- #define ACMD13 (ACMD_MASK | CMD_MASK | 13)
- #define ACMD23 (ACMD_MASK | CMD_MASK | 23)
- #define ACMD41 (ACMD_MASK | CMD_MASK | 41)
- #define IS_ACMD(CMD) ((CMD) & ACMD_MASK)
- #define SDC_COMMAND_LEN 6
- #define SDC_COMMAND_POS 0
- #define SDC_COMMAND_MASK 0x7F
- #define SDC_COMMAND_ARG_POS 1
- #define SDC_COMMAND_CRC_POS 5
- #define SDC_MAX_NCR 8
- #define SDC_R1_LEN 1
- #define SDC_R3_LEN 5
- #define SDC_R7_LEN 5
- #define SDC_R_MAX_LEN 5
- #define SDC_FLAG_IN_IDLE_STATE 0x01
- #define SDC_FLAG_ERASE_RESET 0x02
- #define SDC_FLAG_ILLEGAL_COMMAND 0x04
- #define SDC_FLAG_COM_CRC_ERROR 0x08
- #define SDC_FLAG_ERASE_SEQUENCE_ERROR 0x10
- #define SDC_FLAG_ADDRESS_ERROR 0x20
- #define SDC_FLAG_PARAMETER_ERROR 0x40
- #define SDC_HCS_FLAG_MASK (1uL << 30)
- #define SDC_EMPTY_BYTE 0xFF
- #define SDC_BUSY_BYTE 0x00
- #define SDC_TOKEN_START_BLOCK 0xFE
- #define SDC_TOKEN_START_BLOCK_MULT 0xFC
- #define SDC_TOKEN_DATA_RESP_MASK 0x1F
- #define SDC_TOKEN_DATA_RESP_ACCEPTED 0x05
- #define SDC_TOKEN_DATA_RESP_CRC_ERR 0x0B
- #define SDC_TOKEN_DATA_RESP_DATA_ERR 0x0D
- #define SDC_TOKEN_STOP_TRAN 0xFD
- #define SDC_MAX_RETRY_COUNT_INIT 2000
- #define SDC_MAX_RETRY_COUNT 20000
- #define SDC_SPI_MTU 240
- #define SDC_CRC_CMD0 0x95
- #define SDC_CRC_CMD8 0x87
- #define SDC_CRC_DUMMY 0xFF
- #define SDC_CMD_BUF_LEN 16
- #define SDC_WORK_BUF_LEN 16
- #define SDC_DATA_WAIT_TX_SIZE 16
- #define SDC_CS_ASSERT() do { nrf_gpio_pin_clear(m_cb.cs_pin); } while (0)
- #define SDC_CS_DEASSERT() do { nrf_gpio_pin_set(m_cb.cs_pin); } while (0)
- #define SDC_PT &m_cb.state.pt
- #define SDC_PT_SUB &m_cb.state.pt_sub
- #define SDC_BREAK(PT, EXIT_CODE) do { \
- *p_exit_code = (EXIT_CODE); \
- PT_EXIT(PT); \
- } while (0)
- #define SDC_RESP_CHECK(PT, R1) do { \
- if ((R1) & ~(SDC_FLAG_IN_IDLE_STATE | SDC_FLAG_ERASE_RESET)) \
- { \
- SDC_BREAK((PT), SDC_ERROR_COMMUNICATION); \
- } \
- } while (0)
- #define SDC_RESULT_CHECK(PT, RESULT) do { \
- if ((RESULT) != SDC_SUCCESS) \
- { \
- SDC_BREAK((PT), RESULT); \
- } \
- } while (0);
- static const nrf_drv_spi_t m_spi = NRF_DRV_SPI_INSTANCE(APP_SDCARD_SPI_INSTANCE);
- typedef enum {
- SDC_RNONE = 0,
- SDC_R1,
- SDC_R3,
- SDC_R7
- } sdc_response_t;
- typedef enum {
- SDC_UNINITIALIZED = 0,
- SDC_OP_RESET = 1,
- SDC_OP_IDENTIFICATION = 2,
- SDC_OP_IDLE = 3,
- SDC_OP_READ = 4,
- SDC_OP_WRITE = 5
- } sdc_op_t;
- typedef enum {
- SDC_BUS_IDLE = 0,
- SDC_BUS_CMD = 1,
- SDC_BUS_ACMD = 2,
- SDC_BUS_DATA_WAIT = 3,
- SDC_BUS_DATA = 4
- } sdc_bus_state_t;
- typedef struct {
- uint8_t * buffer;
- uint32_t address;
- uint16_t block_count;
- uint16_t blocks_left;
- uint16_t position;
- } sdc_rw_op_t;
- typedef struct {
- sdc_rw_op_t rw_op;
- pt_t pt;
- pt_t pt_sub;
- uint16_t retry_count;
- volatile sdc_op_t op;
- sdc_bus_state_t bus_state;
- uint8_t rsp_len;
- } sdc_state_t;
- typedef struct {
- sdc_event_handler_t handler;
- app_sdc_info_t info;
- sdc_state_t state;
- uint8_t cmd_buf[SDC_CMD_BUF_LEN];
- uint8_t rsp_buf[SDC_CMD_BUF_LEN];
- uint8_t work_buf[SDC_WORK_BUF_LEN];
- uint8_t cs_pin;
- } sdc_cb_t;
- static sdc_cb_t m_cb;
- __STATIC_INLINE void sdc_spi_transfer(uint8_t const * const p_txb,
- uint8_t tx_len,
- uint8_t * const p_rxb,
- uint8_t rx_len)
- {
- SDC_CS_ASSERT();
- ret_code_t err_code = nrf_drv_spi_transfer(&m_spi, p_txb, tx_len, p_rxb, rx_len);
- APP_ERROR_CHECK(err_code);
- }
- __STATIC_INLINE void sdc_spi_hispeed(void)
- {
- #ifdef SPI_PRESENT
- nrf_spi_frequency_set(m_spi.u.spi.p_reg,
- (nrf_spi_frequency_t) APP_SDCARD_FREQ_DATA);
- #else
- nrf_spim_frequency_set(m_spi.u.spim.p_reg,
- (nrf_spi_frequency_t) APP_SDCARD_FREQ_DATA);
- #endif
- }
- static uint32_t sdc_calculate_size(uint8_t const * const p_csd)
- {
-
- uint8_t csd_version = p_csd[0] >> 6;
- switch (csd_version)
- {
- case 0:
- case 2:
- {
-
- uint32_t c_size = ((uint32_t) p_csd[8] >> 6) + (((uint32_t) p_csd[7]) << 2)
- + ((uint32_t)(p_csd[6] & 0x03) << 10);
- uint32_t read_bl_len = p_csd[5] & 0x0F;
- uint32_t c_size_mult = ((p_csd[10] & 0x80) >> 7) + ((p_csd[9] & 0x03) << 1);
-
-
- return (c_size + 1) << (read_bl_len + c_size_mult + 2 - 9);
- }
- case 1:
- {
-
- uint32_t c_size = (uint32_t) p_csd[9] + ((uint32_t) p_csd[8] << 8)
- + (((uint32_t) p_csd[7] & 0x3F) << 16);
-
-
- return (c_size + 1) * 1024uL;
- }
- default:
- break;
- }
- return 0;
- }
- static ret_code_t sdc_cmd(uint8_t cmd, uint32_t arg, sdc_response_t rsp_type)
- {
- if (m_cb.state.bus_state != SDC_BUS_IDLE)
- {
- return NRF_ERROR_BUSY;
- }
- uint8_t offset = 0;
- m_cb.state.bus_state = SDC_BUS_CMD;
- if (IS_ACMD(cmd))
- {
-
-
- offset = SDC_COMMAND_LEN;
- m_cb.state.bus_state = SDC_BUS_ACMD;
- m_cb.cmd_buf[SDC_COMMAND_POS] = CMD55;
- m_cb.cmd_buf[SDC_COMMAND_ARG_POS] = 0;
- m_cb.cmd_buf[SDC_COMMAND_ARG_POS + 1] = 0;
- m_cb.cmd_buf[SDC_COMMAND_ARG_POS + 2] = 0;
- m_cb.cmd_buf[SDC_COMMAND_ARG_POS + 3] = 0;
- m_cb.cmd_buf[SDC_COMMAND_CRC_POS] = SDC_CRC_DUMMY;
- }
- m_cb.cmd_buf[SDC_COMMAND_POS + offset] = cmd & SDC_COMMAND_MASK;
- m_cb.cmd_buf[SDC_COMMAND_ARG_POS + offset] = (uint8_t)(arg >> 24);
- m_cb.cmd_buf[SDC_COMMAND_ARG_POS + 1 + offset] = (uint8_t)(arg >> 16);
- m_cb.cmd_buf[SDC_COMMAND_ARG_POS + 2 + offset] = (uint8_t)(arg >> 8);
- m_cb.cmd_buf[SDC_COMMAND_ARG_POS + 3 + offset] = (uint8_t)(arg);
-
- uint8_t crc;
- switch (cmd)
- {
- case CMD0:
- crc = SDC_CRC_CMD0;
- break;
- case CMD8:
- crc = SDC_CRC_CMD8;
- break;
- default:
- crc = SDC_CRC_DUMMY;
- break;
- }
- m_cb.cmd_buf[SDC_COMMAND_CRC_POS + offset] = crc;
- switch (rsp_type)
- {
- case SDC_R3:
- m_cb.state.rsp_len = SDC_R3_LEN;
- break;
- case SDC_R7:
- m_cb.state.rsp_len = SDC_R7_LEN;
- break;
- default:
- m_cb.state.rsp_len = SDC_R1_LEN;
- break;
- }
- uint8_t response_len = (IS_ACMD(cmd)) ? SDC_R1_LEN : m_cb.state.rsp_len;
- sdc_spi_transfer(m_cb.cmd_buf,
- SDC_COMMAND_LEN,
- m_cb.rsp_buf,
- SDC_COMMAND_LEN + SDC_MAX_NCR + response_len);
- return NRF_SUCCESS;
- }
- static PT_THREAD(sdc_pt_sub_data_read(uint8_t * p_rx_data,
- uint8_t rx_length,
- uint16_t block_len,
- sdc_result_t * p_exit_code))
- {
- PT_BEGIN(SDC_PT_SUB);
- while (1)
- {
- ASSERT(block_len);
- ASSERT(m_cb.state.rw_op.block_count);
- m_cb.state.rw_op.blocks_left = m_cb.state.rw_op.block_count;
- while (m_cb.state.rw_op.blocks_left)
- {
- m_cb.state.retry_count = 0;
- m_cb.cmd_buf[0] = 0xFF;
- m_cb.state.rw_op.position = 0;
- m_cb.state.bus_state = SDC_BUS_DATA_WAIT;
- while (m_cb.state.bus_state == SDC_BUS_DATA_WAIT)
- {
- ++m_cb.state.retry_count;
- if (m_cb.state.retry_count > SDC_MAX_RETRY_COUNT)
- {
- SDC_BREAK(SDC_PT_SUB, SDC_ERROR_TIMEOUT);
- }
-
- while (rx_length && p_rx_data[0] == SDC_EMPTY_BYTE)
- {
- ++p_rx_data;
- --rx_length;
- }
- if (rx_length)
- {
-
- if (p_rx_data[0] == SDC_TOKEN_START_BLOCK)
- {
-
-
- ++p_rx_data;
- --rx_length;
- m_cb.state.bus_state = SDC_BUS_DATA;
- uint16_t copy_len = (rx_length > block_len) ? block_len : rx_length;
- for (uint32_t i = 0; i < copy_len; ++i)
- {
- m_cb.state.rw_op.buffer[i] = p_rx_data[i];
- }
- m_cb.state.rw_op.position = copy_len;
- m_cb.state.rw_op.buffer += copy_len;
- }
- else
- {
-
- SDC_BREAK(SDC_PT_SUB, SDC_ERROR_DATA);
- }
- }
- else
- {
-
- sdc_spi_transfer(m_cb.cmd_buf, 1, m_cb.rsp_buf, SDC_DATA_WAIT_TX_SIZE);
- PT_YIELD(SDC_PT_SUB);
- }
- }
- while (m_cb.state.rw_op.position < block_len)
- {
- {
- uint16_t chunk_size = block_len - m_cb.state.rw_op.position;
- if (chunk_size > SDC_SPI_MTU)
- {
- chunk_size = SDC_SPI_MTU;
- }
- sdc_spi_transfer(m_cb.cmd_buf, 1,
- m_cb.state.rw_op.buffer, chunk_size);
- m_cb.state.rw_op.buffer += chunk_size;
- m_cb.state.rw_op.position += chunk_size;
- }
- PT_YIELD(SDC_PT_SUB);
- }
-
- --m_cb.state.rw_op.blocks_left;
- sdc_spi_transfer(m_cb.cmd_buf, 1,
- m_cb.rsp_buf, 2);
- PT_YIELD(SDC_PT_SUB);
-
- rx_length = 0;
- }
-
- m_cb.cmd_buf[0] = SDC_EMPTY_BYTE;
- sdc_spi_transfer(m_cb.cmd_buf, 1,
- m_cb.rsp_buf, 2);
- PT_YIELD(SDC_PT_SUB);
- m_cb.state.bus_state = SDC_BUS_IDLE;
- SDC_BREAK(SDC_PT_SUB, SDC_SUCCESS);
- }
- PT_END(SDC_PT_SUB)
- }
- static PT_THREAD(sdc_pt_identification(uint8_t * p_rx_data,
- uint8_t rx_length,
- sdc_result_t * p_exit_code))
- {
- uint8_t r1 = p_rx_data[0];
- uint32_t rsp = ((uint32_t)p_rx_data[1] << 24)
- | ((uint32_t)p_rx_data[2] << 16)
- | ((uint32_t)p_rx_data[3] << 8)
- | ((uint32_t)p_rx_data[4]);
- uint32_t arg;
- ret_code_t err_code;
- sdc_result_t sub_exit_code;
- PT_BEGIN(SDC_PT);
- while (1)
- {
- err_code = sdc_cmd(CMD0, 0, SDC_R1);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- err_code = sdc_cmd(CMD0, 0, SDC_R1);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- SDC_RESP_CHECK(SDC_PT, r1);
-
- err_code = sdc_cmd(CMD8, 0x1AA, SDC_R7);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- if (!(r1 & SDC_FLAG_ILLEGAL_COMMAND))
- {
-
- m_cb.info.type.version = SDC_TYPE_SDV2;
- SDC_RESP_CHECK(SDC_PT, r1);
- }
- m_cb.state.retry_count = 0;
- arg = (m_cb.info.type.version == SDC_TYPE_SDV2) ? SDC_HCS_FLAG_MASK : 0;
- err_code = sdc_cmd(ACMD41, arg, SDC_R3);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- if (r1 & SDC_FLAG_ILLEGAL_COMMAND)
- {
-
- m_cb.info.type.version = SDC_TYPE_MMCV3;
- r1 &= ~SDC_FLAG_ILLEGAL_COMMAND;
- do
- {
- ++m_cb.state.retry_count;
- if (m_cb.state.retry_count > SDC_MAX_RETRY_COUNT_INIT)
- {
- SDC_BREAK(SDC_PT, SDC_ERROR_TIMEOUT);
- }
- err_code = sdc_cmd(CMD1, 0, SDC_R3);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- SDC_RESP_CHECK(SDC_PT, r1);
- }
- while (r1 & SDC_FLAG_IN_IDLE_STATE);
- }
- else
- {
-
- SDC_RESP_CHECK(SDC_PT, r1);
- while (r1 & SDC_FLAG_IN_IDLE_STATE)
- {
- ++m_cb.state.retry_count;
- if (m_cb.state.retry_count > SDC_MAX_RETRY_COUNT_INIT)
- {
- SDC_BREAK(SDC_PT, SDC_ERROR_TIMEOUT);
- }
- arg = (m_cb.info.type.version == SDC_TYPE_SDV2) ? SDC_HCS_FLAG_MASK : 0;
- err_code = sdc_cmd(ACMD41, arg, SDC_R3);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- SDC_RESP_CHECK(SDC_PT, r1);
- }
- err_code = sdc_cmd(CMD58, 0, SDC_R3);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- SDC_RESP_CHECK(SDC_PT, r1);
- if (rsp & SDC_HCS_FLAG_MASK)
- {
- m_cb.info.type.sdhc = 1;
- }
- }
- if (m_cb.info.type.version != SDC_TYPE_SDV2)
- {
-
- err_code = sdc_cmd(CMD16, SDC_SECTOR_SIZE, SDC_R1);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- SDC_RESP_CHECK(SDC_PT, r1);
- }
-
- m_cb.state.rw_op.buffer = m_cb.work_buf;
- m_cb.state.rw_op.block_count = 1;
- err_code = sdc_cmd(CMD9, 0, SDC_R1);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- SDC_RESP_CHECK(SDC_PT, r1);
- p_rx_data += SDC_R1_LEN;
- rx_length -= SDC_R1_LEN;
- PT_SPAWN(SDC_PT, SDC_PT_SUB, sdc_pt_sub_data_read(p_rx_data, rx_length, \
- 16, &sub_exit_code));
- SDC_RESULT_CHECK(SDC_PT, sub_exit_code);
- m_cb.info.num_blocks = sdc_calculate_size(m_cb.work_buf);
- m_cb.info.block_len = SDC_SECTOR_SIZE;
- SDC_BREAK(SDC_PT, SDC_SUCCESS);
- }
- PT_END(SDC_PT)
- }
- static PT_THREAD(sdc_pt_read(uint8_t * p_rx_data,
- uint8_t rx_length,
- sdc_result_t * p_exit_code))
- {
- uint8_t r1;
- ret_code_t err_code;
- sdc_result_t sub_exit_code;
- PT_BEGIN(SDC_PT);
- while (1)
- {
- r1 = p_rx_data[0];
- SDC_RESP_CHECK(SDC_PT, r1);
- p_rx_data += SDC_R1_LEN;
- rx_length -= SDC_R1_LEN;
-
- PT_SPAWN(SDC_PT, SDC_PT_SUB, sdc_pt_sub_data_read(p_rx_data, rx_length,
- SDC_SECTOR_SIZE,
- &sub_exit_code));
- SDC_RESULT_CHECK(SDC_PT, sub_exit_code);
- if (m_cb.state.rw_op.block_count > 1)
- {
-
- err_code = sdc_cmd(CMD12, 0, SDC_R1);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- }
- SDC_BREAK(SDC_PT, SDC_SUCCESS);
- }
- PT_END(SDC_PT)
- }
- static PT_THREAD(sdc_pt_write(uint8_t * rx_data,
- uint8_t rx_length,
- sdc_result_t * p_exit_code))
- {
- ret_code_t err_code;
- PT_BEGIN(SDC_PT);
- while (1)
- {
- uint8_t r1;
- r1 = rx_data[0];
- SDC_RESP_CHECK(SDC_PT, r1);
- if (m_cb.info.type.version != SDC_TYPE_MMCV3 && m_cb.state.rw_op.block_count > 1)
- {
- err_code = sdc_cmd(CMD25, m_cb.state.rw_op.address, SDC_R1);
- APP_ERROR_CHECK(err_code);
- PT_YIELD(SDC_PT);
- r1 = rx_data[0];
- SDC_RESP_CHECK(SDC_PT, r1);
- }
- m_cb.state.rw_op.blocks_left = m_cb.state.rw_op.block_count;
- while (m_cb.state.rw_op.blocks_left)
- {
- m_cb.state.rw_op.position = 0;
- m_cb.state.bus_state = SDC_BUS_DATA;
-
- m_cb.cmd_buf[0] = SDC_EMPTY_BYTE;
- m_cb.cmd_buf[1] = (m_cb.state.rw_op.block_count > 1) ? SDC_TOKEN_START_BLOCK_MULT
- : SDC_TOKEN_START_BLOCK;
- sdc_spi_transfer(m_cb.cmd_buf, 2, m_cb.rsp_buf, 2);
- PT_YIELD(SDC_PT);
-
- while (m_cb.state.rw_op.position < SDC_SECTOR_SIZE)
- {
- {
- uint16_t chunk_size = SDC_SECTOR_SIZE - m_cb.state.rw_op.position;
- if (chunk_size > SDC_SPI_MTU)
- {
- chunk_size = SDC_SPI_MTU;
- }
- sdc_spi_transfer(&m_cb.state.rw_op.buffer[m_cb.state.rw_op.position],
- chunk_size,
- m_cb.rsp_buf,
- 1);
- m_cb.state.rw_op.position += chunk_size;
- }
- PT_YIELD(SDC_PT);
- }
- m_cb.state.rw_op.buffer += SDC_SECTOR_SIZE;
-
- m_cb.state.bus_state = SDC_BUS_DATA_WAIT;
- sdc_spi_transfer(m_cb.cmd_buf, 1,
- m_cb.rsp_buf, 3);
- PT_YIELD(SDC_PT);
- {
- uint8_t token = m_cb.rsp_buf[2] & SDC_TOKEN_DATA_RESP_MASK;
- if (token != SDC_TOKEN_DATA_RESP_ACCEPTED)
- {
- if (token == SDC_TOKEN_DATA_RESP_CRC_ERR
- || token == SDC_TOKEN_DATA_RESP_DATA_ERR)
- {
- SDC_BREAK(SDC_PT, SDC_ERROR_DATA);
- }
- else
- {
- SDC_BREAK(SDC_PT, SDC_ERROR_COMMUNICATION);
- }
- }
- }
-
- m_cb.state.retry_count = 0;
- while (m_cb.state.bus_state == SDC_BUS_DATA_WAIT)
- {
- ++m_cb.state.retry_count;
- if (m_cb.state.retry_count > SDC_MAX_RETRY_COUNT)
- {
- SDC_BREAK(SDC_PT, SDC_ERROR_TIMEOUT);
- }
- sdc_spi_transfer(m_cb.cmd_buf, 1,
- m_cb.rsp_buf, SDC_DATA_WAIT_TX_SIZE);
- PT_YIELD(SDC_PT);
- for (uint32_t i = 0; i < rx_length; ++i)
- {
- if (rx_data[i] != 0x00)
- {
- m_cb.state.bus_state = SDC_BUS_IDLE;
- break;
- }
- }
- }
- --m_cb.state.rw_op.blocks_left;
- }
- if (m_cb.state.rw_op.block_count > 1)
- {
-
- m_cb.cmd_buf[0] = SDC_EMPTY_BYTE;
- m_cb.cmd_buf[1] = SDC_TOKEN_STOP_TRAN;
- sdc_spi_transfer(m_cb.cmd_buf, 2,
- m_cb.rsp_buf, 3);
- PT_YIELD(SDC_PT);
- m_cb.state.retry_count = 0;
- m_cb.state.bus_state = SDC_BUS_DATA_WAIT;
-
- while (m_cb.state.bus_state == SDC_BUS_DATA_WAIT)
- {
- ++m_cb.state.retry_count;
- if (m_cb.state.retry_count > SDC_MAX_RETRY_COUNT)
- {
- SDC_BREAK(SDC_PT, SDC_ERROR_TIMEOUT);
- }
- sdc_spi_transfer(m_cb.cmd_buf, 1,
- m_cb.rsp_buf, SDC_DATA_WAIT_TX_SIZE);
- PT_YIELD(SDC_PT);
- for (uint32_t i = 0; i < rx_length; ++i)
- {
- if (rx_data[i] != 0x00)
- {
- m_cb.state.bus_state = SDC_BUS_IDLE;
- break;
- }
- }
- }
- }
- SDC_BREAK(SDC_PT, SDC_SUCCESS);
- }
- PT_END(SDC_PT)
- }
- static void spi_handler(nrf_drv_spi_evt_t const * p_event,
- void * p_context)
- {
- uint8_t * rx_data = p_event->data.done.p_rx_buffer;
- uint8_t rx_length = p_event->data.done.rx_length;
- if (!m_cb.state.rw_op.blocks_left)
- {
-
- SDC_CS_DEASSERT();
- }
- if (m_cb.state.bus_state == SDC_BUS_ACMD || m_cb.state.bus_state == SDC_BUS_CMD)
- {
-
- ASSERT(rx_length > SDC_COMMAND_LEN);
- rx_length -= SDC_COMMAND_LEN;
- rx_data += SDC_COMMAND_LEN;
- if (p_event->data.done.p_tx_buffer[0] == CMD12)
- {
-
- if (rx_length)
- {
- --rx_length;
- ++rx_data;
- }
- }
- while (rx_length && rx_data[0] == SDC_EMPTY_BYTE)
- {
- --rx_length;
- ++rx_data;
- }
- if (rx_length == 0)
- {
- if (p_event->data.done.p_tx_buffer[0] == CMD12)
- {
-
- ++rx_length;
- --rx_data;
- }
- else
- {
- rx_data = NULL;
- }
- }
- if (!rx_data && m_cb.state.op != SDC_OP_RESET)
- {
-
- sdc_evt_t evt;
- evt.result = SDC_ERROR_NOT_RESPONDING;
- switch (m_cb.state.op)
- {
- case SDC_OP_RESET:
- case SDC_OP_IDENTIFICATION:
- evt.type = SDC_EVT_INIT;
- m_cb.state.op = SDC_OP_IDLE;
- APP_ERROR_CHECK(app_sdc_uninit());
- break;
- case SDC_OP_READ:
- evt.type = SDC_EVT_READ;
- break;
- case SDC_OP_WRITE:
- evt.type = SDC_EVT_WRITE;
- break;
- default:
- APP_ERROR_CHECK(NRF_ERROR_INTERNAL);
- break;
- }
- SDC_CS_DEASSERT();
- m_cb.state.op = SDC_OP_IDLE;
- m_cb.handler(&evt);
- return;
- }
- if (m_cb.state.bus_state == SDC_BUS_ACMD)
- {
-
- m_cb.state.bus_state = SDC_BUS_CMD;
- uint8_t r1 = rx_data[0];
- if (!(r1 & (~SDC_FLAG_IN_IDLE_STATE)))
- {
- sdc_spi_transfer(m_cb.cmd_buf + SDC_COMMAND_LEN, SDC_COMMAND_LEN,
- m_cb.rsp_buf, SDC_COMMAND_LEN + SDC_MAX_NCR + m_cb.state.rsp_len);
- return;
- }
- }
- m_cb.state.bus_state = SDC_BUS_IDLE;
- }
- sdc_result_t exit_code = SDC_ERROR_INTERNAL;
- sdc_evt_t evt;
- switch (m_cb.state.op)
- {
- case SDC_OP_RESET:
- m_cb.state.op = SDC_OP_IDENTIFICATION;
- PT_INIT(SDC_PT);
-
- case SDC_OP_IDENTIFICATION:
- if (!PT_SCHEDULE(sdc_pt_identification(rx_data, rx_length, &exit_code)))
- {
- evt.type = SDC_EVT_INIT;
- evt.result = exit_code;
- m_cb.state.op = SDC_OP_IDLE;
- SDC_CS_DEASSERT();
- sdc_spi_hispeed();
- m_cb.handler(&evt);
- }
- break;
- case SDC_OP_READ:
- if (!PT_SCHEDULE(sdc_pt_read(rx_data, rx_length, &exit_code)))
- {
- evt.type = SDC_EVT_READ;
- evt.result = exit_code;
- m_cb.state.op = SDC_OP_IDLE;
- m_cb.state.rw_op.block_count = 0;
- m_cb.state.rw_op.blocks_left = 0;
- m_cb.state.bus_state = SDC_BUS_IDLE;
- SDC_CS_DEASSERT();
- m_cb.handler(&evt);
- }
- break;
- case SDC_OP_WRITE:
- if (!PT_SCHEDULE(sdc_pt_write(rx_data, rx_length, &exit_code)))
- {
- evt.type = SDC_EVT_WRITE;
- evt.result = exit_code;
- m_cb.state.op = SDC_OP_IDLE;
- m_cb.state.bus_state = SDC_BUS_IDLE;
- m_cb.state.rw_op.block_count = 0;
- m_cb.state.rw_op.blocks_left = 0;
- SDC_CS_DEASSERT();
- m_cb.handler(&evt);
- }
- break;
- default:
- APP_ERROR_CHECK(NRF_ERROR_INTERNAL);
- break;
- }
- return;
- }
- ret_code_t app_sdc_block_read(uint8_t * p_buf, uint32_t block_address, uint16_t block_count)
- {
- ASSERT(p_buf);
- if (m_cb.state.op == SDC_UNINITIALIZED)
- {
- return NRF_ERROR_INVALID_STATE;
- }
- if (m_cb.state.op != SDC_OP_IDLE)
- {
- return NRF_ERROR_BUSY;
- }
- if (block_count == 0)
- {
- return NRF_ERROR_INVALID_PARAM;
- }
- m_cb.state.op = SDC_OP_READ;
- if (!m_cb.info.type.sdhc)
- {
- m_cb.state.rw_op.address = block_address * SDC_SECTOR_SIZE;
- }
- else
- {
- m_cb.state.rw_op.address = block_address;
- }
- m_cb.state.rw_op.buffer = p_buf;
- m_cb.state.rw_op.block_count = block_count;
- m_cb.state.rw_op.blocks_left = block_count;
- PT_INIT(&m_cb.state.pt);
- uint8_t command = (block_count > 1) ? CMD18 : CMD17;
- ret_code_t err_code = sdc_cmd(command, m_cb.state.rw_op.address, SDC_R1);
- APP_ERROR_CHECK(err_code);
- return NRF_SUCCESS;
- }
- ret_code_t app_sdc_block_write(uint8_t const * p_buf, uint32_t block_address, uint16_t block_count)
- {
- ASSERT(p_buf);
- if (m_cb.state.op == SDC_UNINITIALIZED)
- {
- return NRF_ERROR_INVALID_STATE;
- }
- if (m_cb.state.op != SDC_OP_IDLE)
- {
- return NRF_ERROR_BUSY;
- }
- if (block_count == 0)
- {
- return NRF_ERROR_INVALID_PARAM;
- }
- m_cb.state.op = SDC_OP_WRITE;
- if (!m_cb.info.type.sdhc)
- {
- m_cb.state.rw_op.address = block_address * 512uL;
- }
- else
- {
- m_cb.state.rw_op.address = block_address;
- }
- m_cb.state.rw_op.buffer = (uint8_t *) p_buf;
- m_cb.state.rw_op.block_count = block_count;
- m_cb.state.rw_op.blocks_left = block_count;
- PT_INIT(&m_cb.state.pt);
- ret_code_t err_code;
- if (block_count == 1)
- {
- err_code = sdc_cmd(CMD24, m_cb.state.rw_op.address, SDC_R1);
- APP_ERROR_CHECK(err_code);
- return NRF_SUCCESS;
- }
- if (m_cb.info.type.version == SDC_TYPE_MMCV3)
- {
-
- err_code = sdc_cmd(CMD25, m_cb.state.rw_op.address, SDC_R1);
- }
- else
- {
-
- err_code = sdc_cmd(ACMD23, block_count, SDC_R1);
- }
- APP_ERROR_CHECK(err_code);
- return NRF_SUCCESS;
- }
- ret_code_t app_sdc_init(app_sdc_config_t const * const p_config, sdc_event_handler_t event_handler)
- {
- if (m_cb.state.op != SDC_UNINITIALIZED)
- {
- return NRF_ERROR_INVALID_STATE;
- }
- if ((!event_handler)
- || (p_config->cs_pin == NRF_DRV_SPI_PIN_NOT_USED)
- || (p_config->miso_pin == NRF_DRV_SPI_PIN_NOT_USED)
- || (p_config->mosi_pin == NRF_DRV_SPI_PIN_NOT_USED)
- || (p_config->sck_pin == NRF_DRV_SPI_PIN_NOT_USED))
- {
- return NRF_ERROR_INVALID_PARAM;
- }
- ret_code_t err_code;
- ASSERT(p_config->cs_pin && p_config->miso_pin
- && p_config->mosi_pin && p_config->sck_pin);
-
- m_cb.cs_pin = p_config->cs_pin;
- nrf_gpio_cfg_output(m_cb.cs_pin);
- SDC_CS_DEASSERT();
- const nrf_drv_spi_config_t spi_cfg = {
- .sck_pin = p_config->sck_pin,
- .mosi_pin = p_config->mosi_pin,
- .miso_pin = p_config->miso_pin,
- .ss_pin = NRF_DRV_SPI_PIN_NOT_USED,
- .irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY,
- .orc = 0xFF,
- .frequency = (nrf_drv_spi_frequency_t) APP_SDCARD_FREQ_INIT,
- .mode = NRF_DRV_SPI_MODE_0,
- .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST,
- };
- err_code = nrf_drv_spi_init(&m_spi, &spi_cfg, spi_handler, NULL);
- APP_ERROR_CHECK(err_code);
- m_cb.handler = event_handler;
- m_cb.state.op = SDC_OP_RESET;
- m_cb.info.type.version = SDC_TYPE_UNKNOWN;
- m_cb.info.type.sdhc = 0;
- m_cb.state.bus_state = SDC_BUS_IDLE;
-
- m_cb.cmd_buf[0] = 0xFF;
- err_code = nrf_drv_spi_transfer(&m_spi, m_cb.cmd_buf, 1,
- m_cb.rsp_buf, 10);
- APP_ERROR_CHECK(err_code);
- return NRF_SUCCESS;
- }
- ret_code_t app_sdc_uninit(void)
- {
- if (m_cb.state.op == SDC_UNINITIALIZED)
- {
- return NRF_ERROR_INVALID_STATE;
- }
- if (m_cb.state.op != SDC_OP_IDLE)
- {
- return NRF_ERROR_BUSY;
- }
- nrf_drv_spi_uninit(&m_spi);
- nrf_gpio_cfg_input(m_cb.cs_pin, NRF_GPIO_PIN_NOPULL);
- m_cb.state.bus_state = SDC_BUS_IDLE;
- m_cb.state.op = SDC_UNINITIALIZED;
- return NRF_SUCCESS;
- }
- bool app_sdc_busy_check(void)
- {
- return ((m_cb.state.op != SDC_OP_IDLE) && (m_cb.state.op != SDC_UNINITIALIZED));
- }
- app_sdc_info_t const * app_sdc_info_get(void)
- {
- if (m_cb.state.op >= SDC_OP_IDLE)
- {
- return &m_cb.info;
- }
- return NULL;
- }
- #endif
|