Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Zusätzliche Hilfsfunktion für bessere State-Debugging-Nachrichten
- static const char* rmt_fsm_state_to_string(rmt_fsm_t state) {
- switch (state) {
- case RMT_FSM_INIT: return "INIT";
- case RMT_FSM_ENABLE: return "ENABLE";
- case RMT_FSM_WAIT: return "WAIT";
- case RMT_FSM_RUN: return "RUN";
- default: return "UNKNOWN";
- }
- }
- // Modifizierte rmt_receive Funktion mit verbesserter Fehlerbehandlung
- esp_err_t rmt_receive(rmt_channel_handle_t channel, void *buffer, size_t buffer_size, const rmt_receive_config_t *config)
- {
- ESP_RETURN_ON_FALSE_ISR(channel && buffer && buffer_size && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
- ESP_RETURN_ON_FALSE_ISR(channel->direction == RMT_CHANNEL_DIRECTION_RX, ESP_ERR_INVALID_ARG, TAG, "invalid channel direction");
- #if !SOC_RMT_SUPPORT_RX_PINGPONG
- ESP_RETURN_ON_FALSE_ISR(!config->flags.en_partial_rx, ESP_ERR_NOT_SUPPORTED, TAG, "partial receive not supported");
- #endif
- rmt_rx_channel_t *rx_chan = __containerof(channel, rmt_rx_channel_t, base);
- size_t mem_alignment = sizeof(rmt_symbol_word_t);
- #if SOC_RMT_SUPPORT_DMA
- if (channel->dma_chan) {
- // append the alignment requirement from the DMA
- mem_alignment = MAX(mem_alignment, rx_chan->dma_int_mem_alignment);
- // [IDF-8997]: Currently we assume the user buffer is allocated from internal RAM, PSRAM is not supported yet.
- ESP_RETURN_ON_FALSE_ISR(esp_ptr_internal(buffer), ESP_ERR_INVALID_ARG, TAG, "user buffer not in the internal RAM");
- size_t max_buf_sz_per_dma_node = ALIGN_DOWN(DMA_DESCRIPTOR_BUFFER_MAX_SIZE, mem_alignment);
- ESP_RETURN_ON_FALSE_ISR(buffer_size <= rx_chan->num_dma_nodes * max_buf_sz_per_dma_node,
- ESP_ERR_INVALID_ARG, TAG, "buffer size exceeds DMA capacity: %zu", rx_chan->num_dma_nodes * max_buf_sz_per_dma_node);
- }
- #endif // SOC_RMT_SUPPORT_DMA
- // check buffer alignment
- uint32_t align_check_mask = mem_alignment - 1;
- ESP_RETURN_ON_FALSE_ISR(((((uintptr_t)buffer) & align_check_mask) == 0) && (((buffer_size) & align_check_mask) == 0), ESP_ERR_INVALID_ARG,
- TAG, "buffer address or size are not %"PRIu32 "bytes aligned", mem_alignment);
- rmt_group_t *group = channel->group;
- rmt_hal_context_t *hal = &group->hal;
- int channel_id = channel->channel_id;
- uint32_t filter_reg_value = ((uint64_t)rx_chan->filter_clock_resolution_hz * config->signal_range_min_ns) / 1000000000UL;
- uint32_t idle_reg_value = ((uint64_t)channel->resolution_hz * config->signal_range_max_ns) / 1000000000UL;
- ESP_RETURN_ON_FALSE_ISR(filter_reg_value <= RMT_LL_MAX_FILTER_VALUE, ESP_ERR_INVALID_ARG, TAG, "signal_range_min_ns too big, should be less than %"PRIu32" ns", (uint32_t)((uint64_t)RMT_LL_MAX_FILTER_VALUE * 1000000000UL / rx_chan->filter_clock_resolution_hz));
- ESP_RETURN_ON_FALSE_ISR(idle_reg_value <= RMT_LL_MAX_IDLE_VALUE, ESP_ERR_INVALID_ARG, TAG, "signal_range_max_ns too big, should be less than %"PRIu32" ns", (uint32_t)((uint64_t)RMT_LL_MAX_IDLE_VALUE * 1000000000UL / channel->resolution_hz));
- // VERBESSERTE STATE-ÜBERPRÜFUNG mit detaillierter Fehlermeldung
- rmt_fsm_t current_state = atomic_load(&channel->fsm);
- rmt_fsm_t expected_fsm = RMT_FSM_ENABLE;
- if (!atomic_compare_exchange_strong(&channel->fsm, &expected_fsm, RMT_FSM_WAIT)) {
- // State-Check fehlgeschlagen - gebe detaillierte Information über aktuellen State aus
- ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_STATE, TAG,
- "channel not in enable state. Current state: %s (%d), expected: %s (%d). "
- "Channel ID: %d, Group ID: %d",
- rmt_fsm_state_to_string(current_state), (int)current_state,
- rmt_fsm_state_to_string(RMT_FSM_ENABLE), (int)RMT_FSM_ENABLE,
- channel_id, group->group_id);
- }
- // Rest der Funktion bleibt unverändert...
- // fill in the transaction descriptor
- rmt_rx_trans_desc_t *t = &rx_chan->trans_desc;
- memset(t, 0, sizeof(rmt_rx_trans_desc_t));
- t->buffer = buffer;
- t->buffer_size = buffer_size;
- t->received_symbol_num = 0;
- t->copy_dest_off = 0;
- t->dma_desc_index = 0;
- t->flags.en_partial_rx = config->flags.en_partial_rx;
- #if SOC_RMT_SUPPORT_DMA
- if (channel->dma_chan) {
- // invalidate the user buffer, in case cache auto-write back happens and breaks the data just written by the DMA
- uint32_t int_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
- if (int_mem_cache_line_size) {
- // this function will also check the alignment of the buffer and size, against the cache line size
- ESP_RETURN_ON_ERROR_ISR(esp_cache_msync(buffer, buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), TAG, "cache sync failed");
- }
- // we will mount the buffer to multiple DMA nodes, in a balanced way
- size_t per_dma_block_size = buffer_size / rx_chan->num_dma_nodes;
- per_dma_block_size = ALIGN_DOWN(per_dma_block_size, mem_alignment);
- size_t last_dma_block_size = buffer_size - per_dma_block_size * (rx_chan->num_dma_nodes - 1);
- rmt_rx_mount_dma_buffer(rx_chan, buffer, buffer_size, per_dma_block_size, last_dma_block_size);
- gdma_reset(channel->dma_chan);
- gdma_start(channel->dma_chan, (intptr_t)rx_chan->dma_nodes); // note, we must use the cached descriptor address to start the DMA
- }
- #endif
- rx_chan->mem_off = 0;
- portENTER_CRITICAL_SAFE(&channel->spinlock);
- // reset memory writer offset
- rmt_ll_rx_reset_pointer(hal->regs, channel_id);
- rmt_ll_rx_set_mem_owner(hal->regs, channel_id, RMT_LL_MEM_OWNER_HW);
- // set sampling parameters of incoming signals
- rmt_ll_rx_set_filter_thres(hal->regs, channel_id, filter_reg_value);
- rmt_ll_rx_enable_filter(hal->regs, channel_id, config->signal_range_min_ns != 0);
- rmt_ll_rx_set_idle_thres(hal->regs, channel_id, idle_reg_value);
- // turn on RMT RX machine
- rmt_ll_rx_enable(hal->regs, channel_id, true);
- // saying we're in running state, this state will last until the receiving is done
- // i.e., we will switch back to the enable state in the receive done interrupt handler
- atomic_store(&channel->fsm, RMT_FSM_RUN);
- portEXIT_CRITICAL_SAFE(&channel->spinlock);
- return ESP_OK;
- }
- // Zusätzliche Debug-Funktion für Ihr Debugging
- esp_err_t rmt_rx_get_state_info(rmt_channel_handle_t channel, char* state_buffer, size_t buffer_size)
- {
- ESP_RETURN_ON_FALSE(channel && state_buffer && buffer_size > 0, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
- ESP_RETURN_ON_FALSE(channel->direction == RMT_CHANNEL_DIRECTION_RX, ESP_ERR_INVALID_ARG, TAG, "invalid channel direction");
- rmt_fsm_t current_state = atomic_load(&channel->fsm);
- rmt_group_t *group = channel->group;
- snprintf(state_buffer, buffer_size,
- "RMT RX Channel Info:\n"
- "- Channel ID: %d\n"
- "- Group ID: %d\n"
- "- Current State: %s (%d)\n"
- "- GPIO: %d\n"
- "- Resolution: %"PRIu32" Hz\n"
- "- DMA enabled: %s\n",
- channel->channel_id,
- group->group_id,
- rmt_fsm_state_to_string(current_state),
- (int)current_state,
- channel->gpio_num,
- channel->resolution_hz,
- channel->dma_chan ? "Yes" : "No");
- return ESP_OK;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement