Import Mbed OS hard-float snapshot

This commit is contained in:
Beslan
2026-06-01 20:15:04 +03:00
commit d3738e2f89
16278 changed files with 10628036 additions and 0 deletions

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __CC_H__
#define __CC_H__
#include <stdint.h>
#include <stddef.h> /* for size_t */
#include "mbed_toolchain.h"
#include "lwipopts.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ARM/LPC17xx is little endian only */
#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
#ifdef BYTE_ORDER
#undef BYTE_ORDER
#endif
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#ifndef LWIP_PROVIDE_ERRNO
/* Use LWIP error codes */
#define LWIP_PROVIDE_ERRNO
#endif
#if defined (__IAR_SYSTEMS_ICC__)
/* IAR Embedded Workbench tools */
#define PACK_STRUCT_BEGIN __packed
#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(fld) fld
#define IAR_STR(a) #a
#define ALIGNED(n) _Pragma(IAR_STR(data_alignment= ## n ##))
#else
/* GCC tools (CodeSourcery) */
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(fld) fld
#define ALIGNED(n) __attribute__((aligned (n)))
#endif
/* Provide Thumb-2 routines for GCC to improve performance */
#if defined(TOOLCHAIN_GCC) && defined(__thumb2__)
#define MEMCPY(dst,src,len) thumb2_memcpy(dst,src,len)
#define LWIP_CHKSUM thumb2_checksum
/* Set algorithm to 0 so that unused lwip_standard_chksum function
doesn't generate compiler warning */
#define LWIP_CHKSUM_ALGORITHM 0
void* thumb2_memcpy(void* pDest, const void* pSource, size_t length);
uint16_t thumb2_checksum(const void* pData, int length);
#else
/* Used with IP headers only */
#define LWIP_CHKSUM_ALGORITHM 1
#endif
#ifdef LWIP_DEBUG
#if MBED_CONF_LWIP_USE_MBED_TRACE
void lwip_mbed_tracef_debug(const char *fmt, ...);
void lwip_mbed_tracef_error(const char *fmt, ...);
void lwip_mbed_tracef_warn(const char *fmt, ...);
MBED_NORETURN void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line);
#define LWIP_PLATFORM_DIAG(vars) lwip_mbed_tracef_debug vars
#define LWIP_PLATFORM_DIAG_SEVERE(vars) lwip_mbed_tracef_error vars
#define LWIP_PLATFORM_DIAG_SERIOUS(vars) lwip_mbed_tracef_error vars
#define LWIP_PLATFORM_DIAG_WARNING(vars) lwip_mbed_tracef_warn vars
#define LWIP_PLATFORM_ASSERT(message) lwip_mbed_assert_fail(message, __func__, __FILE__, __LINE__)
#else // MBED_CONF_LWIP_USE_MBED_TRACE
#include <stdio.h>
MBED_NORETURN void assert_printf(const char *msg, int line, const char *file);
/* Plaform specific diagnostic output */
#define LWIP_PLATFORM_DIAG(vars) printf vars
#define LWIP_PLATFORM_ASSERT(flag) { assert_printf((flag), __LINE__, __FILE__); }
#endif // MBED_CONF_LWIP_USE_MBED_TRACE
#endif
#if TRACE_TO_ASCII_HEX_DUMP
#define TRACE_TO_ASCII_HEX_DUMPF(prefix, len, data) trace_to_ascii_hex_dump(prefix, len, data)
void trace_to_ascii_hex_dump(char* prefix, int len, char *data);
#else
#define TRACE_TO_ASCII_HEX_DUMPF(prefix, len, data) ((void)0)
#endif
#include "cmsis.h"
#define LWIP_PLATFORM_HTONS(x) __REV16(x)
#define LWIP_PLATFORM_HTONL(x) __REV(x)
/* Define the memory area for the lwip's memory pools */
#ifndef MEMP_SECTION
#if defined(TARGET_LPC1768)
# if defined (__ICCARM__)
# define MEMP_SECTION
# elif defined(TOOLCHAIN_GCC_CR)
# define MEMP_SECTION __attribute__((section(".data.$RamPeriph32")))
# else
# define MEMP_SECTION __attribute__((section("AHBSRAM1"),aligned))
# endif
#endif
#endif
#ifdef MEMP_SECTION
#define SET_MEMP_SECTION(name) extern uint8_t MEMP_SECTION name[]
#if defined (__ICCARM__)
#pragma default_variable_attributes = @ ".ethusbram"
#endif
SET_MEMP_SECTION(memp_memory_REASSDATA_base);
SET_MEMP_SECTION(memp_memory_TCP_PCB_LISTEN_base);
SET_MEMP_SECTION(memp_memory_PBUF_POOL_base);
SET_MEMP_SECTION(memp_memory_NETCONN_base);
SET_MEMP_SECTION(memp_memory_IGMP_GROUP_base);
SET_MEMP_SECTION(memp_memory_UDP_PCB_base);
SET_MEMP_SECTION(memp_memory_TCP_PCB_base);
SET_MEMP_SECTION(memp_memory_FRAG_PBUF_base);
SET_MEMP_SECTION(memp_memory_PBUF_base);
SET_MEMP_SECTION(memp_memory_MLD6_GROUP_base);
SET_MEMP_SECTION(memp_memory_IP6_REASSDATA_base);
SET_MEMP_SECTION(memp_memory_NETBUF_base);
SET_MEMP_SECTION(memp_memory_TCPIP_MSG_INPKT_base);
SET_MEMP_SECTION(memp_memory_SYS_TIMEOUT_base);
SET_MEMP_SECTION(memp_memory_TCP_SEG_base);
SET_MEMP_SECTION(memp_memory_TCPIP_MSG_API_base);
#if defined (__ICCARM__)
#pragma default_variable_attributes =
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* __CC_H__ */

