chore(sdio_slave): format source files

This commit is contained in:
michael
2018-06-07 20:11:08 +08:00
committed by bot
parent 4b91c82cc4
commit 8ab87a6a87
2 changed files with 197 additions and 197 deletions

View File

@@ -171,8 +171,8 @@ esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle);
/** Get received data if exist. The driver returns the ownership of the buffer to the app. /** Get received data if exist. The driver returns the ownership of the buffer to the app.
* *
* @param handle_ret Handle to the buffer holding received data. Use this handle in ``sdio_slave_recv_load_buf`` to receive in the same buffer again. * @param handle_ret Handle to the buffer holding received data. Use this handle in ``sdio_slave_recv_load_buf`` to receive in the same buffer again.
* @param start_o Start address output, set to NULL if not needed. * @param[out] out_addr Output of the start address, set to NULL if not needed.
* @param len_o Actual length of the data in the buffer, set to NULL if not needed. * @param[out] out_len Actual length of the data in the buffer, set to NULL if not needed.
* @param wait Time to wait before data received. * @param wait Time to wait before data received.
* *
* @note Call ``sdio_slave_load_buf`` with the handle to re-load the buffer onto the link list, and receive with the same buffer again. * @note Call ``sdio_slave_load_buf`` with the handle to re-load the buffer onto the link list, and receive with the same buffer again.
@@ -183,7 +183,7 @@ esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle);
* - ESP_ERR_TIMEOUT if timeout before receiving new data * - ESP_ERR_TIMEOUT if timeout before receiving new data
* - ESP_OK if success * - ESP_OK if success
*/ */
esp_err_t sdio_slave_recv(sdio_slave_buf_handle_t* handle_ret, uint8_t **start_o, size_t *len_o, TickType_t wait); esp_err_t sdio_slave_recv(sdio_slave_buf_handle_t* handle_ret, uint8_t **out_addr, size_t *out_len, TickType_t wait);
/** Retrieve the buffer corresponding to a handle. /** Retrieve the buffer corresponding to a handle.
* *
@@ -192,7 +192,7 @@ esp_err_t sdio_slave_recv(sdio_slave_buf_handle_t* handle_ret, uint8_t **start_o
* *
* @return buffer address if success, otherwise NULL. * @return buffer address if success, otherwise NULL.
*/ */
uint8_t* sdio_slave_recv_get_buf( sdio_slave_buf_handle_t handle, size_t *len_o); uint8_t* sdio_slave_recv_get_buf(sdio_slave_buf_handle_t handle, size_t *len_o);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Send * Send
@@ -277,7 +277,7 @@ void sdio_slave_set_host_intena(sdio_slave_hostint_t ena);
* - ESP_ERR_INVALID_ARG if interrupt num error * - ESP_ERR_INVALID_ARG if interrupt num error
* - ESP_OK otherwise * - ESP_OK otherwise
*/ */
esp_err_t sdio_slave_send_host_int( uint8_t pos ); esp_err_t sdio_slave_send_host_int(uint8_t pos);
/** Clear general purpose interrupt to host. /** Clear general purpose interrupt to host.
* *

View File

@@ -100,7 +100,7 @@ The driver of FIFOs works as below:
#define SDIO_SLAVE_CHECK(res, str, ret_val) do { if(!(res)){\ #define SDIO_SLAVE_CHECK(res, str, ret_val) do { if(!(res)){\
SDIO_SLAVE_LOGE( "%s", str);\ SDIO_SLAVE_LOGE("%s", str);\
return ret_val;\ return ret_val;\
} }while (0) } }while (0)
@@ -141,8 +141,8 @@ typedef struct buf_desc_s{
void* arg; /* to hold some parameters */ void* arg; /* to hold some parameters */
} buf_desc_t; } buf_desc_t;
typedef STAILQ_HEAD( bufdesc_stailq_head_s, buf_desc_s ) buf_stailq_t; typedef STAILQ_HEAD(bufdesc_stailq_head_s, buf_desc_s) buf_stailq_t;
typedef TAILQ_HEAD( bufdesc_tailq_head_s, buf_desc_s ) buf_tailq_t; typedef TAILQ_HEAD(bufdesc_tailq_head_s, buf_desc_s) buf_tailq_t;
typedef struct { typedef struct {
uint8_t* data; uint8_t* data;
@@ -155,7 +155,7 @@ typedef struct {
SemaphoreHandle_t remain_cnt; SemaphoreHandle_t remain_cnt;
} sdio_ringbuf_t; } sdio_ringbuf_t;
#define offset_of(type, field) ( (unsigned int)&(((type *)(0))->field) ) #define offset_of(type, field) ((unsigned int)&(((type *)(0))->field))
typedef enum { typedef enum {
ringbuf_write_ptr = offset_of(sdio_ringbuf_t, write_ptr), ringbuf_write_ptr = offset_of(sdio_ringbuf_t, write_ptr),
ringbuf_read_ptr = offset_of(sdio_ringbuf_t, read_ptr), ringbuf_read_ptr = offset_of(sdio_ringbuf_t, read_ptr),
@@ -236,15 +236,15 @@ typedef enum {
static void sdio_ringbuf_deinit(sdio_ringbuf_t* buf) static void sdio_ringbuf_deinit(sdio_ringbuf_t* buf)
{ {
if ( buf->remain_cnt != NULL ) vSemaphoreDelete( buf->remain_cnt ); if (buf->remain_cnt != NULL) vSemaphoreDelete(buf->remain_cnt);
if ( buf->data != NULL ) free(buf->data); if (buf->data != NULL) free(buf->data);
*buf = SDIO_RINGBUF_INITIALIZER(); *buf = SDIO_RINGBUF_INITIALIZER();
} }
static esp_err_t sdio_ringbuf_init(sdio_ringbuf_t* buf, int item_size, int item_cnt) static esp_err_t sdio_ringbuf_init(sdio_ringbuf_t* buf, int item_size, int item_cnt)
{ {
if (buf->data != NULL ) { if (buf->data != NULL) {
SDIO_SLAVE_LOGE( "sdio_ringbuf_init: already initialized"); SDIO_SLAVE_LOGE("sdio_ringbuf_init: already initialized");
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
} }
buf->item_size = item_size; buf->item_size = item_size;
@@ -252,9 +252,9 @@ static esp_err_t sdio_ringbuf_init(sdio_ringbuf_t* buf, int item_size, int item_
buf->size = item_size * (item_cnt+1); buf->size = item_size * (item_cnt+1);
//apply for resources //apply for resources
buf->data = (uint8_t*)malloc(buf->size); buf->data = (uint8_t*)malloc(buf->size);
if ( buf->data == NULL ) goto no_mem; if (buf->data == NULL) goto no_mem;
buf->remain_cnt = xSemaphoreCreateCounting( item_cnt, item_cnt ); buf->remain_cnt = xSemaphoreCreateCounting(item_cnt, item_cnt);
if ( buf->remain_cnt == NULL ) goto no_mem; if (buf->remain_cnt == NULL) goto no_mem;
//initialize pointers //initialize pointers
buf->write_ptr = buf->data; buf->write_ptr = buf->data;
buf->read_ptr = buf->data; buf->read_ptr = buf->data;
@@ -266,7 +266,7 @@ no_mem:
} }
//calculate a pointer with offset to a original pointer of the specific ringbuffer //calculate a pointer with offset to a original pointer of the specific ringbuffer
static inline uint8_t* sdio_ringbuf_offset_ptr( sdio_ringbuf_t *buf, sdio_ringbuf_pointer_t ptr, uint32_t offset ) static inline uint8_t* sdio_ringbuf_offset_ptr(sdio_ringbuf_t *buf, sdio_ringbuf_pointer_t ptr, uint32_t offset)
{ {
uint8_t *buf_ptr = (uint8_t*)*(uint32_t*)(((uint8_t*)buf)+ptr); //get the specific pointer of the buffer uint8_t *buf_ptr = (uint8_t*)*(uint32_t*)(((uint8_t*)buf)+ptr); //get the specific pointer of the buffer
uint8_t *offset_ptr=buf_ptr+offset; uint8_t *offset_ptr=buf_ptr+offset;
@@ -274,21 +274,21 @@ static inline uint8_t* sdio_ringbuf_offset_ptr( sdio_ringbuf_t *buf, sdio_ringbu
return offset_ptr; return offset_ptr;
} }
static esp_err_t sdio_ringbuf_send( sdio_ringbuf_t* buf, esp_err_t (*copy_callback)(uint8_t*, void*), void* arg, TickType_t wait ) static esp_err_t sdio_ringbuf_send(sdio_ringbuf_t* buf, esp_err_t (*copy_callback)(uint8_t*, void*), void* arg, TickType_t wait)
{ {
portBASE_TYPE ret = xSemaphoreTake(buf->remain_cnt, wait); portBASE_TYPE ret = xSemaphoreTake(buf->remain_cnt, wait);
if ( ret != pdTRUE ) return NULL; if (ret != pdTRUE) return NULL;
portENTER_CRITICAL( &buf->write_spinlock ); portENTER_CRITICAL(&buf->write_spinlock);
uint8_t* get_ptr = sdio_ringbuf_offset_ptr( buf, ringbuf_write_ptr, buf->item_size ); uint8_t* get_ptr = sdio_ringbuf_offset_ptr(buf, ringbuf_write_ptr, buf->item_size);
esp_err_t err = ESP_OK; esp_err_t err = ESP_OK;
if (copy_callback) (*copy_callback)(get_ptr, arg); if (copy_callback) (*copy_callback)(get_ptr, arg);
if ( err != ESP_OK ) { if (err != ESP_OK) {
portEXIT_CRITICAL( &buf->write_spinlock ); portEXIT_CRITICAL(&buf->write_spinlock);
return err; return err;
} }
buf->write_ptr = get_ptr; buf->write_ptr = get_ptr;
portEXIT_CRITICAL( &buf->write_spinlock ); portEXIT_CRITICAL(&buf->write_spinlock);
return ESP_OK; return ESP_OK;
} }
@@ -296,65 +296,65 @@ static esp_err_t sdio_ringbuf_send( sdio_ringbuf_t* buf, esp_err_t (*copy_callba
// since this is designed to be called in the ISR, no parallel logic // since this is designed to be called in the ISR, no parallel logic
static inline esp_err_t sdio_ringbuf_recv(sdio_ringbuf_t* buf, uint8_t **start, uint8_t **end, ringbuf_get_all_t get_all, TickType_t wait) static inline esp_err_t sdio_ringbuf_recv(sdio_ringbuf_t* buf, uint8_t **start, uint8_t **end, ringbuf_get_all_t get_all, TickType_t wait)
{ {
assert( buf->free_ptr == buf->read_ptr ); //must return before recv again assert(buf->free_ptr == buf->read_ptr); //must return before recv again
assert(wait == 0); //only implement wait = 0 case now assert(wait == 0); //only implement wait = 0 case now
if ( start == NULL && end == NULL ) return ESP_ERR_INVALID_ARG; // must have a output if (start == NULL && end == NULL) return ESP_ERR_INVALID_ARG; // must have a output
if ( buf->read_ptr == buf->write_ptr ) return ESP_ERR_NOT_FOUND; // no data if (buf->read_ptr == buf->write_ptr) return ESP_ERR_NOT_FOUND; // no data
uint8_t *get_start = sdio_ringbuf_offset_ptr(buf, ringbuf_read_ptr, buf->item_size); uint8_t *get_start = sdio_ringbuf_offset_ptr(buf, ringbuf_read_ptr, buf->item_size);
if ( get_all != RINGBUF_GET_ONE ) { if (get_all != RINGBUF_GET_ONE) {
buf->read_ptr = buf->write_ptr; buf->read_ptr = buf->write_ptr;
} else { } else {
buf->read_ptr = get_start; buf->read_ptr = get_start;
} }
if ( start != NULL ) *start = get_start; if (start != NULL) *start = get_start;
if ( end != NULL ) *end = buf->read_ptr; if (end != NULL) *end = buf->read_ptr;
return ESP_OK; return ESP_OK;
} }
static inline void sdio_ringbuf_return_from_isr(sdio_ringbuf_t* buf, uint8_t *ptr, portBASE_TYPE *yield) static inline void sdio_ringbuf_return_from_isr(sdio_ringbuf_t* buf, uint8_t *ptr, portBASE_TYPE *yield)
{ {
assert( sdio_ringbuf_offset_ptr(buf, ringbuf_free_ptr, buf->item_size) == ptr ); assert(sdio_ringbuf_offset_ptr(buf, ringbuf_free_ptr, buf->item_size) == ptr);
int size = (buf->read_ptr + buf->size - buf->free_ptr)%buf->size; int size = (buf->read_ptr + buf->size - buf->free_ptr)%buf->size;
int count = size/buf->item_size; int count = size/buf->item_size;
assert( count*buf->item_size==size); assert(count*buf->item_size==size);
buf->free_ptr = buf->read_ptr; buf->free_ptr = buf->read_ptr;
for( int i = 0; i < count; i ++ ) { for(int i = 0; i < count; i++) {
portBASE_TYPE ret = xSemaphoreGiveFromISR( buf->remain_cnt, yield ); portBASE_TYPE ret = xSemaphoreGiveFromISR(buf->remain_cnt, yield);
assert( ret == pdTRUE ); assert(ret == pdTRUE);
} }
} }
static inline void sdio_ringbuf_return(sdio_ringbuf_t* buf, uint8_t *ptr) static inline void sdio_ringbuf_return(sdio_ringbuf_t* buf, uint8_t *ptr)
{ {
assert( sdio_ringbuf_offset_ptr(buf, ringbuf_free_ptr, buf->item_size) == ptr ); assert(sdio_ringbuf_offset_ptr(buf, ringbuf_free_ptr, buf->item_size) == ptr);
int size = (buf->read_ptr + buf->size - buf->free_ptr)%buf->size; int size = (buf->read_ptr + buf->size - buf->free_ptr)%buf->size;
int count = size/buf->item_size; int count = size/buf->item_size;
assert( count*buf->item_size==size); assert(count*buf->item_size==size);
buf->free_ptr = buf->read_ptr; buf->free_ptr = buf->read_ptr;
for( int i = 0; i < count; i ++ ) { for(int i = 0; i < count; i++) {
portBASE_TYPE ret = xSemaphoreGive( buf->remain_cnt ); portBASE_TYPE ret = xSemaphoreGive(buf->remain_cnt);
assert( ret == pdTRUE ); assert(ret == pdTRUE);
} }
} }
static inline uint8_t* sdio_ringbuf_peek_front(sdio_ringbuf_t* buf) static inline uint8_t* sdio_ringbuf_peek_front(sdio_ringbuf_t* buf)
{ {
if ( buf->read_ptr != buf->write_ptr ) { if (buf->read_ptr != buf->write_ptr) {
return sdio_ringbuf_offset_ptr(buf, ringbuf_read_ptr, buf->item_size); return sdio_ringbuf_offset_ptr(buf, ringbuf_read_ptr, buf->item_size);
} else { } else {
return NULL; return NULL;
} }
} }
static inline uint8_t* sdio_ringbuf_peek_rear( sdio_ringbuf_t *buf ) static inline uint8_t* sdio_ringbuf_peek_rear(sdio_ringbuf_t *buf)
{ {
return buf->write_ptr; return buf->write_ptr;
} }
static inline bool sdio_ringbuf_empty( sdio_ringbuf_t* buf ) static inline bool sdio_ringbuf_empty(sdio_ringbuf_t* buf)
{ {
return (buf->read_ptr == buf->write_ptr? true : false); return (buf->read_ptr == buf->write_ptr? true : false);
} }
@@ -362,15 +362,15 @@ static inline bool sdio_ringbuf_empty( sdio_ringbuf_t* buf )
static inline void show_ll(buf_desc_t *item) static inline void show_ll(buf_desc_t *item)
{ {
ESP_EARLY_LOGD( TAG, "=> %p: size: %d(%d), eof: %d, owner: %d", item, item->size, item->length, item->eof, item->owner ); ESP_EARLY_LOGD(TAG, "=> %p: size: %d(%d), eof: %d, owner: %d", item, item->size, item->length, item->eof, item->owner);
ESP_EARLY_LOGD( TAG, " buf: %p, stqe_next: %p, tqe-prev: %p", item->buf, item->qe.stqe_next, item->te.tqe_prev ); ESP_EARLY_LOGD(TAG, " buf: %p, stqe_next: %p, tqe-prev: %p", item->buf, item->qe.stqe_next, item->te.tqe_prev);
} }
static void __attribute((unused)) dump_ll(buf_stailq_t *queue) static void __attribute((unused)) dump_ll(buf_stailq_t *queue)
{ {
buf_desc_t *item = NULL; buf_desc_t *item = NULL;
ESP_EARLY_LOGD( TAG, ">>>>> first: %p, last: %p <<<<<", queue->stqh_first, queue->stqh_last ); ESP_EARLY_LOGD(TAG, ">>>>> first: %p, last: %p <<<<<", queue->stqh_first, queue->stqh_last);
STAILQ_FOREACH( item, queue, qe ) { STAILQ_FOREACH(item, queue, qe) {
show_ll(item); show_ll(item);
} }
} }
@@ -378,17 +378,17 @@ static void __attribute((unused)) dump_ll(buf_stailq_t *queue)
static inline void deinit_context() static inline void deinit_context()
{ {
context.config = (sdio_slave_config_t){}; context.config = (sdio_slave_config_t){};
for( int i = 0; i < 9; i ++ ) { for(int i = 0; i < 9; i++) {
if ( context.events[i] != NULL ) { if (context.events[i] != NULL) {
vSemaphoreDelete(context.events[i]); vSemaphoreDelete(context.events[i]);
context.events[i] = NULL; context.events[i] = NULL;
} }
} }
if ( context.ret_queue != NULL ) { if (context.ret_queue != NULL) {
vQueueDelete(context.ret_queue); vQueueDelete(context.ret_queue);
context.ret_queue = NULL; context.ret_queue = NULL;
} }
sdio_ringbuf_deinit( &context.sendbuf ); sdio_ringbuf_deinit(&context.sendbuf);
} }
esp_err_t link_desc_to_last(uint8_t* desc, void* arg) esp_err_t link_desc_to_last(uint8_t* desc, void* arg)
@@ -399,58 +399,58 @@ esp_err_t link_desc_to_last(uint8_t* desc, void* arg)
static esp_err_t init_ringbuf() static esp_err_t init_ringbuf()
{ {
esp_err_t ret = sdio_ringbuf_init( &context.sendbuf, sizeof(buf_desc_t), context.config.send_queue_size ); esp_err_t ret = sdio_ringbuf_init(&context.sendbuf, sizeof(buf_desc_t), context.config.send_queue_size);
if ( ret != ESP_OK ) return ret; if (ret != ESP_OK) return ret;
esp_err_t rcv_res; esp_err_t rcv_res;
buf_desc_t *first=NULL, *last=NULL; buf_desc_t *first=NULL, *last=NULL;
//no copy for the first descriptor //no copy for the first descriptor
ret = sdio_ringbuf_send( &context.sendbuf, NULL, NULL, portMAX_DELAY); ret = sdio_ringbuf_send(&context.sendbuf, NULL, NULL, portMAX_DELAY);
if ( ret != ESP_OK ) return ret; if (ret != ESP_OK) return ret;
//loop in the ringbuf to link all the desc one after another as a ring //loop in the ringbuf to link all the desc one after another as a ring
for ( int i = 0; i < context.config.send_queue_size+1; i++ ) { for (int i = 0; i < context.config.send_queue_size+1; i++) {
rcv_res = sdio_ringbuf_recv( &context.sendbuf, (uint8_t**)&last, NULL, RINGBUF_GET_ONE, 0 ); rcv_res = sdio_ringbuf_recv(&context.sendbuf, (uint8_t**)&last, NULL, RINGBUF_GET_ONE, 0);
assert ( rcv_res == ESP_OK ); assert (rcv_res == ESP_OK);
ret = sdio_ringbuf_send( &context.sendbuf, link_desc_to_last, last, portMAX_DELAY); ret = sdio_ringbuf_send(&context.sendbuf, link_desc_to_last, last, portMAX_DELAY);
if ( ret != ESP_OK ) return ret; if (ret != ESP_OK) return ret;
sdio_ringbuf_return(&context.sendbuf, (uint8_t*)last); sdio_ringbuf_return(&context.sendbuf, (uint8_t*)last);
} }
first = NULL; first = NULL;
last = NULL; last = NULL;
//clear the queue //clear the queue
rcv_res = sdio_ringbuf_recv( &context.sendbuf, (uint8_t**)&first, (uint8_t**)&last, RINGBUF_GET_ALL, 0 ); rcv_res = sdio_ringbuf_recv(&context.sendbuf, (uint8_t**)&first, (uint8_t**)&last, RINGBUF_GET_ALL, 0);
assert ( rcv_res == ESP_OK ); assert (rcv_res == ESP_OK);
assert( first == last ); //there should be only one desc remain assert(first == last); //there should be only one desc remain
sdio_ringbuf_return(&context.sendbuf, (uint8_t*)first ); sdio_ringbuf_return(&context.sendbuf, (uint8_t*)first);
return ESP_OK; return ESP_OK;
} }
static esp_err_t init_context(sdio_slave_config_t *config) static esp_err_t init_context(sdio_slave_config_t *config)
{ {
SDIO_SLAVE_CHECK( *(uint32_t*)&context.config == 0, "sdio slave already initialized", ESP_ERR_INVALID_STATE ); SDIO_SLAVE_CHECK(*(uint32_t*)&context.config == 0, "sdio slave already initialized", ESP_ERR_INVALID_STATE);
context.config = *config; context.config = *config;
// in theory we can queue infinite buffers in the linked list, but for multi-core reason we have to use a queue to // in theory we can queue infinite buffers in the linked list, but for multi-core reason we have to use a queue to
// count the finished buffers. // count the finished buffers.
context.recv_event = xSemaphoreCreateCounting(UINT32_MAX, 0 ); context.recv_event = xSemaphoreCreateCounting(UINT32_MAX, 0);
for( int i = 0; i < 9; i ++ ) { for(int i = 0; i < 9; i++) {
if ( i < 8 ) { if (i < 8) {
context.events[i] = xSemaphoreCreateBinary(); context.events[i] = xSemaphoreCreateBinary();
} //for 8, already created. } //for 8, already created.
if ( context.events[i] == NULL ) { if (context.events[i] == NULL) {
SDIO_SLAVE_LOGE( "event initialize failed"); SDIO_SLAVE_LOGE("event initialize failed");
goto no_mem; goto no_mem;
} }
} }
esp_err_t ret = init_ringbuf(); esp_err_t ret = init_ringbuf();
if ( ret != ESP_OK ) goto no_mem; if (ret != ESP_OK) goto no_mem;
context.ret_queue = xQueueCreate( config->send_queue_size, sizeof(void*) ); context.ret_queue = xQueueCreate(config->send_queue_size, sizeof(void*));
if ( context.ret_queue == NULL ) goto no_mem; if (context.ret_queue == NULL) goto no_mem;
context.recv_link_list = (buf_stailq_t)STAILQ_HEAD_INITIALIZER(context.recv_link_list); context.recv_link_list = (buf_stailq_t)STAILQ_HEAD_INITIALIZER(context.recv_link_list);
context.recv_reg_list = (buf_tailq_t)TAILQ_HEAD_INITIALIZER(context.recv_reg_list); context.recv_reg_list = (buf_tailq_t)TAILQ_HEAD_INITIALIZER(context.recv_reg_list);
@@ -514,7 +514,7 @@ static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config)
SLC.rx_dscr_conf.slc0_token_no_replace = 1; SLC.rx_dscr_conf.slc0_token_no_replace = 1;
HINF.cfg_data1.highspeed_enable = 1; HINF.cfg_data1.highspeed_enable = 1;
switch( config->timing ) { switch(config->timing) {
case SDIO_SLAVE_TIMING_PSEND_PSAMPLE: case SDIO_SLAVE_TIMING_PSEND_PSAMPLE:
HOST.conf.frc_sdio20 = 0xf; HOST.conf.frc_sdio20 = 0xf;
HOST.conf.frc_sdio11 = 0; HOST.conf.frc_sdio11 = 0;
@@ -559,12 +559,12 @@ esp_err_t sdio_slave_initialize(sdio_slave_config_t *config)
intr_handle_t intr_handle = NULL; intr_handle_t intr_handle = NULL;
const int flags = 0; const int flags = 0;
r = esp_intr_alloc(ETS_SLC0_INTR_SOURCE, flags, sdio_intr, NULL, &intr_handle); r = esp_intr_alloc(ETS_SLC0_INTR_SOURCE, flags, sdio_intr, NULL, &intr_handle);
if (r != ESP_OK ) return r; if (r != ESP_OK) return r;
r = sdio_slave_hw_init(config); r = sdio_slave_hw_init(config);
if ( r != ESP_OK ) return r; if (r != ESP_OK) return r;
r = init_context(config); r = init_context(config);
if ( r != ESP_OK ) return r; if (r != ESP_OK) return r;
context.intr_handle = intr_handle; context.intr_handle = intr_handle;
sdio_slave_reset(); sdio_slave_reset();
@@ -584,9 +584,9 @@ esp_err_t sdio_slave_start()
esp_err_t ret; esp_err_t ret;
HOST.slc0_int_clr.val = UINT32_MAX;//clear all interrupts HOST.slc0_int_clr.val = UINT32_MAX;//clear all interrupts
ret = send_start(); ret = send_start();
if ( ret != ESP_OK ) return ret; if (ret != ESP_OK) return ret;
ret = recv_start(); ret = recv_start();
if ( ret != ESP_OK ) return ret; if (ret != ESP_OK) return ret;
HINF.cfg_data1.sdio_ioready1 = 1; //set IO ready to 1 to allow host to use HINF.cfg_data1.sdio_ioready1 = 1; //set IO ready to 1 to allow host to use
return ESP_OK; return ESP_OK;
} }
@@ -616,11 +616,11 @@ static void sdio_intr(void* arg)
{ {
uint32_t int_val = SLC.slc0_int_st.val; uint32_t int_val = SLC.slc0_int_st.val;
uint32_t int_raw = SLC.slc0_int_raw.val; uint32_t int_raw = SLC.slc0_int_raw.val;
ESP_EARLY_LOGV( TAG, "sdio_intr: %08X(%08X)", int_val, int_raw ); ESP_EARLY_LOGV(TAG, "sdio_intr: %08X(%08X)", int_val, int_raw);
if ( int_val & SDIO_SLAVE_SLC_INT_RX_MASK ) sdio_intr_send(arg); if (int_val & SDIO_SLAVE_SLC_INT_RX_MASK) sdio_intr_send(arg);
if ( int_val & SDIO_SLAVE_SLC_INT_TX_MASK ) sdio_intr_recv(arg); if (int_val & SDIO_SLAVE_SLC_INT_TX_MASK) sdio_intr_recv(arg);
if ( int_val & SDIO_SLAVE_SLC_INT_HOST_MASK ) sdio_intr_host(arg); if (int_val & SDIO_SLAVE_SLC_INT_HOST_MASK) sdio_intr_host(arg);
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
@@ -632,47 +632,47 @@ static void sdio_intr_host(void* arg)
portBASE_TYPE yield = pdFALSE; portBASE_TYPE yield = pdFALSE;
SLC.slc0_int_clr.val = int_val; SLC.slc0_int_clr.val = int_val;
for( int i = 0; i < 8; i ++ ) { for(int i = 0; i < 8; i++) {
if ( BIT(i) & int_val ) { if (BIT(i) & int_val) {
if ( context.config.event_cb != NULL ) (*context.config.event_cb)(i); if (context.config.event_cb != NULL) (*context.config.event_cb)(i);
xSemaphoreGiveFromISR( context.events[i], &yield ); xSemaphoreGiveFromISR(context.events[i], &yield);
} }
} }
if ( yield ) portYIELD_FROM_ISR(); if (yield) portYIELD_FROM_ISR();
} }
esp_err_t sdio_slave_wait_int(int pos, TickType_t wait) esp_err_t sdio_slave_wait_int(int pos, TickType_t wait)
{ {
SDIO_SLAVE_CHECK( pos >= 0 && pos < 8, "interrupt num invalid", ESP_ERR_INVALID_ARG); SDIO_SLAVE_CHECK(pos >= 0 && pos < 8, "interrupt num invalid", ESP_ERR_INVALID_ARG);
return xSemaphoreTake( context.events[pos], wait ); return xSemaphoreTake(context.events[pos], wait);
} }
uint8_t sdio_slave_read_reg(int pos) uint8_t sdio_slave_read_reg(int pos)
{ {
if ( pos >= 28 && pos <= 31 ) SDIO_SLAVE_LOGW( "%s: interrupt reg, for reference", __FUNCTION__ ); if (pos >= 28 && pos <= 31) SDIO_SLAVE_LOGW("%s: interrupt reg, for reference", __FUNCTION__);
if ( pos < 0 || pos >= 64 ) SDIO_SLAVE_LOGE( "read register address wrong"); if (pos < 0 || pos >= 64) SDIO_SLAVE_LOGE("read register address wrong");
return *(uint8_t*)(HOST_SLCHOST_CONF_W_REG(pos)); return *(uint8_t*)(HOST_SLCHOST_CONF_W_REG(pos));
} }
esp_err_t sdio_slave_write_reg(int pos, uint8_t reg) esp_err_t sdio_slave_write_reg(int pos, uint8_t reg)
{ {
if ( pos >= 28 && pos <= 31 ) { if (pos >= 28 && pos <= 31) {
SDIO_SLAVE_LOGE( "interrupt reg, please use sdio_slave_clear_int" ); SDIO_SLAVE_LOGE("interrupt reg, please use sdio_slave_clear_int");
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
if ( pos < 0 || pos >= 64 ) { if (pos < 0 || pos >= 64) {
SDIO_SLAVE_LOGE( "write register address wrong"); SDIO_SLAVE_LOGE("write register address wrong");
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
uint32_t addr = HOST_SLCHOST_CONF_W_REG(pos) & (~3); uint32_t addr = HOST_SLCHOST_CONF_W_REG(pos) & (~3);
uint32_t shift = (pos % 4)*8; uint32_t shift = (pos % 4)*8;
portENTER_CRITICAL( &context.reg_spinlock ); portENTER_CRITICAL(&context.reg_spinlock);
int val = *(uint32_t*)addr; int val = *(uint32_t*)addr;
*(uint32_t*)addr = (val & ~(0xff << shift)) | (reg<<shift); *(uint32_t*)addr = (val & ~(0xff << shift)) | (reg<<shift);
portEXIT_CRITICAL( &context.reg_spinlock ); portEXIT_CRITICAL(&context.reg_spinlock);
return ESP_OK; return ESP_OK;
} }
@@ -691,9 +691,9 @@ void sdio_slave_clear_host_int(uint8_t mask)
SLC.intvec_tohost.slc0_intvec = mask; SLC.intvec_tohost.slc0_intvec = mask;
} }
esp_err_t sdio_slave_send_host_int( uint8_t pos ) esp_err_t sdio_slave_send_host_int(uint8_t pos)
{ {
SDIO_SLAVE_CHECK( pos < 8, "interrupt num invalid", ESP_ERR_INVALID_ARG ); SDIO_SLAVE_CHECK(pos < 8, "interrupt num invalid", ESP_ERR_INVALID_ARG);
SLC.intvec_tohost.slc0_intvec = BIT(pos); SLC.intvec_tohost.slc0_intvec = BIT(pos);
return ESP_OK; return ESP_OK;
} }
@@ -709,8 +709,8 @@ esp_err_t sdio_slave_send_host_int( uint8_t pos )
*/ */
static inline void send_length_write(uint32_t len) static inline void send_length_write(uint32_t len)
{ {
SLC.slc0_len_conf.val = FIELD_TO_VALUE2( SLC_SLC0_LEN_WDATA, len ) | FIELD_TO_VALUE2( SLC_SLC0_LEN_WR, 1 ); SLC.slc0_len_conf.val = FIELD_TO_VALUE2(SLC_SLC0_LEN_WDATA, len) | FIELD_TO_VALUE2(SLC_SLC0_LEN_WR, 1);
ESP_EARLY_LOGV(TAG, "send_length_write: %d, last_len: %08X", len, HOST.pkt_len.reg_slc0_len ); ESP_EARLY_LOGV(TAG, "send_length_write: %d, last_len: %08X", len, HOST.pkt_len.reg_slc0_len);
} }
static inline void send_start_transmission(const void* desc) static inline void send_start_transmission(const void* desc)
@@ -743,9 +743,9 @@ DMA_ATTR static const buf_desc_t start_desc = {
static inline void send_isr_invoker_enable() static inline void send_isr_invoker_enable()
{ {
//force trigger rx_done interrupt. the interrupt is abused to invoke ISR from the app by the enable bit and never cleared. //force trigger rx_done interrupt. the interrupt is abused to invoke ISR from the app by the enable bit and never cleared.
send_start_transmission( &start_desc ); send_start_transmission(&start_desc);
//wait for rx_done //wait for rx_done
while( !SLC.slc0_int_raw.rx_done ); while(!SLC.slc0_int_raw.rx_done);
HOST.slc0_int_clr.rx_new_packet = 1; HOST.slc0_int_clr.rx_new_packet = 1;
send_stop_ll_operation(); send_stop_ll_operation();
} }
@@ -785,10 +785,10 @@ static inline void send_set_state(send_state_t state)
//start hw operation with existing data (if exist) //start hw operation with existing data (if exist)
static esp_err_t send_start() static esp_err_t send_start()
{ {
SDIO_SLAVE_CHECK( send_get_state() == STATE_IDLE, SDIO_SLAVE_CHECK(send_get_state() == STATE_IDLE,
"already started", ESP_ERR_INVALID_STATE ); "already started", ESP_ERR_INVALID_STATE);
SLC.slc0_int_clr.rx_eof = 1; SLC.slc0_int_clr.rx_eof = 1;
send_set_state( STATE_WAIT_FOR_START ); send_set_state(STATE_WAIT_FOR_START);
send_intr_enable(); send_intr_enable();
return ESP_OK; return ESP_OK;
} }
@@ -799,7 +799,7 @@ static void send_stop()
SLC.slc0_rx_link.stop = 1; SLC.slc0_rx_link.stop = 1;
send_intr_disable(); send_intr_disable();
send_set_state( STATE_IDLE ); send_set_state(STATE_IDLE);
} }
static inline esp_err_t send_isr_eof(portBASE_TYPE *yield) static inline esp_err_t send_isr_eof(portBASE_TYPE *yield)
@@ -807,21 +807,21 @@ static inline esp_err_t send_isr_eof(portBASE_TYPE *yield)
// inform app to recycle descs // inform app to recycle descs
portBASE_TYPE ret = pdTRUE; portBASE_TYPE ret = pdTRUE;
buf_desc_t *desc = context.in_flight; buf_desc_t *desc = context.in_flight;
assert( desc != NULL ); assert(desc != NULL);
do { do {
ESP_EARLY_LOGV(TAG, "end: %x", desc->arg); ESP_EARLY_LOGV(TAG, "end: %x", desc->arg);
ret = xQueueSendFromISR( context.ret_queue, &desc->arg, yield ); ret = xQueueSendFromISR(context.ret_queue, &desc->arg, yield);
assert(ret == pdTRUE); assert(ret == pdTRUE);
buf_desc_t* next = STAILQ_NEXT(desc, qe); buf_desc_t* next = STAILQ_NEXT(desc, qe);
desc = next; desc = next;
} while(desc!=NULL); } while(desc!=NULL);
STAILQ_NEXT( context.in_flight_end, qe ) = context.in_flight_next; STAILQ_NEXT(context.in_flight_end, qe) = context.in_flight_next;
sdio_ringbuf_return_from_isr(&context.sendbuf, (uint8_t*)context.in_flight, yield); sdio_ringbuf_return_from_isr(&context.sendbuf, (uint8_t*)context.in_flight, yield);
context.in_flight = NULL; context.in_flight = NULL;
context.in_flight_end = NULL; context.in_flight_end = NULL;
// Go to wait for packet state // Go to wait for packet state
send_set_state( STATE_WAIT_FOR_START ); send_set_state(STATE_WAIT_FOR_START);
return ESP_OK; return ESP_OK;
} }
@@ -830,12 +830,12 @@ static inline esp_err_t send_isr_check_new_pkt(portBASE_TYPE *yield)
esp_err_t ret; esp_err_t ret;
buf_desc_t *start = NULL; buf_desc_t *start = NULL;
buf_desc_t *end = NULL; buf_desc_t *end = NULL;
if ( context.config.sending_mode == SDIO_SLAVE_SEND_PACKET ) { if (context.config.sending_mode == SDIO_SLAVE_SEND_PACKET) {
ret = sdio_ringbuf_recv( &context.sendbuf, (uint8_t**)&start, (uint8_t**)&end, RINGBUF_GET_ONE, 0); ret = sdio_ringbuf_recv(&context.sendbuf, (uint8_t**)&start, (uint8_t**)&end, RINGBUF_GET_ONE, 0);
} else { //stream mode } else { //stream mode
ret = sdio_ringbuf_recv( &context.sendbuf, (uint8_t**)&start, (uint8_t**)&end, RINGBUF_GET_ALL, 0); ret = sdio_ringbuf_recv(&context.sendbuf, (uint8_t**)&start, (uint8_t**)&end, RINGBUF_GET_ALL, 0);
} }
if ( ret == ESP_OK ) { if (ret == ESP_OK) {
context.in_flight = start; context.in_flight = start;
context.in_flight_end = end; context.in_flight_end = end;
end->eof = 1; end->eof = 1;
@@ -855,12 +855,12 @@ static inline esp_err_t send_isr_new_packet()
assert(start_desc != NULL && end_desc != NULL); assert(start_desc != NULL && end_desc != NULL);
send_stop_ll_operation(); send_stop_ll_operation();
send_start_transmission( start_desc ); send_start_transmission(start_desc);
// update pkt_len register to allow host reading. // update pkt_len register to allow host reading.
send_length_write( end_desc->pkt_len ); send_length_write(end_desc->pkt_len);
send_set_state( STATE_SENDING ); send_set_state(STATE_SENDING);
ESP_EARLY_LOGD(TAG, "restart new send: %p->%p, pkt_len: %d", start_desc, end_desc, end_desc->pkt_len); ESP_EARLY_LOGD(TAG, "restart new send: %p->%p, pkt_len: %d", start_desc, end_desc, end_desc->pkt_len);
return ESP_OK; return ESP_OK;
@@ -872,26 +872,26 @@ static void sdio_intr_send(void* arg)
portBASE_TYPE yield = pdFALSE; portBASE_TYPE yield = pdFALSE;
// this interrupt is abused to get ISR invoked by app // this interrupt is abused to get ISR invoked by app
if ( SLC.slc0_int_st.rx_done ) SLC.slc0_int_ena.rx_done = 0; if (SLC.slc0_int_st.rx_done) SLC.slc0_int_ena.rx_done = 0;
// Goto idle state (cur_start=NULL) if transmission done, // Goto idle state (cur_start=NULL) if transmission done,
// also update sequence and recycle descs. // also update sequence and recycle descs.
if ( SLC.slc0_int_st.rx_eof ) { if (SLC.slc0_int_st.rx_eof) {
SLC.slc0_int_clr.rx_eof = 1; SLC.slc0_int_clr.rx_eof = 1;
//check current state //check current state
assert( send_get_state() == STATE_SENDING );// context.send_start != NOT_YET && context.send_end != NOT_YET ); assert(send_get_state() == STATE_SENDING);// context.send_start != NOT_YET && context.send_end != NOT_YET);
send_isr_eof(&yield); send_isr_eof(&yield);
} }
// Go to wait sending state (cur_start!=NULL && cur_end==NULL) if not sending and new packet ready. // Go to wait sending state (cur_start!=NULL && cur_end==NULL) if not sending and new packet ready.
// Note we may also enter this state by stopping sending in the app. // Note we may also enter this state by stopping sending in the app.
if ( send_get_state() == STATE_WAIT_FOR_START ) { if (send_get_state() == STATE_WAIT_FOR_START) {
if ( context.in_flight == NULL ) send_isr_check_new_pkt(&yield); if (context.in_flight == NULL) send_isr_check_new_pkt(&yield);
// Go to sending state (cur_start and cur_end != NULL) if has packet to send. // Go to sending state (cur_start and cur_end != NULL) if has packet to send.
if ( context.in_flight ) send_isr_new_packet(); if (context.in_flight) send_isr_new_packet();
} }
if ( yield ) portYIELD_FROM_ISR(); if (yield) portYIELD_FROM_ISR();
} }
esp_err_t send_write_desc(uint8_t* desc, void* arg) esp_err_t send_write_desc(uint8_t* desc, void* arg)
@@ -902,14 +902,14 @@ esp_err_t send_write_desc(uint8_t* desc, void* arg)
//copy and keep the link //copy and keep the link
STAILQ_NEXT(new_desc, qe) = STAILQ_NEXT((buf_desc_t*)desc, qe); STAILQ_NEXT(new_desc, qe) = STAILQ_NEXT((buf_desc_t*)desc, qe);
memcpy( desc, new_desc, sizeof(buf_desc_t) ); memcpy(desc, new_desc, sizeof(buf_desc_t));
return ESP_OK; return ESP_OK;
} }
esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t wait) esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t wait)
{ {
SDIO_SLAVE_CHECK( len > 0, "len <= 0", ESP_ERR_INVALID_ARG ); SDIO_SLAVE_CHECK(len > 0, "len <= 0", ESP_ERR_INVALID_ARG);
SDIO_SLAVE_CHECK( esp_ptr_dma_capable(addr) && (uint32_t)addr%4==0, "buffer to send should be DMA capable and 32-bit aligned", SDIO_SLAVE_CHECK(esp_ptr_dma_capable(addr) && (uint32_t)addr%4==0, "buffer to send should be DMA capable and 32-bit aligned",
ESP_ERR_INVALID_ARG); ESP_ERR_INVALID_ARG);
buf_desc_t new_desc = { buf_desc_t new_desc = {
@@ -923,7 +923,7 @@ esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t
}; };
esp_err_t ret = sdio_ringbuf_send(&context.sendbuf, send_write_desc, &new_desc, wait); esp_err_t ret = sdio_ringbuf_send(&context.sendbuf, send_write_desc, &new_desc, wait);
if ( ret != ESP_OK ) return ret; if (ret != ESP_OK) return ret;
send_isr_invoke(); send_isr_invoke();
return ESP_OK; return ESP_OK;
@@ -931,8 +931,8 @@ esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t
esp_err_t sdio_slave_send_get_finished(void** arg, TickType_t wait) esp_err_t sdio_slave_send_get_finished(void** arg, TickType_t wait)
{ {
portBASE_TYPE err = xQueueReceive( context.ret_queue, arg, wait ); portBASE_TYPE err = xQueueReceive(context.ret_queue, arg, wait);
if ( err != pdTRUE ) return ESP_ERR_TIMEOUT; if (err != pdTRUE) return ESP_ERR_TIMEOUT;
return ESP_OK; return ESP_OK;
} }
@@ -941,11 +941,11 @@ esp_err_t sdio_slave_transmit(uint8_t* addr, size_t len)
uint32_t timestamp = XTHAL_GET_CCOUNT(); uint32_t timestamp = XTHAL_GET_CCOUNT();
uint32_t ret_stamp; uint32_t ret_stamp;
esp_err_t err = sdio_slave_send_queue( addr, len, (void*)timestamp, portMAX_DELAY ); esp_err_t err = sdio_slave_send_queue(addr, len, (void*)timestamp, portMAX_DELAY);
if ( err != ESP_OK ) return err; if (err != ESP_OK) return err;
err = sdio_slave_send_get_finished( (void**)&ret_stamp, portMAX_DELAY ); err = sdio_slave_send_get_finished((void**)&ret_stamp, portMAX_DELAY);
if ( err != ESP_OK ) return err; if (err != ESP_OK) return err;
SDIO_SLAVE_CHECK( ret_stamp == timestamp, "already sent without return before", ESP_ERR_INVALID_STATE); SDIO_SLAVE_CHECK(ret_stamp == timestamp, "already sent without return before", ESP_ERR_INVALID_STATE);
return ESP_OK; return ESP_OK;
} }
@@ -954,43 +954,43 @@ esp_err_t sdio_slave_transmit(uint8_t* addr, size_t len)
static esp_err_t send_flush_data() static esp_err_t send_flush_data()
{ {
//only works in idle state / wait to send state //only works in idle state / wait to send state
SDIO_SLAVE_CHECK( send_get_state() == STATE_IDLE, SDIO_SLAVE_CHECK(send_get_state() == STATE_IDLE,
"flush data when transmission started", ESP_ERR_INVALID_STATE ); "flush data when transmission started", ESP_ERR_INVALID_STATE);
HOST.slc0_int_clr.rx_new_packet = 1; HOST.slc0_int_clr.rx_new_packet = 1;
buf_desc_t *last = NULL; buf_desc_t *last = NULL;
if ( context.in_flight ) { if (context.in_flight) {
buf_desc_t *desc = context.in_flight; buf_desc_t *desc = context.in_flight;
while( desc != NULL ) { while(desc != NULL) {
xQueueSend( context.ret_queue, desc->arg, portMAX_DELAY ); xQueueSend(context.ret_queue, desc->arg, portMAX_DELAY);
last = desc; last = desc;
desc = STAILQ_NEXT(desc, qe); desc = STAILQ_NEXT(desc, qe);
} }
STAILQ_NEXT( context.in_flight_end, qe ) = context.in_flight_next; STAILQ_NEXT(context.in_flight_end, qe) = context.in_flight_next;
sdio_ringbuf_return( &context.sendbuf, (uint8_t*)context.in_flight ); sdio_ringbuf_return(&context.sendbuf, (uint8_t*)context.in_flight);
context.in_flight = NULL; context.in_flight = NULL;
context.in_flight_end = NULL; context.in_flight_end = NULL;
} }
buf_desc_t *head; buf_desc_t *head;
esp_err_t ret = sdio_ringbuf_recv(&context.sendbuf, (uint8_t**)&head, NULL, RINGBUF_GET_ALL, 0); esp_err_t ret = sdio_ringbuf_recv(&context.sendbuf, (uint8_t**)&head, NULL, RINGBUF_GET_ALL, 0);
if ( ret == ESP_OK ) { if (ret == ESP_OK) {
buf_desc_t *desc = head; buf_desc_t *desc = head;
while( desc != NULL ) { while(desc != NULL) {
xQueueSend( context.ret_queue, desc->arg, portMAX_DELAY ); xQueueSend(context.ret_queue, desc->arg, portMAX_DELAY);
last = desc; last = desc;
desc = STAILQ_NEXT(desc, qe); desc = STAILQ_NEXT(desc, qe);
} }
sdio_ringbuf_return( &context.sendbuf, (uint8_t*)head ); sdio_ringbuf_return(&context.sendbuf, (uint8_t*)head);
} }
// if in wait to send state, set the sequence number of tail to the value last sent, just as if the packet wait to // if in wait to send state, set the sequence number of tail to the value last sent, just as if the packet wait to
// send never queued. // send never queued.
// Go to idle state (cur_end!=NULL and cur_start=NULL) // Go to idle state (cur_end!=NULL and cur_start=NULL)
send_set_state( STATE_IDLE ); send_set_state(STATE_IDLE);
if ( last == NULL ) last = (buf_desc_t*)sdio_ringbuf_peek_rear(&context.sendbuf); if (last == NULL) last = (buf_desc_t*)sdio_ringbuf_peek_rear(&context.sendbuf);
last->pkt_len = send_length_read(); last->pkt_len = send_length_read();
return ESP_OK; return ESP_OK;
} }
@@ -998,15 +998,15 @@ static esp_err_t send_flush_data()
//clear counter but keep data //clear counter but keep data
static esp_err_t send_reset_counter() static esp_err_t send_reset_counter()
{ {
SDIO_SLAVE_CHECK( send_get_state() == STATE_IDLE, SDIO_SLAVE_CHECK(send_get_state() == STATE_IDLE,
"reset counter when transmission started", ESP_ERR_INVALID_STATE ); "reset counter when transmission started", ESP_ERR_INVALID_STATE);
send_length_write( 0 ); send_length_write(0);
uint32_t last_cnt=0; uint32_t last_cnt=0;
buf_desc_t *desc = context.in_flight; buf_desc_t *desc = context.in_flight;
buf_desc_t *last = NULL; buf_desc_t *last = NULL;
while( desc != NULL ) { while(desc != NULL) {
last_cnt += desc->length; last_cnt += desc->length;
desc->pkt_len = last_cnt; desc->pkt_len = last_cnt;
last = desc; last = desc;
@@ -1015,13 +1015,13 @@ static esp_err_t send_reset_counter()
// in theory the desc should be the one right next to the last of in_flight, // in theory the desc should be the one right next to the last of in_flight,
// but the link of last is NULL, so get the desc from the ringbuf directly. // but the link of last is NULL, so get the desc from the ringbuf directly.
desc = (buf_desc_t*)sdio_ringbuf_peek_front(&context.sendbuf); desc = (buf_desc_t*)sdio_ringbuf_peek_front(&context.sendbuf);
while( desc != NULL ) { while(desc != NULL) {
last_cnt += desc->length; last_cnt += desc->length;
desc->pkt_len = last_cnt; desc->pkt_len = last_cnt;
last = desc; last = desc;
desc = STAILQ_NEXT(desc, qe); desc = STAILQ_NEXT(desc, qe);
} }
if ( last == NULL ) { if (last == NULL) {
last = (buf_desc_t*)sdio_ringbuf_peek_rear(&context.sendbuf); last = (buf_desc_t*)sdio_ringbuf_peek_rear(&context.sendbuf);
last->pkt_len = 0; last->pkt_len = 0;
} }
@@ -1035,36 +1035,36 @@ static esp_err_t send_reset_counter()
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
//strange but the registers for host->slave transfers are really called "tx*". //strange but the registers for host->slave transfers are really called "tx*".
#define CHECK_HANDLE_IDLE(desc) do { if ( desc == NULL || !desc->not_receiving ) {\ #define CHECK_HANDLE_IDLE(desc) do { if (desc == NULL || !desc->not_receiving) {\
return ESP_ERR_INVALID_ARG; } } while(0) return ESP_ERR_INVALID_ARG; } } while(0)
static inline void critical_enter_recv() static inline void critical_enter_recv()
{ {
portENTER_CRITICAL( &context.recv_spinlock ); portENTER_CRITICAL(&context.recv_spinlock);
} }
static inline void critical_exit_recv() static inline void critical_exit_recv()
{ {
portEXIT_CRITICAL( &context.recv_spinlock ); portEXIT_CRITICAL(&context.recv_spinlock);
} }
static inline void recv_size_inc() static inline void recv_size_inc()
{ {
// fields wdata and inc_more should be written by the same instruction. // fields wdata and inc_more should be written by the same instruction.
SLC.slc0_token1.val = FIELD_TO_VALUE2( SLC_SLC0_TOKEN1_WDATA, 1) | FIELD_TO_VALUE2( SLC_SLC0_TOKEN1_INC_MORE, 1 ); SLC.slc0_token1.val = FIELD_TO_VALUE2(SLC_SLC0_TOKEN1_WDATA, 1) | FIELD_TO_VALUE2(SLC_SLC0_TOKEN1_INC_MORE, 1);
} }
static inline void recv_size_reset() static inline void recv_size_reset()
{ {
SLC.slc0_token1.val = FIELD_TO_VALUE2( SLC_SLC0_TOKEN1_WDATA, 0) | FIELD_TO_VALUE2( SLC_SLC0_TOKEN1_WR, 1 ); SLC.slc0_token1.val = FIELD_TO_VALUE2(SLC_SLC0_TOKEN1_WDATA, 0) | FIELD_TO_VALUE2(SLC_SLC0_TOKEN1_WR, 1);
} }
static inline buf_desc_t* recv_get_first_empty_buf() static inline buf_desc_t* recv_get_first_empty_buf()
{ {
buf_stailq_t *const queue = &context.recv_link_list; buf_stailq_t *const queue = &context.recv_link_list;
buf_desc_t *desc = STAILQ_FIRST(queue); buf_desc_t *desc = STAILQ_FIRST(queue);
while( desc && desc->owner == 0 ) { while(desc && desc->owner == 0) {
desc = STAILQ_NEXT( desc, qe ); desc = STAILQ_NEXT(desc, qe);
} }
return desc; return desc;
} }
@@ -1076,7 +1076,7 @@ static esp_err_t recv_start()
critical_enter_recv(); critical_enter_recv();
buf_desc_t *desc = recv_get_first_empty_buf(); buf_desc_t *desc = recv_get_first_empty_buf();
if ( !desc ) { if (!desc) {
ESP_LOGD(TAG, "recv: restart without desc"); ESP_LOGD(TAG, "recv: restart without desc");
critical_exit_recv(); critical_exit_recv();
return ESP_OK; // if no buffer loaded, return directly. return ESP_OK; // if no buffer loaded, return directly.
@@ -1103,10 +1103,10 @@ static void recv_reset_counter()
critical_enter_recv(); critical_enter_recv();
buf_desc_t *desc = recv_get_first_empty_buf(); buf_desc_t *desc = recv_get_first_empty_buf();
while ( desc != NULL ) { while (desc != NULL) {
assert( desc->owner == 1 ); assert(desc->owner == 1);
recv_size_inc(); recv_size_inc();
desc = STAILQ_NEXT( desc, qe ); desc = STAILQ_NEXT(desc, qe);
} }
critical_exit_recv(); critical_exit_recv();
} }
@@ -1118,14 +1118,14 @@ static void recv_flush_data()
critical_enter_recv(); critical_enter_recv();
while(1) { while(1) {
portBASE_TYPE ret = xSemaphoreTake( context.recv_event, 0 ); portBASE_TYPE ret = xSemaphoreTake(context.recv_event, 0);
if ( ret == pdFALSE ) break; if (ret == pdFALSE) break;
buf_desc_t *desc = STAILQ_FIRST(queue); buf_desc_t *desc = STAILQ_FIRST(queue);
assert ( desc != NULL && desc->owner == 0 ); assert (desc != NULL && desc->owner == 0);
STAILQ_REMOVE_HEAD(queue, qe); STAILQ_REMOVE_HEAD(queue, qe);
desc->owner = 1; desc->owner = 1;
STAILQ_INSERT_TAIL( queue, desc, qe ); STAILQ_INSERT_TAIL(queue, desc, qe);
recv_size_inc(); recv_size_inc();
//we only add it to the tail here, without start the DMA nor increase buffer num. //we only add it to the tail here, without start the DMA nor increase buffer num.
} }
@@ -1135,35 +1135,35 @@ static void recv_flush_data()
static void sdio_intr_recv(void* arg) static void sdio_intr_recv(void* arg)
{ {
portBASE_TYPE yield = 0; portBASE_TYPE yield = 0;
if ( SLC.slc0_int_raw.tx_done ) { if (SLC.slc0_int_raw.tx_done) {
SLC.slc0_int_clr.tx_done = 1; SLC.slc0_int_clr.tx_done = 1;
while ( context.recv_cur_ret && context.recv_cur_ret->owner == 0 ) { while (context.recv_cur_ret && context.recv_cur_ret->owner == 0) {
// This may cause the ``cur_ret`` pointer to be NULL, indicating the list is empty, // This may cause the ``cur_ret`` pointer to be NULL, indicating the list is empty,
// in this case the ``tx_done`` should happen no longer until new desc is appended. // in this case the ``tx_done`` should happen no longer until new desc is appended.
// The app is responsible to place the pointer to the right place again when appending new desc. // The app is responsible to place the pointer to the right place again when appending new desc.
context.recv_cur_ret = STAILQ_NEXT( context.recv_cur_ret, qe ); context.recv_cur_ret = STAILQ_NEXT(context.recv_cur_ret, qe);
ESP_EARLY_LOGV( TAG, "intr_recv: Give"); ESP_EARLY_LOGV(TAG, "intr_recv: Give");
xSemaphoreGiveFromISR( context.recv_event, &yield ); xSemaphoreGiveFromISR(context.recv_event, &yield);
}; };
} }
if ( yield ) portYIELD_FROM_ISR(); if (yield) portYIELD_FROM_ISR();
} }
esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle) esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle)
{ {
buf_desc_t *desc = (buf_desc_t*)handle; buf_desc_t *desc = (buf_desc_t*)handle;
CHECK_HANDLE_IDLE( desc ); CHECK_HANDLE_IDLE(desc);
buf_stailq_t *const queue = &context.recv_link_list; buf_stailq_t *const queue = &context.recv_link_list;
critical_enter_recv(); critical_enter_recv();
TAILQ_REMOVE( &context.recv_reg_list, desc, te ); TAILQ_REMOVE(&context.recv_reg_list, desc, te);
desc->owner = 1; desc->owner = 1;
desc->not_receiving = 0; //manually remove the prev link (by set not_receiving=0), to indicate this is in the queue desc->not_receiving = 0; //manually remove the prev link (by set not_receiving=0), to indicate this is in the queue
buf_desc_t *const tail = STAILQ_LAST(queue, buf_desc_s, qe); buf_desc_t *const tail = STAILQ_LAST(queue, buf_desc_s, qe);
STAILQ_INSERT_TAIL( queue, desc, qe ); STAILQ_INSERT_TAIL(queue, desc, qe);
if (tail == NULL || (tail->owner == 0)) { if (tail == NULL || (tail->owner == 0)) {
//in this case we have to set the ret pointer //in this case we have to set the ret pointer
if (tail != NULL) { if (tail != NULL) {
@@ -1196,11 +1196,11 @@ esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle)
sdio_slave_buf_handle_t sdio_slave_recv_register_buf(uint8_t *start) sdio_slave_buf_handle_t sdio_slave_recv_register_buf(uint8_t *start)
{ {
SDIO_SLAVE_CHECK( esp_ptr_dma_capable(start) && (uint32_t)start%4==0, SDIO_SLAVE_CHECK(esp_ptr_dma_capable(start) && (uint32_t)start%4==0,
"buffer to register should be DMA capable and 32-bit aligned", NULL); "buffer to register should be DMA capable and 32-bit aligned", NULL);
buf_desc_t *desc = (buf_desc_t*)malloc(sizeof(buf_desc_t)); buf_desc_t *desc = (buf_desc_t*)malloc(sizeof(buf_desc_t));
if ( desc == NULL ) { if (desc == NULL) {
SDIO_SLAVE_LOGE( "cannot allocate lldesc for new buffer" ); SDIO_SLAVE_LOGE("cannot allocate lldesc for new buffer");
return NULL; return NULL;
} }
@@ -1211,16 +1211,16 @@ sdio_slave_buf_handle_t sdio_slave_recv_register_buf(uint8_t *start)
//no length required, eof always=0 //no length required, eof always=0
}; };
critical_enter_recv(); critical_enter_recv();
TAILQ_INSERT_TAIL( &context.recv_reg_list, desc, te ); TAILQ_INSERT_TAIL(&context.recv_reg_list, desc, te);
critical_exit_recv(); critical_exit_recv();
return desc; return desc;
} }
esp_err_t sdio_slave_recv(sdio_slave_buf_handle_t* handle_ret, uint8_t **start_o, size_t *len_o, TickType_t wait) esp_err_t sdio_slave_recv(sdio_slave_buf_handle_t* handle_ret, uint8_t **out_addr, size_t *out_len, TickType_t wait)
{ {
SDIO_SLAVE_CHECK( handle_ret != NULL, "handle address cannot be 0", ESP_ERR_INVALID_ARG); SDIO_SLAVE_CHECK(handle_ret != NULL, "handle address cannot be 0", ESP_ERR_INVALID_ARG);
portBASE_TYPE ret = xSemaphoreTake( context.recv_event, wait ); portBASE_TYPE ret = xSemaphoreTake(context.recv_event, wait);
if ( ret == pdFALSE ) return ESP_ERR_TIMEOUT; if (ret == pdFALSE) return ESP_ERR_TIMEOUT;
buf_stailq_t *const queue = &context.recv_link_list; buf_stailq_t *const queue = &context.recv_link_list;
@@ -1228,33 +1228,33 @@ esp_err_t sdio_slave_recv(sdio_slave_buf_handle_t* handle_ret, uint8_t **start_o
//remove from queue, add back to reg list. //remove from queue, add back to reg list.
buf_desc_t *desc = STAILQ_FIRST(queue); buf_desc_t *desc = STAILQ_FIRST(queue);
STAILQ_REMOVE_HEAD(queue, qe); STAILQ_REMOVE_HEAD(queue, qe);
TAILQ_INSERT_TAIL( &context.recv_reg_list, desc, te ); TAILQ_INSERT_TAIL(&context.recv_reg_list, desc, te);
critical_exit_recv(); critical_exit_recv();
assert( desc != NULL && desc->owner == 0 ); assert(desc != NULL && desc->owner == 0);
*handle_ret = (sdio_slave_buf_handle_t)desc; *handle_ret = (sdio_slave_buf_handle_t)desc;
if ( start_o ) *start_o = desc->buf; if (out_addr) *out_addr = desc->buf;
if ( len_o ) *len_o = desc->length; if (out_len) *out_len = desc->length;
return ESP_OK; return ESP_OK;
} }
esp_err_t sdio_slave_recv_unregister_buf(sdio_slave_buf_handle_t handle) esp_err_t sdio_slave_recv_unregister_buf(sdio_slave_buf_handle_t handle)
{ {
buf_desc_t *desc = (buf_desc_t*)handle; buf_desc_t *desc = (buf_desc_t*)handle;
CHECK_HANDLE_IDLE( desc ); //in the queue, fail. CHECK_HANDLE_IDLE(desc); //in the queue, fail.
critical_enter_recv(); critical_enter_recv();
TAILQ_REMOVE( &context.recv_reg_list, desc, te ); TAILQ_REMOVE(&context.recv_reg_list, desc, te);
critical_exit_recv(); critical_exit_recv();
free(desc); free(desc);
return ESP_OK; return ESP_OK;
} }
uint8_t* sdio_slave_recv_get_buf( sdio_slave_buf_handle_t handle, size_t *len_o ) uint8_t* sdio_slave_recv_get_buf(sdio_slave_buf_handle_t handle, size_t *len_o)
{ {
buf_desc_t *desc = (buf_desc_t*)handle; buf_desc_t *desc = (buf_desc_t*)handle;
if ( handle == NULL ) return NULL; if (handle == NULL) return NULL;
if ( len_o!= NULL ) *len_o= desc->length; if (len_o!= NULL) *len_o= desc->length;
return desc->buf; return desc->buf;
} }