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 "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);
}

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);
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

View file

@ -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)

View file

@ -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.

View file

@ -79,6 +79,8 @@ extern "C" {
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/xtruntime.h>
#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. */

View file

@ -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
{

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
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
{

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
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 */

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 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));
}

View file

@ -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
}

View file

@ -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;
}

View file

@ -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) {

View file

@ -6,6 +6,8 @@
#include <unity.h>
#include <esp_spi_flash.h>
#include <esp_attr.h>
#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);
}

View file

@ -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
*

View file

@ -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

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
===============================
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.

View file

@ -9,6 +9,10 @@
#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_DOUBLE

View file

@ -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);
}