View File

@@ -0,0 +1,126 @@
/* Copyright (C) 2013 - Adam Green (https://github.com/adamgreen)
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.
*/
#if defined(TOOLCHAIN_GCC) && defined(__thumb2__)
/* This is a hand written Thumb-2 assembly language version of the
algorithm 3 version of lwip_standard_chksum in lwIP's inet_chksum.c. It
performs the checksumming 32-bits at a time and even unrolls the loop to
perform two of these 32-bit adds per loop iteration.
Returns:
16-bit 1's complement summation (not inversed).
NOTE: This function does return a uint16_t from the assembly language code
but is marked as void so that GCC doesn't issue warning because it
doesn't know about this low level return.
*/
__attribute__((naked)) void /*uint16_t*/ thumb2_checksum(const void* pData, int length)
{
__asm (
".syntax unified\n"
".thumb\n"
// Push non-volatile registers we use on stack. Push link register too to
// keep stack 8-byte aligned and allow single pop to restore and return.
" push {r4, lr}\n"
// Initialize sum, r2, to 0.
" movs r2, #0\n"
// Remember whether pData was at odd address in r3. This is used later to
// know if it needs to swap the result since the summation will be done at
// an offset of 1, rather than 0.
" ands r3, r0, #1\n"
// Need to 2-byte align? If not skip ahead.
" beq 1$\n"
// We can return if there are no bytes to sum.
" cbz r1, 9$\n"
// 2-byte align.
// Place the first data byte in odd summation location since it needs to be
// swapped later. It's ok to overwrite r2 here as it only had a value of 0
// up until now. Advance r0 pointer and decrement r1 length as we go.
" ldrb r2, [r0], #1\n"
" lsls r2, r2, #8\n"
" subs r1, r1, #1\n"
// Need to 4-byte align? If not skip ahead.
"1$:\n"
" ands r4, r0, #3\n"
" beq 2$\n"
// Have more than 1 byte left to align? If not skip ahead to take care of
// trailing byte.
" cmp r1, #2\n"
" blt 7$\n"
// 4-byte align.
" ldrh r4, [r0], #2\n"
" adds r2, r2, r4\n"
" subs r1, r1, #2\n"
// Main summing loop which sums up data 2 words at a time.
// Make sure that we have more than 7 bytes left to sum.
"2$:\n"
" cmp r1, #8\n"
" blt 3$\n"
// Sum next two words. Applying previous upper 16-bit carry to
// lower 16-bits.
" ldr r4, [r0], #4\n"
" adds r2, r4\n"
" adc r2, r2, #0\n"
" ldr r4, [r0], #4\n"
" adds r2, r4\n"
" adc r2, r2, #0\n"
" subs r1, r1, #8\n"
" b 2$\n"
// Sum up any remaining half-words.
"3$:\n"
// Make sure that we have more than 1 byte left to sum.
" cmp r1, #2\n"
" blt 7$\n"
// Sum up next half word, continue to apply carry.
" ldrh r4, [r0], #2\n"
" adds r2, r4\n"
" adc r2, r2, #0\n"
" subs r1, r1, #2\n"
" b 3$\n"
// Handle trailing byte, if it exists
"7$:\n"
" cbz r1, 8$\n"
" ldrb r4, [r0]\n"
" adds r2, r4\n"
" adc r2, r2, #0\n"
// Fold 32-bit checksum into 16-bit checksum.
"8$:\n"
" ubfx r4, r2, #16, #16\n"
" ubfx r2, r2, #0, #16\n"
" adds r2, r4\n"
" ubfx r4, r2, #16, #16\n"
" ubfx r2, r2, #0, #16\n"
" adds r2, r4\n"
// Swap bytes if started at odd address
" cbz r3, 9$\n"
" rev16 r2, r2\n"
// Return final sum.
"9$: mov r0, r2\n"
" pop {r4, pc}\n"
);
}
#endif

View File

@@ -0,0 +1,59 @@
/* Copyright (C) 2013 - Adam Green (https://github.com/adamgreen)
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.
*/
#if defined(TOOLCHAIN_GCC) && defined(__thumb2__)
#include <stdio.h>
/* This is a hand written Thumb-2 assembly language version of the
standard C memcpy() function that can be used by the lwIP networking
stack to improve its performance. It copies 4 bytes at a time and
unrolls the loop to perform 4 of these copies per loop iteration.
*/
__attribute__((naked)) void thumb2_memcpy(void* pDest, const void* pSource, size_t length)
{
__asm (
".syntax unified\n"
".thumb\n"
// Copy 16 bytes at a time first.
" lsrs r3, r2, #4\n"
" beq.n 2$\n"
"1$: ldr r12, [r1], #4\n"
" str r12, [r0], #4\n"
" ldr r12, [r1], #4\n"
" str r12, [r0], #4\n"
" ldr r12, [r1], #4\n"
" str r12, [r0], #4\n"
" ldr r12, [r1], #4\n"
" str r12, [r0], #4\n"
" subs r3, #1\n"
" bne 1$\n"
// Copy byte by byte for what is left.
"2$:\n"
" ands r3, r2, #0xf\n"
" beq.n 4$\n"
"3$: ldrb r12, [r1], #1\n"
" strb r12, [r0], #1\n"
" subs r3, #1\n"
" bne 3$\n"
// Return to caller.
"4$: bx lr\n"
);
}
#endif

View File

@@ -0,0 +1,630 @@
/* Copyright (C) 2012 mbed.org, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
/* mbed includes */
#include "mbed_error.h"
#include "mbed_interface.h"
#include "mbed_rtos_storage.h"
/* lwIP includes. */
#include "lwip/opt.h"
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/mem.h"
/* Define the heap ourselves to give us section placement control */
#ifndef ETHMEM_SECTION
#if defined(TARGET_LPC1768)
# if defined (__ICCARM__)
# define ETHMEM_SECTION
# elif defined(TOOLCHAIN_GCC_CR)
# define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32")))
# else
# define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned))
# endif
#elif defined(TARGET_STM32H7)
# if defined (__ICCARM__)
# define ETHMEM_SECTION
# else
# define ETHMEM_SECTION __attribute__((section(".ethusbram")))
# endif
#else
#define ETHMEM_SECTION
#endif
#endif
/* LWIP's mem.c doesn't give visibility of its overhead; memory area has to be big
* enough to hold "MEM_SIZE" (which we specify) plus mem.c's overhead. Have to work
* it all out here, copying code from mem.c */
struct mem {
/** index (-> ram[next]) of the next struct */
mem_size_t next;
/** index (-> ram[prev]) of the previous struct */
mem_size_t prev;
/** 1: this area is used; 0: this area is unused */
u8_t used;
};
#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
#if defined (__ICCARM__)
#pragma location = ".ethusbram"
#endif
LWIP_DECLARE_MEMORY_ALIGNED(lwip_ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM)) ETHMEM_SECTION;
#if NO_SYS==1
#include "cmsis.h"
/* Saved total time in ms since timer was enabled */
static volatile u32_t systick_timems;
/* Enable systick rate and interrupt */
void SysTick_Init(void) {
if (SysTick_Config(SystemCoreClock / 1000)) {
while (1); /* Capture error */
}
}
/** \brief SysTick IRQ handler and timebase management
*
* This function keeps a timebase for the sysTick that can be
* used for other functions. It also calls an external function
* (SysTick_User) that must be defined outside this handler.
*/
void SysTick_Handler(void) {
systick_timems++;
}
/* Delay for the specified number of milliSeconds */
void osDelay(uint32_t ms) {
uint32_t to = ms + systick_timems;
while (to > systick_timems);
}
/* Returns the current time in mS. This is needed for the LWIP timers */
u32_t sys_now(void) {
return (u32_t) systick_timems;
}
#else
/* CMSIS-RTOS implementation of the lwip operating system abstraction */
#include "arch/sys_arch.h"
/*---------------------------------------------------------------------------*
* Routine: sys_mbox_new
*---------------------------------------------------------------------------*
* Description:
* Creates a new mailbox
* Inputs:
* sys_mbox_t mbox -- Handle of mailbox
* int queue_sz -- Size of elements in the mailbox
* Outputs:
* err_t -- ERR_OK if message posted, else ERR_MEM
*---------------------------------------------------------------------------*/
err_t sys_mbox_new(sys_mbox_t *mbox, int queue_sz) {
if (queue_sz > MB_SIZE)
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_INVALID_SIZE), "sys_mbox_new size error\n", queue_sz);
memset(mbox, 0, sizeof(*mbox));
mbox->attr.cb_mem = &mbox->data;
mbox->attr.cb_size = sizeof(mbox->data);
mbox->id = osEventFlagsNew(&mbox->attr);
if (mbox->id == NULL)
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_mbox_new create error\n", (u32_t)mbox);
osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
return ERR_OK;
}
/*---------------------------------------------------------------------------*
* Routine: sys_mbox_free
*---------------------------------------------------------------------------*
* Description:
* Deallocates a mailbox. If there are messages still present in the
* mailbox when the mailbox is deallocated, it is an indication of a
* programming error in lwIP and the developer should be notified.
* Inputs:
* sys_mbox_t *mbox -- Handle of mailbox
*---------------------------------------------------------------------------*/
void sys_mbox_free(sys_mbox_t *mbox) {
if (mbox->post_idx != mbox->fetch_idx)
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_INVALID_INDEX), "sys_mbox_free error\n", (u32_t)mbox->fetch_idx);
}
/*---------------------------------------------------------------------------*
* Routine: sys_mbox_post
*---------------------------------------------------------------------------*
* Description:
* Post the "msg" to the mailbox.
* Inputs:
* sys_mbox_t mbox -- Handle of mailbox
* void *msg -- Pointer to data to post
*---------------------------------------------------------------------------*/
void sys_mbox_post(sys_mbox_t *mbox, void *msg) {
osEventFlagsWait(mbox->id, SYS_MBOX_POST_EVENT,
osFlagsWaitAny | osFlagsNoClear, osWaitForever);
int state = osKernelLock();
mbox->queue[mbox->post_idx] = msg;
mbox->post_idx = (mbox->post_idx + 1) % MB_SIZE;
osEventFlagsSet(mbox->id, SYS_MBOX_FETCH_EVENT);
if ((mbox->post_idx + 1) % MB_SIZE == mbox->fetch_idx)
osEventFlagsClear(mbox->id, SYS_MBOX_POST_EVENT);
osKernelRestoreLock(state);
}
/*---------------------------------------------------------------------------*
* Routine: sys_mbox_trypost
*---------------------------------------------------------------------------*
* Description:
* Try to post the "msg" to the mailbox. Returns immediately with
* error if cannot.
* Inputs:
* sys_mbox_t mbox -- Handle of mailbox
* void *msg -- Pointer to data to post
* Outputs:
* err_t -- ERR_OK if message posted, else ERR_MEM
* if not.
*---------------------------------------------------------------------------*/
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) {
uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_POST_EVENT,
osFlagsWaitAny | osFlagsNoClear, 0);
if ((flags & osFlagsError) || !(flags & SYS_MBOX_POST_EVENT)) {
MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_mbox_trypost error\n", flags);
return ERR_MEM;
}
int state = osKernelLock();
mbox->queue[mbox->post_idx] = msg;
mbox->post_idx = (mbox->post_idx + 1) % MB_SIZE;
osEventFlagsSet(mbox->id, SYS_MBOX_FETCH_EVENT);
if ((mbox->post_idx + 1) % MB_SIZE == mbox->fetch_idx)
osEventFlagsClear(mbox->id, SYS_MBOX_POST_EVENT);
osKernelRestoreLock(state);
return ERR_OK;
}
err_t
sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg)
{
return sys_mbox_trypost(q, msg);
}
/*---------------------------------------------------------------------------*
* Routine: sys_arch_mbox_fetch
*---------------------------------------------------------------------------*
* Description:
* Blocks the thread until a message arrives in the mailbox, but does
* not block the thread longer than "timeout" milliseconds (similar to
* the sys_arch_sem_wait() function). The "msg" argument is a result
* parameter that is set by the function (i.e., by doing "*msg =
* ptr"). The "msg" parameter maybe NULL to indicate that the message
* should be dropped.
*
* The return values are the same as for the sys_arch_sem_wait() function:
* Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
* timeout.
*
* Note that a function with a similar name, sys_mbox_fetch(), is
* implemented by lwIP.
* Inputs:
* sys_mbox_t mbox -- Handle of mailbox
* void **msg -- Pointer to pointer to msg received
* u32_t timeout -- Number of milliseconds until timeout
* Outputs:
* u32_t -- SYS_ARCH_TIMEOUT if timeout, else number
* of milliseconds until received.
*---------------------------------------------------------------------------*/
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
uint32_t start = osKernelGetTickCount();
uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_FETCH_EVENT,
osFlagsWaitAny | osFlagsNoClear, (timeout ? timeout : osWaitForever));
if ((flags & osFlagsError) || !(flags & SYS_MBOX_FETCH_EVENT)) {
MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_TIME_OUT), "sys_arch_mbox_fetch time-out\n", flags);
return SYS_ARCH_TIMEOUT;
}
int state = osKernelLock();
if (msg)
*msg = mbox->queue[mbox->fetch_idx];
mbox->fetch_idx = (mbox->fetch_idx + 1) % MB_SIZE;
osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
if (mbox->post_idx == mbox->fetch_idx)
osEventFlagsClear(mbox->id, SYS_MBOX_FETCH_EVENT);
osKernelRestoreLock(state);
return osKernelGetTickCount() - start;
}
/*---------------------------------------------------------------------------*
* Routine: sys_arch_mbox_tryfetch
*---------------------------------------------------------------------------*
* Description:
* Similar to sys_arch_mbox_fetch, but if message is not ready
* immediately, we'll return with SYS_MBOX_EMPTY. On success, 0 is
* returned.
* Inputs:
* sys_mbox_t mbox -- Handle of mailbox
* void **msg -- Pointer to pointer to msg received
* Outputs:
* u32_t -- SYS_MBOX_EMPTY if no messages. Otherwise,
* return ERR_OK.
*---------------------------------------------------------------------------*/
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
uint32_t flags = osEventFlagsWait(mbox->id, SYS_MBOX_FETCH_EVENT,
osFlagsWaitAny | osFlagsNoClear, 0);
if ((flags & osFlagsError) || !(flags & SYS_MBOX_FETCH_EVENT)) {
MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_arch_mbox_tryfetch empty\n", flags);
return SYS_MBOX_EMPTY;
}
int state = osKernelLock();
if (msg)
*msg = mbox->queue[mbox->fetch_idx];
mbox->fetch_idx = (mbox->fetch_idx + 1) % MB_SIZE;
osEventFlagsSet(mbox->id, SYS_MBOX_POST_EVENT);
if (mbox->post_idx == mbox->fetch_idx)
osEventFlagsClear(mbox->id, SYS_MBOX_FETCH_EVENT);
osKernelRestoreLock(state);
return ERR_OK;
}
/*---------------------------------------------------------------------------*
* Routine: sys_sem_new
*---------------------------------------------------------------------------*
* Description:
* Creates and returns a new semaphore. The "ucCount" argument specifies
* the initial state of the semaphore.
* NOTE: Currently this routine only creates counts of 1 or 0
* Inputs:
* sys_sem_t sem -- Handle of semaphore
* u8_t count -- Initial count of semaphore
* Outputs:
* err_t -- ERR_OK if semaphore created
*---------------------------------------------------------------------------*/
err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
memset(sem, 0, sizeof(*sem));
sem->attr.cb_mem = &sem->data;
sem->attr.cb_size = sizeof(sem->data);
sem->id = osSemaphoreNew(UINT16_MAX, count, &sem->attr);
if (sem->id == NULL)
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_sem_new create error\n", (u32_t)sem);
return ERR_OK;
}
/*---------------------------------------------------------------------------*
* Routine: sys_arch_sem_wait
*---------------------------------------------------------------------------*
* Description:
* Blocks the thread while waiting for the semaphore to be
* signaled. If the "timeout" argument is non-zero, the thread should
* only be blocked for the specified time (measured in
* milliseconds).
*
* If the timeout argument is non-zero, the return value is the number of
* milliseconds spent waiting for the semaphore to be signaled. If the
* semaphore wasn't signaled within the specified time, the return value is
* SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
* (i.e., it was already signaled), the function may return zero.
*
* Notice that lwIP implements a function with a similar name,
* sys_sem_wait(), that uses the sys_arch_sem_wait() function.
* Inputs:
* sys_sem_t sem -- Semaphore to wait on
* u32_t timeout -- Number of milliseconds until timeout
* Outputs:
* u32_t -- Time elapsed or SYS_ARCH_TIMEOUT.
*---------------------------------------------------------------------------*/
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
u32_t start = osKernelGetTickCount();
if (osSemaphoreAcquire(sem->id, (timeout != 0)?(timeout):(osWaitForever)) != osOK) {
MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_TIME_OUT), "sys_arch_sem_wait time out\n", (u32_t)sem);
return SYS_ARCH_TIMEOUT;
}
return osKernelGetTickCount() - start;
}
/*---------------------------------------------------------------------------*
* Routine: sys_sem_signal
*---------------------------------------------------------------------------*
* Description:
* Signals (releases) a semaphore
* Inputs:
* sys_sem_t sem -- Semaphore to signal
*---------------------------------------------------------------------------*/
void sys_sem_signal(sys_sem_t *data) {
if (osSemaphoreRelease(data->id) != osOK)
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_SEMAPHORE_UNLOCK_FAILED), "sys_sem_signal error\n", (u32_t)data->id);
}
/*---------------------------------------------------------------------------*
* Routine: sys_sem_free
*---------------------------------------------------------------------------*
* Description:
* Deallocates a semaphore
* Inputs:
* sys_sem_t sem -- Semaphore to free
*---------------------------------------------------------------------------*/
void sys_sem_free(sys_sem_t *sem) {}
/** Create a new mutex
* @param mutex pointer to the mutex to create
* @return a new mutex */
err_t sys_mutex_new(sys_mutex_t *mutex) {
memset(mutex, 0, sizeof(*mutex));
mutex->attr.name = "lwip_mutex";
mutex->attr.cb_mem = &mutex->data;
mutex->attr.cb_size = sizeof(mutex->data);
mutex->id = osMutexNew(&mutex->attr);
if (mutex->id == NULL) {
MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_FAILED_OPERATION), "sys_mutex_new error\n", (u32_t)mutex);
return ERR_MEM;
}
return ERR_OK;
}
/** Lock a mutex
* @param mutex the mutex to lock */
void sys_mutex_lock(sys_mutex_t *mutex) {
if (osMutexAcquire(mutex->id, osWaitForever) != osOK)
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "sys_mutex_lock error\n", (u32_t)mutex);
}
/** Unlock a mutex
* @param mutex the mutex to unlock */
void sys_mutex_unlock(sys_mutex_t *mutex) {
if (osMutexRelease(mutex->id) != osOK)
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_MUTEX_UNLOCK_FAILED), "sys_mutex_unlock error\n", (u32_t)mutex);
}
/** Delete a mutex
* @param mutex the mutex to delete */
void sys_mutex_free(sys_mutex_t *mutex) {}
/*---------------------------------------------------------------------------*
* Routine: sys_init
*---------------------------------------------------------------------------*
* Description:
* Initialize sys arch
*---------------------------------------------------------------------------*/
osMutexId_t lwip_sys_mutex;
osMutexAttr_t lwip_sys_mutex_attr;
mbed_rtos_storage_mutex_t lwip_sys_mutex_data;
void sys_init(void) {
lwip_sys_mutex_attr.name = "lwip_sys_mutex";
lwip_sys_mutex_attr.cb_mem = &lwip_sys_mutex_data;
lwip_sys_mutex_attr.cb_size = sizeof(lwip_sys_mutex_data);
lwip_sys_mutex_attr.attr_bits = osMutexPrioInherit | osMutexRecursive;
lwip_sys_mutex = osMutexNew(&lwip_sys_mutex_attr);
if (lwip_sys_mutex == NULL)
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_INITIALIZATION_FAILED), "sys_init error, mutex initialization failed\n");
}
/*---------------------------------------------------------------------------*
* Routine: sys_arch_protect
*---------------------------------------------------------------------------*
* Description:
* This optional function does a "fast" critical region protection and
* returns the previous protection level. This function is only called
* during very short critical regions. An embedded system which supports
* ISR-based drivers might want to implement this function by disabling
* interrupts. Task-based systems might want to implement this by using
* a mutex or disabling tasking. This function should support recursive
* calls from the same task or interrupt. In other words,
* sys_arch_protect() could be called while already protected. In
* that case the return value indicates that it is already protected.
*
* sys_arch_protect() is only required if your port is supporting an
* operating system.
* Outputs:
* sys_prot_t -- Previous protection level (not used here)
*---------------------------------------------------------------------------*/
sys_prot_t sys_arch_protect(void) {
if (osMutexAcquire(lwip_sys_mutex, osWaitForever) != osOK)
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_MUTEX_LOCK_FAILED), "sys_arch_protect error\n");
return (sys_prot_t) 1;
}
/*---------------------------------------------------------------------------*
* Routine: sys_arch_unprotect
*---------------------------------------------------------------------------*
* Description:
* This optional function does a "fast" set of critical region
* protection to the value specified by pval. See the documentation for
* sys_arch_protect() for more information. This function is only
* required if your port is supporting an operating system.
* Inputs:
* sys_prot_t -- Previous protection level (not used here)
*---------------------------------------------------------------------------*/
void sys_arch_unprotect(sys_prot_t p) {
if (osMutexRelease(lwip_sys_mutex) != osOK)
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_MUTEX_UNLOCK_FAILED), "sys_arch_unprotect error\n");
}
u32_t sys_now(void) {
return osKernelGetTickCount();
}
void sys_msleep(u32_t ms) {
osDelay(ms);
}
osThreadId_t lwip_tcpip_thread_id = 0;
void sys_tcpip_thread_set(void)
{
lwip_tcpip_thread_id = osThreadGetId();
}
bool sys_tcpip_thread_check(void)
{
return osThreadGetId() == lwip_tcpip_thread_id;
}
// Keep a pool of thread structures
static int thread_pool_index = 0;
static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N];
/*---------------------------------------------------------------------------*
* Routine: sys_thread_new
*---------------------------------------------------------------------------*
* Description:
* Starts a new thread with priority "prio" that will begin its
* execution in the function "thread()". The "arg" argument will be
* passed as an argument to the thread() function. The id of the new
* thread is returned. Both the id and the priority are system
* dependent.
* Inputs:
* char *name -- Name of thread
* void (*thread)(void *arg) -- Pointer to function to run.
* void *arg -- Argument passed into function
* int stacksize -- Required stack amount in bytes
* int priority -- Thread priority
* Outputs:
* sys_thread_t -- Pointer to thread handle.
*---------------------------------------------------------------------------*/
#ifndef MBED_TZ_DEFAULT_ACCESS
#define MBED_TZ_DEFAULT_ACCESS 0
#endif
sys_thread_t sys_thread_new(const char *pcName,
void (*thread)(void *arg),
void *arg, int stacksize, int priority) {
LWIP_DEBUGF(SYS_DEBUG, ("New Thread: %s\n", pcName));
if (thread_pool_index >= SYS_THREAD_POOL_N)
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_THREAD_CREATE_FAILED), "sys_thread_new number error\n", thread_pool_index);
sys_thread_t t = (sys_thread_t)&thread_pool[thread_pool_index];
thread_pool_index++;
memset(t, 0, sizeof(*t));
t->attr.name = pcName ? pcName : "lwip_unnamed_thread";
t->attr.priority = (osPriority_t)priority;
t->attr.cb_size = sizeof(t->data);
t->attr.cb_mem = &t->data;
t->attr.stack_size = stacksize;
t->attr.stack_mem = malloc(stacksize);
t->attr.tz_module = MBED_TZ_DEFAULT_ACCESS;
if (t->attr.stack_mem == NULL) {
MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_OUT_OF_MEMORY), "unable to allocate thread stack\n", stacksize);
}
t->id = osThreadNew((osThreadFunc_t)thread, arg, &t->attr);
if (t->id == NULL)
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STACK, MBED_ERROR_CODE_THREAD_CREATE_FAILED), "sys_thread_new create error\n");
return t;
}
#endif
#ifdef LWIP_DEBUG
#include <stdbool.h>
#if MBED_CONF_LWIP_USE_MBED_TRACE
#include "mbed-trace/mbed_trace.h"
void lwip_mbed_tracef_debug(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
mbed_vtracef(TRACE_LEVEL_DEBUG, "lwIP", fmt, ap);
va_end(ap);
}
void lwip_mbed_tracef_warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
mbed_vtracef(TRACE_LEVEL_WARN, "lwIP", fmt, ap);
va_end(ap);
}
void lwip_mbed_tracef_error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
mbed_vtracef(TRACE_LEVEL_ERROR, "lwIP", fmt, ap);
va_end(ap);
}
MBED_NORETURN void lwip_mbed_assert_fail(const char *msg, const char *func, const char *file, unsigned int line)
{
mbed_tracef(TRACE_LEVEL_ERROR, "lwIP", "Assertion failed: %s, function %s, file %s, line %u.", msg, func, file, line);
exit(EXIT_FAILURE); // XXX how about abort? mbed_assert uses exit, so follow suit
}
#else // MBED_CONF_LWIP_USE_MBED_TRACE
/** \brief Displays an error message on assertion
This function will display an error message on an assertion
to the debug output.
\param[in] msg Error message to display
\param[in] line Line number in file with error
\param[in] file Filename with error
*/
MBED_NORETURN void assert_printf(const char *msg, int line, const char *file) {
if (msg)
error("%s:%d in file %s\n", msg, line, file);
else
error("LWIP ASSERT\n");
}
#endif // MBED_CONF_LWIP_USE_MBED_TRACE
#if TRACE_TO_ASCII_HEX_DUMP
void trace_to_ascii_hex_dump(char *prefix, int len, char *data)
{
int line_len = 0;
for (int i = 0; i < len; i++) {
if ((line_len % 16) == 0) {
if (line_len != 0) {
LWIP_PLATFORM_DIAG(("\n"));
}
LWIP_PLATFORM_DIAG(("%s %06x", prefix, line_len));
}
line_len++;
LWIP_PLATFORM_DIAG((" %02x", data[i]));
}
LWIP_PLATFORM_DIAG(("\n"));
}
#endif
#endif /* LWIP_DEBUG */

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __PERF_H__
#define __PERF_H__
#define PERF_START /* null definition */
#define PERF_STOP(x) /* null definition */
#endif /* __PERF_H__ */

View File

@@ -0,0 +1,130 @@
/* Copyright (C) 2012 mbed.org, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_SYS_ARCH_H__
#define __ARCH_SYS_ARCH_H__
#include "lwip/opt.h"
#include "mbed_rtos_storage.h"
#include <stdbool.h>
extern u8_t lwip_ram_heap[];
#if NO_SYS == 0
#include "cmsis_os2.h"
// === SEMAPHORE ===
typedef struct {
osSemaphoreId_t id;
osSemaphoreAttr_t attr;
mbed_rtos_storage_semaphore_t data;
} sys_sem_t;
#define sys_sem_valid(x) (((*x).id == NULL) ? 0 : 1)
#define sys_sem_set_invalid(x) ( (*x).id = NULL)
// === MUTEX ===
typedef struct {
osMutexId_t id;
osMutexAttr_t attr;
mbed_rtos_storage_mutex_t data;
} sys_mutex_t;
// === MAIL BOX ===
#define MB_SIZE MBED_CONF_LWIP_MBOX_SIZE
typedef struct {
osEventFlagsId_t id;
osEventFlagsAttr_t attr;
mbed_rtos_storage_event_flags_t data;
uint8_t post_idx;
uint8_t fetch_idx;
void* queue[MB_SIZE];
} sys_mbox_t;
#define SYS_MBOX_FETCH_EVENT 0x1
#define SYS_MBOX_POST_EVENT 0x2
#define SYS_MBOX_NULL ((uint32_t) NULL)
#define sys_mbox_valid(x) (((*x).id == NULL) ? 0 : 1)
#define sys_mbox_set_invalid(x) ( (*x).id = NULL)
#if ((DEFAULT_RAW_RECVMBOX_SIZE) > (MB_SIZE)) || \
((DEFAULT_UDP_RECVMBOX_SIZE) > (MB_SIZE)) || \
((DEFAULT_TCP_RECVMBOX_SIZE) > (MB_SIZE)) || \
((DEFAULT_ACCEPTMBOX_SIZE) > (MB_SIZE)) || \
((TCPIP_MBOX_SIZE) > (MB_SIZE))
# error Mailbox size not supported
#endif
// === THREAD ===
typedef struct {
osThreadId_t id;
osThreadAttr_t attr;
mbed_rtos_storage_thread_t data;
} sys_thread_data_t;
typedef sys_thread_data_t* sys_thread_t;
#define SYS_THREAD_POOL_N 6
#define SYS_DEFAULT_THREAD_STACK_DEPTH OS_STACK_SIZE
// === PROTECTION ===
typedef int sys_prot_t;
void sys_tcpip_thread_set(void);
bool sys_tcpip_thread_check(void);
#else
#ifdef __cplusplus
extern "C" {
#endif
/** \brief Init systick to 1ms rate
*
* This init the systick to 1ms rate. This function is only used in standalone
* systems.
*/
void SysTick_Init(void);
/** \brief Get the current systick time in milliSeconds
*
* Returns the current systick time in milliSeconds. This function is only
* used in standalone systems.
*
* /returns current systick time in milliSeconds
*/
uint32_t SysTick_GetMS(void);
/** \brief Delay for the specified number of milliSeconds
*
* For standalone systems. This function will block for the specified
* number of milliSconds. For RTOS based systems, this function will delay
* the task by the specified number of milliSeconds.
*
* \param[in] ms Time in milliSeconds to delay
*/
void osDelay(uint32_t ms);
#ifdef __cplusplus
}
#endif
#endif
#endif /* __ARCH_SYS_ARCH_H__ */