ESP32 RMT使用记录(坑记录)(大牛欢迎给出建议)

        在timer isr callback里面调用rmt_write_items,同时WIFI STA初始化或者连接,那么100%程序崩溃,崩在

        assert failed: xQueueSemaphoreTake queue.c:1554 (!( ( xTaskGetSchedulerState() == ( ( BaseType_t ) 0 ) ) && ( xTicksToWait != 0 ) ))

        官方答复:不要在中断里面有耗时操作

        但是如果不在timer isr callback里面调用rmt_write_items,使用while循环,那么周期控制就不准

代码如下:

注意:关闭wifi就没有问题了,但是项目必须要用wifi


#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/rmt.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "driver/timer.h"
#include <sys/time.h>

#define RMT_TX_U102_29_CHANNEL  RMT_CHANNEL_0
#define RMT_TX_U102_29_GPIO     4
#define RMT_TX_U102_16_CHANNEL  RMT_CHANNEL_1
#define RMT_TX_U102_16_GPIO     6
#define RMT_TX_U102_15_CHANNEL  RMT_CHANNEL_2
#define RMT_TX_U102_15_GPIO     7


#define	RMT_TIMER_GROUP			TIMER_GROUP_0
#define	RMT_TIMER_INDEX			TIMER_0
#define TIMER_DIVIDER           80//1us   clock 80MHZ
/*
 * Prepare a raw table with a message in the Morse code
 *
 * The message is "ESP" : . ... .--.
 *
 * The table structure represents the RMT item structure:
 * {duration, level, duration, level}
 *
 */
 static const rmt_item32_t morse_esp_type1[] = {
     {{{ 10, 0, 60, 1 }}}, 
 };

static const rmt_item32_t morse_esp2[] = {
    {{{ 100, 1, 10, 0 }}}, 
};

/*
 * Initialize the RMT Tx channel
 */
static void rmt_tx_init(void)
{
    rmt_config_t config1 = RMT_DEFAULT_CONFIG_TX(RMT_TX_U102_29_GPIO, RMT_TX_U102_29_CHANNEL);
    config1.flags = RMT_CHANNEL_FLAGS_INVERT_SIG;
    config1.tx_config.carrier_en = true;
    config1.tx_config.carrier_duty_percent = 50;
    config1.tx_config.carrier_freq_hz = 500000;
    config1.clk_div = 80;

    rmt_config_t config2 = RMT_DEFAULT_CONFIG_TX(RMT_TX_U102_16_GPIO, RMT_TX_U102_16_CHANNEL);
    config2.tx_config.carrier_en = false;
    config2.tx_config.carrier_duty_percent = 50;
    config2.tx_config.carrier_freq_hz = 500000;
    config2.clk_div = 80;

    rmt_config_t config3 = RMT_DEFAULT_CONFIG_TX(RMT_TX_U102_15_GPIO, RMT_TX_U102_15_CHANNEL);
    config3.tx_config.carrier_en = false;
    config3.tx_config.carrier_duty_percent = 50;
    config3.tx_config.carrier_freq_hz = 500000;
    config3.clk_div = 80;

    ESP_ERROR_CHECK(rmt_config_self(&config1, true)); /*20221011 YB added new API to set open Drain for TX or not*/
    //ESP_ERROR_CHECK(rmt_config(&config1));
    ESP_ERROR_CHECK(rmt_config(&config2));
    ESP_ERROR_CHECK(rmt_config(&config3));
    ESP_ERROR_CHECK(rmt_driver_install(config1.channel, 0, 0));
    ESP_ERROR_CHECK(rmt_driver_install(config2.channel, 0, 0));
    ESP_ERROR_CHECK(rmt_driver_install(config3.channel, 0, 0));

    ESP_ERROR_CHECK(rmt_add_channel_to_group(RMT_TX_U102_29_CHANNEL));
    ESP_ERROR_CHECK(rmt_add_channel_to_group(RMT_TX_U102_16_CHANNEL));
    ESP_ERROR_CHECK(rmt_add_channel_to_group(RMT_TX_U102_15_CHANNEL));
}
int test = 0;
static bool IRAM_ATTR adc_timer_group_isr_callback(void *args)
{
    timer_pause(RMT_TIMER_GROUP, RMT_TIMER_INDEX);

    ESP_ERROR_CHECK(rmt_write_items(RMT_TX_U102_15_CHANNEL, morse_esp2, sizeof(morse_esp2) / sizeof(morse_esp2[0]), false));
	ESP_ERROR_CHECK(rmt_write_items(RMT_TX_U102_29_CHANNEL, morse_esp_type1, sizeof(morse_esp_type1) / sizeof(morse_esp_type1[0]), false));
	ESP_ERROR_CHECK(rmt_write_items(RMT_TX_U102_16_CHANNEL, morse_esp_type1, sizeof(morse_esp_type1) / sizeof(morse_esp_type1[0]), false));
    timer_start(RMT_TIMER_GROUP, RMT_TIMER_INDEX);
    test++;
    return pdTRUE; // return whether we need to yield at the end of ISR
}

