From 98e234ea67b0e500d08c71ddbdcd080b9b865b88 Mon Sep 17 00:00:00 2001 From: Jake Carter Date: Mon, 5 Aug 2024 15:33:07 -0600 Subject: [PATCH] feat(ThirdParty): Add USS Library Support (#1102) Co-authored-by: Omer Demir --- Libraries/libs.mk | 15 + Libraries/lwIP/Maxim/freeRTOS/sys_arch.c | 611 +++++++++++++++++++ Libraries/lwIP/Maxim/mxc_eth.c | 3 +- Libraries/lwIP/Maxim/mxc_ppp.c | 255 ++++++++ Libraries/lwIP/include/Maxim/arch/sys_arch.h | 110 +++- Libraries/lwIP/include/Maxim/mxc_ppp.h | 81 +++ USERGUIDE.md | 1 + 7 files changed, 1050 insertions(+), 26 deletions(-) create mode 100644 Libraries/lwIP/Maxim/freeRTOS/sys_arch.c create mode 100644 Libraries/lwIP/Maxim/mxc_ppp.c create mode 100644 Libraries/lwIP/include/Maxim/mxc_ppp.h diff --git a/Libraries/libs.mk b/Libraries/libs.mk index c9aad8e019..903385fa59 100644 --- a/Libraries/libs.mk +++ b/Libraries/libs.mk @@ -319,3 +319,18 @@ LIB_CLI_DIR ?= $(LIBS_DIR)/CLI include $(LIB_CLI_DIR)/CLI.mk endif # ************************ + +# Unified Security Software (USS) (Disabled by default) +# Only available via NDA +# ************************ +LIB_USS ?= 0 +ifeq ($(LIB_USS),1) +LIB_USS_DIR ?= $(LIBS_DIR)/USS + +ifeq ("$(wildcard $(LIB_USS_DIR))","") +$(error ERR_LIBNOTFOUND: USS library not found (Only available via NDA). Please install the USS package to $(LIB_USS_DIR)) +endif + +include $(LIB_USS_DIR)/uss.mk +endif +# ************************ diff --git a/Libraries/lwIP/Maxim/freeRTOS/sys_arch.c b/Libraries/lwIP/Maxim/freeRTOS/sys_arch.c new file mode 100644 index 0000000000..d44cd94c1d --- /dev/null +++ b/Libraries/lwIP/Maxim/freeRTOS/sys_arch.c @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2017 Simon Goldschmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#if !NO_SYS +/* lwIP includes. */ +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "lwip/tcpip.h" +#include "FreeRTOS.h" +#include "semphr.h" +#include "task.h" + +/** Set this to 1 if you want the stack size passed to sys_thread_new() to be + * interpreted as number of stack words (FreeRTOS-like). + * Default is that they are interpreted as byte count (lwIP-like). + */ +#ifndef LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS +#define LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS 0 +#endif + +/** Set this to 1 to use a mutex for SYS_ARCH_PROTECT() critical regions. + * Default is 0 and locks interrupts/scheduler for SYS_ARCH_PROTECT(). + */ +#ifndef LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX +#define LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX 0 +#endif + +/** Set this to 1 to include a sanity check that SYS_ARCH_PROTECT() and + * SYS_ARCH_UNPROTECT() are called matching. + */ +#ifndef LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK +#define LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK 0 +#endif + +/** Set this to 1 to let sys_mbox_free check that queues are empty when freed */ +#ifndef LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE +#define LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE 0 +#endif + +/** Set this to 1 to enable core locking check functions in this port. + * For this to work, you'll have to define LWIP_ASSERT_CORE_LOCKED() + * and LWIP_MARK_TCPIP_THREAD() correctly in your lwipopts.h! */ +#ifndef LWIP_FREERTOS_CHECK_CORE_LOCKING +#define LWIP_FREERTOS_CHECK_CORE_LOCKING 0 +#endif + +/** Set this to 0 to implement sys_now() yourself, e.g. using a hw timer. + * Default is 1, where FreeRTOS ticks are used to calculate back to ms. + */ +#ifndef LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS +#define LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS 1 +#endif + +#if !configSUPPORT_DYNAMIC_ALLOCATION +# error "lwIP FreeRTOS port requires configSUPPORT_DYNAMIC_ALLOCATION" +#endif +#if !INCLUDE_vTaskDelay +# error "lwIP FreeRTOS port requires INCLUDE_vTaskDelay" +#endif +#if !INCLUDE_vTaskSuspend +# error "lwIP FreeRTOS port requires INCLUDE_vTaskSuspend" +#endif +#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX || !LWIP_COMPAT_MUTEX +#if !configUSE_MUTEXES +# error "lwIP FreeRTOS port requires configUSE_MUTEXES" +#endif +#endif + +#if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX +static SemaphoreHandle_t sys_arch_protect_mutex; +#endif +#if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK +static sys_prot_t sys_arch_protect_nesting; +#endif + +/* Initialize this module (see description in sys.h) */ +void +sys_init(void) +{ +#if SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX + /* initialize sys_arch_protect global mutex */ + sys_arch_protect_mutex = xSemaphoreCreateRecursiveMutex(); + LWIP_ASSERT("failed to create sys_arch_protect mutex", + sys_arch_protect_mutex != NULL); +#endif /* SYS_LIGHTWEIGHT_PROT && LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */ +} + +#if configUSE_16_BIT_TICKS == 1 +#error This port requires 32 bit ticks or timer overflow will fail +#endif + +#if LWIP_FREERTOS_SYS_NOW_FROM_FREERTOS +u32_t +sys_now(void) +{ + return xTaskGetTickCount() * portTICK_PERIOD_MS; +} +#endif + +u32_t +sys_jiffies(void) +{ + return xTaskGetTickCount(); +} + +#if SYS_LIGHTWEIGHT_PROT + +sys_prot_t +sys_arch_protect(void) +{ +#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX + BaseType_t ret; + LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL); + + ret = xSemaphoreTakeRecursive(sys_arch_protect_mutex, portMAX_DELAY); + LWIP_ASSERT("sys_arch_protect failed to take the mutex", ret == pdTRUE); +#else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */ + taskENTER_CRITICAL(); +#endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */ +#if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK + { + /* every nested call to sys_arch_protect() returns an increased number */ + sys_prot_t ret = sys_arch_protect_nesting; + sys_arch_protect_nesting++; + LWIP_ASSERT("sys_arch_protect overflow", sys_arch_protect_nesting > ret); + return ret; + } +#else + return 1; +#endif +} + +void +sys_arch_unprotect(sys_prot_t pval) +{ +#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX + BaseType_t ret; +#endif +#if LWIP_FREERTOS_SYS_ARCH_PROTECT_SANITY_CHECK + LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting > 0); + sys_arch_protect_nesting--; + LWIP_ASSERT("unexpected sys_arch_protect_nesting", sys_arch_protect_nesting == pval); +#endif + +#if LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX + LWIP_ASSERT("sys_arch_protect_mutex != NULL", sys_arch_protect_mutex != NULL); + + ret = xSemaphoreGiveRecursive(sys_arch_protect_mutex); + LWIP_ASSERT("sys_arch_unprotect failed to give the mutex", ret == pdTRUE); +#else /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */ + taskEXIT_CRITICAL(); +#endif /* LWIP_FREERTOS_SYS_ARCH_PROTECT_USES_MUTEX */ + LWIP_UNUSED_ARG(pval); +} + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +void +sys_arch_msleep(u32_t delay_ms) +{ + TickType_t delay_ticks = delay_ms / portTICK_RATE_MS; + vTaskDelay(delay_ticks); +} + +#if !LWIP_COMPAT_MUTEX + +/* Create a new mutex*/ +err_t +sys_mutex_new(sys_mutex_t *mutex) +{ + LWIP_ASSERT("mutex != NULL", mutex != NULL); + + mutex->mut = xSemaphoreCreateRecursiveMutex(); + if(mutex->mut == NULL) { + SYS_STATS_INC(mutex.err); + return ERR_MEM; + } + SYS_STATS_INC_USED(mutex); + return ERR_OK; +} + +void +sys_mutex_lock(sys_mutex_t *mutex) +{ + BaseType_t ret; + LWIP_ASSERT("mutex != NULL", mutex != NULL); + LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); + + ret = xSemaphoreTakeRecursive(mutex->mut, portMAX_DELAY); + LWIP_ASSERT("failed to take the mutex", ret == pdTRUE); +} + +void +sys_mutex_unlock(sys_mutex_t *mutex) +{ + BaseType_t ret; + LWIP_ASSERT("mutex != NULL", mutex != NULL); + LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); + + ret = xSemaphoreGiveRecursive(mutex->mut); + LWIP_ASSERT("failed to give the mutex", ret == pdTRUE); +} + +void +sys_mutex_free(sys_mutex_t *mutex) +{ + LWIP_ASSERT("mutex != NULL", mutex != NULL); + LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); + + SYS_STATS_DEC(mutex.used); + vSemaphoreDelete(mutex->mut); + mutex->mut = NULL; +} + +#endif /* !LWIP_COMPAT_MUTEX */ + +err_t +sys_sem_new(sys_sem_t *sem, u8_t initial_count) +{ + LWIP_ASSERT("sem != NULL", sem != NULL); + LWIP_ASSERT("initial_count invalid (not 0 or 1)", + (initial_count == 0) || (initial_count == 1)); + + sem->sem = xSemaphoreCreateBinary(); + if(sem->sem == NULL) { + SYS_STATS_INC(sem.err); + return ERR_MEM; + } + SYS_STATS_INC_USED(sem); + + if(initial_count == 1) { + BaseType_t ret = xSemaphoreGive(sem->sem); + LWIP_ASSERT("sys_sem_new: initial give failed", ret == pdTRUE); + } + return ERR_OK; +} + +void +sys_sem_signal(sys_sem_t *sem) +{ + BaseType_t ret; + LWIP_ASSERT("sem != NULL", sem != NULL); + LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); + + ret = xSemaphoreGive(sem->sem); + /* queue full is OK, this is a signal only... */ + LWIP_ASSERT("sys_sem_signal: sane return value", + (ret == pdTRUE) || (ret == errQUEUE_FULL)); +} + +u32_t +sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout_ms) +{ + BaseType_t ret; + LWIP_ASSERT("sem != NULL", sem != NULL); + LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); + + if(!timeout_ms) { + /* wait infinite */ + ret = xSemaphoreTake(sem->sem, portMAX_DELAY); + LWIP_ASSERT("taking semaphore failed", ret == pdTRUE); + } else { + TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS; + ret = xSemaphoreTake(sem->sem, timeout_ticks); + if (ret == errQUEUE_EMPTY) { + /* timed out */ + return SYS_ARCH_TIMEOUT; + } + LWIP_ASSERT("taking semaphore failed", ret == pdTRUE); + } + + /* Old versions of lwIP required us to return the time waited. + This is not the case any more. Just returning != SYS_ARCH_TIMEOUT + here is enough. */ + return 1; +} + +void +sys_sem_free(sys_sem_t *sem) +{ + LWIP_ASSERT("sem != NULL", sem != NULL); + LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); + + SYS_STATS_DEC(sem.used); + vSemaphoreDelete(sem->sem); + sem->sem = NULL; +} + +err_t +sys_mbox_new(sys_mbox_t *mbox, int size) +{ + LWIP_ASSERT("mbox != NULL", mbox != NULL); + LWIP_ASSERT("size > 0", size > 0); + + mbox->mbx = xQueueCreate((UBaseType_t)size, sizeof(void *)); + if(mbox->mbx == NULL) { + SYS_STATS_INC(mbox.err); + return ERR_MEM; + } + SYS_STATS_INC_USED(mbox); + return ERR_OK; +} + +void +sys_mbox_post(sys_mbox_t *mbox, void *msg) +{ + BaseType_t ret; + LWIP_ASSERT("mbox != NULL", mbox != NULL); + LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); + + ret = xQueueSendToBack(mbox->mbx, &msg, portMAX_DELAY); + LWIP_ASSERT("mbox post failed", ret == pdTRUE); +} + +err_t +sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ + BaseType_t ret; + LWIP_ASSERT("mbox != NULL", mbox != NULL); + LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); + + ret = xQueueSendToBack(mbox->mbx, &msg, 0); + if (ret == pdTRUE) { + return ERR_OK; + } else { + LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL); + SYS_STATS_INC(mbox.err); + return ERR_MEM; + } +} + +err_t +sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg) +{ + BaseType_t ret; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + LWIP_ASSERT("mbox != NULL", mbox != NULL); + LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); + + ret = xQueueSendToBackFromISR(mbox->mbx, &msg, &xHigherPriorityTaskWoken); + if (ret == pdTRUE) { + if (xHigherPriorityTaskWoken == pdTRUE) { + return ERR_NEED_SCHED; + } + return ERR_OK; + } else { + LWIP_ASSERT("mbox trypost failed", ret == errQUEUE_FULL); + SYS_STATS_INC(mbox.err); + return ERR_MEM; + } +} + +u32_t +sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout_ms) +{ + BaseType_t ret; + void *msg_dummy; + LWIP_ASSERT("mbox != NULL", mbox != NULL); + LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); + + if (!msg) { + msg = &msg_dummy; + } + + if (!timeout_ms) { + /* wait infinite */ + ret = xQueueReceive(mbox->mbx, &(*msg), portMAX_DELAY); + LWIP_ASSERT("mbox fetch failed", ret == pdTRUE); + } else { + TickType_t timeout_ticks = timeout_ms / portTICK_RATE_MS; + ret = xQueueReceive(mbox->mbx, &(*msg), timeout_ticks); + if (ret == errQUEUE_EMPTY) { + /* timed out */ + *msg = NULL; + return SYS_ARCH_TIMEOUT; + } + LWIP_ASSERT("mbox fetch failed", ret == pdTRUE); + } + + /* Old versions of lwIP required us to return the time waited. + This is not the case any more. Just returning != SYS_ARCH_TIMEOUT + here is enough. */ + return 1; +} + +u32_t +sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ + BaseType_t ret; + void *msg_dummy; + LWIP_ASSERT("mbox != NULL", mbox != NULL); + LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); + + if (!msg) { + msg = &msg_dummy; + } + + ret = xQueueReceive(mbox->mbx, &(*msg), 0); + if (ret == errQUEUE_EMPTY) { + *msg = NULL; + return SYS_MBOX_EMPTY; + } + LWIP_ASSERT("mbox fetch failed", ret == pdTRUE); + + return 0; +} + +void +sys_mbox_free(sys_mbox_t *mbox) +{ + LWIP_ASSERT("mbox != NULL", mbox != NULL); + LWIP_ASSERT("mbox->mbx != NULL", mbox->mbx != NULL); + +#if LWIP_FREERTOS_CHECK_QUEUE_EMPTY_ON_FREE + { + UBaseType_t msgs_waiting = uxQueueMessagesWaiting(mbox->mbx); + LWIP_ASSERT("mbox quence not empty", msgs_waiting == 0); + + if (msgs_waiting != 0) { + SYS_STATS_INC(mbox.err); + } + } +#endif + + vQueueDelete(mbox->mbx); + + SYS_STATS_DEC(mbox.used); +} + +sys_thread_t +sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) +{ + TaskHandle_t rtos_task; + BaseType_t ret; + sys_thread_t lwip_thread; + size_t rtos_stacksize; + + LWIP_ASSERT("invalid stacksize", stacksize > 0); +#if LWIP_FREERTOS_THREAD_STACKSIZE_IS_STACKWORDS + rtos_stacksize = (size_t)stacksize; +#else + rtos_stacksize = (size_t)stacksize / sizeof(StackType_t); +#endif + + /* lwIP's lwip_thread_fn matches FreeRTOS' TaskFunction_t, so we can pass the + thread function without adaption here. */ + ret = xTaskCreate(thread, name, (configSTACK_DEPTH_TYPE)rtos_stacksize, arg, prio, &rtos_task); + LWIP_ASSERT("task creation failed", ret == pdTRUE); + + lwip_thread.thread_handle = rtos_task; + return lwip_thread; +} + +#if LWIP_NETCONN_SEM_PER_THREAD +#if configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 + +sys_sem_t * +sys_arch_netconn_sem_get(void) +{ + void* ret; + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + LWIP_ASSERT("task != NULL", task != NULL); + + ret = pvTaskGetThreadLocalStoragePointer(task, 0); + return ret; +} + +void +sys_arch_netconn_sem_alloc(void) +{ + void *ret; + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + LWIP_ASSERT("task != NULL", task != NULL); + + ret = pvTaskGetThreadLocalStoragePointer(task, 0); + if(ret == NULL) { + sys_sem_t *sem; + err_t err; + /* need to allocate the memory for this semaphore */ + sem = mem_malloc(sizeof(sys_sem_t)); + LWIP_ASSERT("sem != NULL", sem != NULL); + err = sys_sem_new(sem, 0); + LWIP_ASSERT("err == ERR_OK", err == ERR_OK); + LWIP_ASSERT("sem invalid", sys_sem_valid(sem)); + vTaskSetThreadLocalStoragePointer(task, 0, sem); + } +} + +void sys_arch_netconn_sem_free(void) +{ + void* ret; + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + LWIP_ASSERT("task != NULL", task != NULL); + + ret = pvTaskGetThreadLocalStoragePointer(task, 0); + if(ret != NULL) { + sys_sem_t *sem = ret; + sys_sem_free(sem); + mem_free(sem); + vTaskSetThreadLocalStoragePointer(task, 0, NULL); + } +} + +#else /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */ +#error LWIP_NETCONN_SEM_PER_THREAD needs configNUM_THREAD_LOCAL_STORAGE_POINTERS +#endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 */ + +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#if LWIP_FREERTOS_CHECK_CORE_LOCKING +#if LWIP_TCPIP_CORE_LOCKING + +/** Flag the core lock held. A counter for recursive locks. */ +static u8_t lwip_core_lock_count; +static TaskHandle_t lwip_core_lock_holder_thread; + +void +sys_lock_tcpip_core(void) +{ + sys_mutex_lock(&lock_tcpip_core); + if (lwip_core_lock_count == 0) { + lwip_core_lock_holder_thread = xTaskGetCurrentTaskHandle(); + } + lwip_core_lock_count++; +} + +void +sys_unlock_tcpip_core(void) +{ + lwip_core_lock_count--; + if (lwip_core_lock_count == 0) { + lwip_core_lock_holder_thread = 0; + } + sys_mutex_unlock(&lock_tcpip_core); +} + +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if !NO_SYS +static TaskHandle_t lwip_tcpip_thread; +#endif + +void +sys_mark_tcpip_thread(void) +{ +#if !NO_SYS + lwip_tcpip_thread = xTaskGetCurrentTaskHandle(); +#endif +} + +void +sys_check_core_locking(void) +{ + /* Embedded systems should check we are NOT in an interrupt context here */ + /* E.g. core Cortex-M3/M4 ports: + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + + Instead, we use more generic FreeRTOS functions here, which should fail from ISR: */ + taskENTER_CRITICAL(); + taskEXIT_CRITICAL(); + +#if !NO_SYS + if (lwip_tcpip_thread != 0) { + TaskHandle_t current_thread = xTaskGetCurrentTaskHandle(); + +#if LWIP_TCPIP_CORE_LOCKING + LWIP_ASSERT("Function called without core lock", + current_thread == lwip_core_lock_holder_thread && lwip_core_lock_count > 0); +#else /* LWIP_TCPIP_CORE_LOCKING */ + LWIP_ASSERT("Function called from wrong thread", current_thread == lwip_tcpip_thread); +#endif /* LWIP_TCPIP_CORE_LOCKING */ + } +#endif /* !NO_SYS */ +} + +#endif /* LWIP_FREERTOS_CHECK_CORE_LOCKING*/ +#endif /* !NO_SYS */ \ No newline at end of file diff --git a/Libraries/lwIP/Maxim/mxc_eth.c b/Libraries/lwIP/Maxim/mxc_eth.c index 0e7c96675f..6778a35ccc 100644 --- a/Libraries/lwIP/Maxim/mxc_eth.c +++ b/Libraries/lwIP/Maxim/mxc_eth.c @@ -202,7 +202,7 @@ int MXC_ETH_Tick(void) return E_NO_ERROR; } - +#if NO_SYS u32_t sys_now(void) { if (mxc_eth_config.sys_get_ms) @@ -210,3 +210,4 @@ u32_t sys_now(void) else return 0; } +#endif \ No newline at end of file diff --git a/Libraries/lwIP/Maxim/mxc_ppp.c b/Libraries/lwIP/Maxim/mxc_ppp.c new file mode 100644 index 0000000000..cd98b6947e --- /dev/null +++ b/Libraries/lwIP/Maxim/mxc_ppp.c @@ -0,0 +1,255 @@ +/* + * @file mxc_ppp.c + * + ****************************************************************************** + * + * Copyright (C) 2019-2023 Maxim Integrated Products, Inc. (now owned by + * Analog Devices, Inc.), + * Copyright (C) 2023-2024 Analog Devices, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +#include +#include + +#include "lwip/init.h" +#include "lwip/opt.h" +#include "arch/cc.h" + +#include "lwip/sio.h" + +#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ +#include "mxc_ppp.h" + +/***** Globals *****/ +static sio_fd_t ppp_sio = NULL; +static ppp_pcb *ppp = NULL; +static struct netif ppp_netif; +u8_t sio_idx = 0; +volatile int callClosePpp = 0; + +static sio_open_t mxc_sio_open; +static sio_write_t mxc_sio_write; +static sio_read_t mxc_sio_read; +static sio_read_abort_t mxc_sio_read_abort; + +/***** Functions *****/ +static void ppp_link_status_cb(ppp_pcb *pcb, int err_code, void *ctx) +{ + struct netif *pppif = ppp_netif(pcb); + + switch(err_code) + { + case PPPERR_NONE: /* No error. */ + { + mxc_printf("ppp_cb: connected\n\r"); +#if LWIP_IPV4 + mxc_printf(" ip = %s\n\r", ip4addr_ntoa(netif_ip4_addr(pppif))); + mxc_printf(" peer = %s\n\r", ip4addr_ntoa(netif_ip4_gw(pppif))); + mxc_printf(" netmask = %s\n\r", ip4addr_ntoa(netif_ip4_netmask(pppif))); +#endif /* LWIP_IPV4 */ + if(ctx) + ((ppp_cb)ctx)(pcb); + } + break; + + case PPPERR_PARAM: /* Invalid parameter. */ + mxc_printf("ppp_cb: PPPERR_PARAM\n"); + break; + + case PPPERR_OPEN: /* Unable to open PPP session. */ + mxc_printf("ppp_cb: Unable to open PPP session\n"); + break; + + case PPPERR_DEVICE: /* Invalid I/O device for PPP. */ + mxc_printf("ppp_cb: Invalid I/O device for PPP\n"); + break; + + case PPPERR_ALLOC: /* Unable to allocate resources. */ + mxc_printf("ppp_cb: Unable to allocate resources\n"); + break; + + case PPPERR_USER: /* User interrupt. */ + mxc_printf("ppp_cb: User interrupt\n"); + break; + + case PPPERR_CONNECT: /* Connection lost. */ + mxc_printf("ppp_cb: Connection lost\n"); + if(ctx) + ((ppp_cb)ctx)(pcb); + break; + + case PPPERR_AUTHFAIL: /* Failed authentication challenge. */ + mxc_printf("ppp_cb: Failed authentication challenge\n"); + break; + + case PPPERR_PROTOCOL: /* Failed to meet protocol. */ + mxc_printf("ppp_cb: Failed to meet protocol\n"); + break; + + case PPPERR_PEERDEAD: /* Connection timeout. */ + mxc_printf("ppp_cb: Connection timeout\n"); + break; + + case PPPERR_IDLETIMEOUT: /* Idle Timeout. */ + mxc_printf("ppp_cb: Idle Timeout\n"); + break; + + case PPPERR_CONNECTTIME: /* PPPERR_CONNECTTIME. */ + mxc_printf("ppp_cb: PPPERR_CONNECTTIME\n"); + break; + + case PPPERR_LOOPBACK: /* Connection timeout. */ + mxc_printf("ppp_cb: Connection timeout\n"); + break; + + default: + mxc_printf("ppp_cb: unknown errCode %d\n", err_code); + break; + } +} + +static u32_t ppp_output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) +{ + u32_t size = 0; + + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(ctx); + + if (mxc_sio_write) + size = mxc_sio_write(ppp_sio, data, len); + + return size; +} + +/* This function initializes all network interfaces */ +#if NO_SYS +static void mxc_ppp_netif_init(void *ctx) +{ + if (mxc_sio_open) + ppp_sio = mxc_sio_open(sio_idx); + + if (ppp_sio) + { + ppp = pppos_create(&ppp_netif, ppp_output_cb, ppp_link_status_cb, ctx); + + if (ppp) + { + ppp_set_default(ppp); + //ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password"); + + ppp_connect(ppp, 0); + } + } +} +#else +static void mxc_ppp_netif_init(void *ctx) +{ + if (mxc_sio_open) + ppp_sio = mxc_sio_open(sio_idx); + + if (ppp_sio) + { + ppp = pppapi_pppos_create(&ppp_netif, ppp_output_cb, ppp_link_status_cb, ctx); + + if (ppp) + { + pppapi_set_default(ppp); + //pppapi_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password"); + + pppapi_connect(ppp, 0); + } + } +} +#endif +/* This function initializes this lwIP ppp. */ +void mxc_ppp_init(u8_t uart_port, sio_open_t mxc_open, sio_write_t mxc_write, + sio_read_t mxc_read, sio_read_abort_t mxc_read_abort, void *ctx) +{ + sio_idx = uart_port; + + srand((unsigned int)time(0)); /* init randomizer again (seed per thread) */ + + if(mxc_open && mxc_write && mxc_read && mxc_read_abort) + { + mxc_sio_open = mxc_open; + mxc_sio_write = mxc_write; + mxc_sio_read = mxc_read; + mxc_sio_read_abort = mxc_read_abort; + } + + /* initialize lwIP stack, network interfaces and applications */ +#if NO_SYS //No need to run this again if !NO_SYS + lwip_init(); +#endif + mxc_ppp_netif_init(ctx); /* init network interfaces */ +} + +void mxc_ppp_loop(void) +{ + int count = 0; + u8_t rxbuf[PPP_RX_BUFFER_SIZE]; + + /* handle timers (already done in tcpip.c when NO_SYS=0) */ + sys_check_timeouts(); + + /* try to read characters from serial line and pass them to PPPoS */ + if (mxc_sio_read) + count = mxc_sio_read(ppp_sio, (u8_t*)rxbuf, PPP_RX_BUFFER_SIZE); + + if(count) +#if NO_SYS + pppos_input(ppp, rxbuf, count); +#else + pppos_input_tcpip(ppp, rxbuf, count); +#endif + + if(callClosePpp && ppp) + { + callClosePpp = 0; +#if NO_SYS + ppp_close(ppp, 0); +#else + pppapi_close(ppp, 0); +#endif + ppp = NULL; + } +} + +void mxc_ppp_force_close(void) +{ + if(ppp) + { + u32_t started; + + /* make sure to disconnect PPP before stopping the program... */ +#if NO_SYS + ppp_close(ppp, 0); +#else + pppapi_close(ppp, 0); +#endif + ppp = NULL; + + /* Wait for some time to let PPP finish... */ + started = sys_now(); + do + { + /* @todo: need a better check here: only wait until PPP is down */ + } while(sys_now() - started < 5000); + } +} + +#endif /* PPP_SUPPORT && PPPOS_SUPPORT */ diff --git a/Libraries/lwIP/include/Maxim/arch/sys_arch.h b/Libraries/lwIP/include/Maxim/arch/sys_arch.h index c2e4b0f1cd..0cfc889dec 100644 --- a/Libraries/lwIP/include/Maxim/arch/sys_arch.h +++ b/Libraries/lwIP/include/Maxim/arch/sys_arch.h @@ -1,35 +1,95 @@ -/****************************************************************************** +/* + * Copyright (c) 2017 Simon Goldschmidt + * All rights reserved. * - * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by - * Analog Devices, Inc.), - * Copyright (C) 2023-2024 Analog Devices, Inc. + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * http://www.apache.org/licenses/LICENSE-2.0 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * This file is part of the lwIP TCP/IP stack. * - ******************************************************************************/ + * Author: Simon Goldschmdit + * + */ +#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H + +#include "lwip/opt.h" +#include "lwip/arch.h" + +/** This is returned by _fromisr() sys functions to tell the outermost function + * that a higher priority task was woken and the scheduler needs to be invoked. + */ +#define ERR_NEED_SCHED 123 + +/* This port includes FreeRTOS headers in sys_arch.c only. + * FreeRTOS uses pointers as object types. We use wrapper structs instead of + * void pointers directly to get a tiny bit of type safety. + */ + +void sys_arch_msleep(u32_t delay_ms); +#define sys_msleep(ms) sys_arch_msleep(ms) + +#if SYS_LIGHTWEIGHT_PROT +typedef u32_t sys_prot_t; +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#if !LWIP_COMPAT_MUTEX +struct _sys_mut { + void *mut; +}; +typedef struct _sys_mut sys_mutex_t; +#define sys_mutex_valid_val(mutex) ((mutex).mut != NULL) +#define sys_mutex_valid(mutex) (((mutex) != NULL) && sys_mutex_valid_val(*(mutex))) +#define sys_mutex_set_invalid(mutex) ((mutex)->mut = NULL) +#endif /* !LWIP_COMPAT_MUTEX */ -#ifndef LIBRARIES_LWIP_INCLUDE_MAXIM_ARCH_SYS_ARCH_H_ -#define LIBRARIES_LWIP_INCLUDE_MAXIM_ARCH_SYS_ARCH_H_ +struct _sys_sem { + void *sem; +}; +typedef struct _sys_sem sys_sem_t; +#define sys_sem_valid_val(sema) ((sema).sem != NULL) +#define sys_sem_valid(sema) (((sema) != NULL) && sys_sem_valid_val(*(sema))) +#define sys_sem_set_invalid(sema) ((sema)->sem = NULL) -#define SYS_MBOX_NULL NULL -#define SYS_SEM_NULL NULL +struct _sys_mbox { + void *mbx; +}; +typedef struct _sys_mbox sys_mbox_t; +#define sys_mbox_valid_val(mbox) ((mbox).mbx != NULL) +#define sys_mbox_valid(mbox) (((mbox) != NULL) && sys_mbox_valid_val(*(mbox))) +#define sys_mbox_set_invalid(mbox) ((mbox)->mbx = NULL) -typedef void *sys_prot_t; -typedef void *sys_mutex_t; -typedef void *sys_sem_t; -typedef void *sys_mbox_t; -typedef void *sys_thread_t; +struct _sys_thread { + void *thread_handle; +}; +typedef struct _sys_thread sys_thread_t; -#define sys_arch_mbox_tryfetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 1) +#if LWIP_NETCONN_SEM_PER_THREAD +sys_sem_t* sys_arch_netconn_sem_get(void); +void sys_arch_netconn_sem_alloc(void); +void sys_arch_netconn_sem_free(void); +#define LWIP_NETCONN_THREAD_SEM_GET() sys_arch_netconn_sem_get() +#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_arch_netconn_sem_alloc() +#define LWIP_NETCONN_THREAD_SEM_FREE() sys_arch_netconn_sem_free() +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ -#endif // LIBRARIES_LWIP_INCLUDE_MAXIM_ARCH_SYS_ARCH_H_ +#endif /* LWIP_ARCH_SYS_ARCH_H */ diff --git a/Libraries/lwIP/include/Maxim/mxc_ppp.h b/Libraries/lwIP/include/Maxim/mxc_ppp.h new file mode 100644 index 0000000000..6d1451ed23 --- /dev/null +++ b/Libraries/lwIP/include/Maxim/mxc_ppp.h @@ -0,0 +1,81 @@ +/* + * @file mxc_ppp.h + * + ****************************************************************************** + * + * Copyright (C) 2019-2023 Maxim Integrated Products, Inc. (now owned by + * Analog Devices, Inc.), + * Copyright (C) 2023-2024 Analog Devices, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ +#ifndef LIBRARIES_LWIP_INCLUDE_MAXIM_ARCH_SYS_ARCH_H_ +#define LIBRARIES_LWIP_INCLUDE_MAXIM_ARCH_SYS_ARCH_H_ + +#include "lwip/netif.h" +#include "lwip/sio.h" + +#if NO_SYS +#include "netif/ppp/pppos.h" +#else +#include "netif/ppp/pppapi.h" +#endif + +#define MXC_PPP_DEBUG + +#ifdef MXC_PPP_DEBUG +//extern void uart_printf(const char *msg, ...); +#define mxc_printf printf +#else +#define mxc_printf +#endif + +typedef sio_fd_t (*sio_open_t)(uint8_t); +typedef uint32_t (*sio_write_t)(sio_fd_t, uint8_t *, uint32_t); +typedef uint32_t (*sio_read_t)(sio_fd_t, uint8_t *, uint32_t); +typedef void (*sio_read_abort_t)(sio_fd_t); +typedef void (*ppp_cb)(ppp_pcb *); + +/** + * @brief Initialize lwIP PPP + * + * @param uart_port uart port to be used running pppos + * @param mxc_open uart open function pointer + * @param mxc_write uart write function pointer + * @param mxc_read uart read function pointer + * @param mxc_read_abort uart read abort function pointer + * + * @return #E_NO_ERROR if successful + * @return #E_NULL_PTR if pointer is null + */ +void mxc_ppp_init(u8_t uart_port, sio_open_t mxc_open, sio_write_t mxc_write, + sio_read_t mxc_read, sio_read_abort_t mxc_read_abort, void *ctx); + +/** + * @brief lwIP PPP loop + * + * @return #E_NO_ERROR if successful + * @return #E_NULL_PTR if pointer is null + */ +void mxc_ppp_loop(void); + +/** + * @brief force to close lwIP PPP connection + * + * @return #E_NO_ERROR if successful + * @return #E_NULL_PTR if pointer is null + */ +void mxc_ppp_force_close(void); +#endif /* LIBRARIES_LWIP_INCLUDE_MAXIM_ARCH_SYS_ARCH_H_ */ \ No newline at end of file diff --git a/USERGUIDE.md b/USERGUIDE.md index 2e322be22d..bba3732d4f 100644 --- a/USERGUIDE.md +++ b/USERGUIDE.md @@ -1793,6 +1793,7 @@ The following variables can be used to enable the [available libraries](#librari | `LIB_MAXUSB` | Include the MaxUSB library | This option toggles the inclusion of the MAXUSB library, which facilitates the use of the native USB peripherals on some microcontrollers. Set to `0` to disable or `1` to enable. | | `LIB_SDHC` | Include the SDHC library | This option toggles the Secure Digital High Capacity (SDHC) library, which can be used to interface with SD cards. Additionally, it enables the [FatFS](http://elm-chan.org/fsw/ff/00index_e.html) library, which implements a generic FAT filesystem. | | `LIB_CLI` | Include the MSDK's built-in CLI library | This option toggles the MSDK's built-in CLI library, which can be used to process received commands over UART. | +| `LIB_USS` | Include the USS Library | This option toggles the Unified Security Software library. It is only available via NDA. | #### Build Variables for the PeriphDrivers Library