Merge branch 'bugfix/parlio_coverity_issue' into 'master'

feat(parlio_tx): minor clean up and fix

Closes IDF-9420

See merge request espressif/esp-idf!29663
This commit is contained in:
morris 2024-03-19 10:08:54 +08:00
commit 3a9d082523
7 changed files with 129 additions and 108 deletions

View File

@ -8,5 +8,5 @@ endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${public_include}
PRIV_REQUIRES "esp_pm" "esp_driver_gpio"
PRIV_REQUIRES "esp_pm" "esp_driver_gpio" "esp_mm"
)

View File

@ -150,6 +150,9 @@ esp_err_t parlio_tx_unit_register_event_callbacks(parlio_tx_unit_handle_t tx_uni
*/
typedef struct {
uint32_t idle_value; /*!< The value on the data line when the parallel IO is in idle state */
struct {
uint32_t queue_nonblocking : 1; /*!< If set, when the transaction queue is full, driver will not block the thread but return directly */
} flags; /*!< Transmit specific config flags */
} parlio_transmit_config_t;
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -42,8 +42,6 @@ parlio_group_t *parlio_acquire_group_handle(int group_id)
if (group) {
new_group = true;
s_platform.groups[group_id] = group;
group->group_id = group_id;
group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
PARLIO_RCC_ATOMIC() {
parlio_ll_enable_bus_clock(group_id, true);
parlio_ll_reset_register(group_id);
@ -61,6 +59,8 @@ parlio_group_t *parlio_acquire_group_handle(int group_id)
_lock_release(&s_platform.mutex);
if (new_group) {
portMUX_INITIALIZE(&group->spinlock);
group->group_id = group_id;
ESP_LOGD(TAG, "new group(%d) at %p", group_id, group);
}
return group;
@ -81,11 +81,11 @@ void parlio_release_group_handle(parlio_group_t *group)
PARLIO_RCC_ATOMIC() {
parlio_ll_enable_bus_clock(group_id, false);
}
free(group);
}
_lock_release(&s_platform.mutex);
if (do_deinitialize) {
free(group);
ESP_LOGD(TAG, "del group(%d)", group_id);
}
}
@ -96,23 +96,20 @@ esp_err_t parlio_register_unit_to_group(parlio_unit_base_handle_t unit)
int unit_id = -1;
for (int i = 0; i < SOC_PARLIO_GROUPS; i++) {
group = parlio_acquire_group_handle(i);
parlio_unit_base_handle_t *group_unit = NULL;
ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no memory for group (%d)", i);
portENTER_CRITICAL(&group->spinlock);
if (unit->dir == PARLIO_DIR_TX) {
for (int j = 0; j < SOC_PARLIO_TX_UNITS_PER_GROUP; j++) {
group_unit = &group->tx_units[j];
if (*group_unit == NULL) {
*group_unit = unit;
if (!group->tx_units[j]) {
group->tx_units[j] = unit;
unit_id = j;
break;
}
}
} else {
for (int j = 0; j < SOC_PARLIO_RX_UNITS_PER_GROUP; j++) {
group_unit = &group->rx_units[j];
if (*group_unit == NULL) {
*group_unit = unit;
if (!group->rx_units[j]) {
group->rx_units[j] = unit;
unit_id = j;
break;
}
@ -122,7 +119,6 @@ esp_err_t parlio_register_unit_to_group(parlio_unit_base_handle_t unit)
if (unit_id < 0) {
/* didn't find a free unit slot in the group */
parlio_release_group_handle(group);
group = NULL;
} else {
unit->unit_id = unit_id;
unit->group = group;
@ -138,11 +134,12 @@ void parlio_unregister_unit_from_group(parlio_unit_base_handle_t unit)
{
assert(unit);
parlio_group_t *group = unit->group;
int unit_id = unit->unit_id;
portENTER_CRITICAL(&group->spinlock);
if (unit->dir == PARLIO_DIR_TX) {
group->tx_units[unit->unit_id] = NULL;
group->tx_units[unit_id] = NULL;
} else {
group->rx_units[unit->unit_id] = NULL;
group->rx_units[unit_id] = NULL;
}
portEXIT_CRITICAL(&group->spinlock);
/* the parlio unit has a reference of the group, release it now */

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -10,6 +10,7 @@
#include "freertos/FreeRTOS.h"
#include "soc/soc_caps.h"
#include "soc/gdma_channel.h"
#include "soc/io_mux_reg.h"
#include "hal/parlio_types.h"
#include "hal/parlio_hal.h"
#include "hal/parlio_ll.h"
@ -19,7 +20,10 @@
#include "rom/cache.h"
#include "esp_heap_caps.h"
#include "driver/parlio_types.h"
#include "esp_cache.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/esp_gpio_reserve.h"
#include "esp_private/gpio.h"
#if CONFIG_PARLIO_ISR_IRAM_SAFE
#define PARLIO_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
@ -51,6 +55,8 @@ typedef dma_descriptor_align8_t parlio_dma_desc_t;
#endif
#endif // defined(SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS)
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#ifdef CACHE_LL_L2MEM_NON_CACHE_ADDR
/* The descriptor address can be mapped by a fixed offset */
#define PARLIO_GET_NON_CACHED_DESC_ADDR(desc) (desc ? (parlio_dma_desc_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(desc)) : NULL)
@ -77,12 +83,12 @@ typedef dma_descriptor_align8_t parlio_dma_desc_t;
extern "C" {
#endif
enum {
typedef enum {
PARLIO_TX_QUEUE_READY,
PARLIO_TX_QUEUE_PROGRESS,
PARLIO_TX_QUEUE_COMPLETE,
PARLIO_TX_QUEUE_MAX,
};
} parlio_tx_queue_status_t;
typedef enum {
PARLIO_DIR_TX,
@ -101,21 +107,20 @@ typedef enum {
typedef struct parlio_unit_t *parlio_unit_base_handle_t;
typedef struct parlio_group_t {
int group_id; // group ID, index from 0
portMUX_TYPE spinlock; // to protect per-group register level concurrent access
parlio_hal_context_t hal; // hal layer for each group
parlio_unit_base_handle_t tx_units[SOC_PARLIO_TX_UNITS_PER_GROUP]; // tx unit handles
parlio_unit_base_handle_t rx_units[SOC_PARLIO_RX_UNITS_PER_GROUP]; // rx unit handles
int group_id; // group ID, index from 0
portMUX_TYPE spinlock; // to protect per-group register level concurrent access
parlio_hal_context_t hal; // hal layer context
parlio_unit_base_handle_t tx_units[SOC_PARLIO_TX_UNITS_PER_GROUP]; // tx unit handles
parlio_unit_base_handle_t rx_units[SOC_PARLIO_RX_UNITS_PER_GROUP]; // rx unit handles
} parlio_group_t;
/**
* @brief The common field of rx and tx unit structure
*
*/
struct parlio_unit_t {
int unit_id; // unit id
parlio_dir_t dir;
parlio_group_t *group; // group handle
int unit_id; // unit id
parlio_dir_t dir; // direction
parlio_group_t *group; // group handle
};
/**

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -28,7 +28,6 @@
#include "esp_pm.h"
#include "soc/parlio_periph.h"
#include "hal/parlio_ll.h"
#include "hal/gpio_hal.h"
#include "driver/gpio.h"
#include "driver/parlio_tx.h"
#include "parlio_private.h"
@ -50,6 +49,9 @@ typedef struct parlio_tx_unit_t {
intr_handle_t intr; // allocated interrupt handle
esp_pm_lock_handle_t pm_lock; // power management lock
gdma_channel_handle_t dma_chan; // DMA channel
parlio_dma_desc_t *dma_nodes; // DMA descriptor nodes
parlio_dma_desc_t *dma_nodes_nc;// non-cached DMA descriptor nodes
size_t dma_nodes_num; // number of DMA descriptor nodes
#if CONFIG_PM_ENABLE
char pm_lock_name[PARLIO_PM_LOCK_NAME_LEN_MAX]; // pm lock name
#endif
@ -64,7 +66,6 @@ typedef struct parlio_tx_unit_t {
_Atomic parlio_tx_fsm_t fsm; // Driver FSM state
parlio_tx_done_callback_t on_trans_done; // callback function when the transmission is done
void *user_data; // user data passed to the callback function
parlio_dma_desc_t *dma_nodes; // DMA descriptor nodes
parlio_tx_trans_desc_t trans_desc_pool[]; // transaction descriptor pool
} parlio_tx_unit_t;
@ -122,7 +123,9 @@ static esp_err_t parlio_destroy_tx_unit(parlio_tx_unit_t *tx_unit)
// de-register from group
parlio_unregister_unit_from_group(&tx_unit->base);
}
free(tx_unit->dma_nodes);
if (tx_unit->dma_nodes) {
free(tx_unit->dma_nodes);
}
free(tx_unit);
return ESP_OK;
}
@ -145,8 +148,7 @@ static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed");
esp_rom_gpio_connect_out_signal(config->data_gpio_nums[i],
parlio_periph_signals.groups[group_id].tx_units[unit_id].data_sigs[i], false, false);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->data_gpio_nums[i]], PIN_FUNC_GPIO);
gpio_func_sel(config->data_gpio_nums[i], PIN_FUNC_GPIO);
}
}
// Note: the valid signal will override TXD[PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG]
@ -156,14 +158,14 @@ static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const
esp_rom_gpio_connect_out_signal(config->valid_gpio_num,
parlio_periph_signals.groups[group_id].tx_units[unit_id].data_sigs[PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG],
false, false);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->valid_gpio_num], PIN_FUNC_GPIO);
gpio_func_sel(config->valid_gpio_num, PIN_FUNC_GPIO);
}
if (config->clk_out_gpio_num >= 0) {
gpio_conf.pin_bit_mask = BIT64(config->clk_out_gpio_num);
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk out GPIO failed");
esp_rom_gpio_connect_out_signal(config->clk_out_gpio_num,
parlio_periph_signals.groups[group_id].tx_units[unit_id].clk_out_sig, false, false);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->clk_out_gpio_num], PIN_FUNC_GPIO);
gpio_func_sel(config->clk_out_gpio_num, PIN_FUNC_GPIO);
}
if (config->clk_in_gpio_num >= 0) {
gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_INPUT;
@ -171,7 +173,7 @@ static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const
ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk in GPIO failed");
esp_rom_gpio_connect_in_signal(config->clk_in_gpio_num,
parlio_periph_signals.groups[group_id].tx_units[unit_id].clk_in_sig, false);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->clk_in_gpio_num], PIN_FUNC_GPIO);
gpio_func_sel(config->clk_in_gpio_num, PIN_FUNC_GPIO);
}
return ESP_OK;
}
@ -188,6 +190,12 @@ static esp_err_t parlio_tx_unit_init_dma(parlio_tx_unit_t *tx_unit)
.owner_check = true,
};
gdma_apply_strategy(tx_unit->dma_chan, &gdma_strategy_conf);
// Link the descriptors
size_t dma_nodes_num = tx_unit->dma_nodes_num;
for (int i = 0; i < dma_nodes_num; i++) {
tx_unit->dma_nodes_nc[i].next = (i == dma_nodes_num - 1) ? NULL : &(tx_unit->dma_nodes[i + 1]);
}
return ESP_OK;
}
@ -247,36 +255,51 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un
#endif
esp_err_t ret = ESP_OK;
parlio_tx_unit_t *unit = NULL;
ESP_GOTO_ON_FALSE(config && ret_unit, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(config && ret_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
size_t data_width = config->data_width;
// data_width must be power of 2 and less than or equal to SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH
ESP_GOTO_ON_FALSE(data_width && (data_width <= SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH) && ((data_width & (data_width - 1)) == 0),
ESP_ERR_INVALID_ARG, err, TAG, "invalid data width");
ESP_RETURN_ON_FALSE(data_width && (data_width <= SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH) && ((data_width & (data_width - 1)) == 0),
ESP_ERR_INVALID_ARG, TAG, "invalid data width");
// data_width must not conflict with the valid signal
ESP_GOTO_ON_FALSE(!(config->valid_gpio_num >= 0 && data_width > PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG),
ESP_ERR_INVALID_ARG, err, TAG, "valid signal conflicts with data signal");
ESP_GOTO_ON_FALSE(config->max_transfer_size && config->max_transfer_size <= PARLIO_LL_TX_MAX_BITS_PER_FRAME / 8,
ESP_ERR_INVALID_ARG, err, TAG, "invalid max transfer size");
ESP_RETURN_ON_FALSE(!(config->valid_gpio_num >= 0 && data_width > PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG),
ESP_ERR_INVALID_ARG, TAG, "valid signal conflicts with data signal");
ESP_RETURN_ON_FALSE(config->max_transfer_size && config->max_transfer_size <= PARLIO_LL_TX_MAX_BITS_PER_FRAME / 8,
ESP_ERR_INVALID_ARG, TAG, "invalid max transfer size");
#if SOC_PARLIO_TX_CLK_SUPPORT_GATING
// clock gating is controlled by either the MSB bit of data bus or the valid signal
ESP_GOTO_ON_FALSE(!(config->flags.clk_gate_en && config->valid_gpio_num < 0 && config->data_width <= PARLIO_LL_TX_DATA_LINE_AS_CLK_GATE),
ESP_ERR_INVALID_ARG, err, TAG, "no gpio can control the clock gating");
ESP_RETURN_ON_FALSE(!(config->flags.clk_gate_en && config->valid_gpio_num < 0 && config->data_width <= PARLIO_LL_TX_DATA_LINE_AS_CLK_GATE),
ESP_ERR_INVALID_ARG, TAG, "no gpio can control the clock gating");
#else
ESP_GOTO_ON_FALSE(config->flags.clk_gate_en == 0, ESP_ERR_NOT_SUPPORTED, err, TAG, "clock gating is not supported");
ESP_RETURN_ON_FALSE(config->flags.clk_gate_en == 0, ESP_ERR_NOT_SUPPORTED, TAG, "clock gating is not supported");
#endif // SOC_PARLIO_TX_CLK_SUPPORT_GATING
// malloc unit memory
unit = heap_caps_calloc(1, sizeof(parlio_tx_unit_t) + sizeof(parlio_tx_trans_desc_t) * config->trans_queue_depth, PARLIO_MEM_ALLOC_CAPS);
uint32_t mem_caps = PARLIO_MEM_ALLOC_CAPS;
unit = heap_caps_calloc(1, sizeof(parlio_tx_unit_t) + sizeof(parlio_tx_trans_desc_t) * config->trans_queue_depth, mem_caps);
ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, TAG, "no memory for tx unit");
size_t dma_nodes_num = config->max_transfer_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1;
// DMA descriptors must be placed in internal SRAM
unit->dma_nodes = heap_caps_aligned_calloc(PARLIO_DMA_DESC_ALIGNMENT, dma_nodes_num, sizeof(parlio_dma_desc_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
ESP_GOTO_ON_FALSE(unit->dma_nodes, ESP_ERR_NO_MEM, err, TAG, "no memory for DMA nodes");
// Link the descriptors
for (int i = 0; i < dma_nodes_num; i++) {
unit->dma_nodes[i].next = (i == dma_nodes_num - 1) ? NULL : &(unit->dma_nodes[i + 1]);
// create DMA descriptors
// DMA descriptors must be placed in internal SRAM
mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA;
size_t dma_nodes_num = config->max_transfer_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1;
uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
// the alignment should meet both the DMA and cache requirement
size_t alignment = MAX(data_cache_line_size, PARLIO_DMA_DESC_ALIGNMENT);
size_t dma_nodes_mem_size = ALIGN_UP(dma_nodes_num * sizeof(parlio_dma_desc_t), alignment);
parlio_dma_desc_t *dma_nodes = heap_caps_aligned_calloc(alignment, 1, dma_nodes_mem_size, mem_caps);
ESP_GOTO_ON_FALSE(dma_nodes, ESP_ERR_NO_MEM, err, TAG, "no memory for DMA nodes");
unit->dma_nodes = dma_nodes;
unit->dma_nodes_num = dma_nodes_num;
// write back and then invalidate the cached dma_nodes, we will skip the cache (by non-cacheable address) when access the dma_nodes
if (data_cache_line_size) {
ESP_GOTO_ON_ERROR(esp_cache_msync(dma_nodes, dma_nodes_mem_size,
ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE),
err, TAG, "cache sync failed");
}
// we will use the non-cached address to manipulate the DMA descriptor, for simplicity
unit->dma_nodes_nc = PARLIO_GET_NON_CACHED_DESC_ADDR(dma_nodes);
unit->max_transfer_bits = config->max_transfer_size * 8;
unit->base.dir = PARLIO_DIR_TX;
unit->data_width = data_width;
@ -362,27 +385,27 @@ esp_err_t parlio_del_tx_unit(parlio_tx_unit_handle_t unit)
return parlio_destroy_tx_unit(unit);
}
static void IRAM_ATTR parlio_tx_mount_dma_data(parlio_dma_desc_t *desc_head, const void *buffer, size_t len)
static void IRAM_ATTR parlio_tx_mount_dma_data(parlio_tx_unit_t *tx_unit, const void *buffer, size_t len)
{
size_t prepared_length = 0;
uint8_t *data = (uint8_t *)buffer;
parlio_dma_desc_t *desc = desc_head;
parlio_dma_desc_t *desc_nc = tx_unit->dma_nodes_nc;
while (len) {
parlio_dma_desc_t *non_cache_desc = PARLIO_GET_NON_CACHED_DESC_ADDR(desc);
uint32_t mount_bytes = len > DMA_DESCRIPTOR_BUFFER_MAX_SIZE ? DMA_DESCRIPTOR_BUFFER_MAX_SIZE : len;
len -= mount_bytes;
non_cache_desc->dw0.suc_eof = len == 0; // whether the last frame
non_cache_desc->dw0.size = mount_bytes;
non_cache_desc->dw0.length = mount_bytes;
non_cache_desc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
non_cache_desc->buffer = &data[prepared_length];
desc = desc->next; // move to next descriptor
desc_nc->dw0.suc_eof = (len == 0); // whether the last frame
desc_nc->dw0.size = mount_bytes;
desc_nc->dw0.length = mount_bytes;
desc_nc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
desc_nc->buffer = &data[prepared_length];
desc_nc = PARLIO_GET_NON_CACHED_DESC_ADDR(desc_nc->next);
prepared_length += mount_bytes;
}
#if CONFIG_IDF_TARGET_ESP32P4
// Write back to cache to synchronize the cache before DMA start
Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)buffer, len);
esp_cache_msync(buffer, len, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
#endif // CONFIG_IDF_TARGET_ESP32P4
}
@ -428,7 +451,7 @@ static void IRAM_ATTR parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio
tx_unit->cur_trans = t;
// DMA transfer data based on bytes not bits, so convert the bit length to bytes, round up
parlio_tx_mount_dma_data(tx_unit->dma_nodes, t->payload, (t->payload_bits + 7) / 8);
parlio_tx_mount_dma_data(tx_unit, t->payload, (t->payload_bits + 7) / 8);
parlio_ll_tx_reset_fifo(hal->regs);
PARLIO_RCC_ATOMIC() {
@ -529,10 +552,14 @@ esp_err_t parlio_tx_unit_transmit(parlio_tx_unit_handle_t tx_unit, const void *p
ESP_RETURN_ON_FALSE((payload_bits % 8) == 0, ESP_ERR_INVALID_ARG, TAG, "payload bit length must be multiple of 8");
#endif // !SOC_PARLIO_TRANS_BIT_ALIGN
// acquire one transaction description from ready queue or complete queue
TickType_t queue_wait_ticks = portMAX_DELAY;
if (config->flags.queue_nonblocking) {
queue_wait_ticks = 0;
}
parlio_tx_trans_desc_t *t = NULL;
// acquire one transaction description from ready queue or complete queue
if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_READY], &t, 0) != pdTRUE) {
if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_COMPLETE], &t, 0) == pdTRUE) {
if (xQueueReceive(tx_unit->trans_queues[PARLIO_TX_QUEUE_COMPLETE], &t, queue_wait_ticks) == pdTRUE) {
tx_unit->num_trans_inflight--;
}
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -16,7 +16,6 @@
#include "hal/hal_utils.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/parl_io_struct.h"
#include "soc/hp_sys_clkrst_struct.h"
#define PARLIO_LL_RX_MAX_BYTES_PER_FRAME 0xFFFF
#define PARLIO_LL_RX_MAX_CLK_INT_DIV 0x100
@ -40,13 +39,6 @@
extern "C" {
#endif
typedef enum {
PARLIO_LL_CLK_SRC_XTAL = PARLIO_CLK_SRC_XTAL,
PARLIO_LL_CLK_SRC_PLL_F160M = PARLIO_CLK_SRC_PLL_F160M,
PARLIO_LL_CLK_SRC_RC_FAST = PARLIO_CLK_SRC_RC_FAST,
PARLIO_LL_CLK_SRC_PAD = PARLIO_CLK_SRC_EXTERNAL, // clock source from GPIO pad
} parlio_ll_clock_source_t;
typedef enum {
PARLIO_LL_RX_EOF_COND_RX_FULL, /*!< RX unit generates EOF event when it receives enough data */
PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */
@ -63,22 +55,23 @@ typedef enum {
* @param group_id The group id of the parlio module
* @param enable Set true to enable, false to disable
*/
static inline void parlio_ll_enable_bus_clock(int group_id, bool enable)
static inline void _parlio_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
HP_SYS_CLKRST.soc_clk_ctrl1.reg_parlio_sys_clk_en = enable;
HP_SYS_CLKRST.soc_clk_ctrl2.reg_parlio_apb_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_enable_bus_clock(__VA_ARGS__)
#define parlio_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the parlio module
*
* @param group_id The group id of the parlio module
*/
static inline void parlio_ll_reset_register(int group_id)
static inline void _parlio_ll_reset_register(int group_id)
{
(void)group_id;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio = 1;
@ -87,7 +80,7 @@ static inline void parlio_ll_reset_register(int group_id)
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_reset_register(__VA_ARGS__)
#define parlio_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_reset_register(__VA_ARGS__)
///////////////////////////////////////RX Unit///////////////////////////////////////
@ -97,21 +90,21 @@ static inline void parlio_ll_reset_register(int group_id)
* @param dev Parallel IO register base address
* @param src Clock source
*/
static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src)
static inline void _parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src)
{
(void)dev;
uint32_t clk_sel = 0;
switch (src) {
case PARLIO_LL_CLK_SRC_XTAL:
case PARLIO_CLK_SRC_XTAL:
clk_sel = 0;
break;
case PARLIO_LL_CLK_SRC_RC_FAST:
case PARLIO_CLK_SRC_RC_FAST:
clk_sel = 1;
break;
case PARLIO_LL_CLK_SRC_PLL_F160M:
case PARLIO_CLK_SRC_PLL_F160M:
clk_sel = 2;
break;
case PARLIO_LL_CLK_SRC_PAD:
case PARLIO_CLK_SRC_EXTERNAL:
clk_sel = 3;
break;
@ -124,7 +117,7 @@ static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_rx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_set_clock_source(__VA_ARGS__)
#define parlio_ll_rx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_rx_set_clock_source(__VA_ARGS__)
/**
* @brief Set the clock divider for the RX unit
@ -132,7 +125,7 @@ static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c
* @param dev Parallel IO register base address
* @param clk_div Clock division with integral and decimal part
*/
static inline void parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div)
static inline void _parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div)
{
(void)dev;
HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV);
@ -143,14 +136,14 @@ static inline void parlio_ll_rx_set_clock_div(parl_io_dev_t *dev, const hal_util
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_rx_set_clock_div(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_set_clock_div(__VA_ARGS__)
#define parlio_ll_rx_set_clock_div(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_rx_set_clock_div(__VA_ARGS__)
/**
* @brief Reset the RX unit Core clock domain
*
* @param dev Parallel IO register base address
*/
static inline void parlio_ll_rx_reset_clock(parl_io_dev_t *dev)
static inline void _parlio_ll_rx_reset_clock(parl_io_dev_t *dev)
{
(void)dev;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio_rx = 1;
@ -159,7 +152,7 @@ static inline void parlio_ll_rx_reset_clock(parl_io_dev_t *dev)
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_rx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_reset_clock(__VA_ARGS__)
#define parlio_ll_rx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_rx_reset_clock(__VA_ARGS__)
/**
* @brief Enable the RX unit Core clock domain
@ -168,7 +161,7 @@ static inline void parlio_ll_rx_reset_clock(parl_io_dev_t *dev)
* @param en True to enable, False to disable
*/
__attribute__((always_inline))
static inline void parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en)
static inline void _parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en)
{
(void)dev;
HP_SYS_CLKRST.peri_clk_ctrl117.reg_parlio_rx_clk_en = en;
@ -176,7 +169,7 @@ static inline void parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en)
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_rx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_enable_clock(__VA_ARGS__)
#define parlio_ll_rx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_rx_enable_clock(__VA_ARGS__)
/**
* @brief Set the condition to generate the RX EOF event
@ -420,21 +413,21 @@ static inline void parlio_ll_rx_update_config(parl_io_dev_t *dev)
* @param dev Parallel IO register base address
* @param src Clock source
*/
static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src)
static inline void _parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src)
{
(void)dev;
uint32_t clk_sel = 0;
switch (src) {
case PARLIO_LL_CLK_SRC_XTAL:
case PARLIO_CLK_SRC_XTAL:
clk_sel = 0;
break;
case PARLIO_LL_CLK_SRC_RC_FAST:
case PARLIO_CLK_SRC_RC_FAST:
clk_sel = 1;
break;
case PARLIO_LL_CLK_SRC_PLL_F160M:
case PARLIO_CLK_SRC_PLL_F160M:
clk_sel = 2;
break;
case PARLIO_LL_CLK_SRC_PAD:
case PARLIO_CLK_SRC_EXTERNAL:
clk_sel = 3;
break;
@ -447,7 +440,7 @@ static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_tx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_set_clock_source(__VA_ARGS__)
#define parlio_ll_tx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_tx_set_clock_source(__VA_ARGS__)
/**
* @brief Set the clock divider for the TX unit
@ -455,7 +448,7 @@ static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c
* @param dev Parallel IO register base address
* @param clk_div Clock division with integral and decimal part
*/
static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div)
static inline void _parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_utils_clk_div_t *clk_div)
{
(void)dev;
HAL_ASSERT(clk_div->integer > 0 && clk_div->integer <= PARLIO_LL_RX_MAX_CLK_INT_DIV);
@ -466,7 +459,7 @@ static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_util
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_tx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_set_clock_source(__VA_ARGS__)
#define parlio_ll_tx_set_clock_div(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_tx_set_clock_div(__VA_ARGS__)
/**
* @brief Reset the TX unit Core clock domain
@ -474,7 +467,7 @@ static inline void parlio_ll_tx_set_clock_div(parl_io_dev_t *dev, const hal_util
* @param dev Parallel IO register base address
*/
__attribute__((always_inline))
static inline void parlio_ll_tx_reset_clock(parl_io_dev_t *dev)
static inline void _parlio_ll_tx_reset_clock(parl_io_dev_t *dev)
{
(void)dev;
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_parlio_tx = 1;
@ -483,7 +476,7 @@ static inline void parlio_ll_tx_reset_clock(parl_io_dev_t *dev)
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_tx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_reset_clock(__VA_ARGS__)
#define parlio_ll_tx_reset_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_tx_reset_clock(__VA_ARGS__)
/**
* @brief Enable the TX unit Core clock domain
@ -492,7 +485,7 @@ static inline void parlio_ll_tx_reset_clock(parl_io_dev_t *dev)
* @param en True to enable, False to disable
*/
__attribute__((always_inline))
static inline void parlio_ll_tx_enable_clock(parl_io_dev_t *dev, bool en)
static inline void _parlio_ll_tx_enable_clock(parl_io_dev_t *dev, bool en)
{
(void)dev;
HP_SYS_CLKRST.peri_clk_ctrl118.reg_parlio_tx_clk_en = en;
@ -500,7 +493,7 @@ static inline void parlio_ll_tx_enable_clock(parl_io_dev_t *dev, bool en)
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define parlio_ll_tx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_enable_clock(__VA_ARGS__)
#define parlio_ll_tx_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _parlio_ll_tx_enable_clock(__VA_ARGS__)
/**
* @brief Set the data length to be transmitted

View File

@ -593,11 +593,7 @@ typedef enum {
PARLIO_CLK_SRC_PLL_F160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */
PARLIO_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */
PARLIO_CLK_SRC_EXTERNAL = -1, /*!< Select EXTERNAL clock as the source clock */
#if SOC_CLK_TREE_SUPPORTED
PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default clock choice */
#else
PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default clock choice */
#endif
} soc_periph_parlio_clk_src_t;
//////////////////////////////////////////////////SDMMC///////////////////////////////////////////////////////////////