void rmt_timer_init(uint64_t timer_interval_us)
{
    /* Select and initialize basic parameters of the timer */
    timer_config_t config = {
        .divider = TIMER_DIVIDER,
        .counter_dir = TIMER_COUNT_UP,
        .counter_en = TIMER_PAUSE,
        .alarm_en = TIMER_ALARM_EN,
        .auto_reload = true,
    }; // default clock source is APB
    timer_init(RMT_TIMER_GROUP, RMT_TIMER_INDEX, &config);

    /* Timer's counter will initially start from value below.
       Also, if auto_reload is set, this value will be automatically reload on alarm */
    timer_set_counter_value(RMT_TIMER_GROUP, RMT_TIMER_INDEX, 0);

    /* Configure the alarm value and the interrupt on alarm. */
    timer_set_alarm_value(RMT_TIMER_GROUP, RMT_TIMER_INDEX, timer_interval_us);
    timer_enable_intr(RMT_TIMER_GROUP, RMT_TIMER_INDEX);                    
    timer_isr_callback_add(RMT_TIMER_GROUP, RMT_TIMER_INDEX, adc_timer_group_isr_callback, NULL, 0);

    timer_start(RMT_TIMER_GROUP, RMT_TIMER_INDEX);
}


void HWB_RMT_Task(void *Parameters)
{

    rmt_tx_init();
 
    rmt_timer_init(270);
    while(1){
        printf("test=%d\n",test);
		vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}
/* WiFi station Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "lwip/err.h"
#include "lwip/sys.h"


#define     HWB_WIFI_AP_SSID                        "1TMT_HWB"
#define     HWB_WIFI_AP_PASSWORD                    "12345678" //最小长度是8,最大长度是64
#define     HWB_WIFI_AP_CHANNEL                     1    //范围1-13,默认值1    
#define     HWB_WIFI_AP_MAX_STA_CONN                1
#define     HWB_WIFI_STA_MAXIMUM_RETRY              5
/* The examples use WiFi configuration that you can set via project configuration menu

   If you'd rather not, just change the below entries to strings with
   the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/


static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        printf("WIFI_EVENT_STA_START\n");
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        printf("WIFI_EVENT_STA_DISCONNECTED\n");
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
        printf("WIFI_EVENT_STA_CONNECTED\n");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        printf("IP_EVENT_STA_GOT_IP\n");
    }else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED) {
        printf("WIFI_EVENT_AP_STACONNECTED\n");
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STADISCONNECTED) {
        printf("WIFI_EVENT_AP_STADISCONNECTED\n");
    }
}


void HWB_Set_Ap_Dhcp_Info()
{
	tcpip_adapter_ip_info_t  ap_dhcp_info  = {0};
	//初始化网络和DHCP有关内存,必须要提前执行这个API 不然下面操作直接让设备重启
	tcpip_adapter_init();  
	// 将AP模式的DHCP 模式先关闭
	tcpip_adapter_dhcps_stop ( TCPIP_ADAPTER_IF_AP );
	//将对应的地址转成对应的字节序, 要注意apNetConfInf成员是结构体嵌套结构体,才是数组
	//
	IP4_ADDR( &ap_dhcp_info.ip      , 192 , 168 , 1   , 1);  //设置IP
	IP4_ADDR( &ap_dhcp_info.gw      , 192 , 168 , 1   , 1);  //设置网关
	IP4_ADDR( &ap_dhcp_info.netmask , 255 , 255 , 255 , 0);  //设置子网掩码
	
	tcpip_adapter_set_ip_info( TCPIP_ADAPTER_IF_AP , &ap_dhcp_info ); //设置IP信息
	
	tcpip_adapter_dhcps_start(  TCPIP_ADAPTER_IF_AP ); //重新启动AP模式 DHCP 
}

void HWB_Wifi_Init_Sta_And_Ap()
{
    printf("HWB_Wifi_Init_Sta_And_Ap thread cpu:%d\n",xPortGetCoreID());

    ESP_ERROR_CHECK(esp_netif_init());//创建一个 LwIP(轻量级的 TCP/IP 协议栈)核心任务,并初始化 LwIP 相关工作

    //创建一个系统事件任务,并初始化应用程序事件的回调函数。
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();//创建带有 TCP/IP 堆栈的默认网络接口实例绑定 AP
    //WIFI 驱动程序初始化配置时建议使用 IDF 默认的参数进行配置,WIFI_INIT_CONFIG_DEFAULT是一个宏,
    //这个宏的作用就是对结构体wifi_init_config_t进行初始化
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    //创建 WIFI 驱动程序任务并初始化 WIFI 驱动程序,这个API必须第一个调用,才能调用wifi的其他API
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    //向system event loop注册event handler
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_got_ip));

    //wifi_config_t是配置WIFI的集合union。
    //wifi_ap_config_t  ap  用于配置AP
    //wifi_sta_config_t sta 用于配置STA
    //WIFI STA Config
    wifi_config_t wifi_config_sta;
    memset(&wifi_config_sta, 0, sizeof(wifi_config_sta));
    wifi_config_sta.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
    wifi_config_sta.sta.threshold.authmode = WIFI_AUTH_OPEN;
    //WIFI AP Config
    wifi_config_t wifi_config_ap = {
        .ap = {
            .ssid = HWB_WIFI_AP_SSID,
            .ssid_len = strlen(HWB_WIFI_AP_SSID),
            .channel = HWB_WIFI_AP_CHANNEL,
            .password = HWB_WIFI_AP_PASSWORD,
            .max_connection = HWB_WIFI_AP_MAX_STA_CONN,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK
        },
    };
    if (strlen(HWB_WIFI_AP_PASSWORD) == 0) {
        wifi_config_ap.ap.authmode = WIFI_AUTH_OPEN;
    }
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA) );//配置WIFI的工作模式为AP-STA,即AP 和STA共存模式;
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config_sta) );//对wifi的STA模式进行配置
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config_ap) );//对wifi的AP模式进行配置
    ESP_ERROR_CHECK(esp_wifi_start() );//启动WIFI
    HWB_Set_Ap_Dhcp_Info();
    esp_netif_ip_info_t ip_info;
    esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"), &ip_info);

    char ip_addr[16];
    esp_ip4addr_ntoa(&ip_info.ip, ip_addr, 16);
    printf("wifi ap with IP: %s\n", ip_addr);

    printf("HWB_Wifi_Init_Sta_And_Ap finished.\n");
    while(1){
      vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}
/* Handwrite Board

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_http_client.h"
#include "driver/gpio.h"
#include "nvs_flash.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_wifi.h"

TaskHandle_t wifi_sta_ap_task_handle = NULL;
TaskHandle_t rmt_task_handle = NULL;

//extern method
extern void HWB_Wifi_Init_Sta_And_Ap();
extern void HWB_RMT_Task(void *Parameters);

void HWB_Wifi_Sta_Ap_Task(void *Parameters)
{
  HWB_Wifi_Init_Sta_And_Ap();
}
void app_main(void)
{
	printf("main thread cpu:%d\n",xPortGetCoreID());
    //Initialize NVS
    ESP_ERROR_CHECK(nvs_flash_erase());//test
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    
    //创建业务处理线程,启动wifi sta
	xTaskCreate(HWB_Wifi_Sta_Ap_Task, "HWB_Wifi_Sta_Ap_Task", (10*1024), NULL, 1, &wifi_sta_ap_task_handle);
	xTaskCreate(HWB_RMT_Task, "HWB_RMT_Task", (20*1024), NULL, 1, &rmt_task_handle);
	printf("app_main end\n");	
}

崩溃信息:

Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。

尝试新的跨平台 PowerShell https://aka.ms/pscore6

PS C:\Users\sqc_w\esp\1TMT_HandwriteBoard> set IDF_PATH=C:\Users\sqc_w\esp\esp-idf
PS C:\Users\sqc_w\esp\1TMT_HandwriteBoard> C:\Users\sqc_w\.espressif\Espressif\python_env\idf4.4_py3.8_env\Scripts\python.exe C:\Users\sqc_w\esp\esp-idf\tools\idf_monitor.py -p COM36 -b 115200 --toolchain-prefix xtensa-esp32s3-elf- --target esp32s3 c:\Users\sqc_w\esp\1TMT_HandwriteBoard\build\1TST_HandwriteBoard.elf
--- WARNING: GDB cannot open serial ports accessed as COMx
--- Using \\.\COM36 instead...
--- idf_monitor on \\.\COM36 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0xa (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3808,len:0x1664
load:0x403c9700,len:0xbb8
load:0x403cc700,len:0x2e8c
entry 0x403c9954
I (24) boot: ESP-IDF v4.4.3-dirty 2nd stage bootloader
I (25) boot: compile time 23:28:40
I (25) boot: chip revision: 0
I (27) boot.esp32s3: Boot SPI Speed : 80MHz
I (32) boot.esp32s3: SPI Mode       : DIO
I (36) boot.esp32s3: SPI Flash Size : 8MB
I (41) boot: Enabling RNG early entropy source...
I (46) boot: Partition Table:
I (50) boot: ## Label            Usage          Type ST Offset   Length
I (57) boot:  0 nvs              WiFi data        01 02 00009000 00004000
I (65) boot:  1 otadata          OTA data         01 00 0000d000 00002000
I (72) boot:  2 phy_init         RF data          01 01 0000f000 00001000
I (80) boot:  3 factory          factory app      00 00 00010000 00100000
I (87) boot:  4 ota_0            OTA app          00 10 00110000 00100000
I (95) boot:  5 ota_1            OTA app          00 11 00210000 00100000
I (102) boot: End of partition table
I (106) boot: Defaulting to factory image
I (111) esp_image: segment 0: paddr=00010020 vaddr=3c070020 size=0df00h ( 57088) map
I (130) esp_image: segment 1: paddr=0001df28 vaddr=3fc96db0 size=020f0h (  8432) load
I (132) esp_image: segment 2: paddr=00020020 vaddr=42000020 size=6b1f8h (438776) map
I (215) esp_image: segment 3: paddr=0008b220 vaddr=3fc98ea0 size=01e64h (  7780) load
I (217) esp_image: segment 4: paddr=0008d08c vaddr=40374000 size=12dach ( 77228) load
I (238) esp_image: segment 5: paddr=0009fe40 vaddr=50000000 size=00010h (    16) load
I (246) boot: Loaded app from partition at offset 0x10000
I (246) boot: Disabling RNG early entropy source...
main thread cpu:0
HWB_Wifi_Init_Sta_And_Ap thread cpu:1
app_main end
RTM lib: rmt_set_gpio_new, setOpenDrain(1)
RTM lib: 20221011 set tx to GPIO_MODE_OUTPUT_OD
test=0

assert failed: xQueueSemaphoreTake queue.c:1554 (!( ( xTaskGetSchedulerState() == ( ( BaseType_t ) 0 ) ) && ( xTicksToWait != 0 ) ))


Backtrace: 0x40375b9a:0x3fc97770 0x4037d329:0x3fc97790 0x4038444d:0x3fc977b0 0x4037e2a1:0x3fc978d0 0x42008ec0:0x3fc97910 0x403772b9:0x3fc97950 0x40377cad:0x3fc97970 0x40376cd5:0x3fc97990 0x400559dd:0x3fcf1380 |<-CORRUPTED
0x40375b9a: panic_abort at C:/Users/sqc_w/esp/esp-idf/components/esp_system/panic.c:402

0x4037d329: esp_system_abort at C:/Users/sqc_w/esp/esp-idf/components/esp_system/esp_system.c:128

0x4038444d: __assert_func at C:/Users/sqc_w/esp/esp-idf/components/newlib/assert.c:85

0x4037e2a1: xQueueSemaphoreTake at C:/Users/sqc_w/esp/esp-idf/components/freertos/queue.c:1554 (discriminator 2)

0x42008ec0: rmt_write_items at C:/Users/sqc_w/esp/esp-idf/components/driver/rmt.c:1179 (discriminator 2)

0x403772b9: adc_timer_group_isr_callback at C:/Users/sqc_w/esp/1TMT_HandwriteBoard/main/rmt.c:83

0x40377cad: timer_isr_default at C:/Users/sqc_w/esp/esp-idf/components/driver/timer.c:208

0x40376cd5: _xt_lowint1 at C:/Users/sqc_w/esp/esp-idf/components/freertos/port/xtensa/xtensa_vectors.S:1111





ELF file SHA256: eb4a05cd2860d920

Rebooting...
�ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0xa (SPI_FAST_FLASH_BOOT)
Saved PC:0x40375838
0x40375838: esp_restart_noos at C:/Users/sqc_w/esp/esp-idf/components/esp_system/port/soc/esp32s3/system_internal.c:151 (discriminator 1)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值