Advertisement
DrMickeyLauer

ESP-IDF RMT Debugging++

Jun 30th, 2025
354
0
18 hours
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.55 KB | None | 0 0
  1. // Zusätzliche Hilfsfunktion für bessere State-Debugging-Nachrichten
  2. static const char* rmt_fsm_state_to_string(rmt_fsm_t state) {
  3.     switch (state) {
  4.         case RMT_FSM_INIT:   return "INIT";
  5.         case RMT_FSM_ENABLE: return "ENABLE";
  6.         case RMT_FSM_WAIT:   return "WAIT";
  7.         case RMT_FSM_RUN:    return "RUN";
  8.         default:             return "UNKNOWN";
  9.     }
  10. }
  11.  
  12. // Modifizierte rmt_receive Funktion mit verbesserter Fehlerbehandlung
  13. esp_err_t rmt_receive(rmt_channel_handle_t channel, void *buffer, size_t buffer_size, const rmt_receive_config_t *config)
  14. {
  15.     ESP_RETURN_ON_FALSE_ISR(channel && buffer && buffer_size && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
  16.     ESP_RETURN_ON_FALSE_ISR(channel->direction == RMT_CHANNEL_DIRECTION_RX, ESP_ERR_INVALID_ARG, TAG, "invalid channel direction");
  17. #if !SOC_RMT_SUPPORT_RX_PINGPONG
  18.     ESP_RETURN_ON_FALSE_ISR(!config->flags.en_partial_rx, ESP_ERR_NOT_SUPPORTED, TAG, "partial receive not supported");
  19. #endif
  20.     rmt_rx_channel_t *rx_chan = __containerof(channel, rmt_rx_channel_t, base);
  21.     size_t mem_alignment = sizeof(rmt_symbol_word_t);
  22.  
  23. #if SOC_RMT_SUPPORT_DMA
  24.     if (channel->dma_chan) {
  25.         // append the alignment requirement from the DMA
  26.         mem_alignment = MAX(mem_alignment, rx_chan->dma_int_mem_alignment);
  27.         // [IDF-8997]: Currently we assume the user buffer is allocated from internal RAM, PSRAM is not supported yet.
  28.         ESP_RETURN_ON_FALSE_ISR(esp_ptr_internal(buffer), ESP_ERR_INVALID_ARG, TAG, "user buffer not in the internal RAM");
  29.         size_t max_buf_sz_per_dma_node = ALIGN_DOWN(DMA_DESCRIPTOR_BUFFER_MAX_SIZE, mem_alignment);
  30.         ESP_RETURN_ON_FALSE_ISR(buffer_size <= rx_chan->num_dma_nodes * max_buf_sz_per_dma_node,
  31.                                 ESP_ERR_INVALID_ARG, TAG, "buffer size exceeds DMA capacity: %zu", rx_chan->num_dma_nodes * max_buf_sz_per_dma_node);
  32.     }
  33. #endif // SOC_RMT_SUPPORT_DMA
  34.  
  35.     // check buffer alignment
  36.     uint32_t align_check_mask = mem_alignment - 1;
  37.     ESP_RETURN_ON_FALSE_ISR(((((uintptr_t)buffer) & align_check_mask) == 0) && (((buffer_size) & align_check_mask) == 0), ESP_ERR_INVALID_ARG,
  38.                             TAG, "buffer address or size are not %"PRIu32 "bytes aligned", mem_alignment);
  39.  
  40.     rmt_group_t *group = channel->group;
  41.     rmt_hal_context_t *hal = &group->hal;
  42.     int channel_id = channel->channel_id;
  43.  
  44.     uint32_t filter_reg_value = ((uint64_t)rx_chan->filter_clock_resolution_hz * config->signal_range_min_ns) / 1000000000UL;
  45.     uint32_t idle_reg_value = ((uint64_t)channel->resolution_hz * config->signal_range_max_ns) / 1000000000UL;
  46.     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));
  47.     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));
  48.  
  49.     // VERBESSERTE STATE-ÜBERPRÜFUNG mit detaillierter Fehlermeldung
  50.     rmt_fsm_t current_state = atomic_load(&channel->fsm);
  51.     rmt_fsm_t expected_fsm = RMT_FSM_ENABLE;
  52.    
  53.     if (!atomic_compare_exchange_strong(&channel->fsm, &expected_fsm, RMT_FSM_WAIT)) {
  54.         // State-Check fehlgeschlagen - gebe detaillierte Information über aktuellen State aus
  55.         ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_STATE, TAG,
  56.                                 "channel not in enable state. Current state: %s (%d), expected: %s (%d). "
  57.                                 "Channel ID: %d, Group ID: %d",
  58.                                 rmt_fsm_state_to_string(current_state), (int)current_state,
  59.                                 rmt_fsm_state_to_string(RMT_FSM_ENABLE), (int)RMT_FSM_ENABLE,
  60.                                 channel_id, group->group_id);
  61.     }
  62.  
  63.     // Rest der Funktion bleibt unverändert...
  64.     // fill in the transaction descriptor
  65.     rmt_rx_trans_desc_t *t = &rx_chan->trans_desc;
  66.     memset(t, 0, sizeof(rmt_rx_trans_desc_t));
  67.     t->buffer = buffer;
  68.     t->buffer_size = buffer_size;
  69.     t->received_symbol_num = 0;
  70.     t->copy_dest_off = 0;
  71.     t->dma_desc_index = 0;
  72.     t->flags.en_partial_rx = config->flags.en_partial_rx;
  73.  
  74. #if SOC_RMT_SUPPORT_DMA
  75.     if (channel->dma_chan) {
  76.         // invalidate the user buffer, in case cache auto-write back happens and breaks the data just written by the DMA
  77.         uint32_t int_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
  78.         if (int_mem_cache_line_size) {
  79.             // this function will also check the alignment of the buffer and size, against the cache line size
  80.             ESP_RETURN_ON_ERROR_ISR(esp_cache_msync(buffer, buffer_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), TAG, "cache sync failed");
  81.         }
  82.         // we will mount the buffer to multiple DMA nodes, in a balanced way
  83.         size_t per_dma_block_size = buffer_size / rx_chan->num_dma_nodes;
  84.         per_dma_block_size = ALIGN_DOWN(per_dma_block_size, mem_alignment);
  85.         size_t last_dma_block_size = buffer_size - per_dma_block_size * (rx_chan->num_dma_nodes - 1);
  86.         rmt_rx_mount_dma_buffer(rx_chan, buffer, buffer_size, per_dma_block_size, last_dma_block_size);
  87.         gdma_reset(channel->dma_chan);
  88.         gdma_start(channel->dma_chan, (intptr_t)rx_chan->dma_nodes); // note, we must use the cached descriptor address to start the DMA
  89.     }
  90. #endif
  91.  
  92.     rx_chan->mem_off = 0;
  93.     portENTER_CRITICAL_SAFE(&channel->spinlock);
  94.     // reset memory writer offset
  95.     rmt_ll_rx_reset_pointer(hal->regs, channel_id);
  96.     rmt_ll_rx_set_mem_owner(hal->regs, channel_id, RMT_LL_MEM_OWNER_HW);
  97.     // set sampling parameters of incoming signals
  98.     rmt_ll_rx_set_filter_thres(hal->regs, channel_id, filter_reg_value);
  99.     rmt_ll_rx_enable_filter(hal->regs, channel_id, config->signal_range_min_ns != 0);
  100.     rmt_ll_rx_set_idle_thres(hal->regs, channel_id, idle_reg_value);
  101.     // turn on RMT RX machine
  102.     rmt_ll_rx_enable(hal->regs, channel_id, true);
  103.  
  104.     // saying we're in running state, this state will last until the receiving is done
  105.     // i.e., we will switch back to the enable state in the receive done interrupt handler
  106.     atomic_store(&channel->fsm, RMT_FSM_RUN);
  107.     portEXIT_CRITICAL_SAFE(&channel->spinlock);
  108.  
  109.     return ESP_OK;
  110. }
  111.  
  112. // Zusätzliche Debug-Funktion für Ihr Debugging
  113. esp_err_t rmt_rx_get_state_info(rmt_channel_handle_t channel, char* state_buffer, size_t buffer_size)
  114. {
  115.     ESP_RETURN_ON_FALSE(channel && state_buffer && buffer_size > 0, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
  116.     ESP_RETURN_ON_FALSE(channel->direction == RMT_CHANNEL_DIRECTION_RX, ESP_ERR_INVALID_ARG, TAG, "invalid channel direction");
  117.    
  118.     rmt_fsm_t current_state = atomic_load(&channel->fsm);
  119.     rmt_group_t *group = channel->group;
  120.    
  121.     snprintf(state_buffer, buffer_size,
  122.              "RMT RX Channel Info:\n"
  123.              "- Channel ID: %d\n"
  124.              "- Group ID: %d\n"
  125.              "- Current State: %s (%d)\n"
  126.              "- GPIO: %d\n"
  127.              "- Resolution: %"PRIu32" Hz\n"
  128.              "- DMA enabled: %s\n",
  129.              channel->channel_id,
  130.              group->group_id,
  131.              rmt_fsm_state_to_string(current_state),
  132.              (int)current_state,
  133.              channel->gpio_num,
  134.              channel->resolution_hz,
  135.              channel->dma_chan ? "Yes" : "No");
  136.              
  137.     return ESP_OK;
  138. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement