Merge branch 'master' into feature/btdm_avrc

This commit is contained in:
wangmengyang 2017-04-06 14:59:58 +08:00
commit dbd4e0522e
19 changed files with 606 additions and 133 deletions

View File

@ -18,6 +18,7 @@
#include "future.h" #include "future.h"
#include "esp_err.h" #include "esp_err.h"
#include "btc_config.h" #include "btc_config.h"
#include "alarm.h"
static future_t *main_future[BTC_MAIN_FUTURE_NUM]; static future_t *main_future[BTC_MAIN_FUTURE_NUM];
@ -51,6 +52,8 @@ void btc_init_callback(void)
static void btc_init_bluetooth(void) static void btc_init_bluetooth(void)
{ {
osi_alarm_create_mux();
osi_alarm_init();
btc_config_init(); btc_config_init();
bte_main_boot_entry(btc_init_callback); bte_main_boot_entry(btc_init_callback);
} }
@ -60,6 +63,8 @@ static void btc_deinit_bluetooth(void)
{ {
bte_main_shutdown(); bte_main_shutdown();
btc_config_clean_up(); btc_config_clean_up();
osi_alarm_deinit();
osi_alarm_delete_mux();
future_ready(*btc_main_get_future_p(BTC_MAIN_DEINIT_FUTURE), FUTURE_SUCCESS); future_ready(*btc_main_get_future_p(BTC_MAIN_DEINIT_FUTURE), FUTURE_SUCCESS);
} }

View File

@ -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); //data_dispatcher_register_default(hci->event_dispatcher, btu_hci_msg_queue);
hci->set_data_queue(btu_hci_msg_queue); hci->set_data_queue(btu_hci_msg_queue);
osi_alarm_init();
#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
//bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE); //bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE);
#endif #endif

View File

@ -36,11 +36,73 @@
#define BT_ALARM_FREE_WAIT_TICKS 100 #define BT_ALARM_FREE_WAIT_TICKS 100
#define BT_ALARM_CHG_PERIOD_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 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) 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) 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) 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; assert(alarm_mutex != NULL);
TimerHandle_t t;
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) { if (timer_expire == 0) {
timer_expire = 1000; timer_expire = 1000;
} }
/* TODO mutex lock */ TimerHandle_t t = xTimerCreate(alarm_name, timer_expire / portTICK_PERIOD_MS, pdFALSE, timer_id, alarm_cb_handler);
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);
if (!t) { if (!t) {
LOG_ERROR("%s error\n", __func__); LOG_ERROR("%s failed to create timer\n", __func__);
return NULL; timer_id = NULL;
goto end;
} }
timer_id->alarm_hdl = t; timer_id->alarm_hdl = t;
timer_id->cb = callback; timer_id->cb = callback;
timer_id->cb_data = data; timer_id->cb_data = data;
/* TODO mutex unlock */
end:
osi_mutex_unlock(&alarm_mutex);
return timer_id; 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__); LOG_ERROR("%s null\n", __func__);
return -1; return -1;
} }
if (xTimerDelete(alarm->alarm_hdl, BT_ALARM_FREE_WAIT_TICKS) != pdPASS) { 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; return -2;
} }
/* TODO mutex lock */ memset(alarm, 0, sizeof(osi_alarm_t));
memset(alarm, 0x00, sizeof(osi_alarm_t));
/* TODO mutex unlock */
return 0; 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) int osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout)
{ {
if (!alarm) { assert(alarm_mutex != NULL);
LOG_ERROR("%s null\n", __func__);
return -1; 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) { if (xTimerChangePeriod(alarm->alarm_hdl, timeout / portTICK_PERIOD_MS, BT_ALARM_CHG_PERIOD_WAIT_TICKS) != pdPASS) {
LOG_ERROR("%s chg period error\n", __func__); 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) { if (xTimerStart(alarm->alarm_hdl, BT_ALARM_START_WAIT_TICKS) != pdPASS) {
LOG_ERROR("%s start error\n", __func__); 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) 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__); LOG_ERROR("%s null\n", __func__);
return -1; ret = -1;
goto end;
} }
if (xTimerStop(alarm->alarm_hdl, BT_ALARM_STOP_WAIT_TICKS) != pdPASS) { if (xTimerStop(alarm->alarm_hdl, BT_ALARM_STOP_WAIT_TICKS) != pdPASS) {
LOG_ERROR("%s error\n", __func__); LOG_ERROR("%s failed to stop timer\n", __func__);
return -2; ret = -2;
goto end;
} }
return 0; end:
osi_mutex_unlock(&alarm_mutex);
return ret;
} }
static uint32_t alarm_current_tick(void) static uint32_t alarm_current_tick(void)

View File

@ -35,7 +35,10 @@ typedef struct alarm_t {
void *cb_data; void *cb_data;
} osi_alarm_t; } osi_alarm_t;
int osi_alarm_create_mux(void);
int osi_alarm_delete_mux(void);
void osi_alarm_init(void); void osi_alarm_init(void);
void osi_alarm_deinit(void);
// Creates a new alarm object. The returned object must be freed by calling // Creates a new alarm object. The returned object must be freed by calling
// |alarm_free|. Returns NULL on failure. // |alarm_free|. Returns NULL on failure.

View File

@ -79,6 +79,8 @@ extern "C" {
#include <xtensa/config/core.h> #include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */ #include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/xtruntime.h> #include <xtensa/xtruntime.h>
#include "esp_crosscore_int.h"
//#include "xtensa_context.h" //#include "xtensa_context.h"
@ -261,6 +263,18 @@ void vPortYield( void );
void _frxt_setup_switch( void ); void _frxt_setup_switch( void );
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portYIELD_FROM_ISR() _frxt_setup_switch() #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. */ /* Task function macros as described on the FreeRTOS.org WEB site. */

View File

@ -123,15 +123,9 @@ zero. */
#if( configUSE_PREEMPTION == 0 ) #if( configUSE_PREEMPTION == 0 )
/* If the cooperative scheduler is being used then a yield should not be /* If the cooperative scheduler is being used then a yield should not be
performed just because a higher priority task has been woken. */ performed just because a higher priority task has been woken. */
#define queueYIELD_IF_USING_PREEMPTION_MUX()
#define queueYIELD_IF_USING_PREEMPTION() #define queueYIELD_IF_USING_PREEMPTION()
#else #else
#define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() #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 #endif
/* /*
@ -290,7 +284,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
{ {
queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); queueYIELD_IF_USING_PREEMPTION();
} }
else else
{ {
@ -753,7 +747,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
/* The queue is a member of a queue set, and posting /* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to to the queue set caused a higher priority task to
unblock. A context switch is required. */ unblock. A context switch is required. */
queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); queueYIELD_IF_USING_PREEMPTION();
} }
else else
{ {
@ -772,7 +766,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
our own so yield immediately. Yes it is ok to our own so yield immediately. Yes it is ok to
do this from within the critical section - the do this from within the critical section - the
kernel takes care of that. */ kernel takes care of that. */
queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); queueYIELD_IF_USING_PREEMPTION();
} }
else else
{ {
@ -785,7 +779,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
executed if the task was holding multiple mutexes executed if the task was holding multiple mutexes
and the mutexes were given back in an order that is and the mutexes were given back in an order that is
different to that in which they were taken. */ different to that in which they were taken. */
queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); queueYIELD_IF_USING_PREEMPTION();
} }
else else
{ {
@ -805,7 +799,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
our own so yield immediately. Yes it is ok to do our own so yield immediately. Yes it is ok to do
this from within the critical section - the kernel this from within the critical section - the kernel
takes care of that. */ takes care of that. */
queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); queueYIELD_IF_USING_PREEMPTION();
} }
else else
{ {
@ -818,7 +812,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
executed if the task was holding multiple mutexes and executed if the task was holding multiple mutexes and
the mutexes were given back in an order that is the mutexes were given back in an order that is
different to that in which they were taken. */ different to that in which they were taken. */
queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); queueYIELD_IF_USING_PREEMPTION();
} }
else else
{ {
@ -1493,7 +1487,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
{ {
queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); queueYIELD_IF_USING_PREEMPTION();
} }
else else
{ {
@ -1522,7 +1516,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{ {
/* The task waiting has a higher priority than this task. */ /* The task waiting has a higher priority than this task. */
queueYIELD_IF_USING_PREEMPTION_MUX(&pxQueue->mux); queueYIELD_IF_USING_PREEMPTION();
} }
else else
{ {

View File

@ -120,14 +120,8 @@ functions but without including stdio.h here. */
/* If the cooperative scheduler is being used then a yield should not be /* If the cooperative scheduler is being used then a yield should not be
performed just because a higher priority task has been woken. */ performed just because a higher priority task has been woken. */
#define taskYIELD_IF_USING_PREEMPTION() #define taskYIELD_IF_USING_PREEMPTION()
#define queueYIELD_IF_USING_PREEMPTION_MUX(mux)
#else #else
#define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() #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 #endif
@ -1166,7 +1160,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
{ {
if( xCoreID == xPortGetCoreID() ) if( xCoreID == xPortGetCoreID() )
{ {
taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); taskYIELD_IF_USING_PREEMPTION();
} }
else { else {
taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority); taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority);
@ -1703,7 +1697,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
if( xYieldRequired == pdTRUE ) if( xYieldRequired == pdTRUE )
{ {
taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); taskYIELD_IF_USING_PREEMPTION();
} }
else 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, /* This yield may not cause the task just resumed to run,
but will leave the lists in the correct state for the but will leave the lists in the correct state for the
next yield. */ next yield. */
taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); taskYIELD_IF_USING_PREEMPTION();
} }
else if( pxTCB->xCoreID != xPortGetCoreID() ) else if( pxTCB->xCoreID != xPortGetCoreID() )
{ {
@ -2206,7 +2200,7 @@ BaseType_t xAlreadyYielded = pdFALSE;
xAlreadyYielded = pdTRUE; xAlreadyYielded = pdTRUE;
} }
#endif #endif
taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); taskYIELD_IF_USING_PREEMPTION();
} }
else else
{ {

View File

@ -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 /* 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... */ other processor may still be setting up, so allow time for them to also block on BIT_CALL... */
vTaskDelay(1); vTaskDelay(10);
for (int i = 0; i < COUNT; i++) { for (int i = 0; i < COUNT; i++) {
/* signal all tasks with "CALL" bit... */ /* signal all tasks with "CALL" bit... */
xEventGroupSetBits(eg, BIT_CALL); 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 */ /* Ensure all tasks cleaned up correctly */

View File

@ -0,0 +1,108 @@
/*
Unit tests for FreeRTOS preemption
*/
#include <esp_types.h>
#include <stdio.h>
#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);
}
}

View File

@ -59,6 +59,7 @@
static tcpip_init_done_fn tcpip_init_done; static tcpip_init_done_fn tcpip_init_done;
static void *tcpip_init_done_arg; static void *tcpip_init_done_arg;
static sys_mbox_t mbox; static sys_mbox_t mbox;
sys_thread_t g_lwip_task = NULL;
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
/** The global semaphore to lock the stack. */ /** 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 */ #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); , tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_task_hdlxxx : %x, prio:%d,stack:%d\n", 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));
} }

View File

@ -539,6 +539,8 @@ static void
dhcp_t1_timeout(struct netif *netif) dhcp_t1_timeout(struct netif *netif)
{ {
struct dhcp *dhcp = netif->dhcp; struct dhcp *dhcp = netif->dhcp;
int half_t2_timeout;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n"));
if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
(dhcp->state == DHCP_STATE_RENEWING)) { (dhcp->state == DHCP_STATE_RENEWING)) {
@ -550,15 +552,16 @@ dhcp_t1_timeout(struct netif *netif)
DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */
dhcp_renew(netif); dhcp_renew(netif);
/* Calculate next timeout */ /* Calculate next timeout */
half_t2_timeout = (netif->dhcp->t2_timeout - dhcp->lease_used) / 2;
#if ESP_DHCP_TIMER #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 #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 #endif
} }
@ -573,6 +576,7 @@ static void
dhcp_t2_timeout(struct netif *netif) dhcp_t2_timeout(struct netif *netif)
{ {
struct dhcp *dhcp = netif->dhcp; struct dhcp *dhcp = netif->dhcp;
int half_t0_timeout;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); 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) || if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) ||
(dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) { (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_STATE_REBINDING, not DHCP_STATE_BOUND */
dhcp_rebind(netif); dhcp_rebind(netif);
/* Calculate next timeout */ /* Calculate next timeout */
half_t0_timeout = (netif->dhcp->t0_timeout - dhcp->lease_used) / 2;
#if ESP_DHCP_TIMER #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 #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 #endif
} }

View File

@ -38,12 +38,13 @@
#include "lwip/mem.h" #include "lwip/mem.h"
#include "arch/sys_arch.h" #include "arch/sys_arch.h"
#include "lwip/stats.h" #include "lwip/stats.h"
#include "esp_log.h"
/* This is the number of threads that can be started with sys_thread_new() */ /* This is the number of threads that can be started with sys_thread_new() */
#define SYS_THREAD_MAX 4 #define SYS_THREAD_MAX 4
#define TAG "lwip_arch"
static bool g_lwip_in_critical_section = false; static sys_mutex_t g_lwip_protect_mutex = NULL;
static BaseType_t g_lwip_critical_section_needs_taskswitch;
#if !LWIP_COMPAT_MUTEX #if !LWIP_COMPAT_MUTEX
/** Create a new mutex /** Create a new mutex
@ -125,18 +126,7 @@ sys_sem_new(sys_sem_t *sem, u8_t count)
void void
sys_sem_signal(sys_sem_t *sem) 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); xSemaphoreGive(*sem);
}
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -394,7 +384,7 @@ sys_mbox_free(sys_mbox_t *mbox)
} }
if (count == (MAX_POLL_CNT-1)){ 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); 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 void
sys_init(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(); return xTaskGetTickCount();
} }
static portMUX_TYPE g_lwip_mux = portMUX_INITIALIZER_UNLOCKED;
/* /*
This optional function does a "fast" critical region protection and returns This optional function does a "fast" critical region protection and returns
the previous protection level. This function is only called during very short 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_prot_t
sys_arch_protect(void) sys_arch_protect(void)
{ {
portENTER_CRITICAL(&g_lwip_mux); sys_mutex_lock(&g_lwip_protect_mutex);
g_lwip_in_critical_section = true;
return (sys_prot_t) 1; return (sys_prot_t) 1;
} }
@ -481,13 +472,7 @@ sys_arch_protect(void)
void void
sys_arch_unprotect(sys_prot_t pval) sys_arch_unprotect(sys_prot_t pval)
{ {
(void) pval; sys_mutex_unlock(&g_lwip_protect_mutex);
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();
}
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -497,7 +482,7 @@ sys_arch_unprotect(sys_prot_t pval)
void void
sys_arch_assert(const char *file, int line) 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(); // vTaskEnterCritical();
while(1); 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*)); sys_sem_t *sem = (sys_sem_t*)malloc(sizeof(sys_sem_t*));
if (!sem){ if (!sem){
printf("sem f1\n"); ESP_LOGE(TAG, "thread_sem_init: out of memory");
return 0; return 0;
} }
*sem = xSemaphoreCreateBinary(); *sem = xSemaphoreCreateBinary();
if (!(*sem)){ if (!(*sem)){
free(sem); free(sem);
printf("sem f2\n"); ESP_LOGE(TAG, "thread_sem_init: out of memory");
return 0; return 0;
} }

View File

@ -69,9 +69,12 @@ void IRAM_ATTR spi_flash_op_block_func(void* arg)
uint32_t cpuid = (uint32_t) arg; uint32_t cpuid = (uint32_t) arg;
// Disable cache so that flash operation can start // Disable cache so that flash operation can start
spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]); 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; s_flash_op_can_start = true;
while (!s_flash_op_complete) { 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 // busy loop here and wait for the other CPU to finish flash operation
} }
// Flash operation is complete, re-enable cache // 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 // 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. // disable cache there and block other tasks from executing.
s_flash_op_can_start = false; 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); esp_err_t ret = esp_ipc_call(other_cpuid, &spi_flash_op_block_func, (void*) other_cpuid);
assert(ret == ESP_OK); assert(ret == ESP_OK);
while (!s_flash_op_can_start) { while (!s_flash_op_can_start) {

View File

@ -6,6 +6,8 @@
#include <unity.h> #include <unity.h>
#include <esp_spi_flash.h> #include <esp_spi_flash.h>
#include <esp_attr.h> #include <esp_attr.h>
#include "driver/timer.h"
#include "esp_intr_alloc.h"
struct flash_test_ctx { struct flash_test_ctx {
uint32_t offset; 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); 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);
}

View File

@ -136,6 +136,39 @@ typedef enum{
TCPIP_ADAPTER_IP_REQUEST_RETRY_TIME = 52, /**< request IP address retry counter */ TCPIP_ADAPTER_IP_REQUEST_RETRY_TIME = 52, /**< request IP address retry counter */
} tcpip_adapter_option_id_t; } 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 * @brief Initialize tcpip adapter
* *

