feat(driver): updated drivers to use CreateWithCaps() API

This commit simplifies various drivers by using the ...CreateWithCaps() API
when creating driver objects in internal RAM.
This commit is contained in:
Darian Leung 2023-06-28 10:47:19 +01:00 committed by morris
parent 31d87a0c59
commit 9ed58bf564
9 changed files with 118 additions and 313 deletions

View File

@ -10,6 +10,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/idf_additions.h"
#include "sdkconfig.h"
#include "rom/lldesc.h"
@ -70,12 +71,8 @@ struct dac_continuous_s {
esp_pm_lock_handle_t pm_lock;
#endif
SemaphoreHandle_t mutex;
StaticSemaphore_t mutex_struct; /* Static mutex struct */
QueueHandle_t desc_pool; /* The pool of available descriptors
* The descriptors in the pool are not linked in to pending chain */
StaticQueue_t desc_pool_struct; /* Static message queue struct */
void *desc_pool_storage; /* Static message queue storage */
lldesc_t **desc;
uint8_t **bufs;
@ -224,14 +221,10 @@ esp_err_t dac_continuous_new_channels(const dac_continuous_config_t *cont_cfg, d
dac_continuous_handle_t handle = heap_caps_calloc(1, sizeof(struct dac_continuous_s), DAC_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(handle, ESP_ERR_NO_MEM, TAG, "no memory for the dac continuous mode structure");
/* Allocate static queue */
handle->desc_pool_storage = (uint8_t *)heap_caps_calloc(cont_cfg->desc_num, sizeof(lldesc_t *), DAC_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(handle->desc_pool_storage, ESP_ERR_NO_MEM, err3, TAG, "no memory for message queue storage");
handle->desc_pool = xQueueCreateStatic(cont_cfg->desc_num, sizeof(lldesc_t *), handle->desc_pool_storage, &handle->desc_pool_struct);
/* Allocate queue and mutex*/
handle->desc_pool = xQueueCreateWithCaps(cont_cfg->desc_num, sizeof(lldesc_t *), DAC_MEM_ALLOC_CAPS);
handle->mutex = xSemaphoreCreateMutexWithCaps(DAC_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(handle->desc_pool, ESP_ERR_NO_MEM, err3, TAG, "no memory for message queue");
/* Allocate static mutex */
handle->mutex = xSemaphoreCreateMutexStatic(&handle->mutex_struct);
ESP_GOTO_ON_FALSE(handle->mutex, ESP_ERR_NO_MEM, err3, TAG, "no memory for channels mutex");
/* Create PM lock */
@ -273,13 +266,10 @@ err2:
s_dac_free_dma_desc(handle);
err3:
if (handle->desc_pool) {
vQueueDelete(handle->desc_pool);
}
if (handle->desc_pool_storage) {
free(handle->desc_pool_storage);
vQueueDeleteWithCaps(handle->desc_pool);
}
if (handle->mutex) {
vSemaphoreDelete(handle->mutex);
vSemaphoreDeleteWithCaps(handle->mutex);
}
free(handle);
err4:
@ -312,15 +302,11 @@ esp_err_t dac_continuous_del_channels(dac_continuous_handle_t handle)
/* Free allocated resources */
s_dac_free_dma_desc(handle);
if (handle->desc_pool) {
vQueueDelete(handle->desc_pool);
vQueueDeleteWithCaps(handle->desc_pool);
handle->desc_pool = NULL;
}
if (handle->desc_pool_storage) {
free(handle->desc_pool_storage);
handle->desc_pool_storage = NULL;
}
if (handle->mutex) {
vSemaphoreDelete(handle->mutex);
vSemaphoreDeleteWithCaps(handle->mutex);
handle->mutex = NULL;
}
#if CONFIG_PM_ENABLE

View File

@ -16,6 +16,7 @@
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "freertos/ringbuf.h"
#include "freertos/idf_additions.h"
#include "esp_pm.h"
#include "soc/soc_memory_layout.h"
#include "hal/i2c_hal.h"
@ -104,6 +105,11 @@ static const char *I2C_TAG = "i2c";
#define I2C_CLOCK_INVALID (-1)
#if CONFIG_SPIRAM_USE_MALLOC
#define I2C_MEM_ALLOC_CAPS_INTERNAL (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#endif
#define I2C_MEM_ALLOC_CAPS_DEFAULT MALLOC_CAP_DEFAULT
/**
* I2C bus are defined in the header files, let's check that the values are correct
*/
@ -169,9 +175,7 @@ typedef struct {
i2c_cmd_desc_t cmd_link; /*!< I2C command link */
QueueHandle_t cmd_evt_queue; /*!< I2C command event queue */
#if CONFIG_SPIRAM_USE_MALLOC
uint8_t *evt_queue_storage; /*!< The buffer that will hold the items in the queue */
int intr_alloc_flags; /*!< Used to allocate the interrupt */
StaticQueue_t evt_queue_buffer; /*!< The buffer that will hold the queue structure*/
#endif
SemaphoreHandle_t cmd_mux; /*!< semaphore to lock command process */
#ifdef CONFIG_PM_ENABLE
@ -274,16 +278,13 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
esp_err_t ret = ESP_OK;
if (p_i2c_obj[i2c_num] == NULL) {
#if !CONFIG_SPIRAM_USE_MALLOC
p_i2c_obj[i2c_num] = (i2c_obj_t *) calloc(1, sizeof(i2c_obj_t));
uint32_t alloc_caps;
#if CONFIG_SPIRAM_USE_MALLOC
alloc_caps = (intr_alloc_flags & ESP_INTR_FLAG_IRAM) ? I2C_MEM_ALLOC_CAPS_INTERNAL : I2C_MEM_ALLOC_CAPS_DEFAULT;
#else
if ( !(intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) {
p_i2c_obj[i2c_num] = (i2c_obj_t *) calloc(1, sizeof(i2c_obj_t));
} else {
p_i2c_obj[i2c_num] = (i2c_obj_t *) heap_caps_calloc(1, sizeof(i2c_obj_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
}
alloc_caps = I2C_MEM_ALLOC_CAPS_DEFAULT;
#endif
p_i2c_obj[i2c_num] = (i2c_obj_t *) heap_caps_calloc(1, sizeof(i2c_obj_t), alloc_caps);
if (p_i2c_obj[i2c_num] == NULL) {
ESP_LOGE(I2C_TAG, I2C_DRIVER_MALLOC_ERR_STR);
return ESP_FAIL;
@ -348,21 +349,13 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_
goto err;
}
#endif
#if !CONFIG_SPIRAM_USE_MALLOC
p_i2c->cmd_evt_queue = xQueueCreate(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t));
uint32_t alloc_caps;
#if CONFIG_SPIRAM_USE_MALLOC
alloc_caps = (intr_alloc_flags & ESP_INTR_FLAG_IRAM) ? I2C_MEM_ALLOC_CAPS_INTERNAL : I2C_MEM_ALLOC_CAPS_DEFAULT;
#else
if ( !(intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) {
p_i2c->cmd_evt_queue = xQueueCreate(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t));
} else {
p_i2c->evt_queue_storage = (uint8_t *)heap_caps_calloc(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if ( p_i2c->evt_queue_storage == NULL ) {
ESP_LOGE(I2C_TAG, I2C_DRIVER_MALLOC_ERR_STR);
goto err;
}
memset(&p_i2c->evt_queue_buffer, 0, sizeof(StaticQueue_t));
p_i2c->cmd_evt_queue = xQueueCreateStatic(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t), p_i2c->evt_queue_storage, &p_i2c->evt_queue_buffer);
}
alloc_caps = I2C_MEM_ALLOC_CAPS_DEFAULT;
#endif
p_i2c->cmd_evt_queue = xQueueCreateWithCaps(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t), alloc_caps);
if (p_i2c->cmd_mux == NULL || p_i2c->cmd_evt_queue == NULL) {
ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR);
goto err;
@ -413,7 +406,7 @@ err:
p_i2c_obj[i2c_num]->tx_buf_length = 0;
}
if (p_i2c_obj[i2c_num]->cmd_evt_queue) {
vQueueDelete(p_i2c_obj[i2c_num]->cmd_evt_queue);
vQueueDeleteWithCaps(p_i2c_obj[i2c_num]->cmd_evt_queue);
p_i2c_obj[i2c_num]->cmd_evt_queue = NULL;
}
if (p_i2c_obj[i2c_num]->cmd_mux) {
@ -432,12 +425,6 @@ err:
esp_pm_lock_delete(p_i2c_obj[i2c_num]->pm_lock);
p_i2c_obj[i2c_num]->pm_lock = NULL;
}
#endif
#if CONFIG_SPIRAM_USE_MALLOC
if (p_i2c_obj[i2c_num]->evt_queue_storage) {
free(p_i2c_obj[i2c_num]->evt_queue_storage);
p_i2c_obj[i2c_num]->evt_queue_storage = NULL;
}
#endif
}
free(p_i2c_obj[i2c_num]);
@ -462,7 +449,7 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
vSemaphoreDelete(p_i2c->cmd_mux);
}
if (p_i2c_obj[i2c_num]->cmd_evt_queue) {
vQueueDelete(p_i2c_obj[i2c_num]->cmd_evt_queue);
vQueueDeleteWithCaps(p_i2c_obj[i2c_num]->cmd_evt_queue);
p_i2c_obj[i2c_num]->cmd_evt_queue = NULL;
}
#if SOC_I2C_SUPPORT_SLAVE
@ -490,12 +477,6 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num)
p_i2c->pm_lock = NULL;
}
#endif
#if CONFIG_SPIRAM_USE_MALLOC
if (p_i2c_obj[i2c_num]->evt_queue_storage) {
free(p_i2c_obj[i2c_num]->evt_queue_storage);
p_i2c_obj[i2c_num]->evt_queue_storage = NULL;
}
#endif
i2c_hal_deinit(&i2c_context[i2c_num].hal);
free(p_i2c_obj[i2c_num]);
@ -1122,11 +1103,13 @@ i2c_cmd_handle_t i2c_cmd_link_create_static(uint8_t* buffer, uint32_t size)
i2c_cmd_handle_t i2c_cmd_link_create(void)
{
#if !CONFIG_SPIRAM_USE_MALLOC
i2c_cmd_desc_t *cmd_desc = (i2c_cmd_desc_t *) calloc(1, sizeof(i2c_cmd_desc_t));
uint32_t alloc_caps;
#if CONFIG_SPIRAM_USE_MALLOC
alloc_caps = I2C_MEM_ALLOC_CAPS_INTERNAL;
#else
i2c_cmd_desc_t *cmd_desc = (i2c_cmd_desc_t *) heap_caps_calloc(1, sizeof(i2c_cmd_desc_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
alloc_caps = I2C_MEM_ALLOC_CAPS_DEFAULT;
#endif
i2c_cmd_desc_t *cmd_desc = (i2c_cmd_desc_t *) heap_caps_calloc(1, sizeof(i2c_cmd_desc_t), alloc_caps);
return (i2c_cmd_handle_t) cmd_desc;
}
@ -1182,11 +1165,13 @@ static esp_err_t i2c_cmd_allocate(i2c_cmd_desc_t *cmd_desc, size_t n, size_t siz
cmd_desc->free_size -= required;
}
} else {
#if !CONFIG_SPIRAM_USE_MALLOC
*outptr = calloc(n, size);
uint32_t alloc_caps;
#if CONFIG_SPIRAM_USE_MALLOC
alloc_caps = I2C_MEM_ALLOC_CAPS_INTERNAL;
#else
*outptr = heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
alloc_caps = I2C_MEM_ALLOC_CAPS_DEFAULT;
#endif
*outptr = heap_caps_calloc(n, size, alloc_caps);
if (*outptr == NULL) {
err = ESP_FAIL;
}

View File

@ -10,6 +10,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/idf_additions.h"
#include "sdkconfig.h"
@ -246,29 +247,12 @@ static esp_err_t i2s_register_channel(i2s_controller_t *i2s_obj, i2s_dir_t dir,
#if CONFIG_PM_ENABLE
new_chan->pm_lock = NULL; // Init in i2s_set_clock according to clock source
#endif
#if CONFIG_I2S_ISR_IRAM_SAFE
new_chan->msg_que_storage = (uint8_t *)heap_caps_calloc(desc_num - 1, sizeof(uint8_t *), I2S_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(new_chan->msg_que_storage, ESP_ERR_NO_MEM, err, TAG, "No memory for message queue storage");
new_chan->msg_que_struct = (StaticQueue_t *)heap_caps_calloc(1, sizeof(StaticQueue_t), I2S_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(new_chan->msg_que_struct, ESP_ERR_NO_MEM, err, TAG, "No memory for message queue struct");
new_chan->msg_queue = xQueueCreateStatic(desc_num - 1, sizeof(uint8_t *), new_chan->msg_que_storage, new_chan->msg_que_struct);
new_chan->msg_queue = xQueueCreateWithCaps(desc_num - 1, sizeof(uint8_t *), I2S_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(new_chan->msg_queue, ESP_ERR_NO_MEM, err, TAG, "No memory for message queue");
new_chan->mutex_struct = (StaticSemaphore_t *)heap_caps_calloc(1, sizeof(StaticSemaphore_t), I2S_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(new_chan->mutex_struct, ESP_ERR_NO_MEM, err, TAG, "No memory for mutex struct");
new_chan->mutex = xSemaphoreCreateMutexStatic(new_chan->mutex_struct);
ESP_GOTO_ON_FALSE(new_chan->mutex, ESP_ERR_NO_MEM, err, TAG, "No memory for mutex");
new_chan->binary_struct = (StaticSemaphore_t *)heap_caps_calloc(1, sizeof(StaticSemaphore_t), I2S_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(new_chan->binary_struct, ESP_ERR_NO_MEM, err, TAG, "No memory for binary struct");
new_chan->binary = xSemaphoreCreateBinaryStatic(new_chan->binary_struct);
ESP_GOTO_ON_FALSE(new_chan->binary, ESP_ERR_NO_MEM, err, TAG, "No memory for binary");
#else
new_chan->msg_queue = xQueueCreate(desc_num - 1, sizeof(uint8_t *));
ESP_GOTO_ON_FALSE(new_chan->msg_queue, ESP_ERR_NO_MEM, err, TAG, "No memory for message queue");
new_chan->mutex = xSemaphoreCreateMutex();
new_chan->mutex = xSemaphoreCreateMutexWithCaps(I2S_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(new_chan->mutex, ESP_ERR_NO_MEM, err, TAG, "No memory for mutex semaphore");
new_chan->binary = xSemaphoreCreateBinary();
new_chan->binary = xSemaphoreCreateBinaryWithCaps(I2S_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(new_chan->binary, ESP_ERR_NO_MEM, err, TAG, "No memory for binary semaphore");
#endif
new_chan->callbacks.on_recv = NULL;
new_chan->callbacks.on_recv_q_ovf = NULL;
@ -293,28 +277,14 @@ static esp_err_t i2s_register_channel(i2s_controller_t *i2s_obj, i2s_dir_t dir,
}
return ret;
err:
#if CONFIG_I2S_ISR_IRAM_SAFE
if (new_chan->msg_que_storage) {
free(new_chan->msg_que_storage);
}
if (new_chan->msg_que_struct) {
free(new_chan->msg_que_struct);
}
if (new_chan->mutex_struct) {
free(new_chan->mutex_struct);
}
if (new_chan->binary_struct) {
free(new_chan->binary_struct);
}
#endif
if (new_chan->msg_queue) {
vQueueDelete(new_chan->msg_queue);
vQueueDeleteWithCaps(new_chan->msg_queue);
}
if (new_chan->mutex) {
vSemaphoreDelete(new_chan->mutex);
vSemaphoreDeleteWithCaps(new_chan->mutex);
}
if (new_chan->binary) {
vSemaphoreDelete(new_chan->binary);
vSemaphoreDeleteWithCaps(new_chan->binary);
}
free(new_chan);
@ -895,28 +865,14 @@ esp_err_t i2s_del_channel(i2s_chan_handle_t handle)
if (handle->dma.desc) {
i2s_free_dma_desc(handle);
}
#if CONFIG_I2S_ISR_IRAM_SAFE
if (handle->msg_que_storage) {
free(handle->msg_que_storage);
}
if (handle->msg_que_struct) {
free(handle->msg_que_struct);
}
if (handle->mutex) {
free(handle->mutex_struct);
}
if (handle->binary_struct) {
free(handle->binary_struct);
}
#endif
if (handle->msg_queue) {
vQueueDelete(handle->msg_queue);
vQueueDeleteWithCaps(handle->msg_queue);
}
if (handle->mutex) {
vSemaphoreDelete(handle->mutex);
vSemaphoreDeleteWithCaps(handle->mutex);
}
if (handle->binary) {
vSemaphoreDelete(handle->binary);
vSemaphoreDeleteWithCaps(handle->binary);
}
#if SOC_I2S_HW_VERSION_1
i2s_obj->chan_occupancy = 0;

View File

@ -99,12 +99,6 @@ struct i2s_channel_obj_t {
SemaphoreHandle_t binary; /*!< Binary semaphore for writing / reading / enabling / disabling */
#if CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock; /*!< Power management lock, to avoid apb clock frequency changes while i2s is working */
#endif
#if CONFIG_I2S_ISR_IRAM_SAFE
StaticSemaphore_t *mutex_struct; /*!< Static mutex struct */
StaticSemaphore_t *binary_struct; /*!< Static binary struct */
StaticQueue_t *msg_que_struct; /*!< Static message queue struct */
void *msg_que_storage; /*!< Static message queue storage */
#endif
QueueHandle_t msg_queue; /*!< Message queue handler, used for transporting data between interrupt and read/write task */
i2s_event_callbacks_t callbacks; /*!< Callback functions */

View File

@ -13,6 +13,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/idf_additions.h"
#if CONFIG_PARLIO_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
@ -59,9 +60,7 @@ typedef struct parlio_tx_unit_t {
size_t max_transfer_bits; // maximum transfer size in bits
size_t queue_depth; // size of transaction queue
size_t num_trans_inflight; // indicates the number of transactions that are undergoing but not recycled to ready_queue
void *queues_storage; // storage of transaction queues
QueueHandle_t trans_queues[PARLIO_TX_QUEUE_MAX]; // transaction queues
StaticQueue_t trans_queue_structs[PARLIO_TX_QUEUE_MAX]; // memory to store the static structure for trans_queues
parlio_tx_trans_desc_t *cur_trans; // points to current transaction
uint32_t idle_value_mask; // mask of idle value
_Atomic parlio_tx_fsm_t fsm; // Driver FSM state
@ -113,26 +112,33 @@ static void parlio_tx_unregister_to_group(parlio_tx_unit_t *unit, parlio_group_t
static esp_err_t parlio_tx_create_trans_queue(parlio_tx_unit_t *tx_unit, const parlio_tx_unit_config_t *config)
{
esp_err_t ret;
tx_unit->queue_depth = config->trans_queue_depth;
// the queue only saves transaction description pointers
tx_unit->queues_storage = heap_caps_calloc(config->trans_queue_depth * PARLIO_TX_QUEUE_MAX, sizeof(parlio_tx_trans_desc_t *), PARLIO_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(tx_unit->queues_storage, ESP_ERR_NO_MEM, TAG, "no mem for queue storage");
parlio_tx_trans_desc_t **pp_trans_desc = (parlio_tx_trans_desc_t **)tx_unit->queues_storage;
// Allocate transaction queues. Each queue only holds pointers to the transaction descriptors
for (int i = 0; i < PARLIO_TX_QUEUE_MAX; i++) {
tx_unit->trans_queues[i] = xQueueCreateStatic(config->trans_queue_depth, sizeof(parlio_tx_trans_desc_t *),
(uint8_t *)pp_trans_desc, &tx_unit->trans_queue_structs[i]);
pp_trans_desc += config->trans_queue_depth;
// because trans_queue_structs is guaranteed to be non-NULL, so the trans_queues will also not be NULL
assert(tx_unit->trans_queues[i]);
tx_unit->trans_queues[i] = xQueueCreateWithCaps(config->trans_queue_depth, sizeof(parlio_tx_trans_desc_t *), PARLIO_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(tx_unit->trans_queues[i], ESP_ERR_NO_MEM, exit, TAG, "no mem for queue");
}
// initialize the ready queue
// Initialize the ready queue
parlio_tx_trans_desc_t *p_trans_desc = NULL;
for (int i = 0; i < config->trans_queue_depth; i++) {
p_trans_desc = &tx_unit->trans_desc_pool[i];
ESP_RETURN_ON_FALSE(xQueueSend(tx_unit->trans_queues[PARLIO_TX_QUEUE_READY], &p_trans_desc, 0) == pdTRUE,
ESP_ERR_INVALID_STATE, TAG, "ready queue full");
ESP_GOTO_ON_FALSE(xQueueSend(tx_unit->trans_queues[PARLIO_TX_QUEUE_READY], &p_trans_desc, 0) == pdTRUE,
ESP_ERR_INVALID_STATE, exit, TAG, "ready queue full");
}
return ESP_OK;
exit:
for (int i = 0; i < PARLIO_TX_QUEUE_MAX; i++) {
if (tx_unit->trans_queues[i]) {
vQueueDeleteWithCaps(tx_unit->trans_queues[i]);
tx_unit->trans_queues[i] = NULL;
}
}
return ret;
}
static esp_err_t parlio_destroy_tx_unit(parlio_tx_unit_t *tx_unit)
@ -149,14 +155,13 @@ static esp_err_t parlio_destroy_tx_unit(parlio_tx_unit_t *tx_unit)
}
for (int i = 0; i < PARLIO_TX_QUEUE_MAX; i++) {
if (tx_unit->trans_queues[i]) {
vQueueDelete(tx_unit->trans_queues[i]);
vQueueDeleteWithCaps(tx_unit->trans_queues[i]);
}
}
if (tx_unit->group) {
// de-register from group
parlio_tx_unregister_to_group(tx_unit, tx_unit->group);
}
free(tx_unit->queues_storage);
free(tx_unit->dma_nodes);
free(tx_unit);
return ESP_OK;

View File

@ -10,6 +10,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/idf_additions.h"
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "hal/rmt_types.h"
@ -139,9 +140,7 @@ struct rmt_tx_channel_t {
size_t ping_pong_symbols; // ping-pong size (half of the RMT channel memory)
size_t queue_size; // size of transaction queue
size_t num_trans_inflight; // indicates the number of transactions that are undergoing but not recycled to ready_queue
void *queues_storage; // storage of transaction queues
QueueHandle_t trans_queues[RMT_TX_QUEUE_MAX]; // transaction queues
StaticQueue_t trans_queue_structs[RMT_TX_QUEUE_MAX]; // memory to store the static structure for trans_queues
rmt_tx_trans_desc_t *cur_trans; // points to current transaction
void *user_data; // user context
rmt_tx_done_callback_t on_trans_done; // callback, invoked on trans done

View File

@ -145,26 +145,33 @@ static void rmt_tx_unregister_from_group(rmt_channel_t *channel, rmt_group_t *gr
static esp_err_t rmt_tx_create_trans_queue(rmt_tx_channel_t *tx_channel, const rmt_tx_channel_config_t *config)
{
esp_err_t ret;
tx_channel->queue_size = config->trans_queue_depth;
// the queue only saves transaction description pointers
tx_channel->queues_storage = heap_caps_calloc(config->trans_queue_depth * RMT_TX_QUEUE_MAX, sizeof(rmt_tx_trans_desc_t *), RMT_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(tx_channel->queues_storage, ESP_ERR_NO_MEM, TAG, "no mem for queue storage");
rmt_tx_trans_desc_t **pp_trans_desc = (rmt_tx_trans_desc_t **)tx_channel->queues_storage;
// Allocate transaction queues. Each queue only holds pointers to the transaction descriptors
for (int i = 0; i < RMT_TX_QUEUE_MAX; i++) {
tx_channel->trans_queues[i] = xQueueCreateStatic(config->trans_queue_depth, sizeof(rmt_tx_trans_desc_t *),
(uint8_t *)pp_trans_desc, &tx_channel->trans_queue_structs[i]);
pp_trans_desc += config->trans_queue_depth;
// sanity check
assert(tx_channel->trans_queues[i]);
tx_channel->trans_queues[i] = xQueueCreateWithCaps(config->trans_queue_depth, sizeof(rmt_tx_trans_desc_t *), RMT_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(tx_channel->trans_queues[i], ESP_ERR_NO_MEM, exit, TAG, "no mem for queues");
}
// initialize the ready queue
// Initialize the ready queue
rmt_tx_trans_desc_t *p_trans_desc = NULL;
for (int i = 0; i < config->trans_queue_depth; i++) {
p_trans_desc = &tx_channel->trans_desc_pool[i];
ESP_RETURN_ON_FALSE(xQueueSend(tx_channel->trans_queues[RMT_TX_QUEUE_READY], &p_trans_desc, 0) == pdTRUE,
ESP_ERR_INVALID_STATE, TAG, "ready queue full");
ESP_GOTO_ON_FALSE(xQueueSend(tx_channel->trans_queues[RMT_TX_QUEUE_READY], &p_trans_desc, 0) == pdTRUE,
ESP_ERR_INVALID_STATE, exit, TAG, "ready queue full");
}
return ESP_OK;
exit:
for (int i = 0; i < RMT_TX_QUEUE_MAX; i++) {
if (tx_channel->trans_queues[i]) {
vQueueDeleteWithCaps(tx_channel->trans_queues[i]);
tx_channel->trans_queues[i] = NULL;
}
}
return ret;
}
static esp_err_t rmt_tx_destroy(rmt_tx_channel_t *tx_channel)
@ -182,12 +189,9 @@ static esp_err_t rmt_tx_destroy(rmt_tx_channel_t *tx_channel)
#endif // SOC_RMT_SUPPORT_DMA
for (int i = 0; i < RMT_TX_QUEUE_MAX; i++) {
if (tx_channel->trans_queues[i]) {
vQueueDelete(tx_channel->trans_queues[i]);
vQueueDeleteWithCaps(tx_channel->trans_queues[i]);
}
}
if (tx_channel->queues_storage) {
free(tx_channel->queues_storage);
}
if (tx_channel->base.dma_mem_base) {
free(tx_channel->base.dma_mem_base);
}
@ -380,7 +384,6 @@ esp_err_t rmt_new_sync_manager(const rmt_sync_manager_config_t *config, rmt_sync
}
portEXIT_CRITICAL(&group->spinlock);
*ret_synchro = synchro;
ESP_LOGD(TAG, "new sync manager at %p, with channel mask:%02"PRIx32, synchro, synchro->channel_mask);
return ESP_OK;

View File

@ -9,6 +9,7 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/idf_additions.h"
#include "esp_types.h"
#include "esp_log.h"
#include "esp_intr_alloc.h"
@ -71,13 +72,6 @@ typedef struct {
uint32_t bus_error_count;
intr_handle_t isr_handle;
//TX and RX
#ifdef CONFIG_TWAI_ISR_IN_IRAM
void *tx_queue_buff;
void *tx_queue_struct;
void *rx_queue_buff;
void *rx_queue_struct;
void *semphr_struct;
#endif
QueueHandle_t tx_queue;
QueueHandle_t rx_queue;
int tx_msg_count;
@ -331,23 +325,15 @@ static void twai_free_driver_obj(twai_obj_t *p_obj)
}
//Delete queues and semaphores
if (p_obj->tx_queue != NULL) {
vQueueDelete(p_obj->tx_queue);
vQueueDeleteWithCaps(p_obj->tx_queue);
}
if (p_obj->rx_queue != NULL) {
vQueueDelete(p_obj->rx_queue);
vQueueDeleteWithCaps(p_obj->rx_queue);
}
if (p_obj->alert_semphr != NULL) {
vSemaphoreDelete(p_obj->alert_semphr);
vSemaphoreDeleteWithCaps(p_obj->alert_semphr);
}
#ifdef CONFIG_TWAI_ISR_IN_IRAM
//Free memory used by static queues and semaphores. free() allows freeing NULL pointers
free(p_obj->tx_queue_buff);
free(p_obj->tx_queue_struct);
free(p_obj->rx_queue_buff);
free(p_obj->rx_queue_struct);
free(p_obj->semphr_struct);
#endif //CONFIG_TWAI_ISR_IN_IRAM
free(p_obj);
heap_caps_free(p_obj);
}
static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, twai_clock_source_t clk_src, int controller_id, twai_obj_t **p_twai_obj_ret)
@ -360,48 +346,15 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw
if (p_obj == NULL) {
return ESP_ERR_NO_MEM;
}
#ifdef CONFIG_TWAI_ISR_IN_IRAM
//Allocate memory for queues and semaphores in DRAM
if (g_config->tx_queue_len > 0) {
p_obj->tx_queue_buff = heap_caps_calloc(g_config->tx_queue_len, sizeof(twai_hal_frame_t), TWAI_MALLOC_CAPS);
p_obj->tx_queue_struct = heap_caps_calloc(1, sizeof(StaticQueue_t), TWAI_MALLOC_CAPS);
if (p_obj->tx_queue_buff == NULL || p_obj->tx_queue_struct == NULL) {
ret = ESP_ERR_NO_MEM;
goto err;
}
p_obj->tx_queue = xQueueCreateWithCaps(g_config->tx_queue_len, sizeof(twai_hal_frame_t), TWAI_MALLOC_CAPS);
}
p_obj->rx_queue_buff = heap_caps_calloc(g_config->rx_queue_len, sizeof(twai_hal_frame_t), TWAI_MALLOC_CAPS);
p_obj->rx_queue_struct = heap_caps_calloc(1, sizeof(StaticQueue_t), TWAI_MALLOC_CAPS);
p_obj->semphr_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), TWAI_MALLOC_CAPS);
if (p_obj->rx_queue_buff == NULL || p_obj->rx_queue_struct == NULL || p_obj->semphr_struct == NULL) {
ret = ESP_ERR_NO_MEM;
goto err;
}
//Create static queues and semaphores
if (g_config->tx_queue_len > 0) {
p_obj->tx_queue = xQueueCreateStatic(g_config->tx_queue_len, sizeof(twai_hal_frame_t), p_obj->tx_queue_buff, p_obj->tx_queue_struct);
if (p_obj->tx_queue == NULL) {
ret = ESP_ERR_NO_MEM;
goto err;
}
}
p_obj->rx_queue = xQueueCreateStatic(g_config->rx_queue_len, sizeof(twai_hal_frame_t), p_obj->rx_queue_buff, p_obj->rx_queue_struct);
p_obj->alert_semphr = xSemaphoreCreateBinaryStatic(p_obj->semphr_struct);
if (p_obj->rx_queue == NULL || p_obj->alert_semphr == NULL) {
ret = ESP_ERR_NO_MEM;
goto err;
}
#else //CONFIG_TWAI_ISR_IN_IRAM
if (g_config->tx_queue_len > 0) {
p_obj->tx_queue = xQueueCreate(g_config->tx_queue_len, sizeof(twai_hal_frame_t));
}
p_obj->rx_queue = xQueueCreate(g_config->rx_queue_len, sizeof(twai_hal_frame_t));
p_obj->alert_semphr = xSemaphoreCreateBinary();
p_obj->rx_queue = xQueueCreateWithCaps(g_config->rx_queue_len, sizeof(twai_hal_frame_t), TWAI_MALLOC_CAPS);
p_obj->alert_semphr = xSemaphoreCreateBinaryWithCaps(TWAI_MALLOC_CAPS);
if ((g_config->tx_queue_len > 0 && p_obj->tx_queue == NULL) || p_obj->rx_queue == NULL || p_obj->alert_semphr == NULL) {
ret = ESP_ERR_NO_MEM;
goto err;
}
#endif //CONFIG_TWAI_ISR_IN_IRAM
//Allocate interrupt
ret = esp_intr_alloc(twai_controller_periph_signals.controllers[controller_id].irq_id,
g_config->intr_flags | ESP_INTR_FLAG_INTRDISABLED,

View File

@ -13,8 +13,10 @@
#include "esp_check.h"
#include "malloc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/ringbuf.h"
#include "freertos/idf_additions.h"
#include "esp_private/critical_section.h"
#include "hal/uart_hal.h"
#include "hal/gpio_hal.h"
@ -144,19 +146,6 @@ typedef struct {
SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/
SemaphoreHandle_t tx_done_sem; /*!< UART TX done semaphore*/
SemaphoreHandle_t tx_brk_sem; /*!< UART TX send break done semaphore*/
#if CONFIG_UART_ISR_IN_IRAM
void *event_queue_storage;
void *event_queue_struct;
void *rx_ring_buf_storage;
void *rx_ring_buf_struct;
void *tx_ring_buf_storage;
void *tx_ring_buf_struct;
void *rx_mux_struct;
void *tx_mux_struct;
void *tx_fifo_sem_struct;
void *tx_done_sem_struct;
void *tx_brk_sem_struct;
#endif
} uart_obj_t;
typedef struct {
@ -1480,44 +1469,32 @@ esp_err_t uart_flush_input(uart_port_t uart_num)
static void uart_free_driver_obj(uart_obj_t *uart_obj)
{
if (uart_obj->tx_fifo_sem) {
vSemaphoreDelete(uart_obj->tx_fifo_sem);
vSemaphoreDeleteWithCaps(uart_obj->tx_fifo_sem);
}
if (uart_obj->tx_done_sem) {
vSemaphoreDelete(uart_obj->tx_done_sem);
vSemaphoreDeleteWithCaps(uart_obj->tx_done_sem);
}
if (uart_obj->tx_brk_sem) {
vSemaphoreDelete(uart_obj->tx_brk_sem);
vSemaphoreDeleteWithCaps(uart_obj->tx_brk_sem);
}
if (uart_obj->tx_mux) {
vSemaphoreDelete(uart_obj->tx_mux);
vSemaphoreDeleteWithCaps(uart_obj->tx_mux);
}
if (uart_obj->rx_mux) {
vSemaphoreDelete(uart_obj->rx_mux);
vSemaphoreDeleteWithCaps(uart_obj->rx_mux);
}
if (uart_obj->event_queue) {
vQueueDelete(uart_obj->event_queue);
vQueueDeleteWithCaps(uart_obj->event_queue);
}
if (uart_obj->rx_ring_buf) {
vRingbufferDelete(uart_obj->rx_ring_buf);
vRingbufferDeleteWithCaps(uart_obj->rx_ring_buf);
}
if (uart_obj->tx_ring_buf) {
vRingbufferDelete(uart_obj->tx_ring_buf);
vRingbufferDeleteWithCaps(uart_obj->tx_ring_buf);
}
#if CONFIG_UART_ISR_IN_IRAM
free(uart_obj->event_queue_storage);
free(uart_obj->event_queue_struct);
free(uart_obj->tx_ring_buf_storage);
free(uart_obj->tx_ring_buf_struct);
free(uart_obj->rx_ring_buf_storage);
free(uart_obj->rx_ring_buf_struct);
free(uart_obj->rx_mux_struct);
free(uart_obj->tx_mux_struct);
free(uart_obj->tx_brk_sem_struct);
free(uart_obj->tx_done_sem_struct);
free(uart_obj->tx_fifo_sem_struct);
#endif
free(uart_obj->rx_data_buf);
free(uart_obj);
heap_caps_free(uart_obj->rx_data_buf);
heap_caps_free(uart_obj);
}
static uart_obj_t *uart_alloc_driver_obj(uart_port_t uart_num, int event_queue_size, int tx_buffer_size, int rx_buffer_size)
@ -1530,82 +1507,29 @@ static uart_obj_t *uart_alloc_driver_obj(uart_port_t uart_num, int event_queue_s
if (!uart_obj->rx_data_buf) {
goto err;
}
#if CONFIG_UART_ISR_IN_IRAM
if (event_queue_size > 0) {
uart_obj->event_queue_storage = heap_caps_calloc(event_queue_size, sizeof(uart_event_t), UART_MALLOC_CAPS);
uart_obj->event_queue_struct = heap_caps_calloc(1, sizeof(StaticQueue_t), UART_MALLOC_CAPS);
if (!uart_obj->event_queue_storage || !uart_obj->event_queue_struct) {
goto err;
}
}
if (tx_buffer_size > 0) {
uart_obj->tx_ring_buf_storage = heap_caps_calloc(1, tx_buffer_size, UART_MALLOC_CAPS);
uart_obj->tx_ring_buf_struct = heap_caps_calloc(1, sizeof(StaticRingbuffer_t), UART_MALLOC_CAPS);
if (!uart_obj->tx_ring_buf_storage || !uart_obj->tx_ring_buf_struct) {
goto err;
}
}
uart_obj->rx_ring_buf_storage = heap_caps_calloc(1, rx_buffer_size, UART_MALLOC_CAPS);
uart_obj->rx_ring_buf_struct = heap_caps_calloc(1, sizeof(StaticRingbuffer_t), UART_MALLOC_CAPS);
uart_obj->rx_mux_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS);
uart_obj->tx_mux_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS);
uart_obj->tx_brk_sem_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS);
uart_obj->tx_done_sem_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS);
uart_obj->tx_fifo_sem_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS);
if (!uart_obj->rx_ring_buf_storage || !uart_obj->rx_ring_buf_struct || !uart_obj->rx_mux_struct ||
!uart_obj->tx_mux_struct || !uart_obj->tx_brk_sem_struct || !uart_obj->tx_done_sem_struct ||
!uart_obj->tx_fifo_sem_struct) {
goto err;
}
if (event_queue_size > 0) {
uart_obj->event_queue = xQueueCreateStatic(event_queue_size, sizeof(uart_event_t),
uart_obj->event_queue_storage, uart_obj->event_queue_struct);
uart_obj->event_queue = xQueueCreateWithCaps(event_queue_size, sizeof(uart_event_t), UART_MALLOC_CAPS);
if (!uart_obj->event_queue) {
goto err;
}
}
if (tx_buffer_size > 0) {
uart_obj->tx_ring_buf = xRingbufferCreateStatic(tx_buffer_size, RINGBUF_TYPE_NOSPLIT,
uart_obj->tx_ring_buf_storage, uart_obj->tx_ring_buf_struct);
uart_obj->tx_ring_buf = xRingbufferCreateWithCaps(tx_buffer_size, RINGBUF_TYPE_NOSPLIT, UART_MALLOC_CAPS);
if (!uart_obj->tx_ring_buf) {
goto err;
}
}
uart_obj->rx_ring_buf = xRingbufferCreateStatic(rx_buffer_size, RINGBUF_TYPE_BYTEBUF,
uart_obj->rx_ring_buf_storage, uart_obj->rx_ring_buf_struct);
uart_obj->rx_mux = xSemaphoreCreateMutexStatic(uart_obj->rx_mux_struct);
uart_obj->tx_mux = xSemaphoreCreateMutexStatic(uart_obj->tx_mux_struct);
uart_obj->tx_brk_sem = xSemaphoreCreateBinaryStatic(uart_obj->tx_brk_sem_struct);
uart_obj->tx_done_sem = xSemaphoreCreateBinaryStatic(uart_obj->tx_done_sem_struct);
uart_obj->tx_fifo_sem = xSemaphoreCreateBinaryStatic(uart_obj->tx_fifo_sem_struct);
uart_obj->rx_ring_buf = xRingbufferCreateWithCaps(rx_buffer_size, RINGBUF_TYPE_BYTEBUF, UART_MALLOC_CAPS);
uart_obj->tx_mux = xSemaphoreCreateMutexWithCaps(UART_MALLOC_CAPS);
uart_obj->rx_mux = xSemaphoreCreateMutexWithCaps(UART_MALLOC_CAPS);
uart_obj->tx_brk_sem = xSemaphoreCreateBinaryWithCaps(UART_MALLOC_CAPS);
uart_obj->tx_done_sem = xSemaphoreCreateBinaryWithCaps(UART_MALLOC_CAPS);
uart_obj->tx_fifo_sem = xSemaphoreCreateBinaryWithCaps(UART_MALLOC_CAPS);
if (!uart_obj->rx_ring_buf || !uart_obj->rx_mux || !uart_obj->tx_mux || !uart_obj->tx_brk_sem ||
!uart_obj->tx_done_sem || !uart_obj->tx_fifo_sem) {
goto err;
}
#else
if (event_queue_size > 0) {
uart_obj->event_queue = xQueueCreate(event_queue_size, sizeof(uart_event_t));
if (!uart_obj->event_queue) {
goto err;
}
}
if (tx_buffer_size > 0) {
uart_obj->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT);
if (!uart_obj->tx_ring_buf) {
goto err;
}
}
uart_obj->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF);
uart_obj->tx_mux = xSemaphoreCreateMutex();
uart_obj->rx_mux = xSemaphoreCreateMutex();
uart_obj->tx_brk_sem = xSemaphoreCreateBinary();
uart_obj->tx_done_sem = xSemaphoreCreateBinary();
uart_obj->tx_fifo_sem = xSemaphoreCreateBinary();
if (!uart_obj->rx_ring_buf || !uart_obj->rx_mux || !uart_obj->tx_mux || !uart_obj->tx_brk_sem ||
!uart_obj->tx_done_sem || !uart_obj->tx_fifo_sem) {
goto err;
}
#endif
return uart_obj;
err: