diff --git a/components/bt/bluedroid/btc/core/btc_main.c b/components/bt/bluedroid/btc/core/btc_main.c index 9181b6ab2a..d251782e40 100644 --- a/components/bt/bluedroid/btc/core/btc_main.c +++ b/components/bt/bluedroid/btc/core/btc_main.c @@ -18,6 +18,7 @@ #include "future.h" #include "esp_err.h" #include "btc_config.h" +#include "alarm.h" static future_t *main_future[BTC_MAIN_FUTURE_NUM]; @@ -51,6 +52,8 @@ void btc_init_callback(void) static void btc_init_bluetooth(void) { + osi_alarm_create_mux(); + osi_alarm_init(); btc_config_init(); bte_main_boot_entry(btc_init_callback); } @@ -60,6 +63,8 @@ static void btc_deinit_bluetooth(void) { bte_main_shutdown(); btc_config_clean_up(); + osi_alarm_deinit(); + osi_alarm_delete_mux(); future_ready(*btc_main_get_future_p(BTC_MAIN_DEINIT_FUTURE), FUTURE_SUCCESS); } diff --git a/components/bt/bluedroid/main/bte_main.c b/components/bt/bluedroid/main/bte_main.c index 1ca3946d62..1b74d558fd 100644 --- a/components/bt/bluedroid/main/bte_main.c +++ b/components/bt/bluedroid/main/bte_main.c @@ -144,8 +144,6 @@ int bte_main_boot_entry(bluedroid_init_done_cb_t cb) //data_dispatcher_register_default(hci->event_dispatcher, btu_hci_msg_queue); hci->set_data_queue(btu_hci_msg_queue); - osi_alarm_init(); - #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) //bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE); #endif diff --git a/components/bt/bluedroid/osi/alarm.c b/components/bt/bluedroid/osi/alarm.c index 6ef8d304ad..3d36be7270 100644 --- a/components/bt/bluedroid/osi/alarm.c +++ b/components/bt/bluedroid/osi/alarm.c @@ -36,11 +36,73 @@ #define BT_ALARM_FREE_WAIT_TICKS 100 #define BT_ALARM_CHG_PERIOD_WAIT_TICKS 100 +enum { + ALARM_STATE_IDLE, + ALARM_STATE_OPEN, +}; + +static osi_mutex_t alarm_mutex; +static int alarm_state; + static struct alarm_t alarm_cbs[ALARM_CBS_NUM]; +static int alarm_free(osi_alarm_t *alarm); + +int osi_alarm_create_mux(void) +{ + if (alarm_state != ALARM_STATE_IDLE) { + LOG_WARN("%s, invalid state %d\n", __func__, alarm_state); + return -1; + } + osi_mutex_new(&alarm_mutex); + return 0; +} + +int osi_alarm_delete_mux(void) +{ + if (alarm_state != ALARM_STATE_IDLE) { + LOG_WARN("%s, invalid state %d\n", __func__, alarm_state); + return -1; + } + osi_mutex_free(&alarm_mutex); + return 0; +} + void osi_alarm_init(void) { - memset(&alarm_cbs[0], 0x00, sizeof(alarm_cbs)); + assert(alarm_mutex != NULL); + + osi_mutex_lock(&alarm_mutex); + if (alarm_state != ALARM_STATE_IDLE) { + LOG_WARN("%s, invalid state %d\n", __func__, alarm_state); + goto end; + } + memset(alarm_cbs, 0x00, sizeof(alarm_cbs)); + alarm_state = ALARM_STATE_OPEN; + +end: + osi_mutex_unlock(&alarm_mutex); +} + +void osi_alarm_deinit(void) +{ + assert(alarm_mutex != NULL); + + osi_mutex_lock(&alarm_mutex); + if (alarm_state != ALARM_STATE_OPEN) { + LOG_WARN("%s, invalid state %d\n", __func__, alarm_state); + goto end; + } + + for (int i = 0; i < ALARM_CBS_NUM; i++) { + if (alarm_cbs[i].alarm_hdl != NULL) { + alarm_free(&alarm_cbs[i]); + } + } + alarm_state = ALARM_STATE_IDLE; + +end: + osi_mutex_unlock(&alarm_mutex); } static struct alarm_t *alarm_cbs_lookfor_available(void) @@ -75,88 +137,141 @@ static void alarm_cb_handler(TimerHandle_t xTimer) osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire) { - struct alarm_t *timer_id; - TimerHandle_t t; + assert(alarm_mutex != NULL); + + struct alarm_t *timer_id = NULL; + + osi_mutex_lock(&alarm_mutex); + if (alarm_state != ALARM_STATE_OPEN) { + LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state); + timer_id = NULL; + goto end; + } + + timer_id = alarm_cbs_lookfor_available(); + + if (!timer_id) { + LOG_ERROR("%s alarm_cbs exhausted\n", __func__); + timer_id = NULL; + goto end; + } if (timer_expire == 0) { timer_expire = 1000; } - /* TODO mutex lock */ - timer_id = alarm_cbs_lookfor_available(); - if (!timer_id) { - LOG_ERROR("%s full\n", __func__); - return NULL; - } - - t = xTimerCreate(alarm_name, timer_expire / portTICK_PERIOD_MS, pdFALSE, timer_id, alarm_cb_handler); + TimerHandle_t t = xTimerCreate(alarm_name, timer_expire / portTICK_PERIOD_MS, pdFALSE, timer_id, alarm_cb_handler); if (!t) { - LOG_ERROR("%s error\n", __func__); - return NULL; + LOG_ERROR("%s failed to create timer\n", __func__); + timer_id = NULL; + goto end; } timer_id->alarm_hdl = t; timer_id->cb = callback; timer_id->cb_data = data; - /* TODO mutex unlock */ +end: + osi_mutex_unlock(&alarm_mutex); return timer_id; } -int osi_alarm_free(osi_alarm_t *alarm) +static int alarm_free(osi_alarm_t *alarm) { - if (!alarm) { + if (!alarm || alarm->alarm_hdl == NULL) { LOG_ERROR("%s null\n", __func__); return -1; } if (xTimerDelete(alarm->alarm_hdl, BT_ALARM_FREE_WAIT_TICKS) != pdPASS) { - LOG_ERROR("%s error\n", __func__); + LOG_ERROR("%s alarm delete error\n", __func__); return -2; } - - /* TODO mutex lock */ - memset(alarm, 0x00, sizeof(osi_alarm_t)); - /* TODO mutex unlock */ - + + memset(alarm, 0, sizeof(osi_alarm_t)); return 0; } +int osi_alarm_free(osi_alarm_t *alarm) +{ + assert(alarm_mutex != NULL); + + int ret = 0; + osi_mutex_lock(&alarm_mutex); + if (alarm_state != ALARM_STATE_OPEN) { + LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state); + ret = -3; + goto end; + } + alarm_free(alarm); + +end: + osi_mutex_unlock(&alarm_mutex); + return ret; +} + int osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout) { - if (!alarm) { - LOG_ERROR("%s null\n", __func__); - return -1; + assert(alarm_mutex != NULL); + + int ret = 0; + osi_mutex_lock(&alarm_mutex); + if (alarm_state != ALARM_STATE_OPEN) { + LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state); + ret = -3; + goto end; } - + + if (!alarm || alarm->alarm_hdl == NULL) { + LOG_ERROR("%s null\n", __func__); + ret = -1; + goto end; + } + if (xTimerChangePeriod(alarm->alarm_hdl, timeout / portTICK_PERIOD_MS, BT_ALARM_CHG_PERIOD_WAIT_TICKS) != pdPASS) { LOG_ERROR("%s chg period error\n", __func__); - return -2; + ret = -2; + goto end; } if (xTimerStart(alarm->alarm_hdl, BT_ALARM_START_WAIT_TICKS) != pdPASS) { LOG_ERROR("%s start error\n", __func__); - return -3; + ret = -2; + goto end; } - return 0; +end: + osi_mutex_unlock(&alarm_mutex); + return ret; } int osi_alarm_cancel(osi_alarm_t *alarm) { - if (!alarm) { + int ret = 0; + osi_mutex_lock(&alarm_mutex); + if (alarm_state != ALARM_STATE_OPEN) { + LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state); + ret = -3; + goto end; + } + + if (!alarm || alarm->alarm_hdl == NULL) { LOG_ERROR("%s null\n", __func__); - return -1; + ret = -1; + goto end; } if (xTimerStop(alarm->alarm_hdl, BT_ALARM_STOP_WAIT_TICKS) != pdPASS) { - LOG_ERROR("%s error\n", __func__); - return -2; + LOG_ERROR("%s failed to stop timer\n", __func__); + ret = -2; + goto end; } - return 0; +end: + osi_mutex_unlock(&alarm_mutex); + return ret; } static uint32_t alarm_current_tick(void) diff --git a/components/bt/bluedroid/osi/include/alarm.h b/components/bt/bluedroid/osi/include/alarm.h index 2e226ed27f..35c0f4666b 100644 --- a/components/bt/bluedroid/osi/include/alarm.h +++ b/components/bt/bluedroid/osi/include/alarm.h @@ -35,7 +35,10 @@ typedef struct alarm_t { void *cb_data; } osi_alarm_t; +int osi_alarm_create_mux(void); +int osi_alarm_delete_mux(void); void osi_alarm_init(void); +void osi_alarm_deinit(void); // Creates a new alarm object. The returned object must be freed by calling // |alarm_free|. Returns NULL on failure. diff --git a/components/freertos/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h index 7cae4b05b6..157b9156f7 100644 --- a/components/freertos/include/freertos/portmacro.h +++ b/components/freertos/include/freertos/portmacro.h @@ -79,6 +79,8 @@ extern "C" { #include #include /* required for XSHAL_CLIB */ #include +#include "esp_crosscore_int.h" + //#include "xtensa_context.h" @@ -261,6 +263,18 @@ void vPortYield( void ); void _frxt_setup_switch( void ); #define portYIELD() vPortYield() #define portYIELD_FROM_ISR() _frxt_setup_switch() + +static inline uint32_t xPortGetCoreID(); + +/* Yielding within an API call (when interrupts are off), means the yield should be delayed + until interrupts are re-enabled. + + To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This + is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is + happening on the same CPU. +*/ +#define portYIELD_WITHIN_API() esp_crosscore_int_send_yield(xPortGetCoreID()) + /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ diff --git a/components/freertos/queue.c b/components/freertos/queue.c index 7c491f6952..66a7ed0497 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -123,15 +123,9 @@ zero. */ #if( configUSE_PREEMPTION == 0 ) /* If the cooperative scheduler is being used then a yield should not be performed just because a higher priority task has been woken. */ - #define queueYIELD_IF_USING_PREEMPTION_MUX() #define queueYIELD_IF_USING_PREEMPTION() #else #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() - #define queueYIELD_IF_USING_PREEMPTION_MUX(mux) { \ - taskEXIT_CRITICAL(mux); \ - portYIELD_WITHIN_API(); \ - taskENTER_CRITICAL(mux); \ - } while(0) #endif /* @@ -290,7 +284,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) { - queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + queueYIELD_IF_USING_PREEMPTION(); } else { @@ -753,7 +747,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* The queue is a member of a queue set, and posting to the queue set caused a higher priority task to unblock. A context switch is required. */ - queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + queueYIELD_IF_USING_PREEMPTION(); } else { @@ -772,7 +766,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; our own so yield immediately. Yes it is ok to do this from within the critical section - the kernel takes care of that. */ - queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + queueYIELD_IF_USING_PREEMPTION(); } else { @@ -785,7 +779,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; executed if the task was holding multiple mutexes and the mutexes were given back in an order that is different to that in which they were taken. */ - queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + queueYIELD_IF_USING_PREEMPTION(); } else { @@ -805,7 +799,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; our own so yield immediately. Yes it is ok to do this from within the critical section - the kernel takes care of that. */ - queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + queueYIELD_IF_USING_PREEMPTION(); } else { @@ -818,7 +812,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; executed if the task was holding multiple mutexes and the mutexes were given back in an order that is different to that in which they were taken. */ - queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + queueYIELD_IF_USING_PREEMPTION(); } else { @@ -1493,7 +1487,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; { if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) { - queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + queueYIELD_IF_USING_PREEMPTION(); } else { @@ -1522,7 +1516,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) { /* The task waiting has a higher priority than this task. */ - queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); + queueYIELD_IF_USING_PREEMPTION(); } else { diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 145554a740..ff407d9baf 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -120,14 +120,8 @@ functions but without including stdio.h here. */ /* If the cooperative scheduler is being used then a yield should not be performed just because a higher priority task has been woken. */ #define taskYIELD_IF_USING_PREEMPTION() - #define queueYIELD_IF_USING_PREEMPTION_MUX(mux) #else #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() - #define taskYIELD_IF_USING_PREEMPTION_MUX(mux) { \ - taskEXIT_CRITICAL(mux); \ - portYIELD_WITHIN_API(); \ - taskENTER_CRITICAL(mux); \ - } while(0) #endif @@ -1166,7 +1160,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode { if( xCoreID == xPortGetCoreID() ) { - taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); + taskYIELD_IF_USING_PREEMPTION(); } else { taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority); @@ -1703,7 +1697,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode if( xYieldRequired == pdTRUE ) { - taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); + taskYIELD_IF_USING_PREEMPTION(); } else { @@ -1895,7 +1889,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode /* This yield may not cause the task just resumed to run, but will leave the lists in the correct state for the next yield. */ - taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); + taskYIELD_IF_USING_PREEMPTION(); } else if( pxTCB->xCoreID != xPortGetCoreID() ) { @@ -2206,7 +2200,7 @@ BaseType_t xAlreadyYielded = pdFALSE; xAlreadyYielded = pdTRUE; } #endif - taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); + taskYIELD_IF_USING_PREEMPTION(); } else { diff --git a/components/freertos/test/test_freertos_eventgroups.c b/components/freertos/test/test_freertos_eventgroups.c index f32c20ade9..8d5a5fb326 100644 --- a/components/freertos/test/test_freertos_eventgroups.c +++ b/components/freertos/test/test_freertos_eventgroups.c @@ -52,14 +52,15 @@ TEST_CASE("FreeRTOS Event Groups", "[freertos]") } /* Tasks all start instantly, but this task will resume running at the same time as the higher priority tasks on the - other processor may still be setting up, so give a tick for them to also block on BIT_CALL... */ - vTaskDelay(1); + other processor may still be setting up, so allow time for them to also block on BIT_CALL... */ + vTaskDelay(10); for (int i = 0; i < COUNT; i++) { /* signal all tasks with "CALL" bit... */ xEventGroupSetBits(eg, BIT_CALL); - TEST_ASSERT_EQUAL_HEX16(ALL_RESPONSE_BITS, xEventGroupWaitBits(eg, ALL_RESPONSE_BITS, true, true, 100 / portMAX_DELAY)); + /* Only wait for 1 tick, the wakeup should be immediate... */ + TEST_ASSERT_EQUAL_HEX16(ALL_RESPONSE_BITS, xEventGroupWaitBits(eg, ALL_RESPONSE_BITS, true, true, 1)); } /* Ensure all tasks cleaned up correctly */ diff --git a/components/freertos/test/test_preemption.c b/components/freertos/test/test_preemption.c new file mode 100644 index 0000000000..09dbcc003a --- /dev/null +++ b/components/freertos/test/test_preemption.c @@ -0,0 +1,108 @@ +/* + Unit tests for FreeRTOS preemption +*/ + +#include +#include +#include "rom/ets_sys.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "soc/cpu.h" + +static volatile bool trigger; +static volatile bool flag; + +/* Task: + - Waits for 'trigger' variable to be set + - Reads the cycle count on this CPU + - Pushes it into a queue supplied as a param + - Busy-waits until the main task terminates it +*/ +static void task_send_to_queue(void *param) +{ + QueueHandle_t queue = (QueueHandle_t) param; + uint32_t ccount; + + while(!trigger) {} + + RSR(CCOUNT, ccount); + flag = true; + xQueueSendToBack(queue, &ccount, 0); + /* This is to ensure that higher priority task + won't wake anyhow, due to this task terminating. + + The task runs until terminated by the main task. + */ + while(1) {} +} + +TEST_CASE("Yield from lower priority task, same CPU", "[freertos]") +{ + /* Do this 3 times, mostly for the benchmark value - the first + run includes a cache miss so uses more cycles than it should. */ + for (int i = 0; i < 3; i++) { + TaskHandle_t sender_task; + QueueHandle_t queue = xQueueCreate(1, sizeof(uint32_t)); + flag = false; + trigger = false; + + /* "yield" task sits on our CPU, lower priority to us */ + xTaskCreatePinnedToCore(task_send_to_queue, "YIELD", 2048, (void *)queue, UNITY_FREERTOS_PRIORITY - 1, &sender_task, UNITY_FREERTOS_CPU); + + vTaskDelay(1); /* make sure everything is set up */ + trigger = true; + + uint32_t yield_ccount, now_ccount, delta; + TEST_ASSERT( xQueueReceive(queue, &yield_ccount, 100 / portTICK_PERIOD_MS) ); + RSR(CCOUNT, now_ccount); + TEST_ASSERT( flag ); + + delta = now_ccount - yield_ccount; + printf("Yielding from lower priority task took %u cycles\n", delta); + TEST_ASSERT(delta < 10000); + + vQueueDelete(queue); + vTaskDelete(sender_task); + } +} + + +TEST_CASE("Yield from lower priority task, other CPU", "[freertos]") +{ + uint32_t trigger_ccount, yield_ccount, now_ccount, delta; + + /* Do this 3 times, mostly for the benchmark value - the first + run includes a cache miss so uses more cycles than it should. */ + for (int i = 0; i < 3; i++) { + TaskHandle_t sender_task; + QueueHandle_t queue = xQueueCreate(1, sizeof(uint32_t)); + trigger = false; + flag = false; + + /* "send_to_queue" task sits on the other CPU, lower priority to us */ + xTaskCreatePinnedToCore(task_send_to_queue, "YIELD", 2048, (void *)queue, UNITY_FREERTOS_PRIORITY - 1, + &sender_task, !UNITY_FREERTOS_CPU); + + vTaskDelay(2); /* make sure everything is set up */ + trigger = true; + RSR(CCOUNT, trigger_ccount); + + // yield_ccount is not useful in this test as it's the other core's CCOUNT + // so we use trigger_ccount instead + TEST_ASSERT( xQueueReceive(queue, &yield_ccount, 100 / portTICK_PERIOD_MS) ); + RSR(CCOUNT, now_ccount); + TEST_ASSERT( flag ); + + delta = now_ccount - trigger_ccount; + printf("Yielding from task on other core took %u cycles\n", delta); + TEST_ASSERT(delta < 10000); + + vQueueDelete(queue); + vTaskDelete(sender_task); + } +} diff --git a/components/lwip/api/tcpip.c b/components/lwip/api/tcpip.c index 8374c429cd..ac6a711ee1 100755 --- a/components/lwip/api/tcpip.c +++ b/components/lwip/api/tcpip.c @@ -59,6 +59,7 @@ static tcpip_init_done_fn tcpip_init_done; static void *tcpip_init_done_arg; static sys_mbox_t mbox; +sys_thread_t g_lwip_task = NULL; #if LWIP_TCPIP_CORE_LOCKING /** The global semaphore to lock the stack. */ @@ -498,11 +499,11 @@ tcpip_init(tcpip_init_done_fn initfunc, void *arg) #endif /* LWIP_TCPIP_CORE_LOCKING */ - sys_thread_t xLwipTaskHandle = sys_thread_new(TCPIP_THREAD_NAME + g_lwip_task = sys_thread_new(TCPIP_THREAD_NAME , tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_task_hdlxxx : %x, prio:%d,stack:%d\n", - (u32_t)xLwipTaskHandle,TCPIP_THREAD_PRIO,TCPIP_THREAD_STACKSIZE)); + (u32_t)g_lwip_task,TCPIP_THREAD_PRIO,TCPIP_THREAD_STACKSIZE)); } diff --git a/components/lwip/core/ipv4/dhcp.c b/components/lwip/core/ipv4/dhcp.c index 1f180511ed..1c18494e15 100755 --- a/components/lwip/core/ipv4/dhcp.c +++ b/components/lwip/core/ipv4/dhcp.c @@ -539,6 +539,8 @@ static void dhcp_t1_timeout(struct netif *netif) { struct dhcp *dhcp = netif->dhcp; + int half_t2_timeout; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING)) { @@ -550,15 +552,16 @@ dhcp_t1_timeout(struct netif *netif) DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ dhcp_renew(netif); /* Calculate next timeout */ + half_t2_timeout = (netif->dhcp->t2_timeout - dhcp->lease_used) / 2; #if ESP_DHCP_TIMER - if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= (60 + DHCP_COARSE_TIMER_SECS / 2) ) + if (half_t2_timeout*DHCP_COARSE_TIMER_SECS >= 3) { - netif->dhcp->t1_renew_time = (netif->dhcp->t2_timeout - dhcp->lease_used) / 2; + netif->dhcp->t1_renew_time = half_t2_timeout; } #else - if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + if (half_t2_timeout >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) { - netif->dhcp->t1_renew_time = ((netif->dhcp->t2_timeout - dhcp->lease_used) / 2); + netif->dhcp->t1_renew_time = half_t2_timeout; } #endif } @@ -573,6 +576,7 @@ static void dhcp_t2_timeout(struct netif *netif) { struct dhcp *dhcp = netif->dhcp; + int half_t0_timeout; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) { @@ -583,15 +587,16 @@ dhcp_t2_timeout(struct netif *netif) DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */ dhcp_rebind(netif); /* Calculate next timeout */ + half_t0_timeout = (netif->dhcp->t0_timeout - dhcp->lease_used) / 2; #if ESP_DHCP_TIMER - if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= (60 + DHCP_COARSE_TIMER_SECS / 2)) + if (half_t0_timeout*DHCP_COARSE_TIMER_SECS >= 3) { - netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2); + netif->dhcp->t2_rebind_time = half_t0_timeout; } #else - if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) + if (half_t0_timeout >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) { - netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2); + netif->dhcp->t2_rebind_time = half_t0_timeout; } #endif } diff --git a/components/lwip/port/freertos/sys_arch.c b/components/lwip/port/freertos/sys_arch.c index 7f96c9b859..9d3aca8d7a 100755 --- a/components/lwip/port/freertos/sys_arch.c +++ b/components/lwip/port/freertos/sys_arch.c @@ -38,12 +38,13 @@ #include "lwip/mem.h" #include "arch/sys_arch.h" #include "lwip/stats.h" +#include "esp_log.h" /* This is the number of threads that can be started with sys_thread_new() */ #define SYS_THREAD_MAX 4 +#define TAG "lwip_arch" -static bool g_lwip_in_critical_section = false; -static BaseType_t g_lwip_critical_section_needs_taskswitch; +static sys_mutex_t g_lwip_protect_mutex = NULL; #if !LWIP_COMPAT_MUTEX /** Create a new mutex @@ -125,18 +126,7 @@ sys_sem_new(sys_sem_t *sem, u8_t count) void sys_sem_signal(sys_sem_t *sem) { - if (g_lwip_in_critical_section){ - /* In function event_callback in sockets.c, lwip signals a semaphore inside a critical - * section. According to the FreeRTOS documentation for FreertosTaskEnterCritical, it's - * not allowed to call any FreeRTOS API function within a critical region. Unfortunately, - * it's not feasible to rework the affected region in LWIP. As a solution, when in a - * critical region, we call xSemaphoreGiveFromISR. This routine is hand-vetted to work - * in a critical region and it will not cause a task switch. - */ - xSemaphoreGiveFromISR(*sem, &g_lwip_critical_section_needs_taskswitch); - } else { xSemaphoreGive(*sem); - } } /*-----------------------------------------------------------------------------------*/ @@ -394,7 +384,7 @@ sys_mbox_free(sys_mbox_t *mbox) } if (count == (MAX_POLL_CNT-1)){ - printf("WARNING: mbox %p had a consumer who never unblocked. Leaking!\n", (*mbox)->os_mbox); + ESP_LOGW(TAG, "WARNING: mbox %p had a consumer who never unblocked. Leaking!\n", (*mbox)->os_mbox); } sys_delay_ms(PER_POLL_DELAY); } @@ -440,6 +430,9 @@ sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize void sys_init(void) { + if (ERR_OK != sys_mutex_new(&g_lwip_protect_mutex)) { + ESP_LOGE(TAG, "sys_init: failed to init lwip protect mutex\n"); + } } /*-----------------------------------------------------------------------------------*/ @@ -449,7 +442,6 @@ sys_now(void) return xTaskGetTickCount(); } -static portMUX_TYPE g_lwip_mux = portMUX_INITIALIZER_UNLOCKED; /* This optional function does a "fast" critical region protection and returns the previous protection level. This function is only called during very short @@ -466,8 +458,7 @@ static portMUX_TYPE g_lwip_mux = portMUX_INITIALIZER_UNLOCKED; sys_prot_t sys_arch_protect(void) { - portENTER_CRITICAL(&g_lwip_mux); - g_lwip_in_critical_section = true; + sys_mutex_lock(&g_lwip_protect_mutex); return (sys_prot_t) 1; } @@ -481,13 +472,7 @@ sys_arch_protect(void) void sys_arch_unprotect(sys_prot_t pval) { - (void) pval; - g_lwip_in_critical_section = false; - portEXIT_CRITICAL(&g_lwip_mux); - if (g_lwip_critical_section_needs_taskswitch){ - g_lwip_critical_section_needs_taskswitch = 0; - portYIELD(); - } + sys_mutex_unlock(&g_lwip_protect_mutex); } /*-----------------------------------------------------------------------------------*/ @@ -497,7 +482,7 @@ sys_arch_unprotect(sys_prot_t pval) void sys_arch_assert(const char *file, int line) { - printf("\nAssertion: %d in %s\n", line, file); + ESP_LOGE(TAG, "\nAssertion: %d in %s\n", line, file); // vTaskEnterCritical(); while(1); @@ -537,14 +522,14 @@ sys_sem_t* sys_thread_sem_init(void) sys_sem_t *sem = (sys_sem_t*)malloc(sizeof(sys_sem_t*)); if (!sem){ - printf("sem f1\n"); + ESP_LOGE(TAG, "thread_sem_init: out of memory"); return 0; } *sem = xSemaphoreCreateBinary(); if (!(*sem)){ free(sem); - printf("sem f2\n"); + ESP_LOGE(TAG, "thread_sem_init: out of memory"); return 0; } diff --git a/components/spi_flash/cache_utils.c b/components/spi_flash/cache_utils.c index 6d0dd91845..b4e5fa6db5 100644 --- a/components/spi_flash/cache_utils.c +++ b/components/spi_flash/cache_utils.c @@ -69,9 +69,12 @@ void IRAM_ATTR spi_flash_op_block_func(void* arg) uint32_t cpuid = (uint32_t) arg; // Disable cache so that flash operation can start spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]); + // s_flash_op_complete flag is cleared on *this* CPU, otherwise the other + // CPU may reset the flag back to false before IPC task has a chance to check it + // (if it is preempted by an ISR taking non-trivial amount of time) + s_flash_op_complete = false; s_flash_op_can_start = true; while (!s_flash_op_complete) { - // until we have a way to use interrupts for inter-CPU communication, // busy loop here and wait for the other CPU to finish flash operation } // Flash operation is complete, re-enable cache @@ -105,7 +108,6 @@ void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu() // Signal to the spi_flash_op_block_task on the other CPU that we need it to // disable cache there and block other tasks from executing. s_flash_op_can_start = false; - s_flash_op_complete = false; esp_err_t ret = esp_ipc_call(other_cpuid, &spi_flash_op_block_func, (void*) other_cpuid); assert(ret == ESP_OK); while (!s_flash_op_can_start) { diff --git a/components/spi_flash/test/test_spi_flash.c b/components/spi_flash/test/test_spi_flash.c index c7829ead2a..f3bd3dc104 100644 --- a/components/spi_flash/test/test_spi_flash.c +++ b/components/spi_flash/test/test_spi_flash.c @@ -6,6 +6,8 @@ #include #include #include +#include "driver/timer.h" +#include "esp_intr_alloc.h" struct flash_test_ctx { uint32_t offset; @@ -87,3 +89,81 @@ TEST_CASE("flash write and erase work both on PRO CPU and on APP CPU", "[spi_fla vSemaphoreDelete(done); } + + +typedef struct { + size_t buf_size; + uint8_t* buf; + size_t flash_addr; + size_t repeat_count; + SemaphoreHandle_t done; +} read_task_arg_t; + + +typedef struct { + size_t delay_time_us; + size_t repeat_count; +} block_task_arg_t; + +static void IRAM_ATTR timer_isr(void* varg) { + block_task_arg_t* arg = (block_task_arg_t*) varg; + TIMERG0.int_clr_timers.t0 = 1; + TIMERG0.hw_timer[0].config.alarm_en = 1; + ets_delay_us(arg->delay_time_us); + arg->repeat_count++; +} + +static void read_task(void* varg) { + read_task_arg_t* arg = (read_task_arg_t*) varg; + for (size_t i = 0; i < arg->repeat_count; ++i) { + ESP_ERROR_CHECK( spi_flash_read(arg->flash_addr, arg->buf, arg->buf_size) ); + } + xSemaphoreGive(arg->done); + vTaskDelay(1); + vTaskDelete(NULL); +} + +TEST_CASE("spi flash functions can run along with IRAM interrupts", "[spi_flash]") +{ + const size_t size = 128; + read_task_arg_t read_arg = { + .buf_size = size, + .buf = (uint8_t*) malloc(size), + .flash_addr = 0, + .repeat_count = 1000, + .done = xSemaphoreCreateBinary() + }; + + timer_config_t config = { + .alarm_en = true, + .counter_en = false, + .intr_type = TIMER_INTR_LEVEL, + .counter_dir = TIMER_COUNT_UP, + .auto_reload = true, + .divider = 80 + }; + + block_task_arg_t block_arg = { + .repeat_count = 0, + .delay_time_us = 100 + }; + + ESP_ERROR_CHECK( timer_init(TIMER_GROUP_0, TIMER_0, &config) ); + timer_pause(TIMER_GROUP_0, TIMER_0); + ESP_ERROR_CHECK( timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 120) ); + intr_handle_t handle; + ESP_ERROR_CHECK( timer_isr_register(TIMER_GROUP_0, TIMER_0, &timer_isr, &block_arg, ESP_INTR_FLAG_IRAM, &handle) ); + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); + timer_enable_intr(TIMER_GROUP_0, TIMER_0); + timer_start(TIMER_GROUP_0, TIMER_0); + + xTaskCreatePinnedToCore(read_task, "r", 2048, &read_arg, 3, NULL, 1); + xSemaphoreTake(read_arg.done, portMAX_DELAY); + + timer_pause(TIMER_GROUP_0, TIMER_0); + timer_disable_intr(TIMER_GROUP_0, TIMER_0); + esp_intr_free(handle); + vSemaphoreDelete(read_arg.done); + free(read_arg.buf); +} + diff --git a/components/tcpip_adapter/include/tcpip_adapter.h b/components/tcpip_adapter/include/tcpip_adapter.h index 4f3b49ed27..f1a0a9e2f8 100644 --- a/components/tcpip_adapter/include/tcpip_adapter.h +++ b/components/tcpip_adapter/include/tcpip_adapter.h @@ -136,6 +136,39 @@ typedef enum{ TCPIP_ADAPTER_IP_REQUEST_RETRY_TIME = 52, /**< request IP address retry counter */ } tcpip_adapter_option_id_t; +struct tcpip_adapter_api_msg_s; +typedef int (*tcpip_adapter_api_fn)(struct tcpip_adapter_api_msg_s *msg); +typedef struct tcpip_adapter_api_msg_s { + int type; /**< The first field MUST be int */ + int ret; + tcpip_adapter_api_fn api_fn; + tcpip_adapter_if_t tcpip_if; + tcpip_adapter_ip_info_t *ip_info; + uint8_t *mac; + const char *hostname; +} tcpip_adapter_api_msg_t; + +#define TCPIP_ADAPTER_TRHEAD_SAFE 1 +#define TCPIP_ADAPTER_IPC_LOCAL 0 +#define TCPIP_ADAPTER_IPC_REMOTE 1 + +#define TCPIP_ADAPTER_IPC_CALL(_if, _mac, _ip, _hostname, _fn) do {\ + tcpip_adapter_api_msg_t msg;\ + memset(&msg, 0, sizeof(msg));\ + msg.tcpip_if = (_if);\ + msg.mac = (_mac);\ + msg.ip_info = (_ip);\ + msg.hostname = (_hostname);\ + msg.api_fn = (_fn);\ + if (TCPIP_ADAPTER_IPC_REMOTE == tcpip_adapter_ipc_check(&msg)) {\ + ESP_LOGD(TAG, "check: remote, if=%d fn=%p\n", (_if), (_fn));\ + return msg.ret;\ + } else {\ + ESP_LOGD(TAG, "check: local, if=%d fn=%p\n", (_if), (_fn));\ + }\ +}while(0) + + /** * @brief Initialize tcpip adapter * diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c index 7ee710f39a..bc50c79b97 100644 --- a/components/tcpip_adapter/tcpip_adapter_lwip.c +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -25,6 +25,7 @@ #include "lwip/ip_addr.h" #include "lwip/ip6_addr.h" #include "lwip/nd6.h" +#include "lwip/priv/tcpip_priv.h" #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ #include "lwip/dns.h" #endif @@ -34,6 +35,7 @@ #include "apps/dhcpserver.h" #include "esp_event.h" +#include "esp_log.h" static struct netif *esp_netif[TCPIP_ADAPTER_IF_MAX]; static tcpip_adapter_ip_info_t esp_ip[TCPIP_ADAPTER_IF_MAX]; @@ -41,13 +43,42 @@ static tcpip_adapter_ip6_info_t esp_ip6[TCPIP_ADAPTER_IF_MAX]; static tcpip_adapter_dhcp_status_t dhcps_status = TCPIP_ADAPTER_DHCP_INIT; static tcpip_adapter_dhcp_status_t dhcpc_status[TCPIP_ADAPTER_IF_MAX] = {TCPIP_ADAPTER_DHCP_INIT}; +static esp_err_t tcpip_adapter_start_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_stop_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_up_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_down_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_set_ip_info_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_create_ip6_linklocal_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_dhcps_start_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_dhcps_stop_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_dhcpc_start_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_dhcpc_stop_api(tcpip_adapter_api_msg_t * msg); +static esp_err_t tcpip_adapter_set_hostname_api(tcpip_adapter_api_msg_t * msg); +static sys_sem_t api_sync_sem = NULL; +extern sys_thread_t g_lwip_task; -#define TCPIP_ADAPTER_DEBUG(...) -//#define TCPIP_ADAPTER_DEBUG printf +#define TAG "tcpip_adapter" + +static void tcpip_adapter_api_cb(void* api_msg) +{ + tcpip_adapter_api_msg_t *msg = (tcpip_adapter_api_msg_t*)api_msg; + + if (!msg || !msg->api_fn) { + ESP_LOGD(TAG, "null msg/api_fn"); + return; + } + + msg->ret = msg->api_fn(msg); + ESP_LOGD(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret); + sys_sem_signal(&api_sync_sem); + + return; +} void tcpip_adapter_init(void) { static bool tcpip_inited = false; + int ret; if (tcpip_inited == false) { tcpip_inited = true; @@ -57,6 +88,10 @@ void tcpip_adapter_init(void) IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].ip, 192, 168 , 4, 1); IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].gw, 192, 168 , 4, 1); IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].netmask, 255, 255 , 255, 0); + ret = sys_sem_new(&api_sync_sem, 0); + if (ERR_OK != ret) { + ESP_LOGD(TAG, "tcpip adatper api sync sem init fail"); + } } } @@ -77,10 +112,29 @@ static netif_init_fn tcpip_if_to_netif_init_fn(tcpip_adapter_if_t tcpip_if) } } +static int tcpip_adapter_ipc_check(tcpip_adapter_api_msg_t *msg) +{ +#if TCPIP_ADAPTER_TRHEAD_SAFE + xTaskHandle local_task = xTaskGetCurrentTaskHandle(); + + if (local_task == g_lwip_task) { + return TCPIP_ADAPTER_IPC_LOCAL; + } + + tcpip_send_api_msg((tcpip_callback_fn)tcpip_adapter_api_cb, msg, &api_sync_sem); + + return TCPIP_ADAPTER_IPC_REMOTE; +#else + return TCPIP_ADAPTER_IPC_LOCAL; +#endif +} + esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, tcpip_adapter_ip_info_t *ip_info) { netif_init_fn netif_init; + TCPIP_ADAPTER_IPC_CALL(tcpip_if, mac, ip_info, 0, tcpip_adapter_start_api); + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || mac == NULL || ip_info == NULL) { return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; } @@ -103,7 +157,7 @@ esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, tcpip_a if (dhcps_status == TCPIP_ADAPTER_DHCP_INIT) { dhcps_start(esp_netif[tcpip_if], ip_info->ip); - TCPIP_ADAPTER_DEBUG("dhcp server start:(ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR ")\n", + ESP_LOGD(TAG, "dhcp server start:(ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR ")", IP2STR(&ip_info->ip), IP2STR(&ip_info->netmask), IP2STR(&ip_info->gw)); dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; @@ -122,8 +176,15 @@ esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, tcpip_a return ESP_OK; } +static esp_err_t tcpip_adapter_start_api(tcpip_adapter_api_msg_t * msg) +{ + return tcpip_adapter_start(msg->tcpip_if, msg->mac, msg->ip_info); +} + esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if) { + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_stop_api); + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; } @@ -162,8 +223,16 @@ esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if) return ESP_OK; } +static esp_err_t tcpip_adapter_stop_api(tcpip_adapter_api_msg_t * msg) +{ + msg->ret = tcpip_adapter_stop(msg->tcpip_if); + return msg->ret; +} + esp_err_t tcpip_adapter_up(tcpip_adapter_if_t tcpip_if) { + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_up_api); + if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH ) { if (esp_netif[tcpip_if] == NULL) { return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; @@ -177,8 +246,16 @@ esp_err_t tcpip_adapter_up(tcpip_adapter_if_t tcpip_if) return ESP_OK; } +static esp_err_t tcpip_adapter_up_api(tcpip_adapter_api_msg_t * msg) +{ + msg->ret = tcpip_adapter_up(msg->tcpip_if); + return msg->ret; +} + esp_err_t tcpip_adapter_down(tcpip_adapter_if_t tcpip_if) { + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_down_api); + if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH ) { if (esp_netif[tcpip_if] == NULL) { return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; @@ -203,6 +280,11 @@ esp_err_t tcpip_adapter_down(tcpip_adapter_if_t tcpip_if) return ESP_OK; } +static esp_err_t tcpip_adapter_down_api(tcpip_adapter_api_msg_t * msg) +{ + return tcpip_adapter_down(msg->tcpip_if); +} + esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) { struct netif *p_netif; @@ -233,6 +315,8 @@ esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_i struct netif *p_netif; tcpip_adapter_dhcp_status_t status; + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, ip_info, 0, tcpip_adapter_set_ip_info_api); + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL || ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask)) { return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; @@ -271,12 +355,17 @@ esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_i return ESP_OK; } +static esp_err_t tcpip_adapter_set_ip_info_api(tcpip_adapter_api_msg_t * msg) +{ + return tcpip_adapter_set_ip_info(msg->tcpip_if, msg->ip_info); +} + static void tcpip_adapter_nd6_cb(struct netif *p_netif, uint8_t ip_idex) { tcpip_adapter_ip6_info_t *ip6_info; if (!p_netif) { - TCPIP_ADAPTER_DEBUG("null p_netif=%p\n", p_netif); + ESP_LOGD(TAG, "null p_netif=%p", p_netif); return; } @@ -302,6 +391,8 @@ esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if) { struct netif *p_netif; + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_create_ip6_linklocal_api); + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; } @@ -317,6 +408,11 @@ esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if) } } +static esp_err_t tcpip_adapter_create_ip6_linklocal_api(tcpip_adapter_api_msg_t * msg) +{ + return tcpip_adapter_create_ip6_linklocal(msg->tcpip_if); +} + esp_err_t tcpip_adapter_get_ip6_linklocal(tcpip_adapter_if_t tcpip_if, ip6_addr_t *if_ip6) { struct netif *p_netif; @@ -474,9 +570,11 @@ esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adap esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if) { + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_dhcps_start_api); + /* only support ap now */ if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - TCPIP_ADAPTER_DEBUG("dhcp server invalid if=%d\n", tcpip_if); + ESP_LOGD(TAG, "dhcp server invalid if=%d", tcpip_if); return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; } @@ -488,24 +586,32 @@ esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if) tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &default_ip); dhcps_start(p_netif, default_ip.ip); dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; - TCPIP_ADAPTER_DEBUG("dhcp server start successfully\n"); + ESP_LOGD(TAG, "dhcp server start successfully"); return ESP_OK; } else { - TCPIP_ADAPTER_DEBUG("dhcp server re init\n"); + ESP_LOGD(TAG, "dhcp server re init"); dhcps_status = TCPIP_ADAPTER_DHCP_INIT; return ESP_OK; } } - TCPIP_ADAPTER_DEBUG("dhcp server already start\n"); + ESP_LOGD(TAG, "dhcp server already start"); return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; } +static esp_err_t tcpip_adapter_dhcps_start_api(tcpip_adapter_api_msg_t * msg) +{ + return tcpip_adapter_dhcps_start(msg->tcpip_if); +} + + esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if) { + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_dhcps_stop_api); + /* only support ap now */ if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - TCPIP_ADAPTER_DEBUG("dhcp server invalid if=%d\n", tcpip_if); + ESP_LOGD(TAG, "dhcp server invalid if=%d", tcpip_if); return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; } @@ -515,19 +621,24 @@ esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if) if (p_netif != NULL) { dhcps_stop(p_netif); } else { - TCPIP_ADAPTER_DEBUG("dhcp server if not ready\n"); + ESP_LOGD(TAG, "dhcp server if not ready"); return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; } } else if (dhcps_status == TCPIP_ADAPTER_DHCP_STOPPED) { - TCPIP_ADAPTER_DEBUG("dhcp server already stoped\n"); + ESP_LOGD(TAG, "dhcp server already stoped"); return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED; } - TCPIP_ADAPTER_DEBUG("dhcp server stop successfully\n"); + ESP_LOGD(TAG, "dhcp server stop successfully"); dhcps_status = TCPIP_ADAPTER_DHCP_STOPPED; return ESP_OK; } +static esp_err_t tcpip_adapter_dhcps_stop_api(tcpip_adapter_api_msg_t * msg) +{ + return tcpip_adapter_dhcps_stop(msg->tcpip_if); +} + esp_err_t tcpip_adapter_dhcpc_option(tcpip_adapter_option_mode_t opt_op, tcpip_adapter_option_id_t opt_id, void *opt_val, uint32_t opt_len) { // TODO: when dhcp request timeout,change the retry count @@ -537,12 +648,12 @@ esp_err_t tcpip_adapter_dhcpc_option(tcpip_adapter_option_mode_t opt_op, tcpip_a static void tcpip_adapter_dhcpc_cb(struct netif *netif) { if (!netif) { - TCPIP_ADAPTER_DEBUG("null netif=%p\n", netif); + ESP_LOGD(TAG, "null netif=%p", netif); return; } if (netif != esp_netif[TCPIP_ADAPTER_IF_STA] && netif != esp_netif[TCPIP_ADAPTER_IF_ETH]) { - TCPIP_ADAPTER_DEBUG("err netif=%p\n", netif); + ESP_LOGD(TAG, "err netif=%p", netif); return; } @@ -575,7 +686,7 @@ static void tcpip_adapter_dhcpc_cb(struct netif *netif) esp_event_send(&evt); } else { - TCPIP_ADAPTER_DEBUG("ip unchanged\n"); + ESP_LOGD(TAG, "ip unchanged"); } } @@ -591,9 +702,11 @@ esp_err_t tcpip_adapter_dhcpc_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adap esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if) { + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_dhcpc_start_api); + /* only support sta now, need to support ethernet */ if ((tcpip_if != TCPIP_ADAPTER_IF_STA && tcpip_if != TCPIP_ADAPTER_IF_ETH) || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - TCPIP_ADAPTER_DEBUG("dhcp client invalid if=%d\n", tcpip_if); + ESP_LOGD(TAG, "dhcp client invalid if=%d", tcpip_if); return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; } @@ -606,42 +719,49 @@ esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if) if (p_netif != NULL) { if (netif_is_up(p_netif)) { - TCPIP_ADAPTER_DEBUG("dhcp client init ip/mask/gw to all-0\n"); + ESP_LOGD(TAG, "dhcp client init ip/mask/gw to all-0"); ip_addr_set_zero(&p_netif->ip_addr); ip_addr_set_zero(&p_netif->netmask); ip_addr_set_zero(&p_netif->gw); } else { - TCPIP_ADAPTER_DEBUG("dhcp client re init\n"); + ESP_LOGD(TAG, "dhcp client re init"); dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; return ESP_OK; } if (dhcp_start(p_netif) != ERR_OK) { - TCPIP_ADAPTER_DEBUG("dhcp client start failed\n"); + ESP_LOGD(TAG, "dhcp client start failed"); return ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED; } dhcp_set_cb(p_netif, tcpip_adapter_dhcpc_cb); - TCPIP_ADAPTER_DEBUG("dhcp client start successfully\n"); + ESP_LOGD(TAG, "dhcp client start successfully"); dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_STARTED; return ESP_OK; } else { - TCPIP_ADAPTER_DEBUG("dhcp client re init\n"); + ESP_LOGD(TAG, "dhcp client re init"); dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; return ESP_OK; } } - TCPIP_ADAPTER_DEBUG("dhcp client already started\n"); + ESP_LOGD(TAG, "dhcp client already started"); return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; } +static esp_err_t tcpip_adapter_dhcpc_start_api(tcpip_adapter_api_msg_t * msg) +{ + return tcpip_adapter_dhcpc_start(msg->tcpip_if); +} + esp_err_t tcpip_adapter_dhcpc_stop(tcpip_adapter_if_t tcpip_if) { + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_dhcpc_stop_api); + /* only support sta now, need to support ethernet */ if (tcpip_if != TCPIP_ADAPTER_IF_STA || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - TCPIP_ADAPTER_DEBUG("dhcp client invalid if=%d\n", tcpip_if); + ESP_LOGD(TAG, "dhcp client invalid if=%d", tcpip_if); return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; } @@ -655,19 +775,24 @@ esp_err_t tcpip_adapter_dhcpc_stop(tcpip_adapter_if_t tcpip_if) ip4_addr_set_zero(&esp_ip[tcpip_if].gw); ip4_addr_set_zero(&esp_ip[tcpip_if].netmask); } else { - TCPIP_ADAPTER_DEBUG("dhcp client if not ready\n"); + ESP_LOGD(TAG, "dhcp client if not ready"); return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; } } else if (dhcpc_status[tcpip_if] == TCPIP_ADAPTER_DHCP_STOPPED) { - TCPIP_ADAPTER_DEBUG("dhcp client already stoped\n"); + ESP_LOGD(TAG, "dhcp client already stoped"); return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED; } - TCPIP_ADAPTER_DEBUG("dhcp client stop successfully\n"); + ESP_LOGD(TAG, "dhcp client stop successfully"); dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_STOPPED; return ESP_OK; } +static esp_err_t tcpip_adapter_dhcpc_stop_api(tcpip_adapter_api_msg_t * msg) +{ + return tcpip_adapter_dhcpc_stop(msg->tcpip_if); +} + esp_err_t tcpip_adapter_eth_input(void *buffer, uint16_t len, void *eb) { ethernetif_input(esp_netif[TCPIP_ADAPTER_IF_ETH], buffer, len); @@ -730,6 +855,7 @@ esp_err_t tcpip_adapter_get_sta_list(wifi_sta_list_t *wifi_sta_list, tcpip_adapt esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname) { #if LWIP_NETIF_HOSTNAME + TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, hostname, tcpip_adapter_set_hostname_api); struct netif *p_netif; static char hostinfo[TCPIP_ADAPTER_IF_MAX][TCPIP_HOSTNAME_MAX_SIZE + 1]; @@ -755,6 +881,11 @@ esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *ho #endif } +static esp_err_t tcpip_adapter_set_hostname_api(tcpip_adapter_api_msg_t * msg) +{ + return tcpip_adapter_set_hostname(msg->tcpip_if, msg->hostname); +} + esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char **hostname) { #if LWIP_NETIF_HOSTNAME diff --git a/docs/windows-setup.rst b/docs/windows-setup.rst index 6037761687..828afbd9bc 100644 --- a/docs/windows-setup.rst +++ b/docs/windows-setup.rst @@ -56,7 +56,7 @@ You can also find a range of example projects under the "examples" directory in Step 4: Configuring the project =============================== -Open an MSYS2 terminal window by running ``C:\msys32\msys2_shell.cmd``. The environment in this window is a bash shell. +Open an MSYS2 terminal window by running ``C:\msys32\mingw32.exe``. The environment in this window is a bash shell. Type a command like this to set the path to ESP-IDF directory: ``export IDF_PATH="C:/path/to/esp-idf"`` (note the forward-slashes not back-slashes for the path). If you don't want to run this command every time you open an MSYS2 window, create a new file in ``C:/msys32/etc/profile.d/`` and paste this line in - then it will be run each time you open an MYS2 terminal. diff --git a/tools/unit-test-app/components/unity/include/unity_config.h b/tools/unit-test-app/components/unity/include/unity_config.h index 07df5b3058..bacb79e00b 100644 --- a/tools/unit-test-app/components/unity/include/unity_config.h +++ b/tools/unit-test-app/components/unity/include/unity_config.h @@ -9,6 +9,10 @@ #include +/* Some definitions applicable to Unity running in FreeRTOS */ +#define UNITY_FREERTOS_PRIORITY 5 +#define UNITY_FREERTOS_CPU 0 + #define UNITY_EXCLUDE_FLOAT #define UNITY_EXCLUDE_DOUBLE diff --git a/tools/unit-test-app/main/app_main.c b/tools/unit-test-app/main/app_main.c index 58a1951720..c5df02b943 100644 --- a/tools/unit-test-app/main/app_main.c +++ b/tools/unit-test-app/main/app_main.c @@ -2,9 +2,9 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "unity.h" +#include "unity_config.h" - -void unityTask(void *pvParameters) +void unityTask(void *pvParameters) { vTaskDelay(1000 / portTICK_PERIOD_MS); unity_run_menu(); @@ -15,6 +15,6 @@ void app_main() { // Note: if unpinning this task, change the way run times are calculated in // unity_platform - xTaskCreatePinnedToCore(unityTask, "unityTask", 4096, NULL, 5, NULL, 0); + xTaskCreatePinnedToCore(unityTask, "unityTask", 4096, NULL, + UNITY_FREERTOS_PRIORITY, NULL, UNITY_FREERTOS_CPU); } -