1 // Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
21 #include "sdio_host.h"
27 /** Macros/Constants **/
28 #define CHECK_SDIO_ERR(ErR) {\
30 printf("%s: %u err %u\r\n",__func__,__LINE__,ErR); \
35 /** Global Variable **/
36 /* Counter to hold the amount of buffers already sent to sdio slave */
37 static uint32_t tx_sent_buffers = 0;
39 /* Counter to hold the amount of bytes already received from sdio slave */
40 static uint32_t rx_got_bytes = 0;
42 /** Functions Declaration **/
44 /** SDIO slave initialization **/
45 static stm_ret_t esp_slave_init_io(void);
46 static uint32_t esp_sdio_host_get_buffer_size(void);
47 static stm_ret_t esp_sdio_slave_get_rx_data_size(uint32_t* rx_size);
49 /** Functions Defination **/
52 * @brief SDIO slave initialization
54 * @retval STM_OK for success or failure from enum stm_ret_t
56 static stm_ret_t esp_slave_init_io(void)
58 uint8_t ioe = 0, ior = 0, ie = 0;
59 uint8_t bsl = 0, bsh = 0;
60 uint8_t func1_bsl = 0, func1_bsh = 0;
61 uint8_t func2_bsl = 0, func2_bsh = 0;
63 CHECK_SDIO_ERR(sdio_driver_read_byte(SDIO_FUNC_0, SD_IO_CCCR_FN_ENABLE, &ioe));
65 //printf("%s %u IOE: 0x%02x\n\r", __func__, __LINE__,ioe);
68 CHECK_SDIO_ERR(sdio_driver_read_byte(SDIO_FUNC_0, SD_IO_CCCR_FN_READY, &ior));
70 //printf("%s %u IOR: 0x%02x\n\r", __func__, __LINE__, ior);
75 CHECK_SDIO_ERR(sdio_driver_write_byte(SDIO_FUNC_0, SD_IO_CCCR_FN_ENABLE, ioe, &ioe));
77 //printf("%s %u IOE: 0x%02x\n\r", __func__,__LINE__,ioe);
81 CHECK_SDIO_ERR(sdio_driver_write_byte(SDIO_FUNC_0, SD_IO_CCCR_FN_READY, ioe, &ior));
83 // printf("%s %u IOE: 0x%02x\n\r", __func__,__LINE__,ior);
86 // get interrupt status
87 CHECK_SDIO_ERR(sdio_driver_read_byte(SDIO_FUNC_0, SD_IO_CCCR_INT_ENABLE, &ie));
89 // printf("IE: 0x%02x\n\r", ie);
92 // enable interrupts for function 1&2 and master enable
94 CHECK_SDIO_ERR(sdio_driver_write_byte(SDIO_FUNC_0, SD_IO_CCCR_INT_ENABLE, ie, &ie));
96 // printf("%s: %u IE: 0x%02x\n\r", __func__,__LINE__,ie);
99 CHECK_SDIO_ERR(sdio_driver_write_byte(SDIO_FUNC_0, SD_IO_CCCR_BLKSIZEL, bsl, &bsl));
101 // printf("%s:%u Function 0 BSL: 0x%02x\n\r", __func__,__LINE__,bsl);
105 CHECK_SDIO_ERR(sdio_driver_write_byte(SDIO_FUNC_0, SD_IO_CCCR_BLKSIZEH, bsh, &bsh));
107 // printf("%s %u Function 0 BSH: 0x%02x\n\r", __func__,__LINE__,bsh);
110 CHECK_SDIO_ERR(sdio_driver_write_byte(SDIO_FUNC_0, 0x110, func1_bsl, &func1_bsl));
112 // printf("%s %u Function 1 BSL: 0x%02x\n\r", __func__,__LINE__,func1_bsl);
115 func1_bsh = 2; // Set block size 512 (0x200)
116 CHECK_SDIO_ERR(sdio_driver_write_byte(SDIO_FUNC_0, 0x111, func1_bsh, &func1_bsh));
118 // printf("%s %u Function 1 BSH: 0x%02x\n\r", __func__,__LINE__, func1_bsh);
121 CHECK_SDIO_ERR(sdio_driver_write_byte(SDIO_FUNC_0, 0x210, func2_bsl, &func2_bsl));
123 // printf("%s %u Function 2 BSL: 0x%02x\n\r", __func__,__LINE__, func2_bsl);
127 CHECK_SDIO_ERR(sdio_driver_write_byte(SDIO_FUNC_0, 0x210, func2_bsh, &func2_bsh));
129 // printf("%s %u Function 2 BSH: 0x%02x\n\r", __func__,__LINE__,func2_bsh);
130 printf("Slave Initialization completed\n\r");
136 * @brief host use this to initialize the slave as well as SDIO register
138 * @retval STM_OK for success or failure from enum stm_ret_t
140 stm_ret_t sdio_host_init(void)
142 CHECK_SDIO_ERR(sdio_driver_init());
144 CHECK_SDIO_ERR(esp_slave_init_io());
149 /** receive functions **/
151 * @brief HOST receive data
152 * @param rx_size - read data size
153 * @retval STM_OK for success or failure from enum stm_ret_t
155 static stm_ret_t esp_sdio_slave_get_rx_data_size(uint32_t* rx_size)
157 uint32_t len = 0, temp = 0;
158 stm_ret_t err = sdio_driver_read_bytes(SDIO_FUNC_1,
159 SDIO_REG(ESP_SLAVE_PACKET_LEN_REG), &len, 4, 0);
163 len &= ESP_SLAVE_LEN_MASK;
164 //len = (len + ESP_SLAVE_LEN_MASK - rx_got_bytes)%ESP_SLAVE_LEN_MASK;
165 if(len >= rx_got_bytes) {
166 len = (len + ESP_RX_BYTE_MAX - rx_got_bytes)%ESP_RX_BYTE_MAX;
168 temp = ESP_RX_BYTE_MAX - rx_got_bytes;
175 /* length is expected to be in multiple of ESP_BLOCK_SIZE */
176 if(len&(ESP_BLOCK_SIZE-1))
180 if (len > MAX_SDIO_BUFFER_SIZE) {
181 printf("%s: Len from slave[%lu] exceeds max [%d]\n",
182 __func__, len, MAX_SDIO_BUFFER_SIZE);
190 * @brief Get a packet from SDIO slave
191 * @param [out] out_data - Data output address
192 * size - The size of the output buffer,
193 * if the buffer is smaller than
194 * the size of data to receive from slave,
195 * the driver returns ESP_ERR_NOT_FINISHED
196 * [out] out_length - Output of length the data received from slave
197 * wait_ms - Time to wait before timeout, in ms
198 * @retval STM_OK for success or failure from enum stm_ret_t
200 stm_ret_t sdio_host_get_packet(void* out_data, size_t size,
201 size_t* out_length, uint32_t wait_ms)
203 stm_ret_t err = STM_OK;
204 uint32_t len = 0, wait_time = 0, len_remain = 0;
205 uint8_t* start_ptr = NULL;
206 int len_to_send = 0, block_n = 0;
209 printf("Invalid size:%d\n\r", size);
210 return STM_FAIL_INVALID_ARG;
214 err = esp_sdio_slave_get_rx_data_size(&len);
216 if (err == STM_OK && len > 0) {
218 printf("Expected length to be read %lu\n\n",len);
223 /* If no error and no data, retry */
226 if (wait_time >= wait_ms) {
227 return STM_FAIL_TIMEOUT;
235 printf("Pkt size to be read[%lu] > max sdio size supported[%u]\n\r",len, size);
240 start_ptr = (uint8_t*)out_data;
243 /* currently driver supports only block size of 512 */
245 block_n = len_remain / ESP_BLOCK_SIZE;
248 len_to_send = ESP_BLOCK_SIZE;
250 printf("block_n %u, len-to_send %lu\n\r",block_n,len_to_send);
253 err = sdio_driver_read_blocks(SDIO_FUNC_1,
254 ESP_SLAVE_CMD53_END_ADDR - len_remain,
255 start_ptr, len_to_send, block_n);
257 len_to_send = len_remain;
258 /* though the driver supports to split packet of unaligned size into length
259 * of 4x and 1~3, we still get aligned size of data to get higher
260 * efficiency. The length is determined by the SDIO address, and the
261 * remaining will be ignored by the slave hardware
263 err = sdio_driver_read_bytes(SDIO_FUNC_1,
264 ESP_SLAVE_CMD53_END_ADDR - len_remain, start_ptr,
265 (len_to_send + 3) & (~3), block_n);
270 printf("Err from read bytes %x\n\r",err);
275 start_ptr += len_to_send;
276 len_remain -= len_to_send;
277 } while (len_remain != 0);
281 if (rx_got_bytes >= ESP_RX_BYTE_MAX) {
282 rx_got_bytes -= ESP_RX_BYTE_MAX;
289 * @brief Clear interrupt bits of SDIO slave
290 * @param intr_mask - Mask of interrupt bits to clear
291 * @retval STM_OK for success or failure from enum stm_ret_t
293 stm_ret_t sdio_host_clear_intr(uint32_t intr_mask)
295 return sdio_driver_write_bytes(SDIO_FUNC_1,
296 SDIO_REG(ESP_SLAVE_INT_CLR_REG), (uint8_t*)&intr_mask, 4);
300 * @brief Get interrupt bits of SDIO slave
302 * @param intr_st - Output of the masked interrupt bits
303 * set to NULL if only raw bits are read
305 * @retval STM_OK for success or failure from enum stm_ret_t
307 stm_ret_t sdio_host_get_intr(uint32_t* intr_st)
309 stm_ret_t ret = STM_OK;
311 if (intr_st == NULL) {
312 return STM_FAIL_INVALID_ARG;
315 if (intr_st != NULL) {
316 ret = sdio_driver_read_bytes(SDIO_FUNC_1,
317 SDIO_REG(ESP_SLAVE_INT_ST_REG), (uint8_t*)intr_st, 4, 0);
326 /** send functions **/
329 * @brief Get available buffer to write to slave before transmit
332 * Number of buffers available at slave
334 static uint32_t esp_sdio_host_get_buffer_size(void)
336 stm_ret_t ret = STM_OK;
337 uint32_t len = 0, len1 = 0;
339 ret = sdio_driver_read_bytes(SDIO_FUNC_1,
340 SDIO_REG(ESP_SLAVE_TOKEN_RDATA), &len, 4, 0);
342 printf("Read length error, ret=%d\n\r", ret);
346 //printf("%s len %lu \n\r", __func__, len);
348 len = (len >> ESP_SDIO_SEND_OFFSET) & ESP_TX_BUFFER_MASK;
349 len = (len + ESP_TX_BUFFER_MAX - tx_sent_buffers) % ESP_TX_BUFFER_MAX;
351 //printf("Read ESP32 len: %lu len1 : %lu \n\r", len, len1);
357 * @brief Send a interrupt signal to the SDIO slave
358 * @param intr_no - interrupt number, now only support 0
359 * @retval STM_OK for success or failure from enum stm_ret_t
361 stm_ret_t sdio_host_send_intr(uint8_t intr_no)
363 uint32_t intr_mask = 0;
365 printf(" Error interrupt number\n\r");
366 return STM_FAIL_INVALID_ARG;
369 intr_mask = 0x1 << (intr_no + ESP_SDIO_CONF_OFFSET);
370 return STM32WriteReg(SDIO_FUNC_1, SDIO_REG(ESP_SLAVE_SCRATCH_REG_7), intr_mask);
374 * @brief Send a packet to the SDIO slave
375 * @param start - Start address of the packet to send
376 * length - Length of data to send, if the packet is over-size,
377 * the it will be divided into blocks and hold into different
378 * buffers automatically
379 * @retval STM_OK for success or failure from enum stm_ret_t
381 stm_ret_t sdio_host_send_packet(const void* start, uint32_t length)
384 uint8_t* start_ptr = (uint8_t*)start;
385 uint32_t len_remain = length, num = 0, cnt = 300;
386 // printf("length received %d %lu \n\r", length, len_remain);
388 int buffer_used, block_n = 0,len_to_send = 0;
390 buffer_used = (length + ESP_BLOCK_SIZE - 1) / ESP_BLOCK_SIZE;
394 num = esp_sdio_host_get_buffer_size();
396 //printf("Buffer size %lu can be send, input len: %u, len_remain: %lu\n\r", num, length, len_remain);
399 if (num * ESP_BLOCK_SIZE < length) {
401 printf("buff not enough: curr[%lu], exp[%d]\n\r", num, buffer_used);
402 return STM_FAIL_TIMEOUT;
404 printf("buff not enough: curr[%lu], exp[%d], retry..\n\r", num, buffer_used);
415 /* Though the driver supports to split packet of unaligned size into
416 * length of 4x and 1~3, we still send aligned size of data to get
417 * higher effeciency. The length is determined by the SDIO address, and
418 * the remainning will be discard by the slave hardware
420 block_n = len_remain / ESP_BLOCK_SIZE;
423 len_to_send = block_n * ESP_BLOCK_SIZE;
424 err = sdio_driver_write_blocks(SDIO_FUNC_1,
425 ESP_SLAVE_CMD53_END_ADDR - len_remain,
426 start_ptr, len_to_send);
428 len_to_send = len_remain;
429 err = sdio_driver_write_bytes(SDIO_FUNC_1,
430 ESP_SLAVE_CMD53_END_ADDR - len_remain,
431 start_ptr, (len_to_send + 3) & (~3));
438 start_ptr += len_to_send;
439 len_remain -= len_to_send;
440 } while (len_remain);
442 if (tx_sent_buffers >= ESP_TX_BUFFER_MAX) {
443 tx_sent_buffers -= ESP_TX_BUFFER_MAX;
446 tx_sent_buffers += buffer_used;