diff --git a/examples/peripherals/sdio/README.md b/examples/peripherals/sdio/README.md index 737f6c7611..39ef48a16a 100644 --- a/examples/peripherals/sdio/README.md +++ b/examples/peripherals/sdio/README.md @@ -84,7 +84,7 @@ better or disabling the HS mode in menuconfig. to pull down DAT2 line to set proper flash voltage. This conflicts with SDIO pullup requirements. Currently devkits using PICO-D4 and Wroom-32 series modules have this problem. You can either: - + - Use Wrover Kit v3 which integrates a Wrover module - Still use PICO-D4 or Wroom-32 Series modules as the slave, however: - Don't connect the DAT2 pin and leave it floating. This means @@ -101,13 +101,8 @@ and ``api_reference/peripherals/sd_pullup_requirements`` to see more descriptions about pullups and MTDI requirements and solutions of official modules and devkits. -## About esp_slave component in this example +## About `esp_serial_slave_link` component used in this example -The component in this example shows how to communicate with esp32 sdio slave -correctly. However, currently it is for example purpose only. - -The example shows how to talk with the slave, but doesn't show how to handle -exceptions. Assertion fails if any of the preconditions (connections, -grounding, slave data preparation, etc.) is not met. - -Please do check and handle the return value in your real product. +`esp_serial_slave_link` component in the IDF is used to communicate to a ESP slave device. +When the `esp_serial_slave_link` device is initialized with an `essl_sdio_config_t` structure, +the `esp_serial_slave_link` can be used to communicate with an ESP32 SDIO slave. diff --git a/examples/peripherals/sdio/host/components/esp_slave/CMakeLists.txt b/examples/peripherals/sdio/host/components/esp_slave/CMakeLists.txt deleted file mode 100644 index 9f5c38bbaf..0000000000 --- a/examples/peripherals/sdio/host/components/esp_slave/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "esp_slave.c" - INCLUDE_DIRS "include" - REQUIRES driver sdmmc) \ No newline at end of file diff --git a/examples/peripherals/sdio/host/components/esp_slave/esp_slave.c b/examples/peripherals/sdio/host/components/esp_slave/esp_slave.c deleted file mode 100644 index fdfaa291e3..0000000000 --- a/examples/peripherals/sdio/host/components/esp_slave/esp_slave.c +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "esp_slave.h" -#include "esp_log.h" -#include "freertos/task.h" -#include "soc/sdio_slave_periph.h" - -static const char TAG[] = "esp_slave"; - -#define ESP_SLAVE_CMD53_END_ADDR 0x1f800 - -#define TX_BUFFER_MAX 0x1000 -#define TX_BUFFER_MASK 0xFFF -#define RX_BYTE_MAX 0x100000 -#define RX_BYTE_MASK 0xFFFFF - -#define FUNC1_EN_MASK (BIT(1)) - -esp_err_t esp_slave_init_io(esp_slave_context_t *context) -{ - esp_err_t err; - uint8_t ioe; - sdmmc_card_t* card = context->card; - - err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_FN_ENABLE, &ioe); - if (err != ESP_OK) return err; - ESP_LOGD(TAG, "IOE: 0x%02x", ioe); - - uint8_t ior = 0; - err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_FN_READY, &ior); - if (err != ESP_OK) return err; - ESP_LOGD(TAG, "IOR: 0x%02x", ior); - - // enable function 1 - ioe |= FUNC1_EN_MASK; - err = sdmmc_io_write_byte(card, 0, SD_IO_CCCR_FN_ENABLE, ioe, &ioe); - if (err != ESP_OK) return err; - ESP_LOGD(TAG, "IOE: 0x%02x", ioe); - - // wait for the card to become ready - while ((ior & FUNC1_EN_MASK) == 0) { - err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_FN_READY, &ior); - if (err != ESP_OK) return err; - ESP_LOGD(TAG, "IOR: 0x%02x", ior); - } - - // get interrupt status - uint8_t ie; - err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_INT_ENABLE, &ie); - if (err != ESP_OK) return err; - ESP_LOGD(TAG,"IE: 0x%02x", ie); - - // enable interrupts for function 1&2 and master enable - ie |= BIT(0) | FUNC1_EN_MASK; - err = sdmmc_io_write_byte(card, 0, SD_IO_CCCR_INT_ENABLE, ie, &ie); - if (err != ESP_OK) return err; - ESP_LOGD(TAG, "IE: 0x%02x", ie); - - // get bus width register - uint8_t bus_width; - err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_BUS_WIDTH, &bus_width); - if (err != ESP_OK) return err; - ESP_LOGD(TAG,"BUS_WIDTH: 0x%02x", bus_width); - - // enable continuous SPI interrupts - bus_width |= CCCR_BUS_WIDTH_ECSI; - err = sdmmc_io_write_byte(card, 0, SD_IO_CCCR_BUS_WIDTH, bus_width, &bus_width); - if (err != ESP_OK) return err; - ESP_LOGD(TAG, "BUS_WIDTH: 0x%02x", bus_width); - - uint16_t bs = 512; - const uint8_t* bs_u8 = (const uint8_t*) &bs; - uint16_t bs_read = 0; - uint8_t* bs_read_u8 = (uint8_t*) &bs_read; - // Set block sizes for functions 0 to 512 bytes - ESP_ERROR_CHECK(sdmmc_io_read_byte(card, 0, SD_IO_CCCR_BLKSIZEL, &bs_read_u8[0])); - ESP_ERROR_CHECK(sdmmc_io_read_byte(card, 0, SD_IO_CCCR_BLKSIZEH, &bs_read_u8[1])); - ESP_LOGI(TAG, "Function 0 BS: %04x", (int) bs_read); - - ESP_ERROR_CHECK(sdmmc_io_write_byte(card, 0, SD_IO_CCCR_BLKSIZEL, bs_u8[0], NULL)); - ESP_ERROR_CHECK(sdmmc_io_write_byte(card, 0, SD_IO_CCCR_BLKSIZEH, bs_u8[1], NULL)); - ESP_ERROR_CHECK(sdmmc_io_read_byte(card, 0, SD_IO_CCCR_BLKSIZEL, &bs_read_u8[0])); - ESP_ERROR_CHECK(sdmmc_io_read_byte(card, 0, SD_IO_CCCR_BLKSIZEH, &bs_read_u8[1])); - ESP_LOGI(TAG, "Function 0 BS: %04x", (int) bs_read); - - // Set block sizes for functions 1 to given value (default value = 512). - if (context->block_size > 0 || context->block_size <= 2048) { - bs = context->block_size; - } else { - bs = 512; - } - size_t offset = SD_IO_FBR_START * 1; - ESP_ERROR_CHECK(sdmmc_io_read_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEL, &bs_read_u8[0])); - ESP_ERROR_CHECK(sdmmc_io_read_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEH, &bs_read_u8[1])); - ESP_LOGI(TAG, "Function 1 BS: %04x", (int) bs_read); - - ESP_ERROR_CHECK(sdmmc_io_write_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEL, bs_u8[0], NULL)); - ESP_ERROR_CHECK(sdmmc_io_write_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEH, bs_u8[1], NULL)); - ESP_ERROR_CHECK(sdmmc_io_read_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEL, &bs_read_u8[0])); - ESP_ERROR_CHECK(sdmmc_io_read_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEH, &bs_read_u8[1])); - ESP_LOGI(TAG, "Function 1 BS: %04x", (int) bs_read); - - if (bs_read != context->block_size) { - ESP_LOGW(TAG, "Function1 block size %d different than set value %d", bs_read, context->block_size); - context->block_size = bs_read; - } - return ESP_OK; -} - -esp_err_t esp_slave_wait_for_ioready(esp_slave_context_t *context) -{ - ESP_LOGV(TAG, "wait_for_ioready"); - esp_err_t err; - sdmmc_card_t *card = context->card; - // wait for the card to become ready - uint8_t ior = 0; - while ((ior & FUNC1_EN_MASK) == 0) { - err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_FN_READY, &ior); - if (err != ESP_OK) return err; - ESP_LOGI(TAG, "IOR: 0x%02x", ior); - } - return ESP_OK; -} - -static inline esp_err_t esp_slave_write_byte(esp_slave_context_t *context, uint32_t addr, uint8_t val, uint8_t *val_o) -{ - return sdmmc_io_write_byte(context->card, 1, addr&0x3FF, val, val_o); -} - -static inline esp_err_t esp_slave_write_bytes(esp_slave_context_t *context, uint32_t addr, uint8_t *val, int len) -{ - return sdmmc_io_write_bytes(context->card, 1, addr&0x3FF, val, len); -} - -static inline esp_err_t esp_slave_read_byte(esp_slave_context_t *context, uint32_t addr, uint8_t *val_o) -{ - return sdmmc_io_read_byte(context->card, 1, addr&0x3FF, val_o); -} - -static inline esp_err_t esp_slave_read_bytes(esp_slave_context_t *context, uint32_t addr, uint8_t *val_o, int len) -{ - return sdmmc_io_read_bytes(context->card, 1, addr&0x3FF, val_o, len); -} - -esp_err_t esp_slave_send_packet(esp_slave_context_t *context, const void* start, size_t length, uint32_t wait_ms) -{ - sdmmc_card_t *card = context->card; - uint16_t buffer_size = context->buffer_size; - int buffer_used = (length + buffer_size - 1)/buffer_size; - esp_err_t err; - const uint32_t wait_ticks = wait_ms/portTICK_PERIOD_MS; - uint32_t pre = xTaskGetTickCount(); - - assert(length>0); - for(;;) { - uint32_t num = 0; - err = esp_slave_get_tx_buffer_num(context, &num); - if (err == ESP_OK && num * buffer_size >= length) break; - if (err != ESP_OK && err != ESP_ERR_TIMEOUT) return err; - //not error and buffer not enough, retry ``timeout_cnt`` times - uint32_t now = xTaskGetTickCount(); - if (now-pre >= wait_ticks) { - ESP_LOGD(TAG, "buffer is not enough: %d, %d required.", num, buffer_used); - return ESP_ERR_TIMEOUT; - } else { - ESP_LOGV(TAG, "buffer is not enough: %d, %d required. Retry...", num, buffer_used); - } - vTaskDelay(1); - } - - ESP_LOGV(TAG, "send_packet: len: %d", length); - uint8_t *start_ptr = (uint8_t*)start; - uint32_t len_remain = length; - do { - const int block_size = 512; - /* Though the driver supports to split packet of unaligned size into - * length of 4x and 1~3, we still send aligned size of data to get - * higher effeciency. The length is determined by the SDIO address, and - * the remainning will be discard by the slave hardware. - */ - int block_n = len_remain/block_size; - int len_to_send; - if (block_n) { - len_to_send = block_n * block_size; - err = sdmmc_io_write_blocks(card, 1, ESP_SLAVE_CMD53_END_ADDR - len_remain, start_ptr, len_to_send); - } else { - len_to_send = len_remain; - err = sdmmc_io_write_bytes(card, 1, ESP_SLAVE_CMD53_END_ADDR - len_remain, start_ptr, (len_to_send + 3) & (~3)); - } - if (err != ESP_OK) return err; - start_ptr += len_to_send; - len_remain -= len_to_send; - } while (len_remain); - - context->tx_sent_buffers += buffer_used; - return ESP_OK; -} - -esp_err_t esp_slave_get_packet(esp_slave_context_t *context, void* out_data, size_t size, size_t *out_length, uint32_t wait_ms) -{ - sdmmc_card_t *card = context->card; - esp_err_t err; - esp_err_t ret = ESP_OK; - uint32_t len; - const uint32_t wait_ticks = wait_ms/portTICK_PERIOD_MS; - uint32_t pre = xTaskGetTickCount(); - - assert (size>0); - for (;;) { - err = esp_slave_get_rx_data_size(context, &len); - if (err == ESP_OK && len > 0) break; - if (err != ESP_OK && err != ESP_ERR_TIMEOUT) return err; - //not error and no data, retry ``timeout_cnt`` times. - uint32_t now = xTaskGetTickCount(); - if (now-pre >= wait_ticks) return ESP_ERR_NOT_FOUND; - vTaskDelay(1); - } - - ESP_LOGV(TAG, "get_packet: slave len=%d, max read size=%d", len, size); - if (len > size) { - len = size; - ret = ESP_ERR_NOT_FINISHED; - } - - uint8_t *start = out_data; - uint32_t len_remain = len; - do { - const int block_size = 512; //currently our driver don't support block size other than 512 - int len_to_send; - - int block_n = len_remain/block_size; - if (block_n != 0) { - len_to_send = block_n * block_size; - err = sdmmc_io_read_blocks(card, 1, ESP_SLAVE_CMD53_END_ADDR - len_remain, start, len_to_send); - } else { - len_to_send = len_remain; - /* though the driver supports to split packet of unaligned size into length - * of 4x and 1~3, we still get aligned size of data to get higher - * effeciency. The length is determined by the SDIO address, and the - * remainning will be ignored by the slave hardware. - */ - err = sdmmc_io_read_bytes(card, 1, ESP_SLAVE_CMD53_END_ADDR - len_remain, start, (len_to_send + 3) & (~3)); - } - if (err != ESP_OK) return err; - start += len_to_send; - len_remain -= len_to_send; - } while(len_remain!=0); - - context->rx_got_bytes += len; - *out_length = len; - return ret; -} - -esp_err_t esp_slave_get_tx_buffer_num(esp_slave_context_t *context, uint32_t* tx_num) -{ - uint32_t len; - esp_err_t err; - - ESP_LOGV(TAG, "get_tx_buffer_num"); - err = esp_slave_read_bytes(context, HOST_SLC0HOST_TOKEN_RDATA_REG, (uint8_t*)&len, 4); - if (err != ESP_OK) return err; - len = (len>>16)&TX_BUFFER_MASK; - len = (len + TX_BUFFER_MAX - context->tx_sent_buffers)%TX_BUFFER_MAX; - *tx_num = len; - return ESP_OK; -} - -esp_err_t esp_slave_get_rx_data_size(esp_slave_context_t *context, uint32_t* rx_size) -{ - uint32_t len; - esp_err_t err; - - ESP_LOGV(TAG, "get_rx_data_size: got_bytes: %d", context->rx_got_bytes); - err = esp_slave_read_bytes(context, HOST_SLCHOST_PKT_LEN_REG, (uint8_t*)&len, 4); - if (err != ESP_OK) return err; - len &= RX_BYTE_MASK; - len = (len + RX_BYTE_MAX - context->rx_got_bytes)%RX_BYTE_MAX; - *rx_size = len; - return ESP_OK; -} - -esp_err_t esp_slave_clear_intr(esp_slave_context_t *context, uint32_t intr_mask) -{ - ESP_LOGV(TAG, "clear_intr: %08X", intr_mask); - return esp_slave_write_bytes(context, HOST_SLC0HOST_INT_CLR_REG, (uint8_t*)&intr_mask, 4); -} - -esp_err_t esp_slave_get_intr(esp_slave_context_t *context, uint32_t *intr_raw, uint32_t *intr_st) -{ - esp_err_t r; - ESP_LOGV(TAG, "get_intr"); - if (intr_raw == NULL && intr_st == NULL) return ESP_ERR_INVALID_ARG; - - if (intr_raw != NULL) { - r= esp_slave_read_bytes(context, HOST_SLC0HOST_INT_RAW_REG, (uint8_t*)intr_raw, 4); - if (r != ESP_OK) return r; - } - if (intr_st != NULL) { - r = esp_slave_read_bytes(context, HOST_SLC0HOST_INT_ST_REG, (uint8_t*)intr_st, 4); - if (r != ESP_OK) return r; - } - return ESP_OK; -} - -esp_err_t esp_slave_set_intr_ena(esp_slave_context_t *context, uint32_t ena_mask) -{ - ESP_LOGV(TAG, "set_intr_ena: %08X", ena_mask); - return esp_slave_write_bytes(context, HOST_SLC0HOST_INT_ENA_REG, (uint8_t*)&ena_mask, 4); -} - -esp_err_t esp_slave_get_intr_ena(esp_slave_context_t *context, uint32_t *ena_mask_o) -{ - ESP_LOGV(TAG, "get_intr_ena"); - esp_err_t ret = esp_slave_read_bytes(context, HOST_SLC0HOST_INT_ENA_REG, (uint8_t*)ena_mask_o, 4); - ESP_LOGV(TAG, "ena: %08X", *ena_mask_o); - return ret; -} - -esp_err_t esp_slave_write_reg(esp_slave_context_t *context, uint8_t addr, uint8_t value, uint8_t* value_o) -{ - ESP_LOGV(TAG, "write_reg: %08X", value); - // addrress over range - if (addr >= 64) return ESP_ERR_INVALID_ARG; - // reserved for interrupts - if (addr >= 28 && addr <= 31) return ESP_ERR_INVALID_ARG; - return esp_slave_write_byte(context, HOST_SLCHOST_CONF_W_REG(addr), value, value_o); -} - -esp_err_t esp_slave_read_reg(esp_slave_context_t *context, uint8_t add, uint8_t *value_o) -{ - ESP_LOGV(TAG, "read_reg"); - // address over range - if (add >= 64) return ESP_ERR_INVALID_ARG; - esp_err_t ret = esp_slave_read_byte(context, HOST_SLCHOST_CONF_W_REG(add), value_o); - ESP_LOGV(TAG, "reg: %08X", *value_o); - return ret; -} - -esp_err_t esp_slave_send_slave_intr(esp_slave_context_t *context, uint8_t intr_mask) -{ - ESP_LOGV(TAG, "send_slave_intr: %02x", intr_mask); - return esp_slave_write_byte(context, HOST_SLCHOST_CONF_W7_REG+0, intr_mask, NULL); -} - - diff --git a/examples/peripherals/sdio/host/components/esp_slave/include/esp_slave.h b/examples/peripherals/sdio/host/components/esp_slave/include/esp_slave.h deleted file mode 100644 index c2d4d31d24..0000000000 --- a/examples/peripherals/sdio/host/components/esp_slave/include/esp_slave.h +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "sdmmc_cmd.h" -#include "driver/sdmmc_defs.h" -#include "soc/sdio_slave_periph.h" - -/* - * NOTE: This component is for example purpose only. Assertion fails if any of - * the preconditions (connections, grounding, slave data preparation, etc.) is - * not met. - * Please do check and handle the return value in your real product. -*/ - -#define ESP_ERR_NOT_FINISHED 0x201 - -/** Context used by the ``esp_slave`` component. - */ -typedef struct { - sdmmc_card_t* card; ///< Initialized sdmmc_cmd card - uint16_t buffer_size; - ///< All data that do not fully fill a buffer is still counted as one buffer. E.g. 10 bytes data costs 2 buffers if the size is 8 bytes per buffer. - ///< Buffer size of the slave pre-defined between host and slave before communication. - uint16_t block_size; - ///< If this is too large, it takes time to send stuff bits; while if too small, intervals between blocks cost much. - ///< Should be set according to length of data, and larger than ``TRANS_LEN_MAX/511``. - ///< Block size of the SDIO function 1. After the initialization this will hold the value the slave really do. Valid value is 1-2048. - size_t tx_sent_buffers; ///< Counter hold the amount of buffers already sent to ESP32 slave. Should be set to 0 when initialization. - size_t rx_got_bytes; ///< Counter hold the amount of bytes already received from ESP32 slave. Should be set to 0 when initialization. -} esp_slave_context_t; - -/** Initialize ``esp_slave_context_t`` by this macro. -*/ -#define ESP_SLAVE_DEFAULT_CONTEXT(card) (esp_slave_context_t){\ - .card = card, \ - .block_size = 0x200, \ - .buffer_size = 128, \ - .tx_sent_buffers = 0, \ - .rx_got_bytes = 0, \ - } - -/** SDIO Initialize process of a ESP32 slave device. - * - * @param context Context of the ``esp_slave`` component. Send to other functions later. - * - * @return - * - ESP_OK if success - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_init_io(esp_slave_context_t *context); - -/** Wait for interrupt of a ESP32 slave device. - * - * @param context Context of the ``esp_slave`` component. - * - * @return - * - ESP_OK if success - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_wait_for_ioready(esp_slave_context_t *context); - -/** Get buffer num for the host to send data to the slave. The buffers are size of ``buffer_size``. - * - * @param context Context of the component. - * @param tx_num Output of buffer num that host can send data to ESP32 slave. - * - * @return - * - ESP_OK Success - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_get_tx_buffer_num(esp_slave_context_t *context, uint32_t* tx_num); - -/** Get amount of data the ESP32 slave preparing to send to host. - * - * @param context Context of the component. - * @param rx_size Output of data size to read from slave. - * - * @return - * - ESP_OK Success - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_get_rx_data_size(esp_slave_context_t *context, uint32_t* rx_size); - - -/** Reset the counters of this component. Usually you don't need to do this unless you know the slave is reset. - * - * @param context Context of the component. - */ -inline static void esp_slave_reset_cnt(esp_slave_context_t *context) -{ - context->rx_got_bytes = 0; - context->tx_sent_buffers = 0; -} - -/** Send a packet to the ESP32 slave. The slave receive the packet into buffers whose size is ``buffer_size`` in the context. - * - * @param context Context of the component. - * @param start Start address of the packet to send - * @param length Length of data to send, if the packet is over-size, the it will be divided into blocks and hold into different buffers automatically. - * @param wait_ms Time to wait before timeout, in ms. - * - * @return - * - ESP_OK Success - * - ESP_ERR_TIMEOUT No buffer to use, or error ftrom SDMMC host controller - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_send_packet(esp_slave_context_t *context, const void* start, size_t length, uint32_t wait_ms); - -/** Get a packet from ESP32 slave. - * - * @param context Context of the component. - * @param[out] out_data Data output address - * @param size The size of the output buffer, if the buffer is smaller than the size of data to receive from slave, the driver returns ``ESP_ERR_NOT_FINISHED`` - * @param[out] out_length Output of length the data actually received from slave. - * @param wait_ms Time to wait before timeout, in ms. - * - * @return - * - ESP_OK Success, all the data are read from the slave. - * - ESP_ERR_NOT_FINISHED Read success, while there're data remaining. - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_get_packet(esp_slave_context_t *context, void* out_data, size_t size, size_t *out_length, uint32_t wait_ms); - -/** wait for an interrupt of the slave - * - * @param context Context of the component. - * @param wait Ticks to wait. - * - * @return - * - ESP_ERR_NOT_SUPPORTED Currently our driver doesnot support SDIO with SPI interface. - * - ESP_OK If interrupt triggered. - * - ESP_ERR_TIMEOUT No interrupts before timeout. - */ -inline static esp_err_t esp_slave_wait_int(esp_slave_context_t *context, TickType_t wait) -{ - return sdmmc_io_wait_int(context->card, wait); -} - -/** Clear interrupt bits of ESP32 slave. All the bits set in the mask will be cleared, while other bits will stay the same. - * - * @param context Context of the component. - * @param intr_mask Mask of interrupt bits to clear. - * - * @return - * - ESP_OK Success - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_clear_intr(esp_slave_context_t *context, uint32_t intr_mask); - -/** Get interrupt bits of ESP32 slave. - * - * @param context Context of the component. - * @param intr_raw Output of the raw interrupt bits. Set to NULL if only masked bits are read. - * @param intr_st Output of the masked interrupt bits. set to NULL if only raw bits are read. - * - * @return - * - ESP_OK Success - * - ESP_INVALID_ARG if both ``intr_raw`` and ``intr_st`` are NULL. - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_get_intr(esp_slave_context_t *context, uint32_t *intr_raw, uint32_t *intr_st); - -/** Set interrupt enable bits of ESP32 slave. The slave only sends interrupt on the line when there is a bit both the raw status and the enable are set. - * - * @param context Context of the component. - * @param ena_mask Mask of the interrupt bits to enable. - * - * @return - * - ESP_OK Success - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_set_intr_ena(esp_slave_context_t *context, uint32_t ena_mask); - -/** Get interrupt enable bits of ESP32 slave. - * - * @param context Context of the component. - * @param ena_mask_o Output of interrupt bit enable mask. - * - * @return - * - ESP_OK Success - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_get_intr_ena(esp_slave_context_t *context, uint32_t *ena_mask_o); - -/** Write general purpose R/W registers (8-bit) of ESP32 slave. - * - * @param context Context of the component. - * @param addr Address of register to write. Valid address: 0-27, 32-63 (28-31 reserved). - * @param value Value to write to the register. - * - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Address not valid. - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_write_reg(esp_slave_context_t *context, uint8_t addr, uint8_t value, uint8_t* value_o); - -/** Read general purpose R/W registers (8-bit) of ESP32 slave. - * - * @param context Context of the component. - * @param add Address of register to read. Valid address: 0-27, 32-63 (28-31 reserved, return interrupt bits on read). - * @param value Output value read from the register. - * - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Address not valid. - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_read_reg(esp_slave_context_t *context, uint8_t add, uint8_t *value_o); - -/** Send interrupts to slave. Each bit of the interrupt will be triggered. - * - * @param context Context of the component. - * @param intr_mask Mask of interrupt bits to send to slave. - * - * @return - * - ESP_OK Success - * - One of the error codes from SDMMC host controller - */ -esp_err_t esp_slave_send_slave_intr(esp_slave_context_t *context, uint8_t intr_mask); - - diff --git a/examples/peripherals/sdio/host/main/Kconfig.projbuild b/examples/peripherals/sdio/host/main/Kconfig.projbuild index 7fb21ebd19..ad79d6587a 100644 --- a/examples/peripherals/sdio/host/main/Kconfig.projbuild +++ b/examples/peripherals/sdio/host/main/Kconfig.projbuild @@ -33,25 +33,21 @@ menu "Example Configuration" If the example does not work, please try disabling the HS mode. choice EXAMPLE_SLAVE - prompt "Id of Slave used in Espressif master-slave board." + prompt "GPIO to control slave EN in Espressif master-slave board." default EXAMPLE_SLAVE_NONE help - If Espressif master-slave board is used, select which slave is used. + If Espressif master-slave board is used, select the correct GPIO to control slave's EN. config EXAMPLE_SLAVE_NONE bool "Not using Espressif master-slave board." config EXAMPLE_SLAVE_B1 bool "Using slave B1" - config EXAMPLE_SLAVE_B2 - bool "Using slave B2" - config EXAMPLE_SLAVE_B3 - bool "Using slave B3" endchoice config EXAMPLE_SLAVE_PWR_NEGTIVE_ACTIVE bool "Slave power control pin is negtive active, otherwise postive active" depends on !EXAMPLE_SLAVE_NONE - default y + default n help Slave power control pin is negtive active, otherwise postive active diff --git a/examples/peripherals/sdio/host/main/app_main.c b/examples/peripherals/sdio/host/main/app_main.c index 840126e963..c5eb083137 100644 --- a/examples/peripherals/sdio/host/main/app_main.c +++ b/examples/peripherals/sdio/host/main/app_main.c @@ -1,4 +1,4 @@ -/* SDIO example, host (uses sdmmc host driver) +/* SDIO example, host (uses sdmmc_host/sdspi_host driver) This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -20,26 +20,18 @@ #include "soc/sdio_slave_periph.h" #include "esp_log.h" #include "esp_attr.h" -#include "esp_slave.h" +#include "esp_serial_slave_link/essl_sdio.h" #include "sdkconfig.h" #include "driver/sdmmc_host.h" #include "driver/sdspi_host.h" +#define TIMEOUT_MAX UINT32_MAX -/* - * For SDIO master-slave board, we have 3 pins controlling power of 3 different - * slaves individially. We only enable one at a time. - */ -#define GPIO_B1 5 -#define GPIO_B2 18 -#define GPIO_B3 19 + +#define GPIO_B1 21 #if CONFIG_EXAMPLE_SLAVE_B1 #define SLAVE_PWR_GPIO GPIO_B1 -#elif CONFIG_EXAMPLE_SLAVE_B2 -#define SLAVE_PWR_GPIO GPIO_B2 -#elif CONFIG_EXAMPLE_SLAVE_B3 -#define SLAVE_PWR_GPIO GPIO_B3 #endif /* @@ -85,6 +77,7 @@ #define WRITE_BUFFER_LEN 4096 #define READ_BUFFER_LEN 4096 +#define SLAVE_BUFFER_SIZE 128 static const char TAG[] = "example_host"; @@ -103,21 +96,21 @@ typedef enum { } example_job_t; //host use this to inform the slave it should reset its counters -esp_err_t slave_reset(esp_slave_context_t *context) +esp_err_t slave_reset(essl_handle_t handle) { esp_err_t ret; ESP_LOGI(TAG, "send reset to slave..."); - ret = esp_slave_write_reg(context, 0, JOB_RESET, NULL); + ret = essl_write_reg(handle, 0, JOB_RESET, NULL, TIMEOUT_MAX); if (ret != ESP_OK) { return ret; } - ret = esp_slave_send_slave_intr(context, BIT(SLAVE_INTR_NOTIFY)); + ret = essl_send_slave_intr(handle, BIT(SLAVE_INTR_NOTIFY), TIMEOUT_MAX); if (ret != ESP_OK) { return ret; } vTaskDelay(500 / portTICK_RATE_MS); - ret = esp_slave_wait_for_ioready(context); + ret = essl_wait_for_ready(handle, TIMEOUT_MAX); ESP_LOGI(TAG, "slave io ready"); return ret; } @@ -166,7 +159,7 @@ static esp_err_t print_sdio_cis_information(sdmmc_card_t* card) } //host use this to initialize the slave card as well as SDIO registers -esp_err_t slave_init(esp_slave_context_t *context) +esp_err_t slave_init(essl_handle_t* handle) { esp_err_t err; /* Probe */ @@ -247,8 +240,14 @@ esp_err_t slave_init(esp_slave_context_t *context) gpio_pullup_en(13); gpio_pulldown_dis(13); - *context = ESP_SLAVE_DEFAULT_CONTEXT(card); - esp_err_t ret = esp_slave_init_io(context); + essl_sdio_config_t ser_config = { + .card = card, + .recv_buffer_size = SLAVE_BUFFER_SIZE, + }; + err = essl_sdio_init_dev(handle, &ser_config); + ESP_ERROR_CHECK(err); + + esp_err_t ret = essl_init(*handle, TIMEOUT_MAX); ESP_ERROR_CHECK(ret); ret = print_sdio_cis_information(card); @@ -267,7 +266,7 @@ void slave_power_on(void) level_active = 1; #endif gpio_config_t cfg = { - .pin_bit_mask = BIT64(GPIO_B1) | BIT64(GPIO_B2) | BIT64(GPIO_B3), + .pin_bit_mask = BIT64(GPIO_B1), .mode = GPIO_MODE_DEF_OUTPUT, .pull_up_en = false, .pull_down_en = false, @@ -275,8 +274,6 @@ void slave_power_on(void) }; gpio_config(&cfg); gpio_set_level(GPIO_B1, !level_active); - gpio_set_level(GPIO_B2, !level_active); - gpio_set_level(GPIO_B3, !level_active); vTaskDelay(100); gpio_set_level(SLAVE_PWR_GPIO, level_active); @@ -288,18 +285,18 @@ void slave_power_on(void) DMA_ATTR uint8_t rcv_buffer[READ_BUFFER_LEN]; //try to get an interrupt from the slave and handle it, return if none. -esp_err_t process_event(esp_slave_context_t *context) +esp_err_t process_event(essl_handle_t handle) { - esp_err_t ret = esp_slave_wait_int(context, 0); + esp_err_t ret = essl_wait_int(handle, 0); if (ret == ESP_ERR_TIMEOUT) { return ret; } ESP_ERROR_CHECK(ret); uint32_t intr_raw, intr_st; - ret = esp_slave_get_intr(context, &intr_raw, &intr_st); + ret = essl_get_intr(handle, &intr_raw, &intr_st, TIMEOUT_MAX); ESP_ERROR_CHECK(ret); - ret = esp_slave_clear_intr(context, intr_raw); + ret = essl_clear_intr(handle, intr_raw, TIMEOUT_MAX); ESP_ERROR_CHECK(ret); ESP_LOGD(TAG, "intr: %08X", intr_raw); @@ -314,7 +311,7 @@ esp_err_t process_event(esp_slave_context_t *context) ESP_LOGD(TAG, "new packet coming"); while (1) { size_t size_read = READ_BUFFER_LEN; - ret = esp_slave_get_packet(context, rcv_buffer, READ_BUFFER_LEN, &size_read, wait_ms); + ret = essl_get_packet(handle, rcv_buffer, READ_BUFFER_LEN, &size_read, wait_ms); if (ret == ESP_ERR_NOT_FOUND) { ESP_LOGE(TAG, "interrupt but no data can be read"); break; @@ -334,32 +331,32 @@ esp_err_t process_event(esp_slave_context_t *context) } //tell the slave to do a job -static inline esp_err_t slave_inform_job(esp_slave_context_t *context, example_job_t job) +static inline esp_err_t slave_inform_job(essl_handle_t handle, example_job_t job) { esp_err_t ret; - ret = esp_slave_write_reg(context, SLAVE_REG_JOB, job, NULL); + ret = essl_write_reg(handle, SLAVE_REG_JOB, job, NULL, TIMEOUT_MAX); ESP_ERROR_CHECK(ret); - ret = esp_slave_send_slave_intr(context, BIT(SLAVE_INTR_NOTIFY)); + ret = essl_send_slave_intr(handle, BIT(SLAVE_INTR_NOTIFY), TIMEOUT_MAX); ESP_ERROR_CHECK(ret); return ret; } //tell the slave to write registers by write one of them, and read them back -void job_write_reg(esp_slave_context_t *context, int value) +void job_write_reg(essl_handle_t handle, int value) { esp_err_t ret; - uint8_t reg_read[64]; + uint8_t reg_read[60]; ESP_LOGI(TAG, "========JOB: write slave reg========"); - ret = esp_slave_write_reg(context, SLAVE_REG_VALUE, value, NULL); + ret = essl_write_reg(handle, SLAVE_REG_VALUE, value, NULL, TIMEOUT_MAX); ESP_ERROR_CHECK(ret); - ret = slave_inform_job(context, JOB_WRITE_REG); + ret = slave_inform_job(handle, JOB_WRITE_REG); ESP_ERROR_CHECK(ret); vTaskDelay(10); - for (int i = 0; i < 64; i++) { + for (int i = 0; i < 60; i++) { ESP_LOGD(TAG, "reading register %d", i); - ret = esp_slave_read_reg(context, i, ®_read[i]); + ret = essl_read_reg(handle, i, ®_read[i], TIMEOUT_MAX); ESP_ERROR_CHECK(ret); } @@ -374,7 +371,7 @@ int packet_len[] = {6, 12, 1024, 512, 3, 513, 517}; DMA_ATTR uint8_t send_buffer[READ_BUFFER_LEN]; //send packets to the slave (they will return and be handled by the interrupt handler) -void job_fifo(esp_slave_context_t *context) +void job_fifo(essl_handle_t handle) { for (int i = 0; i < READ_BUFFER_LEN; i++) { send_buffer[i] = 0x46 + i * 5; @@ -392,7 +389,7 @@ void job_fifo(esp_slave_context_t *context) for (int i = 0; i < sizeof(packet_len) / sizeof(int); i++) { const int wait_ms = 50; int length = packet_len[i]; - ret = esp_slave_send_packet(context, send_buffer + pointer, length, wait_ms); + ret = essl_send_packet(handle, send_buffer + pointer, length, wait_ms); if (ret == ESP_ERR_TIMEOUT) { ESP_LOGD(TAG, "several packets are expected to timeout."); } else { @@ -404,15 +401,15 @@ void job_fifo(esp_slave_context_t *context) } //inform the slave to send interrupts to host (the interrupts will be handled in the interrupt handler) -void job_getint(esp_slave_context_t *context) +void job_getint(essl_handle_t handle) { ESP_LOGI(TAG, "========JOB: get interrupts from slave========"); - slave_inform_job(context, JOB_SEND_INT); + slave_inform_job(handle, JOB_SEND_INT); } void app_main(void) { - esp_slave_context_t context; + essl_handle_t handle; esp_err_t err; //enable the power if on espressif SDIO master-slave board @@ -420,23 +417,23 @@ void app_main(void) ESP_LOGI(TAG, "host ready, start initializing slave..."); - err = slave_init(&context); + err = slave_init(&handle); ESP_ERROR_CHECK(err); - err = slave_reset(&context); + err = slave_reset(handle); ESP_ERROR_CHECK(err); uint32_t start, end; - job_write_reg(&context, 10); + job_write_reg(handle, 10); int times = 2; while (1) { - job_getint(&context); + job_getint(handle); start = xTaskGetTickCount(); while (1) { - process_event(&context); + process_event(handle); vTaskDelay(1); end = xTaskGetTickCount(); if ((end - start) * 1000 / CONFIG_FREERTOS_HZ > 5000) { @@ -449,11 +446,11 @@ void app_main(void) }; while (1) { - job_fifo(&context); + job_fifo(handle); start = xTaskGetTickCount(); while (1) { - process_event(&context); + process_event(handle); vTaskDelay(1); end = xTaskGetTickCount(); if ((end - start) * 1000 / CONFIG_FREERTOS_HZ > 2000) {