diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index d18ec6b892..c298ca40e5 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -163,6 +163,7 @@ menu "OpenThread" config OPENTHREAD_RCP_SPI bool "SPI RCP" + select GPIO_CTRL_FUNC_IN_IRAM help Select this to enable SPI connection to host. endchoice diff --git a/components/openthread/src/port/esp_openthread_spi_slave.c b/components/openthread/src/port/esp_openthread_spi_slave.c index 33268bb8c5..979e6067e7 100644 --- a/components/openthread/src/port/esp_openthread_spi_slave.c +++ b/components/openthread/src/port/esp_openthread_spi_slave.c @@ -17,10 +17,10 @@ #include "esp_attr.h" #include "esp_check.h" #include "esp_err.h" +#include "esp_heap_caps.h" #include "esp_openthread_common_macro.h" #include "esp_openthread_task_queue.h" #include "esp_openthread_types.h" -#include "esp_rom_sys.h" #include #include #include "driver/gpio.h" @@ -33,37 +33,38 @@ static const char *SPI_SLAVE_TAG = "spi_slave"; static void *s_context = NULL; -static uint8_t *s_prev_output_buf; -static uint16_t s_prev_output_len; -static uint8_t *s_prev_input_buf; -static uint16_t s_prev_input_len; +static uint8_t *s_output_buf; +static uint16_t s_output_len; +static uint8_t *s_input_buf; +static uint16_t s_input_len; static bool s_request_transaction = false; - -static esp_openthread_spi_slave_config_t s_spi_config; -static otPlatSpiSlaveTransactionProcessCallback s_process_callback = NULL; -static otPlatSpiSlaveTransactionCompleteCallback s_complete_callback = NULL; -static spi_slave_transaction_t s_spi_transaction; - typedef struct { uint16_t output_buf_len; uint16_t input_buf_len; } pending_transaction_t; +static otPlatSpiSlaveTransactionProcessCallback s_process_callback = NULL; +static otPlatSpiSlaveTransactionCompleteCallback s_complete_callback = NULL; + +static DRAM_ATTR esp_openthread_spi_slave_config_t *s_spi_config; +static DRAM_ATTR spi_slave_transaction_t *s_spi_transaction; +static DRAM_ATTR pending_transaction_t *s_pending_transaction; + static void IRAM_ATTR handle_spi_setup_done(spi_slave_transaction_t *trans) { if (s_request_transaction) { - gpio_set_level(s_spi_config.intr_pin, 0); + gpio_set_level(s_spi_config->intr_pin, 0); } } static void IRAM_ATTR handle_spi_transaction_done(spi_slave_transaction_t *trans) { - gpio_set_level(s_spi_config.intr_pin, 1); - pending_transaction_t *pending_transaction = (pending_transaction_t *)&(trans->user); + gpio_set_level(s_spi_config->intr_pin, 1); + pending_transaction_t *pending_transaction = (pending_transaction_t *)(trans->user); trans->trans_len /= CHAR_BIT; if (s_complete_callback && - s_complete_callback(s_context, (uint8_t *)trans->tx_buffer, pending_transaction->output_buf_len, + s_complete_callback(s_context, (void*)trans->tx_buffer, pending_transaction->output_buf_len, trans->rx_buffer, pending_transaction->input_buf_len, trans->trans_len)) { esp_openthread_task_queue_post(s_process_callback, s_context); } @@ -72,23 +73,38 @@ static void IRAM_ATTR handle_spi_transaction_done(spi_slave_transaction_t *trans esp_err_t esp_openthread_host_rcp_spi_init(const esp_openthread_platform_config_t *config) { - s_spi_config = config->host_config.spi_slave_config; + s_spi_config = heap_caps_malloc(sizeof(esp_openthread_spi_slave_config_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + ESP_RETURN_ON_FALSE(s_spi_config != NULL, ESP_ERR_NO_MEM, OT_PLAT_LOG_TAG, + "failed to allocate memory for SPI transaction on internal heap"); + memcpy(s_spi_config, &(config->host_config.spi_slave_config), sizeof(esp_openthread_spi_slave_config_t)); gpio_config_t io_conf = { .intr_type = GPIO_INTR_DISABLE, .mode = GPIO_MODE_OUTPUT, - .pin_bit_mask = (1 << s_spi_config.intr_pin), + .pin_bit_mask = (1 << s_spi_config->intr_pin), }; ESP_RETURN_ON_ERROR(gpio_config(&io_conf), OT_PLAT_LOG_TAG, "fail to configure SPI gpio"); - gpio_set_pull_mode(s_spi_config.bus_config.mosi_io_num, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(s_spi_config.bus_config.sclk_io_num, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(s_spi_config.slave_config.spics_io_num, GPIO_PULLUP_ONLY); + gpio_set_pull_mode(s_spi_config->bus_config.mosi_io_num, GPIO_PULLUP_ONLY); + gpio_set_pull_mode(s_spi_config->bus_config.sclk_io_num, GPIO_PULLUP_ONLY); + gpio_set_pull_mode(s_spi_config->slave_config.spics_io_num, GPIO_PULLUP_ONLY); + + s_spi_transaction = heap_caps_malloc(sizeof(spi_slave_transaction_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + s_pending_transaction = heap_caps_malloc(sizeof(pending_transaction_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (s_spi_transaction == NULL || s_pending_transaction == NULL) { + heap_caps_free(s_spi_config); + heap_caps_free(s_spi_transaction); + heap_caps_free(s_pending_transaction); + ESP_LOGE(OT_PLAT_LOG_TAG, "failed to allocate memory for SPI transaction on internal heap"); + return ESP_ERR_NO_MEM; + } + + s_spi_transaction->user = (void *)s_pending_transaction; /* Initialize SPI slave interface */ - s_spi_config.slave_config.post_setup_cb = handle_spi_setup_done; - s_spi_config.slave_config.post_trans_cb = handle_spi_transaction_done; - ESP_RETURN_ON_ERROR(spi_slave_initialize(s_spi_config.host_device, &s_spi_config.bus_config, - &s_spi_config.slave_config, SPI_DMA_CH_AUTO), + s_spi_config->slave_config.post_setup_cb = handle_spi_setup_done; + s_spi_config->slave_config.post_trans_cb = handle_spi_transaction_done; + ESP_RETURN_ON_ERROR(spi_slave_initialize(s_spi_config->host_device, &s_spi_config->bus_config, + &s_spi_config->slave_config, SPI_DMA_CH_AUTO), OT_PLAT_LOG_TAG, "fail to initialize SPI slave"); return ESP_OK; @@ -96,9 +112,15 @@ esp_err_t esp_openthread_host_rcp_spi_init(const esp_openthread_platform_config_ void esp_openthread_spi_slave_deinit(void) { - spi_slave_free(s_spi_config.host_device); - s_spi_config.slave_config.post_setup_cb = NULL; - s_spi_config.slave_config.post_trans_cb = NULL; + spi_slave_free(s_spi_config->host_device); + s_spi_config->slave_config.post_setup_cb = NULL; + s_spi_config->slave_config.post_trans_cb = NULL; + heap_caps_free(s_spi_config); + heap_caps_free(s_spi_transaction); + heap_caps_free(s_pending_transaction); + s_spi_config = NULL; + s_spi_transaction = NULL; + s_pending_transaction = NULL; return; } @@ -115,43 +137,38 @@ otError IRAM_ATTR otPlatSpiSlavePrepareTransaction(uint8_t *aOutputBuf, uint16_t uint16_t aInputBufLen, bool aRequestTransactionFlag) { esp_err_t trans_state = ESP_OK; - pending_transaction_t *pending_transaction = NULL; - if (aOutputBuf == NULL) { - aOutputBuf = s_prev_output_buf; - aOutputBufLen = s_prev_output_len; + uint16_t trans_length = 0; + + if (aOutputBuf != NULL) { + s_output_buf = aOutputBuf; + s_output_len = aOutputBufLen; } - if (aInputBuf == NULL) { - aInputBuf = s_prev_input_buf; - aInputBufLen = s_prev_input_len; + if (aInputBuf != NULL) { + s_input_buf = aInputBuf; + s_input_len = aInputBufLen; } - s_prev_output_buf = aOutputBuf; - s_prev_output_len = aOutputBufLen; - s_prev_input_buf = aInputBuf; - s_prev_input_len = aInputBufLen; - s_spi_transaction.length = aOutputBufLen > aInputBufLen ? aOutputBufLen : aInputBufLen; - s_spi_transaction.length *= CHAR_BIT; - s_spi_transaction.rx_buffer = aInputBuf; - s_spi_transaction.tx_buffer = aOutputBuf; - - assert(sizeof(s_spi_transaction.user) >= sizeof(pending_transaction_t)); - pending_transaction = (pending_transaction_t *)&(s_spi_transaction.user); - pending_transaction->input_buf_len = aInputBufLen; - pending_transaction->output_buf_len = aOutputBufLen; - s_spi_transaction.user = pending_transaction; - s_request_transaction = aRequestTransactionFlag; - - if ((gpio_get_level(s_spi_config.slave_config.spics_io_num) == 0)) { + trans_length = s_output_len > s_input_len ? s_output_len : s_input_len; + trans_length *= CHAR_BIT; + if ((gpio_get_level(s_spi_config->slave_config.spics_io_num) == 0)) { ESP_EARLY_LOGE(SPI_SLAVE_TAG, "SPI busy"); return OT_ERROR_BUSY; } + s_spi_transaction->length = trans_length; + s_spi_transaction->rx_buffer = s_input_buf; + s_spi_transaction->tx_buffer = s_output_buf; + + pending_transaction_t *pending_transaction = (pending_transaction_t *)s_spi_transaction->user; + pending_transaction->input_buf_len = s_input_len; + pending_transaction->output_buf_len = s_output_len; + s_request_transaction = aRequestTransactionFlag; if (xPortCanYield()) { - spi_slave_queue_reset(s_spi_config.host_device); - trans_state = spi_slave_queue_trans(s_spi_config.host_device, &s_spi_transaction, 0); + spi_slave_queue_reset(s_spi_config->host_device); + trans_state = spi_slave_queue_trans(s_spi_config->host_device, s_spi_transaction, 0); } else { - spi_slave_queue_reset_isr(s_spi_config.host_device); - trans_state = spi_slave_queue_trans_isr(s_spi_config.host_device, &s_spi_transaction); + spi_slave_queue_reset_isr(s_spi_config->host_device); + trans_state = spi_slave_queue_trans_isr(s_spi_config->host_device, s_spi_transaction); } if (trans_state == ESP_OK) {