/** Tests validity of pointed data */ inline enum IMUErrorMask eIMUDataValid( const struct IMUData * const pxIMUData ) { enum IMUErrorMask eErrorMask = IMU_ERR_NONE; eErrorMask |= prvAltitudeValid( pxIMUData ) | prvAngleValid( pxIMUData ); /* | prvSpeedValid( pxIMUData ) | prvAccelValid( pxIMUData ); */ if( eErrorMask == IMU_ERR_NONE ) { ulDebugMsg( xTaskGetTickCount(), "INFO ", pcTaskGetTaskName( NULL ), uxTaskPriorityGet( NULL ), MODULE, "eIMUDataValid()", "IMU measure is in valid range" ); } else { ulDebugMsg( xTaskGetTickCount(), "ERROR", pcTaskGetTaskName( NULL ), uxTaskPriorityGet( NULL ), MODULE, "eIMUDataValid()", "IMU measure is not in valid range !" ); } return eErrorMask; }
void TaskBase::print_status (emstream& ser_dev) { ser_dev.puts (pcTaskGetTaskName (handle)); ser_dev.putchar ('\t'); if (strlen ((const char*)(pcTaskGetTaskName (handle))) < 8) { ser_dev.putchar ('\t'); } ser_dev << (uint8_t)(uxTaskPriorityGet (handle)) << PMS ("\t") << get_state () #if (INCLUDE_uxTaskGetStackHighWaterMark == 1) << PMS ("\t") << uxTaskGetStackHighWaterMark(handle) << PMS ("/") << (size_t)(get_total_stack ()) << PMS ("\t") #endif << PMS ("\t") << runs; }
/** Gets IMU attitude measurements */ inline void vIMUGetData( struct IMUData * const pxIMUData ) { ulDebugMsg( xTaskGetTickCount(), "TODO", pcTaskGetTaskName( NULL ), uxTaskPriorityGet( NULL ), "imu", "vIMUGetData()", "Does nothing ATM" ); /* TODO : implement during integration */ }
/** Tests correct behavior of the IMU */ inline uint8_t ucIMUTest( void ) { ulDebugMsg( xTaskGetTickCount(), "TODO", pcTaskGetTaskName( NULL ), uxTaskPriorityGet( NULL ), "imu", "ucIMUTest()", "Does nothing ATM" ); return 0; }
/** * @brief This function handles Hard Fault exception. * @param None * @retval None */ void HardFault_Handler(void) { #ifdef FREERTOS_CONFIG_H CurrentTaskHandle = xTaskGetCurrentTaskHandle(); pNameCurrentTask = pcTaskGetTaskName(CurrentTaskHandle); #endif /* Go to infinite loop when Hard Fault exception occurs */ while (1) { } }
static void task_wdt_isr(void *arg) { wdt_task_t *wdttask; const char *cpu; //Feed the watchdog so we do not reset TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; //Ack interrupt TIMERG0.int_clr_timers.wdt=1; //We are taking a spinlock while doing I/O (ets_printf) here. Normally, that is a pretty //bad thing, possibly (temporarily) hanging up the 2nd core and stopping FreeRTOS. In this case, //something bad already happened and reporting this is considered more important //than the badness caused by a spinlock here. portENTER_CRITICAL(&taskwdt_spinlock); if (!wdt_task_list) { //No task on list. Maybe none registered yet. portEXIT_CRITICAL(&taskwdt_spinlock); return; } //Watchdog got triggered because at least one task did not report in. ets_printf("Task watchdog got triggered. The following tasks did not feed the watchdog in time:\n"); for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) { if (!wdttask->fed_watchdog) { cpu=xTaskGetAffinity(wdttask->task_handle)==0?DRAM_STR("CPU 0"):DRAM_STR("CPU 1"); if (xTaskGetAffinity(wdttask->task_handle)==tskNO_AFFINITY) cpu=DRAM_STR("CPU 0/1"); ets_printf(" - %s (%s)\n", pcTaskGetTaskName(wdttask->task_handle), cpu); } } ets_printf(DRAM_STR("Tasks currently running:\n")); for (int x=0; x<portNUM_PROCESSORS; x++) { ets_printf("CPU %d: %s\n", x, pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(x))); } #if CONFIG_TASK_WDT_PANIC ets_printf("Aborting.\n"); abort(); #endif portEXIT_CRITICAL(&taskwdt_spinlock); }
void putsTaskFunction(void *parameters) { portTickType waketime = xTaskGetTickCount(); for (;;) { vTaskDelayUntil(&waketime, (MESSAGE_PERIOD/2 + (lrand48() % (MESSAGE_PERIOD/2)))/portTICK_RATE_MS); xSemaphoreTake(console_lock, portMAX_DELAY); printf("This is %s\n", pcTaskGetTaskName(NULL)); xSemaphoreGive(console_lock); } }
/** * @brief This is the code that gets called when the processor receives an * unexpected interrupt. This simply enters an infinite loop, * preserving the system state for examination by a debugger. * @param None * @retval None */ static void Default_Handler(void) { /* Go into an infinite loop. */ int i; static char buffer[64]; snprintf(buffer, 64,"SOMETHING WRONG IN TASK: %s \r\n", pcTaskGetTaskName(NULL) ); log_func(buffer); for( ;; ); while (1) { } }
/**************************************************************************//** * @brief Simple task which is blinking led * @param *pParameters pointer to parameters passed to the function *****************************************************************************/ static void LedTask(void *pParameters) { vTaskDelay(1000 / portTICK_RATE_MS); LedTaskParams_t * pData = (LedTaskParams_t*) pParameters; const portTickType delay = pData->delay; for (;;) { BSP_LedToggle(pData->ledNo); vTaskDelay(delay); printf("%s. FreeHeap: %d\n", pcTaskGetTaskName(NULL), xPortGetFreeHeapSize()); } }
/* This is an entry point for the application. All application specific initialization is performed here. */ int main(void) { int ret = 0; TaskHandle_t blinkLEDHandle = NULL; int priority; /* Initializes console on UART0 */ ret = wmstdio_init(UART0_ID, 0); if (ret == -WM_FAIL) { wmprintf("Failed to initialize console on uart0\r\n"); return -1; } wmprintf(" LED demo application started\r\n"); wmprintf(" This application demonstrates the" " use of blinking led\r\n"); gpio_led = (board_led_2()).gpio; wmprintf(" LED Pin : %d\r\n", gpio_led); configure_gpios(); xTaskCreate(prvBlinkLedTask, "Blink led", ( uint16_t ) BLINK_LED_STACK_SIZE, NULL, ( ( UBaseType_t ) BLINK_LED_TASK_PRIORITY ) | portPRIVILEGE_BIT, &blinkLEDHandle); // dump blink led task related information if (NULL != blinkLEDHandle) { priority = uxTaskPriorityGet(blinkLEDHandle); wmprintf("blink led priority is %d\r\n", priority); wmprintf("blink led task name:%s\r\n", pcTaskGetTaskName(blinkLEDHandle)); } wmprintf("run blink led task for 30 seconds\r\n"); vTaskDelay(30000); wmprintf("delete blink led task\r\n"); if (NULL != blinkLEDHandle) { vTaskDelete(blinkLEDHandle); blinkLEDHandle = NULL; } while (1) { vTaskDelay(1000); } return 0; }
void UTL_FreeRtosTaskStackCheck(void) { taskInfoArray[PrintTaskIndex].FreeEntries = uxTaskGetStackHighWaterMark(taskInfoArray[PrintTaskIndex].taskHandle); /* free, used, total */ PrintF("%s %d %d %d", (char*)pcTaskGetTaskName(taskInfoArray[PrintTaskIndex].taskHandle), taskInfoArray[PrintTaskIndex].FreeEntries, taskInfoArray[PrintTaskIndex].Depth - taskInfoArray[PrintTaskIndex].FreeEntries, taskInfoArray[PrintTaskIndex].Depth)); PrintTaskIndex ++; if (rintTaskIndex >= TaskIndex) { PrintTaskIndex = 3; CreateAndSendMessage(&Msg, QueryMemoryMsg, MSG_OPT_NONE); } }
/** Gets IMU attitude measurements */ inline void vIMUGetData( struct IMUData * const pxIMUData ) { ulDebugMsg( xTaskGetTickCount(), "INFO ", pcTaskGetTaskName( NULL ), uxTaskPriorityGet( NULL ), MODULE, "vIMUGetData()", "Receiving IMU measurements" ); /* Reception is now handled by an interrupt */ //taskENTER_CRITICAL(); //imu_receive_frame( pusBuff ); //taskEXIT_CRITICAL(); /** @todo Ensure pusBuff is protected from overwriting while it is being parsed. */ imu_parse_frame( pxIMUData ); /* Displaced to prvSendStatus() */ // printf( "\r\n\t\tIMU measurements :" // "\r\n\t\t\tPitch = %d\r\n\t\t\tRoll = %d\r\n\t\t\tYaw = %d", // pxIMUData->plAngle[ IMU_AXIS_Y ], // pxIMUData->plAngle[ IMU_AXIS_X ], // pxIMUData->plAngle[ IMU_AXIS_Z ] ); }
static void prvDemonstrateTaskStateAndHandleGetFunctions( void ) { TaskHandle_t xIdleTaskHandle, xTimerTaskHandle; char *pcTaskName; static portBASE_TYPE xPerformedOneShotTests = pdFALSE; TaskHandle_t xTestTask; /* Demonstrate the use of the xTimerGetTimerDaemonTaskHandle() and xTaskGetIdleTaskHandle() functions. Also try using the function that sets the task number. */ xIdleTaskHandle = xTaskGetIdleTaskHandle(); xTimerTaskHandle = xTimerGetTimerDaemonTaskHandle(); /* This is the idle hook, so the current task handle should equal the returned idle task handle. */ if( xTaskGetCurrentTaskHandle() != xIdleTaskHandle ) { pcStatusMessage = "Error: Returned idle task handle was incorrect"; } /* Check the timer task handle was returned correctly. */ pcTaskName = pcTaskGetTaskName( xTimerTaskHandle ); if( strcmp( pcTaskName, "Tmr Svc" ) != 0 ) { pcStatusMessage = "Error: Returned timer task handle was incorrect"; } /* This task is running, make sure it's state is returned as running. */ if( eTaskStateGet( xIdleTaskHandle ) != eRunning ) { pcStatusMessage = "Error: Returned idle task state was incorrect"; } /* If this task is running, then the timer task must be blocked. */ if( eTaskStateGet( xTimerTaskHandle ) != eBlocked ) { pcStatusMessage = "Error: Returned timer task state was incorrect"; } /* Other tests that should only be performed once follow. The test task is not created on each iteration because to do so would cause the death task to report an error (too many tasks running). */ if( xPerformedOneShotTests == pdFALSE ) { /* Don't run this part of the test again. */ xPerformedOneShotTests = pdTRUE; /* Create a test task to use to test other eTaskStateGet() return values. */ if( xTaskCreate( prvTestTask, "Test", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTestTask ) == pdPASS ) { /* If this task is running, the test task must be in the ready state. */ if( eTaskStateGet( xTestTask ) != eReady ) { pcStatusMessage = "Error: Returned test task state was incorrect 1"; } /* Now suspend the test task and check its state is reported correctly. */ vTaskSuspend( xTestTask ); if( eTaskStateGet( xTestTask ) != eSuspended ) { pcStatusMessage = "Error: Returned test task state was incorrect 2"; } /* Now delete the task and check its state is reported correctly. */ vTaskDelete( xTestTask ); if( eTaskStateGet( xTestTask ) != eDeleted ) { pcStatusMessage = "Error: Returned test task state was incorrect 3"; } } } }
void vPortExceptionHandler( void *pvExceptionID ) { extern void *pxCurrentTCB; /* Fill an xPortRegisterDump structure with the MicroBlaze context as it was immediately before the exception occurrence. */ /* First fill in the name and handle of the task that was in the Running state when the exception occurred. */ xRegisterDump.xCurrentTaskHandle = pxCurrentTCB; xRegisterDump.pcCurrentTaskName = pcTaskGetTaskName( NULL ); configASSERT( pulStackPointerOnFunctionEntry ); /* Obtain the values of registers that were stacked prior to this function being called, and may have changed since they were stacked. */ xRegisterDump.ulR3 = pulStackPointerOnFunctionEntry[ portexR3_STACK_OFFSET ]; xRegisterDump.ulR4 = pulStackPointerOnFunctionEntry[ portexR4_STACK_OFFSET ]; xRegisterDump.ulR5 = pulStackPointerOnFunctionEntry[ portexR5_STACK_OFFSET ]; xRegisterDump.ulR6 = pulStackPointerOnFunctionEntry[ portexR6_STACK_OFFSET ]; xRegisterDump.ulR7 = pulStackPointerOnFunctionEntry[ portexR7_STACK_OFFSET ]; xRegisterDump.ulR8 = pulStackPointerOnFunctionEntry[ portexR8_STACK_OFFSET ]; xRegisterDump.ulR9 = pulStackPointerOnFunctionEntry[ portexR9_STACK_OFFSET ]; xRegisterDump.ulR10 = pulStackPointerOnFunctionEntry[ portexR10_STACK_OFFSET ]; xRegisterDump.ulR11 = pulStackPointerOnFunctionEntry[ portexR11_STACK_OFFSET ]; xRegisterDump.ulR12 = pulStackPointerOnFunctionEntry[ portexR12_STACK_OFFSET ]; xRegisterDump.ulR15_return_address_from_subroutine = pulStackPointerOnFunctionEntry[ portexR15_STACK_OFFSET ]; xRegisterDump.ulR18 = pulStackPointerOnFunctionEntry[ portexR18_STACK_OFFSET ]; xRegisterDump.ulR19 = pulStackPointerOnFunctionEntry[ portexR19_STACK_OFFSET ]; xRegisterDump.ulMSR = pulStackPointerOnFunctionEntry[ portexMSR_STACK_OFFSET ]; /* Obtain the value of all other registers. */ xRegisterDump.ulR2_small_data_area = mfgpr( R2 ); xRegisterDump.ulR13_read_write_small_data_area = mfgpr( R13 ); xRegisterDump.ulR14_return_address_from_interrupt = mfgpr( R14 ); xRegisterDump.ulR16_return_address_from_trap = mfgpr( R16 ); xRegisterDump.ulR17_return_address_from_exceptions = mfgpr( R17 ); xRegisterDump.ulR20 = mfgpr( R20 ); xRegisterDump.ulR21 = mfgpr( R21 ); xRegisterDump.ulR22 = mfgpr( R22 ); xRegisterDump.ulR23 = mfgpr( R23 ); xRegisterDump.ulR24 = mfgpr( R24 ); xRegisterDump.ulR25 = mfgpr( R25 ); xRegisterDump.ulR26 = mfgpr( R26 ); xRegisterDump.ulR27 = mfgpr( R27 ); xRegisterDump.ulR28 = mfgpr( R28 ); xRegisterDump.ulR29 = mfgpr( R29 ); xRegisterDump.ulR30 = mfgpr( R30 ); xRegisterDump.ulR31 = mfgpr( R31 ); xRegisterDump.ulR1_SP = ( ( unsigned long ) pulStackPointerOnFunctionEntry ) + portexASM_HANDLER_STACK_FRAME_SIZE; xRegisterDump.ulEAR = mfear(); xRegisterDump.ulESR = mfesr(); xRegisterDump.ulEDR = mfedr(); /* Move the saved program counter back to the instruction that was executed when the exception occurred. This is only valid for certain types of exception. */ xRegisterDump.ulPC = xRegisterDump.ulR17_return_address_from_exceptions - portexINSTRUCTION_SIZE; #if XPAR_MICROBLAZE_0_USE_FPU == 1 { xRegisterDump.ulFSR = mffsr(); } #else { xRegisterDump.ulFSR = 0UL; } #endif /* Also fill in a string that describes what type of exception this is. The string uses the same ID names as defined in the MicroBlaze standard library exception header files. */ switch( ( unsigned long ) pvExceptionID ) { case XEXC_ID_FSL : xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_FSL"; break; case XEXC_ID_UNALIGNED_ACCESS : xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_UNALIGNED_ACCESS"; break; case XEXC_ID_ILLEGAL_OPCODE : xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_ILLEGAL_OPCODE"; break; case XEXC_ID_M_AXI_I_EXCEPTION : xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_M_AXI_I_EXCEPTION or XEXC_ID_IPLB_EXCEPTION"; break; case XEXC_ID_M_AXI_D_EXCEPTION : xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_M_AXI_D_EXCEPTION or XEXC_ID_DPLB_EXCEPTION"; break; case XEXC_ID_DIV_BY_ZERO : xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_DIV_BY_ZERO"; break; case XEXC_ID_STACK_VIOLATION : xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_STACK_VIOLATION or XEXC_ID_MMU"; break; #if XPAR_MICROBLAZE_0_USE_FPU == 1 case XEXC_ID_FPU : xRegisterDump.pcExceptionCause = ( signed char * const ) "XEXC_ID_FPU see ulFSR value"; break; #endif /* XPAR_MICROBLAZE_0_USE_FPU */ } /* vApplicationExceptionRegisterDump() is a callback function that the application can optionally define to receive the populated xPortRegisterDump structure. If the application chooses not to define a version of vApplicationExceptionRegisterDump() then the weekly defined default implementation within this file will be called instead. */ vApplicationExceptionRegisterDump( &xRegisterDump ); /* Must not attempt to leave this function! */ for( ;; ) { portNOP(); } }
inline void vPWMSet( enum PWMId ePWMId ) { ulDebugMsg( xTaskGetTickCount(), "TODO", pcTaskGetTaskName( NULL ), uxTaskPriorityGet( NULL ), "pwm", "vPWMSet", "Does nothing ATM" ); }
void aws_iot_task(void *param) { char cPayload[100]; int32_t i = 0; IoT_Error_t rc = FAILURE; AWS_IoT_Client client; IoT_Client_Init_Params mqttInitParams = iotClientInitParamsDefault; IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault; IoT_Publish_Message_Params paramsQOS0; IoT_Publish_Message_Params paramsQOS1; ESP_LOGI(TAG, "AWS IoT SDK Version %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG); mqttInitParams.enableAutoReconnect = false; // We enable this later below mqttInitParams.pHostURL = HostAddress; mqttInitParams.port = port; #if defined(CONFIG_EXAMPLE_EMBEDDED_CERTS) mqttInitParams.pRootCALocation = (const char *)aws_root_ca_pem_start; mqttInitParams.pDeviceCertLocation = (const char *)certificate_pem_crt_start; mqttInitParams.pDevicePrivateKeyLocation = (const char *)private_pem_key_start; #elif defined(CONFIG_EXAMPLE_FILESYSTEM_CERTS) mqttInitParams.pRootCALocation = ROOT_CA_PATH; mqttInitParams.pDeviceCertLocation = DEVICE_CERTIFICATE_PATH; mqttInitParams.pDevicePrivateKeyLocation = DEVICE_PRIVATE_KEY_PATH; #endif mqttInitParams.mqttCommandTimeout_ms = 20000; mqttInitParams.tlsHandshakeTimeout_ms = 5000; mqttInitParams.isSSLHostnameVerify = true; mqttInitParams.disconnectHandler = disconnectCallbackHandler; mqttInitParams.disconnectHandlerData = NULL; #ifdef CONFIG_EXAMPLE_SDCARD_CERTS ESP_LOGI(TAG, "Mounting SD card..."); sdmmc_host_t host = SDMMC_HOST_DEFAULT(); sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = false, .max_files = 3, }; sdmmc_card_t* card; esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to mount SD card VFAT filesystem. Error: %s", esp_err_to_name(ret)); abort(); } #endif rc = aws_iot_mqtt_init(&client, &mqttInitParams); if(SUCCESS != rc) { ESP_LOGE(TAG, "aws_iot_mqtt_init returned error : %d ", rc); abort(); } /* Wait for WiFI to show as connected */ xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); connectParams.keepAliveIntervalInSec = 10; connectParams.isCleanSession = true; connectParams.MQTTVersion = MQTT_3_1_1; /* Client ID is set in the menuconfig of the example */ connectParams.pClientID = CONFIG_AWS_EXAMPLE_CLIENT_ID; connectParams.clientIDLen = (uint16_t) strlen(CONFIG_AWS_EXAMPLE_CLIENT_ID); connectParams.isWillMsgPresent = false; ESP_LOGI(TAG, "Connecting to AWS..."); do { rc = aws_iot_mqtt_connect(&client, &connectParams); if(SUCCESS != rc) { ESP_LOGE(TAG, "Error(%d) connecting to %s:%d", rc, mqttInitParams.pHostURL, mqttInitParams.port); vTaskDelay(1000 / portTICK_RATE_MS); } } while(SUCCESS != rc); /* * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h * #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL * #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL */ rc = aws_iot_mqtt_autoreconnect_set_status(&client, true); if(SUCCESS != rc) { ESP_LOGE(TAG, "Unable to set Auto Reconnect to true - %d", rc); abort(); } const char *TOPIC = "test_topic/esp32"; const int TOPIC_LEN = strlen(TOPIC); ESP_LOGI(TAG, "Subscribing..."); rc = aws_iot_mqtt_subscribe(&client, TOPIC, TOPIC_LEN, QOS0, iot_subscribe_callback_handler, NULL); if(SUCCESS != rc) { ESP_LOGE(TAG, "Error subscribing : %d ", rc); abort(); } sprintf(cPayload, "%s : %d ", "hello from SDK", i); paramsQOS0.qos = QOS0; paramsQOS0.payload = (void *) cPayload; paramsQOS0.isRetained = 0; paramsQOS1.qos = QOS1; paramsQOS1.payload = (void *) cPayload; paramsQOS1.isRetained = 0; while(1) { //Max time the yield function will wait for read messages rc = aws_iot_mqtt_yield(&client, 100); if(NETWORK_ATTEMPTING_RECONNECT == rc) { // If the client is attempting to reconnect we will skip the rest of the loop. continue; } ESP_LOGI(TAG, "Stack remaining for task '%s' is %lu bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL)); vTaskDelay(1000 / portTICK_RATE_MS); sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS0)", i++); paramsQOS0.payloadLen = strlen(cPayload); rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS0); sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS1)", i++); paramsQOS1.payloadLen = strlen(cPayload); rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, ¶msQOS1); if (rc == MQTT_REQUEST_TIMEOUT_ERROR) { ESP_LOGW(TAG, "QOS1 publish ack not received."); rc = SUCCESS; } } ESP_LOGE(TAG, "An error occurred in the main loop."); abort(); } static void initialise_wifi(void) { tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); wifi_config_t wifi_config = { .sta = { .ssid = EXAMPLE_WIFI_SSID, .password = EXAMPLE_WIFI_PASS, }, }; ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); ESP_ERROR_CHECK( esp_wifi_start() ); }