View File

@ -25,6 +25,7 @@
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "lwip/ip6_addr.h" #include "lwip/ip6_addr.h"
#include "lwip/nd6.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 */ #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
#include "lwip/dns.h" #include "lwip/dns.h"
#endif #endif
@ -34,6 +35,7 @@
#include "apps/dhcpserver.h" #include "apps/dhcpserver.h"
#include "esp_event.h" #include "esp_event.h"
#include "esp_log.h"
static struct netif *esp_netif[TCPIP_ADAPTER_IF_MAX]; static struct netif *esp_netif[TCPIP_ADAPTER_IF_MAX];
static tcpip_adapter_ip_info_t esp_ip[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 dhcps_status = TCPIP_ADAPTER_DHCP_INIT;
static tcpip_adapter_dhcp_status_t dhcpc_status[TCPIP_ADAPTER_IF_MAX] = {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 TAG "tcpip_adapter"
//#define TCPIP_ADAPTER_DEBUG printf
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) void tcpip_adapter_init(void)
{ {
static bool tcpip_inited = false; static bool tcpip_inited = false;
int ret;
if (tcpip_inited == false) { if (tcpip_inited == false) {
tcpip_inited = true; 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].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].gw, 192, 168 , 4, 1);
IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].netmask, 255, 255 , 255, 0); 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) 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; 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) { if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || mac == NULL || ip_info == NULL) {
return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; 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) { if (dhcps_status == TCPIP_ADAPTER_DHCP_INIT) {
dhcps_start(esp_netif[tcpip_if], ip_info->ip); 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)); IP2STR(&ip_info->ip), IP2STR(&ip_info->netmask), IP2STR(&ip_info->gw));
dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; 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; 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) 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) { if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) {
return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; 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; 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) 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 (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH ) {
if (esp_netif[tcpip_if] == NULL) { if (esp_netif[tcpip_if] == NULL) {
return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; 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; 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) 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 (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH ) {
if (esp_netif[tcpip_if] == NULL) { if (esp_netif[tcpip_if] == NULL) {
return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; 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; 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) 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; 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; struct netif *p_netif;
tcpip_adapter_dhcp_status_t status; 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 || if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL ||
ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask)) { ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask)) {
return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; 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; 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) static void tcpip_adapter_nd6_cb(struct netif *p_netif, uint8_t ip_idex)
{ {
tcpip_adapter_ip6_info_t *ip6_info; tcpip_adapter_ip6_info_t *ip6_info;
if (!p_netif) { if (!p_netif) {
TCPIP_ADAPTER_DEBUG("null p_netif=%p\n", p_netif); ESP_LOGD(TAG, "null p_netif=%p", p_netif);
return; return;
} }
@ -302,6 +391,8 @@ esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if)
{ {
struct netif *p_netif; 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) { if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) {
return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; 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) esp_err_t tcpip_adapter_get_ip6_linklocal(tcpip_adapter_if_t tcpip_if, ip6_addr_t *if_ip6)
{ {
struct netif *p_netif; 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) 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 */ /* only support ap now */
if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { 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; 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); tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &default_ip);
dhcps_start(p_netif, default_ip.ip); dhcps_start(p_netif, default_ip.ip);
dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; dhcps_status = TCPIP_ADAPTER_DHCP_STARTED;
TCPIP_ADAPTER_DEBUG("dhcp server start successfully\n"); ESP_LOGD(TAG, "dhcp server start successfully");
return ESP_OK; return ESP_OK;
} else { } else {
TCPIP_ADAPTER_DEBUG("dhcp server re init\n"); ESP_LOGD(TAG, "dhcp server re init");
dhcps_status = TCPIP_ADAPTER_DHCP_INIT; dhcps_status = TCPIP_ADAPTER_DHCP_INIT;
return ESP_OK; 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; 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) 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 */ /* only support ap now */
if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { 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; 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) { if (p_netif != NULL) {
dhcps_stop(p_netif); dhcps_stop(p_netif);
} else { } 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; return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY;
} }
} else if (dhcps_status == TCPIP_ADAPTER_DHCP_STOPPED) { } 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; 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; dhcps_status = TCPIP_ADAPTER_DHCP_STOPPED;
return ESP_OK; 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) 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 // 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) static void tcpip_adapter_dhcpc_cb(struct netif *netif)
{ {
if (!netif) { if (!netif) {
TCPIP_ADAPTER_DEBUG("null netif=%p\n", netif); ESP_LOGD(TAG, "null netif=%p", netif);
return; return;
} }
if (netif != esp_netif[TCPIP_ADAPTER_IF_STA] && netif != esp_netif[TCPIP_ADAPTER_IF_ETH]) { 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; return;
} }
@ -575,7 +686,7 @@ static void tcpip_adapter_dhcpc_cb(struct netif *netif)
esp_event_send(&evt); esp_event_send(&evt);
} else { } 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) 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 */ /* 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) { 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; 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 (p_netif != NULL) {
if (netif_is_up(p_netif)) { 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->ip_addr);
ip_addr_set_zero(&p_netif->netmask); ip_addr_set_zero(&p_netif->netmask);
ip_addr_set_zero(&p_netif->gw); ip_addr_set_zero(&p_netif->gw);
} else { } else {
TCPIP_ADAPTER_DEBUG("dhcp client re init\n"); ESP_LOGD(TAG, "dhcp client re init");
dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT;
return ESP_OK; return ESP_OK;
} }
if (dhcp_start(p_netif) != ERR_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; return ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED;
} }
dhcp_set_cb(p_netif, tcpip_adapter_dhcpc_cb); 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; dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_STARTED;
return ESP_OK; return ESP_OK;
} else { } else {
TCPIP_ADAPTER_DEBUG("dhcp client re init\n"); ESP_LOGD(TAG, "dhcp client re init");
dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT;
return ESP_OK; 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; 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) 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 */ /* only support sta now, need to support ethernet */
if (tcpip_if != TCPIP_ADAPTER_IF_STA || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { 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; 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].gw);
ip4_addr_set_zero(&esp_ip[tcpip_if].netmask); ip4_addr_set_zero(&esp_ip[tcpip_if].netmask);
} else { } 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; return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY;
} }
} else if (dhcpc_status[tcpip_if] == TCPIP_ADAPTER_DHCP_STOPPED) { } 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; 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; dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_STOPPED;
return ESP_OK; 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) esp_err_t tcpip_adapter_eth_input(void *buffer, uint16_t len, void *eb)
{ {
ethernetif_input(esp_netif[TCPIP_ADAPTER_IF_ETH], buffer, len); 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) esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname)
{ {
#if LWIP_NETIF_HOSTNAME #if LWIP_NETIF_HOSTNAME
TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, hostname, tcpip_adapter_set_hostname_api);
struct netif *p_netif; struct netif *p_netif;
static char hostinfo[TCPIP_ADAPTER_IF_MAX][TCPIP_HOSTNAME_MAX_SIZE + 1]; 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 #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) esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char **hostname)
{ {
#if LWIP_NETIF_HOSTNAME #if LWIP_NETIF_HOSTNAME

View File

@ -56,7 +56,7 @@ You can also find a range of example projects under the "examples" directory in
Step 4: Configuring the project 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. 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.

View File

@ -9,6 +9,10 @@
#include <esp_err.h> #include <esp_err.h>
/* 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_FLOAT
#define UNITY_EXCLUDE_DOUBLE #define UNITY_EXCLUDE_DOUBLE

View File

@ -2,9 +2,9 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "unity.h" #include "unity.h"
#include "unity_config.h"
void unityTask(void *pvParameters)
void unityTask(void *pvParameters)
{ {
vTaskDelay(1000 / portTICK_PERIOD_MS); vTaskDelay(1000 / portTICK_PERIOD_MS);
unity_run_menu(); unity_run_menu();
@ -15,6 +15,6 @@ void app_main()
{ {
// Note: if unpinning this task, change the way run times are calculated in // Note: if unpinning this task, change the way run times are calculated in
// unity_platform // unity_platform
xTaskCreatePinnedToCore(unityTask, "unityTask", 4096, NULL, 5, NULL, 0); xTaskCreatePinnedToCore(unityTask, "unityTask", 4096, NULL,
UNITY_FREERTOS_PRIORITY, NULL, UNITY_FREERTOS_CPU);
} }