/* * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 *//* ... */#pragmaonce#include<stdatomic.h>#include"sdkconfig.h"#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"soc/gdma_channel.h"#include"hal/rmt_types.h"#include"hal/rmt_hal.h"#include"hal/dma_types.h"#include"hal/cache_ll.h"#include"esp_intr_alloc.h"#include"esp_heap_caps.h"#include"esp_clk_tree.h"#include"esp_pm.h"#include"esp_attr.h"#include"esp_private/gdma.h"#include"esp_private/esp_gpio_reserve.h"#include"esp_private/gpio.h"#include"esp_private/sleep_retention.h"#include"driver/rmt_common.h"23 includes#ifdef__cplusplusextern"C"{#endif#ifCONFIG_RMT_ISR_IRAM_SAFE||CONFIG_RMT_RECV_FUNC_IN_IRAM#defineRMT_MEM_ALLOC_CAPS(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)#else#defineRMT_MEM_ALLOC_CAPSMALLOC_CAP_DEFAULT#endif// RMT driver object is per-channel, the interrupt source is shared between channels#ifCONFIG_RMT_ISR_IRAM_SAFE#defineRMT_INTR_ALLOC_FLAG(ESP_INTR_FLAG_SHARED|ESP_INTR_FLAG_IRAM)#else#defineRMT_INTR_ALLOC_FLAG(ESP_INTR_FLAG_SHARED)#endif// Hopefully the channel offset won't change in other targets#defineRMT_TX_CHANNEL_OFFSET_IN_GROUP0#defineRMT_RX_CHANNEL_OFFSET_IN_GROUP(SOC_RMT_CHANNELS_PER_GROUP-SOC_RMT_TX_CANDIDATES_PER_GROUP)#defineRMT_ALLOW_INTR_PRIORITY_MASKESP_INTR_FLAG_LOWMED#defineRMT_DMA_NODES_PING_PONG2// two nodes ping-pong#defineRMT_PM_LOCK_NAME_LEN_MAX16#defineRMT_GROUP_INTR_PRIORITY_UNINITIALIZED(-1)// RMT is a slow peripheral, it only supports AHB-GDMA#defineRMT_DMA_DESC_ALIGN47 definestypedefdma_descriptor_align4_trmt_dma_descriptor_t;#ifdefCACHE_LL_L2MEM_NON_CACHE_ADDR#defineRMT_GET_NON_CACHE_ADDR(addr)(CACHE_LL_L2MEM_NON_CACHE_ADDR(addr))#else#defineRMT_GET_NON_CACHE_ADDR(addr)(addr)#endif#defineALIGN_UP(num,align)(((num)+((align)-1))&~((align)-1))#defineALIGN_DOWN(num,align)((num)&~((align)-1))#defineRMT_USE_RETENTION_LINK(SOC_RMT_SUPPORT_SLEEP_RETENTION&&CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)typedefstruct{struct{rmt_symbol_word_tsymbols[SOC_RMT_MEM_WORDS_PER_CHANNEL];}{ ... }channels[SOC_RMT_CHANNELS_PER_GROUP];}{ ... }rmt_block_mem_t;// RMTMEM address is declared in <target>.peripherals.ldexternrmt_block_mem_tRMTMEM;typedefenum{RMT_CHANNEL_DIRECTION_TX,RMT_CHANNEL_DIRECTION_RX,}{ ... }rmt_channel_direction_t;typedefenum{RMT_FSM_INIT_WAIT,RMT_FSM_INIT,RMT_FSM_ENABLE_WAIT,RMT_FSM_ENABLE,RMT_FSM_RUN_WAIT,RMT_FSM_RUN,}{ ... }rmt_fsm_t;enum{RMT_TX_QUEUE_READY,RMT_TX_QUEUE_PROGRESS,RMT_TX_QUEUE_COMPLETE,RMT_TX_QUEUE_MAX,}{ ... };typedefstructrmt_group_trmt_group_t;typedefstructrmt_channel_trmt_channel_t;typedefstructrmt_tx_channel_trmt_tx_channel_t;typedefstructrmt_rx_channel_trmt_rx_channel_t;typedefstructrmt_sync_manager_trmt_sync_manager_t;structrmt_group_t{intgroup_id;// group ID, index from 0portMUX_TYPEspinlock;// to protect per-group register level concurrent accessrmt_hal_context_thal;// hal layer for each grouprmt_clock_source_tclk_src;// record the group clock source, group clock is shared by all channelsuint32_tresolution_hz;// resolution of group clockuint32_toccupy_mask;// a set bit in the mask indicates the channel is not availablermt_tx_channel_t*tx_channels[SOC_RMT_TX_CANDIDATES_PER_GROUP];// array of RMT TX channelsrmt_rx_channel_t*rx_channels[SOC_RMT_RX_CANDIDATES_PER_GROUP];// array of RMT RX channelsrmt_sync_manager_t*sync_manager;// sync manager, this can be extended into an array if there're more sync controllers in one RMT groupintintr_priority;// RMT interrupt priority}{ ... };structrmt_channel_t{intchannel_id;// channel ID, index from 0intgpio_num;// GPIO number used by RMT RX channeluint32_tchannel_mask;// mask of the memory blocks that occupied by the channelsize_tmem_block_num;// number of occupied RMT memory blocksrmt_group_t*group;// which group the channel belongs toportMUX_TYPEspinlock;// prevent channel resource accessing by user and interrupt concurrentlyuint32_tresolution_hz;// channel clock resolutionintr_handle_tintr;// allocated interrupt handle for each channel_Atomicrmt_fsm_tfsm;// channel life cycle specific FSMrmt_channel_direction_tdirection;// channel directionrmt_symbol_word_t*hw_mem_base;// base address of RMT channel hardware memorygdma_channel_handle_tdma_chan;// DMA channelesp_pm_lock_handle_tpm_lock;// power management lock#ifCONFIG_PM_ENABLEcharpm_lock_name[RMT_PM_LOCK_NAME_LEN_MAX];// pm lock name#endif// RMT channel common interface// The following IO functions will have per-implementation for TX and RX channelesp_err_t(*del)(rmt_channel_t*channel);esp_err_t(*set_carrier_action)(rmt_channel_t*channel,constrmt_carrier_config_t*config);esp_err_t(*enable)(rmt_channel_t*channel);esp_err_t(*disable)(rmt_channel_t*channel);}{ ... };typedefstruct{rmt_encoder_handle_tencoder;// encode user payload into RMT symbolsconstvoid*payload;// encoder payloadsize_tpayload_bytes;// payload sizeintloop_count;// transaction can be continued in a loop for specific timesintremain_loop_count;// user required loop count may exceed hardware limitation, the driver will transfer them in batchessize_ttransmitted_symbol_num;// track the number of transmitted symbolsstruct{uint32_teot_level:1;// Set the output level for the "End Of Transmission"uint32_tencoding_done:1;// Indicate whether the encoding has finished (not the encoding of transmission)}{ ... }flags;}{ ... }rmt_tx_trans_desc_t;structrmt_tx_channel_t{rmt_channel_tbase;// channel base classrmt_symbol_word_t*dma_mem_base;// base address of RMT channel DMA bufferrmt_symbol_word_t*dma_mem_base_nc;// base address of RMT channel DMA buffer, accessed in non-cached waysize_tmem_off;// runtime argument, indicating the next writing position in the RMT hardware memorysize_tmem_end;// runtime argument, indicating the end of current writing regionsize_tping_pong_symbols;// ping-pong size (half of the RMT channel memory)size_tqueue_size;// size of transaction queuesize_tnum_trans_inflight;// indicates the number of transactions that are undergoing but not recycled to ready_queueQueueHandle_ttrans_queues[RMT_TX_QUEUE_MAX];// transaction queuesrmt_tx_trans_desc_t*cur_trans;// points to current transactionvoid*user_data;// user contextrmt_tx_done_callback_ton_trans_done;// callback, invoked on trans donermt_dma_descriptor_t*dma_nodes;// DMA descriptor nodesrmt_dma_descriptor_t*dma_nodes_nc;// DMA descriptor nodes accessed in non-cached wayrmt_tx_trans_desc_ttrans_desc_pool[];// transfer descriptor pool}{ ... };typedefstruct{void*buffer;// buffer for saving the received symbolssize_tbuffer_size;// size of the buffer, in bytessize_treceived_symbol_num;// track the number of received symbolssize_tcopy_dest_off;// tracking offset in the copy destinationintdma_desc_index;// tracking the DMA descriptor used by ping-pongstruct{uint32_ten_partial_rx:1;// packet is too long, we need to notify the user to process the data piece by piece, in a ping-pong approach}{ ... }flags;}{ ... }rmt_rx_trans_desc_t;structrmt_rx_channel_t{rmt_channel_tbase;// channel base classuint32_tfilter_clock_resolution_hz;// filter clock resolution, in Hzsize_tmem_off;// starting offset to fetch the symbols in RMT-MEMsize_tping_pong_symbols;// ping-pong size (half of the RMT channel memory)rmt_rx_done_callback_ton_recv_done;// callback, invoked on receive donevoid*user_data;// user contextrmt_rx_trans_desc_ttrans_desc;// transaction descriptionsize_tnum_dma_nodes;// number of DMA nodes, determined by how big the memory block that user configuressize_tdma_int_mem_alignment;// DMA buffer alignment (both in size and address) for internal RX memoryrmt_dma_descriptor_t*dma_nodes;// DMA link nodesrmt_dma_descriptor_t*dma_nodes_nc;// DMA descriptor nodes accessed in non-cached way}{ ... };/** * @brief Acquire RMT group handle * * @param group_id Group ID * @return RMT group handle *//* ... */rmt_group_t*rmt_acquire_group_handle(intgroup_id);/** * @brief Release RMT group handle * * @param group RMT group handle, returned from `rmt_acquire_group_handle` *//* ... */voidrmt_release_group_handle(rmt_group_t*group);/** * @brief Set clock source for RMT peripheral * * @param chan RMT channel handle * @param clk_src Clock source * @return * - ESP_OK: Set clock source successfully * - ESP_ERR_NOT_SUPPORTED: Set clock source failed because the clk_src is not supported * - ESP_ERR_INVALID_STATE: Set clock source failed because the clk_src is different from other RMT channel * - ESP_FAIL: Set clock source failed because of other error *//* ... */esp_err_trmt_select_periph_clock(rmt_channel_handle_tchan,rmt_clock_source_tclk_src);/** * @brief Set interrupt priority to RMT group * @param group RMT group to set interrupt priority to * @param intr_priority User-specified interrupt priority (in num, not bitmask) * @return If the priority conflicts * - true: Interrupt priority conflict with previous specified * - false: Interrupt priority set successfully *//* ... */boolrmt_set_intr_priority_to_group(rmt_group_t*group,intintr_priority);/** * @brief Get isr_flags to be passed to `esp_intr_alloc_intrstatus()` according to `intr_priority` set in RMT group * @param group RMT group * @return isr_flags *//* ... */intrmt_get_isr_flags(rmt_group_t*group);/** * @brief Create sleep retention link * * @param group RMT group handle, returned from `rmt_acquire_group_handle` *//* ... */voidrmt_create_retention_module(rmt_group_t*group);#ifdef__cplusplus}{...}#endif
Details
Show: from
Types: Columns:
All items filtered out
All items filtered out
This file uses the notable symbols shown below. Click anywhere in the file to view more details.