Merge pull request #437 from ourairquality/oaq-merge-1
* bmp180: comment typo * ds3231: minor code style fixes. Comment, on the week day start. * Reverse engineered ets_timers.o Switch from FreeRTOS queue to task notification. Removed unknown/unused code. Rename sdk_ets_handler_isr to process_pending_timers. Add function for microseconds Simplify time to ticks conversion * ets_timer: code for using the FreeRTOS timers, and remove from libs. * libc: update to a recent newlib version. * LwIP v2 support * spi_write: use uint32_t for the page iteration counter. The page counter was using an uint8_t which seems unnecessary and might wrap. * sysparam_get_bool: memcpy the binary values out. * FreeRTOS 9.0.1 * Add an argument to ISRs. Disable interrupts while masking them. * sysparam: reserve one more flash sector before placing the sysparams. This is to help work with recent SDKs that add a RF cal sector by default in the fifth last sector - just so the sysparam sectors do not jump around when using different SDK versions. * upnp example: strip down the lwipopts.h file * sysparam editor: accept newline to end a line of input. * Add Wificfg. Uses the sysparam store to save the wifi configuration. Adds a basic http server for configuration. * lwip: disable the tcpip_core_locking_input option. With this option enabled some lwip input processing occurs in the pp task which works well for some uses but some code uses a lot of stack (e.g. mdns) and will overflow the pp task stask, or might unnecessarily slow the critical pp task, so disable this by default and if not already defined. * sdk_cnx_add_rc: fix overflow of the table, when no match is found. Also adds source code for sdk_cnx_rc_search, adding a null pointer dereference. Check (that is not expected to be seen), and source code for sdk_cnx_remove_rc. * http_get example: fix compilation with ipv6 disabled. * lwip: update to master branch. * wificfg: allow the AP channel to be 1. * lwip: rework the tcp ooseq handling. It now accounts for the number of rx pool buffers used and the available memory when deciding the number of ooseq buffers to retain. Enable the TCP Selective ACK support which appears to help a lot on lossy wifi when using the OOSEQ option. * Update lwip, fixes losses of pcbs and associated problems. * lwip: revise the tcp ooseq limit calulations. Was making a mess of the calculation sign. Also added a COPY_PP_RX_PBUFS define to include appropriate limits for this option. * lwip: ooseq_max_bytes() - set a practical target memory size. * lwip: revise ooseq handling. Modified for lwip backwards compatibility based on upstream feedback. * lwip: update to the 2.0.3 release * lwip: merge upstream master. * libc: update to upstream master. * lwip: fix building without TCP_QUEUE_OOSEQ
This commit is contained in:
commit
546cc47121
183 changed files with 10793 additions and 11817 deletions
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -1,6 +1,6 @@
|
|||
[submodule "lwip/lwip"]
|
||||
path = lwip/lwip
|
||||
url = https://github.com/SuperHouse/esp-lwip.git
|
||||
url = https://github.com/ourairquality/lwip.git
|
||||
[submodule "extras/mbedtls/mbedtls"]
|
||||
path = extras/mbedtls/mbedtls
|
||||
url = https://github.com/ARMmbed/mbedtls.git
|
||||
|
|
|
@ -1,65 +1,61 @@
|
|||
The FreeRTOS.org source code is licensed by the *modified* GNU General Public
|
||||
License (GPL), text provided below. A special exception to the GPL is
|
||||
included to allow you to distribute a combined work that includes FreeRTOS
|
||||
without being obliged to provide the source code for any proprietary
|
||||
components. See the licensing section of http://www.FreeRTOS.org for full
|
||||
details. The exception text is also included at the bottom of this file.
|
||||
The FreeRTOS open source license covers the FreeRTOS source files,
|
||||
which are located in the /FreeRTOS/Source directory of the official FreeRTOS
|
||||
download. It also covers most of the source files in the demo application
|
||||
projects, which are located in the /FreeRTOS/Demo directory of the official
|
||||
FreeRTOS download. The demo projects may also include third party software that
|
||||
is not part of FreeRTOS and is licensed separately to FreeRTOS. Examples of
|
||||
third party software includes header files provided by chip or tools vendors,
|
||||
linker scripts, peripheral drivers, etc. All the software in subdirectories of
|
||||
the /FreeRTOS directory is either open source or distributed with permission,
|
||||
and is free for use. For the avoidance of doubt, refer to the comments at the
|
||||
top of each source file.
|
||||
|
||||
The FreeRTOS download also includes demo application source code, some of
|
||||
which is provided by third parties AND IS LICENSED SEPARATELY FROM FREERTOS.
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
For the avoidance of any doubt refer to the comment included at the top
|
||||
of each source and header file for license and copyright information.
|
||||
NOTE: The modification to the GPL is included to allow you to distribute a
|
||||
combined work that includes FreeRTOS without being obliged to provide the source
|
||||
code for proprietary components.
|
||||
|
||||
This is a list of files for which Real Time Engineers Ltd are not the
|
||||
copyright owner and are NOT COVERED BY THE GPL.
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Applying to FreeRTOS V8.2.3 up to the latest version, the FreeRTOS GPL Exception
|
||||
Text follows:
|
||||
|
||||
Any FreeRTOS *source code*, whether modified or in it's original release form,
|
||||
or whether in whole or in part, can only be distributed by you under the terms
|
||||
of the GNU General Public License plus this exception. An independent module is
|
||||
a module which is not derived from or based on FreeRTOS.
|
||||
|
||||
Clause 1:
|
||||
|
||||
Linking FreeRTOS with other modules is making a combined work based on FreeRTOS.
|
||||
Thus, the terms and conditions of the GNU General Public License V2 cover the
|
||||
whole combination.
|
||||
|
||||
As a special exception, the copyright holders of FreeRTOS give you permission to
|
||||
link FreeRTOS with independent modules to produce a statically linked
|
||||
executable, regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the terms and
|
||||
conditions of the license of that module. An independent module is a module
|
||||
which is not derived from or based on FreeRTOS.
|
||||
|
||||
Clause 2:
|
||||
|
||||
FreeRTOS may not be used for any competitive or comparative purpose, including
|
||||
the publication of any form of run time or compile time metric, without the
|
||||
express permission of Real Time Engineers Ltd. (this is the norm within the
|
||||
industry and is intended to ensure information accuracy).
|
||||
|
||||
|
||||
1) Various header files provided by silicon manufacturers and tool vendors
|
||||
that define processor specific memory addresses and utility macros.
|
||||
Permission has been granted by the various copyright holders for these
|
||||
files to be included in the FreeRTOS download. Users must ensure license
|
||||
conditions are adhered to for any use other than compilation of the
|
||||
FreeRTOS demo applications.
|
||||
|
||||
2) The uIP TCP/IP stack the copyright of which is held by Adam Dunkels.
|
||||
Users must ensure the open source license conditions stated at the top
|
||||
of each uIP source file is understood and adhered to.
|
||||
|
||||
3) The lwIP TCP/IP stack the copyright of which is held by the Swedish
|
||||
Institute of Computer Science. Users must ensure the open source license
|
||||
conditions stated at the top of each lwIP source file is understood and
|
||||
adhered to.
|
||||
|
||||
4) Various peripheral driver source files and binaries provided by silicon
|
||||
manufacturers and tool vendors. Permission has been granted by the
|
||||
various copyright holders for these files to be included in the FreeRTOS
|
||||
download. Users must ensure license conditions are adhered to for any
|
||||
use other than compilation of the FreeRTOS demo applications.
|
||||
|
||||
5) The files contained within FreeRTOS\Demo\WizNET_DEMO_TERN_186\tern_code,
|
||||
which are slightly modified versions of code provided by and copyright to
|
||||
Tern Inc.
|
||||
|
||||
Errors and omissions should be reported to Richard Barry, contact details for
|
||||
whom can be obtained from http://www.FreeRTOS.org.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
The GPL license text follows.
|
||||
|
||||
A special exception to the GPL is included to allow you to distribute a
|
||||
combined work that includes FreeRTOS without being obliged to provide
|
||||
the source code for any proprietary components. See the licensing section
|
||||
of http://www.FreeRTOS.org for full details. The exception text is also
|
||||
included at the bottom of this file.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
The standard GPL V2 text:
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
|
@ -401,40 +397,3 @@ consider it more useful to permit linking proprietary applications with the
|
|||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
The FreeRTOS GPL Exception Text:
|
||||
|
||||
Any FreeRTOS source code, whether modified or in it's original release form,
|
||||
or whether in whole or in part, can only be distributed by you under the terms
|
||||
of the GNU General Public License plus this exception. An independent module is
|
||||
a module which is not derived from or based on FreeRTOS.
|
||||
|
||||
Clause 1:
|
||||
|
||||
Linking FreeRTOS statically or dynamically with other modules is making a
|
||||
combined work based on FreeRTOS. Thus, the terms and conditions of the GNU
|
||||
General Public License cover the whole combination.
|
||||
|
||||
As a special exception, the copyright holder of FreeRTOS gives you permission
|
||||
to link FreeRTOS with independent modules that communicate with FreeRTOS
|
||||
solely through the FreeRTOS API interface, regardless of the license terms of
|
||||
these independent modules, and to copy and distribute the resulting combined
|
||||
work under terms of your choice, provided that
|
||||
|
||||
+ Every copy of the combined work is accompanied by a written statement that
|
||||
details to the recipient the version of FreeRTOS used and an offer by yourself
|
||||
to provide the FreeRTOS source code (including any modifications you may have
|
||||
made) should the recipient request it.
|
||||
|
||||
+ The combined work is not itself an RTOS, scheduler, kernel or related product.
|
||||
|
||||
+ The independent modules add significant and primary functionality to FreeRTOS
|
||||
and do not merely extend the existing functionality already present in FreeRTOS.
|
||||
|
||||
Clause 2:
|
||||
|
||||
FreeRTOS may not be used for any competitive or comparative purpose, including the
|
||||
publication of any form of run time or compile time metric, without the express
|
||||
permission of Real Time Engineers Ltd. (this is the norm within the industry and
|
||||
is intended to ensure information accuracy).
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -139,6 +139,16 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co
|
|||
/* A StaticEventGroup_t object must be provided. */
|
||||
configASSERT( pxEventGroupBuffer );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
/* Sanity check that the size of the structure used to declare a
|
||||
variable of type StaticEventGroup_t equals the size of the real
|
||||
event group structure. */
|
||||
volatile size_t xSize = sizeof( StaticEventGroup_t );
|
||||
configASSERT( xSize == sizeof( EventGroup_t ) );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/* The user has provided a statically allocated event group - use it. */
|
||||
pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
|
||||
|
||||
|
@ -602,7 +612,7 @@ BaseType_t xMatchFound = pdFALSE;
|
|||
eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
|
||||
that is was unblocked due to its required bits matching, rather
|
||||
than because it timed out. */
|
||||
( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
}
|
||||
|
||||
/* Move onto the next list item. Note pxListItem->pxNext is not
|
||||
|
@ -633,9 +643,9 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
|
|||
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
|
||||
{
|
||||
/* Unblock the task, returning 0 as the event list is being deleted
|
||||
and cannot therefore have any bits set. */
|
||||
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
|
||||
( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
and cannot therefore have any bits set. */
|
||||
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
|
||||
vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
}
|
||||
|
||||
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -126,6 +126,10 @@ extern "C" {
|
|||
#error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details.
|
||||
#endif
|
||||
|
||||
#if configMAX_PRIORITIES < 1
|
||||
#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_PREEMPTION
|
||||
#error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
|
||||
#endif
|
||||
|
@ -142,10 +146,6 @@ extern "C" {
|
|||
#error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details.
|
||||
#endif
|
||||
|
||||
#ifndef configMAX_PRIORITIES
|
||||
#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_CO_ROUTINES
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#endif
|
||||
|
@ -408,6 +408,14 @@ extern "C" {
|
|||
#define configCHECK_FOR_STACK_OVERFLOW 0
|
||||
#endif
|
||||
|
||||
#ifndef configRECORD_STACK_HIGH_ADDRESS
|
||||
#define configRECORD_STACK_HIGH_ADDRESS 0
|
||||
#endif
|
||||
|
||||
#ifndef configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H
|
||||
#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 0
|
||||
#endif
|
||||
|
||||
/* The following event macros are embedded in the kernel API calls. */
|
||||
|
||||
#ifndef traceMOVED_TASK_TO_READY_STATE
|
||||
|
@ -708,6 +716,10 @@ extern "C" {
|
|||
#define configUSE_TICKLESS_IDLE 0
|
||||
#endif
|
||||
|
||||
#ifndef configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING
|
||||
#define configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( x )
|
||||
#endif
|
||||
|
||||
#ifndef configPRE_SLEEP_PROCESSING
|
||||
#define configPRE_SLEEP_PROCESSING( x )
|
||||
#endif
|
||||
|
@ -724,6 +736,10 @@ extern "C" {
|
|||
#define portTASK_USES_FLOATING_POINT()
|
||||
#endif
|
||||
|
||||
#ifndef portTASK_CALLS_SECURE_FUNCTIONS
|
||||
#define portTASK_CALLS_SECURE_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_TIME_SLICING
|
||||
#define configUSE_TIME_SLICING 1
|
||||
#endif
|
||||
|
@ -782,6 +798,12 @@ extern "C" {
|
|||
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
||||
#endif
|
||||
|
||||
#ifndef configSTACK_DEPTH_TYPE
|
||||
/* Defaults to uint16_t for backward compatibility, but can be overridden
|
||||
in FreeRTOSConfig.h if uint16_t is too restrictive. */
|
||||
#define configSTACK_DEPTH_TYPE uint16_t
|
||||
#endif
|
||||
|
||||
/* Sanity check the configuration. */
|
||||
#if( configUSE_TICKLESS_IDLE != 0 )
|
||||
#if( INCLUDE_vTaskSuspend != 1 )
|
||||
|
@ -797,6 +819,10 @@ extern "C" {
|
|||
#error configUSE_MUTEXES must be set to 1 to use recursive mutexes
|
||||
#endif
|
||||
|
||||
#ifndef configINITIAL_TICK_COUNT
|
||||
#define configINITIAL_TICK_COUNT 0
|
||||
#endif
|
||||
|
||||
#if( portTICK_TYPE_IS_ATOMIC == 0 )
|
||||
/* Either variables of tick type cannot be read atomically, or
|
||||
portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when
|
||||
|
@ -917,7 +943,7 @@ typedef struct xSTATIC_TCB
|
|||
UBaseType_t uxDummy5;
|
||||
void *pxDummy6;
|
||||
uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ];
|
||||
#if ( portSTACK_GROWTH > 0 )
|
||||
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
|
||||
void *pxDummy8;
|
||||
#endif
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
|
@ -945,10 +971,14 @@ typedef struct xSTATIC_TCB
|
|||
uint32_t ulDummy18;
|
||||
uint8_t ucDummy19;
|
||||
#endif
|
||||
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
#if( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
|
||||
uint8_t uxDummy20;
|
||||
#endif
|
||||
|
||||
#if( INCLUDE_xTaskAbortDelay == 1 )
|
||||
uint8_t ucDummy21;
|
||||
#endif
|
||||
|
||||
} StaticTask_t;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,15 +1,38 @@
|
|||
/* Default esp-open-sdk FreeRTOSConfig file.
|
||||
/*
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
You can override settings in here by creating your own
|
||||
FreeRTOSConfig.h file in your program directory.
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
You could just copy this file there and edit it, but it's
|
||||
recommended you instead define whatever you want to override and
|
||||
then use #include_next<FreeRTOSConfig.h> to pick up these defaults.
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
The "blink" example in "examples/blink" provides an example of how
|
||||
to do this.
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
|
||||
For esp-open-rtos, you can override settings in here by creating your own
|
||||
FreeRTOSConfig.h file in your program directory. You could just copy this
|
||||
file there and edit it, but it's recommended you instead define whatever you
|
||||
want to override and then use #include_next<FreeRTOSConfig.h> to pick up
|
||||
these defaults. The "blink" example in "examples/blink" provides an example
|
||||
of how to do this.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __DEFAULT_FREERTOS_CONFIG_H
|
||||
#define __DEFAULT_FREERTOS_CONFIG_H
|
||||
|
||||
|
@ -20,7 +43,7 @@
|
|||
* application requirements.
|
||||
*
|
||||
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
|
@ -47,7 +70,7 @@
|
|||
#define configTICK_RATE_HZ ( ( TickType_t ) 100 )
|
||||
#endif
|
||||
#ifndef configMAX_PRIORITIES
|
||||
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 15 )
|
||||
#define configMAX_PRIORITIES ( 15 )
|
||||
#endif
|
||||
#ifndef configMINIMAL_STACK_SIZE
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short )256 )
|
||||
|
@ -108,6 +131,10 @@
|
|||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_NEWLIB_REENTRANT
|
||||
#define configUSE_NEWLIB_REENTRANT 1
|
||||
#endif
|
||||
|
||||
/* Set the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
#ifndef INCLUDE_vTaskPrioritySet
|
||||
|
@ -144,5 +171,10 @@ to exclude the API function. */
|
|||
#define configENABLE_BACKWARD_COMPATIBILITY 0
|
||||
#endif
|
||||
|
||||
/* Normal assert() semantics without relying on the provision of an assert.h
|
||||
header file. */
|
||||
void vAssertCalled(const char * pcFile, unsigned long ulLine);
|
||||
#define configASSERT(x) if((x) == 0) vAssertCalled(__FILE__, __LINE__);
|
||||
|
||||
#endif /* __DEFAULT_FREERTOS_CONFIG_H */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -205,7 +205,7 @@ typedef struct xMINI_LIST_ITEM MiniListItem_t;
|
|||
typedef struct xLIST
|
||||
{
|
||||
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
configLIST_VOLATILE UBaseType_t uxNumberOfItems;
|
||||
volatile UBaseType_t uxNumberOfItems;
|
||||
ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
|
||||
MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
|
||||
listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -83,6 +83,7 @@
|
|||
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask );
|
||||
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer );
|
||||
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
|
||||
BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
|
||||
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
|
||||
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete );
|
||||
void MPU_vTaskDelay( const TickType_t xTicksToDelay );
|
||||
|
@ -124,7 +125,9 @@ BaseType_t MPU_xTaskGetSchedulerState( void );
|
|||
|
||||
/* MPU versions of queue.h API function. */
|
||||
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition );
|
||||
BaseType_t MPU_xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek );
|
||||
BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait );
|
||||
BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait );
|
||||
BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait );
|
||||
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue );
|
||||
UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue );
|
||||
void MPU_vQueueDelete( QueueHandle_t xQueue );
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -130,7 +130,9 @@ only for ports that are using the MPU. */
|
|||
|
||||
/* Map standard queue.h API functions to the MPU equivalents. */
|
||||
#define xQueueGenericSend MPU_xQueueGenericSend
|
||||
#define xQueueGenericReceive MPU_xQueueGenericReceive
|
||||
#define xQueueReceive MPU_xQueueReceive
|
||||
#define xQueuePeek MPU_xQueuePeek
|
||||
#define xQueueSemaphoreTake MPU_xQueueSemaphoreTake
|
||||
#define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
|
||||
#define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable
|
||||
#define vQueueDelete MPU_vQueueDelete
|
||||
|
@ -177,8 +179,11 @@ only for ports that are using the MPU. */
|
|||
#define xEventGroupSync MPU_xEventGroupSync
|
||||
#define vEventGroupDelete MPU_vEventGroupDelete
|
||||
|
||||
/* Remove the privileged function macro. */
|
||||
/* Remove the privileged function macro, but keep the PRIVILEGED_DATA
|
||||
macro so applications can place data in privileged access sections
|
||||
(useful when using statically allocated objects). */
|
||||
#define PRIVILEGED_FUNCTION
|
||||
#define PRIVILEGED_DATA __attribute__((section("privileged_data")))
|
||||
|
||||
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -696,12 +696,10 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ
|
|||
* <pre>
|
||||
BaseType_t xQueuePeek(
|
||||
QueueHandle_t xQueue,
|
||||
void *pvBuffer,
|
||||
void * const pvBuffer,
|
||||
TickType_t xTicksToWait
|
||||
);</pre>
|
||||
*
|
||||
* This is a macro that calls the xQueueGenericReceive() function.
|
||||
*
|
||||
* Receive an item from a queue without removing the item from the queue.
|
||||
* The item is received by copy so a buffer of adequate size must be
|
||||
* provided. The number of bytes copied into the buffer was defined when
|
||||
|
@ -782,10 +780,10 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ
|
|||
// ... Rest of task code.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueReceive xQueueReceive
|
||||
* \defgroup xQueuePeek xQueuePeek
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE )
|
||||
BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
|
@ -829,8 +827,6 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIV
|
|||
TickType_t xTicksToWait
|
||||
);</pre>
|
||||
*
|
||||
* This is a macro that calls the xQueueGenericReceive() function.
|
||||
*
|
||||
* Receive an item from a queue. The item is received by copy so a buffer of
|
||||
* adequate size must be provided. The number of bytes copied into the buffer
|
||||
* was defined when the queue was created.
|
||||
|
@ -911,106 +907,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIV
|
|||
* \defgroup xQueueReceive xQueueReceive
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE )
|
||||
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
BaseType_t xQueueGenericReceive(
|
||||
QueueHandle_t xQueue,
|
||||
void *pvBuffer,
|
||||
TickType_t xTicksToWait
|
||||
BaseType_t xJustPeek
|
||||
);</pre>
|
||||
*
|
||||
* It is preferred that the macro xQueueReceive() be used rather than calling
|
||||
* this function directly.
|
||||
*
|
||||
* Receive an item from a queue. The item is received by copy so a buffer of
|
||||
* adequate size must be provided. The number of bytes copied into the buffer
|
||||
* was defined when the queue was created.
|
||||
*
|
||||
* This function must not be used in an interrupt service routine. See
|
||||
* xQueueReceiveFromISR for an alternative that can.
|
||||
*
|
||||
* @param xQueue The handle to the queue from which the item is to be
|
||||
* received.
|
||||
*
|
||||
* @param pvBuffer Pointer to the buffer into which the received item will
|
||||
* be copied.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time the task should block
|
||||
* waiting for an item to receive should the queue be empty at the time
|
||||
* of the call. The time is defined in tick periods so the constant
|
||||
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
|
||||
* xQueueGenericReceive() will return immediately if the queue is empty and
|
||||
* xTicksToWait is 0.
|
||||
*
|
||||
* @param xJustPeek When set to true, the item received from the queue is not
|
||||
* actually removed from the queue - meaning a subsequent call to
|
||||
* xQueueReceive() will return the same item. When set to false, the item
|
||||
* being received from the queue is also removed from the queue.
|
||||
*
|
||||
* @return pdTRUE if an item was successfully received from the queue,
|
||||
* otherwise pdFALSE.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
struct AMessage
|
||||
{
|
||||
char ucMessageID;
|
||||
char ucData[ 20 ];
|
||||
} xMessage;
|
||||
|
||||
QueueHandle_t xQueue;
|
||||
|
||||
// Task to create a queue and post a value.
|
||||
void vATask( void *pvParameters )
|
||||
{
|
||||
struct AMessage *pxMessage;
|
||||
|
||||
// Create a queue capable of containing 10 pointers to AMessage structures.
|
||||
// These should be passed by pointer as they contain a lot of data.
|
||||
xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
|
||||
if( xQueue == 0 )
|
||||
{
|
||||
// Failed to create the queue.
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
// Send a pointer to a struct AMessage object. Don't block if the
|
||||
// queue is already full.
|
||||
pxMessage = & xMessage;
|
||||
xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
|
||||
|
||||
// ... Rest of task code.
|
||||
}
|
||||
|
||||
// Task to receive from the queue.
|
||||
void vADifferentTask( void *pvParameters )
|
||||
{
|
||||
struct AMessage *pxRxedMessage;
|
||||
|
||||
if( xQueue != 0 )
|
||||
{
|
||||
// Receive a message on the created queue. Block for 10 ticks if a
|
||||
// message is not immediately available.
|
||||
if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
|
||||
{
|
||||
// pcRxedMessage now points to the struct AMessage variable posted
|
||||
// by vATask.
|
||||
}
|
||||
}
|
||||
|
||||
// ... Rest of task code.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueReceive xQueueReceive
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
|
@ -1560,7 +1457,9 @@ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION
|
|||
QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
|
||||
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
|
||||
QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
|
||||
void* xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* For internal use only. Use xSemaphoreTakeMutexRecursive() or
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -328,7 +328,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
|
|||
* \defgroup xSemaphoreTake xSemaphoreTake
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
|
||||
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
|
@ -392,23 +392,23 @@ typedef QueueHandle_t SemaphoreHandle_t;
|
|||
|
||||
// ...
|
||||
// For some reason due to the nature of the code further calls to
|
||||
// xSemaphoreTakeRecursive() are made on the same mutex. In real
|
||||
// code these would not be just sequential calls as this would make
|
||||
// no sense. Instead the calls are likely to be buried inside
|
||||
// a more complex call structure.
|
||||
// xSemaphoreTakeRecursive() are made on the same mutex. In real
|
||||
// code these would not be just sequential calls as this would make
|
||||
// no sense. Instead the calls are likely to be buried inside
|
||||
// a more complex call structure.
|
||||
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
|
||||
xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
|
||||
|
||||
// The mutex has now been 'taken' three times, so will not be
|
||||
// available to another task until it has also been given back
|
||||
// three times. Again it is unlikely that real code would have
|
||||
// these calls sequentially, but instead buried in a more complex
|
||||
// call structure. This is just for illustrative purposes.
|
||||
// available to another task until it has also been given back
|
||||
// three times. Again it is unlikely that real code would have
|
||||
// these calls sequentially, but instead buried in a more complex
|
||||
// call structure. This is just for illustrative purposes.
|
||||
xSemaphoreGiveRecursive( xMutex );
|
||||
xSemaphoreGiveRecursive( xMutex );
|
||||
xSemaphoreGiveRecursive( xMutex );
|
||||
xSemaphoreGiveRecursive( xMutex );
|
||||
xSemaphoreGiveRecursive( xMutex );
|
||||
|
||||
// Now the mutex can be taken by other tasks.
|
||||
// Now the mutex can be taken by other tasks.
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1154,6 +1154,17 @@ typedef QueueHandle_t SemaphoreHandle_t;
|
|||
*/
|
||||
#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) )
|
||||
|
||||
/**
|
||||
* semphr.h
|
||||
* <pre>TaskHandle_t xSemaphoreGetMutexHolderFromISR( SemaphoreHandle_t xMutex );</pre>
|
||||
*
|
||||
* If xMutex is indeed a mutex type semaphore, return the current mutex holder.
|
||||
* If xMutex is not a mutex type semaphore, or the mutex is available (not held
|
||||
* by a task), return NULL.
|
||||
*
|
||||
*/
|
||||
#define xSemaphoreGetMutexHolderFromISR( xSemaphore ) xQueueGetMutexHolderFromISR( ( xSemaphore ) )
|
||||
|
||||
/**
|
||||
* semphr.h
|
||||
* <pre>UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );</pre>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -160,6 +160,9 @@ typedef struct xTASK_PARAMETERS
|
|||
UBaseType_t uxPriority;
|
||||
StackType_t *puxStackBuffer;
|
||||
MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
|
||||
#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
||||
StaticTask_t * const pxTaskBuffer;
|
||||
#endif
|
||||
} TaskParameters_t;
|
||||
|
||||
/* Used with the uxTaskGetSystemState() function to return the state of each task
|
||||
|
@ -269,7 +272,7 @@ is used in assert() statements. */
|
|||
BaseType_t xTaskCreate(
|
||||
TaskFunction_t pvTaskCode,
|
||||
const char * const pcName,
|
||||
uint16_t usStackDepth,
|
||||
configSTACK_DEPTH_TYPE usStackDepth,
|
||||
void *pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t *pvCreatedTask
|
||||
|
@ -358,11 +361,11 @@ is used in assert() statements. */
|
|||
*/
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const uint16_t usStackDepth,
|
||||
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const configSTACK_DEPTH_TYPE usStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -474,12 +477,12 @@ is used in assert() statements. */
|
|||
*/
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const uint32_t ulStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
StackType_t * const puxStackBuffer,
|
||||
StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
/**
|
||||
|
@ -487,6 +490,8 @@ is used in assert() statements. */
|
|||
*<pre>
|
||||
BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );</pre>
|
||||
*
|
||||
* Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1.
|
||||
*
|
||||
* xTaskCreateRestricted() should only be used in systems that include an MPU
|
||||
* implementation.
|
||||
*
|
||||
|
@ -494,6 +499,9 @@ is used in assert() statements. */
|
|||
* The function parameters define the memory regions and associated access
|
||||
* permissions allocated to the task.
|
||||
*
|
||||
* See xTaskCreateRestrictedStatic() for a version that does not use any
|
||||
* dynamic memory allocation.
|
||||
*
|
||||
* @param pxTaskDefinition Pointer to a structure that contains a member
|
||||
* for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
|
||||
* documentation) plus an optional stack buffer and the memory region
|
||||
|
@ -553,6 +561,94 @@ TaskHandle_t xHandle;
|
|||
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* task. h
|
||||
*<pre>
|
||||
BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );</pre>
|
||||
*
|
||||
* Only available when configSUPPORT_STATIC_ALLOCATION is set to 1.
|
||||
*
|
||||
* xTaskCreateRestrictedStatic() should only be used in systems that include an
|
||||
* MPU implementation.
|
||||
*
|
||||
* Internally, within the FreeRTOS implementation, tasks use two blocks of
|
||||
* memory. The first block is used to hold the task's data structures. The
|
||||
* second block is used by the task as its stack. If a task is created using
|
||||
* xTaskCreateRestricted() then the stack is provided by the application writer,
|
||||
* and the memory used to hold the task's data structure is automatically
|
||||
* dynamically allocated inside the xTaskCreateRestricted() function. If a task
|
||||
* is created using xTaskCreateRestrictedStatic() then the application writer
|
||||
* must provide the memory used to hold the task's data structures too.
|
||||
* xTaskCreateRestrictedStatic() therefore allows a memory protected task to be
|
||||
* created without using any dynamic memory allocation.
|
||||
*
|
||||
* @param pxTaskDefinition Pointer to a structure that contains a member
|
||||
* for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
|
||||
* documentation) plus an optional stack buffer and the memory region
|
||||
* definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure
|
||||
* contains an additional member, which is used to point to a variable of type
|
||||
* StaticTask_t - which is then used to hold the task's data structure.
|
||||
*
|
||||
* @param pxCreatedTask Used to pass back a handle by which the created task
|
||||
* can be referenced.
|
||||
*
|
||||
* @return pdPASS if the task was successfully created and added to a ready
|
||||
* list, otherwise an error code defined in the file projdefs.h
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Create an TaskParameters_t structure that defines the task to be created.
|
||||
// The StaticTask_t variable is only included in the structure when
|
||||
// configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro can
|
||||
// be used to force the variable into the RTOS kernel's privileged data area.
|
||||
static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
|
||||
static const TaskParameters_t xCheckTaskParameters =
|
||||
{
|
||||
vATask, // pvTaskCode - the function that implements the task.
|
||||
"ATask", // pcName - just a text name for the task to assist debugging.
|
||||
100, // usStackDepth - the stack size DEFINED IN WORDS.
|
||||
NULL, // pvParameters - passed into the task function as the function parameters.
|
||||
( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
|
||||
cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
|
||||
|
||||
// xRegions - Allocate up to three separate memory regions for access by
|
||||
// the task, with appropriate access permissions. Different processors have
|
||||
// different memory alignment requirements - refer to the FreeRTOS documentation
|
||||
// for full information.
|
||||
{
|
||||
// Base address Length Parameters
|
||||
{ cReadWriteArray, 32, portMPU_REGION_READ_WRITE },
|
||||
{ cReadOnlyArray, 32, portMPU_REGION_READ_ONLY },
|
||||
{ cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE }
|
||||
}
|
||||
|
||||
&xTaskBuffer; // Holds the task's data structure.
|
||||
};
|
||||
|
||||
int main( void )
|
||||
{
|
||||
TaskHandle_t xHandle;
|
||||
|
||||
// Create a task from the const structure defined above. The task handle
|
||||
// is requested (the second parameter is not NULL) but in this case just for
|
||||
// demonstration purposes as its not actually used.
|
||||
xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
|
||||
|
||||
// Start the scheduler.
|
||||
vTaskStartScheduler();
|
||||
|
||||
// Will only get here if there was insufficient memory to create the idle
|
||||
// and/or timer task.
|
||||
for( ;; );
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
||||
BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* task. h
|
||||
*<pre>
|
||||
|
@ -2141,14 +2237,14 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTi
|
|||
* Removes a task from both the specified event list and the list of blocked
|
||||
* tasks, and places it on a ready queue.
|
||||
*
|
||||
* xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called
|
||||
* xTaskRemoveFromEventList()/vTaskRemoveFromUnorderedEventList() will be called
|
||||
* if either an event occurs to unblock a task, or the block timeout period
|
||||
* expires.
|
||||
*
|
||||
* xTaskRemoveFromEventList() is used when the event list is in task priority
|
||||
* order. It removes the list item from the head of the event list as that will
|
||||
* have the highest priority owning task of all the tasks on the event list.
|
||||
* xTaskRemoveFromUnorderedEventList() is used when the event list is not
|
||||
* vTaskRemoveFromUnorderedEventList() is used when the event list is not
|
||||
* ordered and the event list items hold something other than the owning tasks
|
||||
* priority. In this case the event list item value is updated to the value
|
||||
* passed in the xItemValue parameter.
|
||||
|
@ -2157,7 +2253,7 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTi
|
|||
* making the call, otherwise pdFALSE.
|
||||
*/
|
||||
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION;
|
||||
void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY
|
||||
|
@ -2207,7 +2303,7 @@ BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION;
|
|||
* Raises the priority of the mutex holder to that of the calling task should
|
||||
* the mutex holder have a priority less than the calling task.
|
||||
*/
|
||||
void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
|
||||
BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Set the priority of a task back to its proper priority in the case that it
|
||||
|
@ -2215,6 +2311,16 @@ void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTIO
|
|||
*/
|
||||
BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* If a higher priority task attempting to obtain a mutex caused a lower
|
||||
* priority task to inherit the higher priority task's priority - but the higher
|
||||
* priority task then timed out without obtaining the mutex, then the lower
|
||||
* priority task will disinherit the priority again - but only down as far as
|
||||
* the highest priority task that is still waiting for the mutex (if there were
|
||||
* more than one task waiting for the mutex).
|
||||
*/
|
||||
void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
|
||||
*/
|
||||
|
@ -2258,6 +2364,13 @@ eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION;
|
|||
*/
|
||||
void *pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* For internal use only. Same as vTaskSetTimeOutState(), but without a critial
|
||||
* section.
|
||||
*/
|
||||
void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -75,10 +75,10 @@
|
|||
#error "include FreeRTOS.h must appear in source files before include timers.h"
|
||||
#endif
|
||||
|
||||
/*lint -e537 This headers are only multiply included if the application code
|
||||
/*lint -save -e537 This headers are only multiply included if the application code
|
||||
happens to also be including task.h. */
|
||||
#include "task.h"
|
||||
/*lint +e537 */
|
||||
/*lint -restore */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -266,11 +266,11 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
|
|||
* @endverbatim
|
||||
*/
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
TimerHandle_t xTimerCreate( const char * const pcTimerName,
|
||||
TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const TickType_t xTimerPeriodInTicks,
|
||||
const UBaseType_t uxAutoReload,
|
||||
void * const pvTimerID,
|
||||
TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -396,12 +396,12 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
|
|||
* @endverbatim
|
||||
*/
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
TimerHandle_t xTimerCreateStatic( const char * const pcTimerName,
|
||||
TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const TickType_t xTimerPeriodInTicks,
|
||||
const UBaseType_t uxAutoReload,
|
||||
void * const pvTimerID,
|
||||
TimerCallbackFunction_t pxCallbackFunction,
|
||||
StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
|
@ -73,10 +73,12 @@
|
|||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtensa_ops.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "xtensa_rtos.h"
|
||||
|
||||
unsigned cpu_sr;
|
||||
|
@ -91,6 +93,13 @@ char level1_int_disabled;
|
|||
*/
|
||||
void *xPortSupervisorStackPointer;
|
||||
|
||||
void vAssertCalled(const char * pcFile, unsigned long ulLine)
|
||||
{
|
||||
printf("rtos assert %s %lu\n", pcFile, ulLine);
|
||||
abort();
|
||||
//for (;;);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stack initialization
|
||||
*/
|
||||
|
@ -100,7 +109,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, TaskFunctio
|
|||
portSTACK_TYPE *sp, *tp;
|
||||
|
||||
/* Create interrupt stack frame aligned to 16 byte boundary */
|
||||
sp = (portSTACK_TYPE*) (((uint32_t)(pxTopOfStack+1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);
|
||||
sp = (portSTACK_TYPE*) (((uint32_t)(pxTopOfStack + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);
|
||||
|
||||
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
|
||||
for (tp = sp; tp <= pxTopOfStack; ++tp)
|
||||
|
@ -121,30 +130,29 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, TaskFunctio
|
|||
static int pending_soft_sv;
|
||||
static int pending_maclayer_sv;
|
||||
|
||||
/* PendSV is called in place of vPortYield() to request a supervisor
|
||||
call.
|
||||
|
||||
The portYIELD macro calls pendSV if it's a software request.
|
||||
|
||||
The libpp and libudhcp libraries also call this function, assuming
|
||||
always with arg==2 (but maybe sometimes with arg==1?)
|
||||
|
||||
In the original esp_iot_rtos_sdk implementation, arg was a char. Using an
|
||||
enum is ABI-compatible, though.
|
||||
*/
|
||||
/*
|
||||
* The portYIELD macro calls PendSV with SVC_Software to set a pending interrupt
|
||||
* service callback that allows a task switch, and this occur when interrupts
|
||||
* are enabled which might be after exiting the critical region below.
|
||||
*
|
||||
* The wdev NMI calls this function from pp_post() with SVC_MACLayer to set a
|
||||
* pending interrupt service callback which flushs the queue of messages that
|
||||
* the NMI stashes away. This interrupt will be triggered after the return from
|
||||
* the NMI and when interrupts are enabled. The NMI can not touch the FreeRTOS
|
||||
* queues itself. The NMI must not touch the interrupt masks so that path must
|
||||
* not call vPortEnterCritical and vPortExitCritical.
|
||||
*/
|
||||
void IRAM PendSV(enum SVC_ReqType req)
|
||||
{
|
||||
vPortEnterCritical();
|
||||
|
||||
if(req == SVC_Software)
|
||||
{
|
||||
pending_soft_sv = 1;
|
||||
}
|
||||
else if(req == SVC_MACLayer)
|
||||
pending_maclayer_sv= 1;
|
||||
|
||||
WSR(BIT(INUM_SOFT), interrupt);
|
||||
vPortExitCritical();
|
||||
if (req == SVC_Software) {
|
||||
vPortEnterCritical();
|
||||
pending_soft_sv = 1;
|
||||
WSR(BIT(INUM_SOFT), interrupt);
|
||||
vPortExitCritical();
|
||||
} else if (req == SVC_MACLayer) {
|
||||
pending_maclayer_sv= 1;
|
||||
WSR(BIT(INUM_SOFT), interrupt);
|
||||
}
|
||||
}
|
||||
|
||||
/* This MAC layer ISR handler is defined in libpp.a, and is called
|
||||
|
@ -153,31 +161,24 @@ void IRAM PendSV(enum SVC_ReqType req)
|
|||
*/
|
||||
extern portBASE_TYPE sdk_MacIsrSigPostDefHdl(void);
|
||||
|
||||
void IRAM SV_ISR(void)
|
||||
void IRAM SV_ISR(void *arg)
|
||||
{
|
||||
portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE ;
|
||||
if(pending_maclayer_sv)
|
||||
{
|
||||
xHigherPriorityTaskWoken = sdk_MacIsrSigPostDefHdl();
|
||||
pending_maclayer_sv = 0;
|
||||
}
|
||||
if( xHigherPriorityTaskWoken || pending_soft_sv)
|
||||
{
|
||||
sdk__xt_timer_int1();
|
||||
pending_soft_sv = 0;
|
||||
}
|
||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE ;
|
||||
if (pending_maclayer_sv) {
|
||||
xHigherPriorityTaskWoken = sdk_MacIsrSigPostDefHdl();
|
||||
pending_maclayer_sv = 0;
|
||||
}
|
||||
if (xHigherPriorityTaskWoken || pending_soft_sv) {
|
||||
sdk__xt_timer_int1();
|
||||
pending_soft_sv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void xPortSysTickHandle (void)
|
||||
{
|
||||
//CloseNMI();
|
||||
{
|
||||
if(xTaskIncrementTick() !=pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
}
|
||||
//OpenNMI();
|
||||
if (xTaskIncrementTick() != pdFALSE) {
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -185,11 +186,11 @@ void xPortSysTickHandle (void)
|
|||
*/
|
||||
portBASE_TYPE xPortStartScheduler( void )
|
||||
{
|
||||
_xt_isr_attach(INUM_SOFT, SV_ISR);
|
||||
_xt_isr_attach(INUM_SOFT, SV_ISR, NULL);
|
||||
_xt_isr_unmask(BIT(INUM_SOFT));
|
||||
|
||||
/* Initialize system tick timer interrupt and schedule the first tick. */
|
||||
_xt_isr_attach(INUM_TICK, sdk__xt_timer_int);
|
||||
_xt_isr_attach(INUM_TICK, sdk__xt_timer_int, NULL);
|
||||
_xt_isr_unmask(BIT(INUM_TICK));
|
||||
sdk__xt_tick_timer_init();
|
||||
|
||||
|
@ -221,8 +222,10 @@ size_t xPortGetFreeHeapSize( void )
|
|||
uint32_t brk_val = (uint32_t) sbrk(0);
|
||||
|
||||
intptr_t sp = (intptr_t)xPortSupervisorStackPointer;
|
||||
if(sp == 0) /* scheduler not started */
|
||||
if (sp == 0) {
|
||||
/* scheduler not started */
|
||||
SP(sp);
|
||||
}
|
||||
return sp - brk_val + mi.fordblks;
|
||||
}
|
||||
|
||||
|
@ -233,8 +236,6 @@ void vPortEndScheduler( void )
|
|||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
variable. */
|
||||
static unsigned portBASE_TYPE uxCriticalNesting = 0;
|
||||
|
||||
/* These nested vPortEnter/ExitCritical macros are called by SDK
|
||||
|
@ -243,26 +244,42 @@ static unsigned portBASE_TYPE uxCriticalNesting = 0;
|
|||
* It may be possible to replace the global nesting count variable
|
||||
* with a save/restore of interrupt level, although it's difficult as
|
||||
* the functions have no return value.
|
||||
*
|
||||
* These should not be called from the NMI in regular operation and
|
||||
* the NMI must not touch the interrupt mask, but that might occur in
|
||||
* exceptional paths such as aborts and debug code.
|
||||
*/
|
||||
void IRAM vPortEnterCritical( void )
|
||||
{
|
||||
void IRAM vPortEnterCritical(void) {
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IRAM vPortExitCritical( void )
|
||||
{
|
||||
void IRAM vPortExitCritical(void) {
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
portENABLE_INTERRUPTS();
|
||||
if (uxCriticalNesting == 0)
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
|
||||
/* Backward compatibility with libmain.a and libpp.a and can remove when these are open. */
|
||||
signed portBASE_TYPE xTaskGenericCreate( TaskFunction_t pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, TaskHandle_t *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const MemoryRegion_t * const xRegions )
|
||||
{
|
||||
(void)puxStackBuffer; (void)xRegions;
|
||||
return xTaskCreate( pxTaskCode, (const char * const)pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask);
|
||||
/* Backward compatibility, for the sdk library. */
|
||||
|
||||
signed portBASE_TYPE xTaskGenericCreate(TaskFunction_t pxTaskCode,
|
||||
const signed char * const pcName,
|
||||
unsigned short usStackDepth,
|
||||
void *pvParameters,
|
||||
unsigned portBASE_TYPE uxPriority,
|
||||
TaskHandle_t *pxCreatedTask,
|
||||
portSTACK_TYPE *puxStackBuffer,
|
||||
const MemoryRegion_t * const xRegions) {
|
||||
(void)puxStackBuffer;
|
||||
(void)xRegions;
|
||||
return xTaskCreate(pxTaskCode, (const char * const)pcName, usStackDepth,
|
||||
pvParameters, uxPriority, pxCreatedTask);
|
||||
}
|
||||
|
||||
|
||||
BaseType_t xQueueGenericReceive(QueueHandle_t xQueue, void * const pvBuffer,
|
||||
TickType_t xTicksToWait, const BaseType_t xJustPeeking) {
|
||||
configASSERT(xJustPeeking == 0);
|
||||
return xQueueReceive(xQueue, pvBuffer, xTicksToWait);
|
||||
}
|
||||
|
|
|
@ -1,65 +1,29 @@
|
|||
/*
|
||||
FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that has become a de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly and support the FreeRTOS *
|
||||
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* Thank you! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
>>! NOTE: The modification to the GPL is included to allow you to distribute
|
||||
>>! a combined work that includes FreeRTOS without being obliged to provide
|
||||
>>! the source code for proprietary components outside of the FreeRTOS
|
||||
>>! kernel.
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available from the following
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Having a problem? Start by reading the FAQ "My application does *
|
||||
* not run, what could be wrong?" *
|
||||
* *
|
||||
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||
license and Real Time Engineers Ltd. contact details.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
|
@ -92,16 +56,15 @@ extern "C" {
|
|||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE unsigned portLONG
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portPOINTER_SIZE_TYPE unsigned portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef portBASE_TYPE BaseType_t;
|
||||
typedef unsigned portBASE_TYPE UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffff
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
|
@ -156,6 +119,9 @@ extern unsigned cpu_sr;
|
|||
prefer to _xt_disable_interrupts & _xt_enable_interrupts and store
|
||||
the ps value in a local variable - that approach is recursive-safe
|
||||
and generally better.
|
||||
|
||||
The NMI must not touch the interrupt mask and it should not in
|
||||
regular operation, but there is a guard here just in case.
|
||||
*/
|
||||
inline static __attribute__((always_inline)) void portDISABLE_INTERRUPTS(void)
|
||||
{
|
||||
|
@ -185,6 +151,10 @@ not necessary for to use this port. They are defined so the common demo files
|
|||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
/* FreeRTOS API functions should not be called from the NMI handler. */
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT(sdk_NMIIrqIsOn == 0)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
20
FreeRTOS/Source/portable/readme.txt
Normal file
20
FreeRTOS/Source/portable/readme.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
Each real time kernel port consists of three files that contain the core kernel
|
||||
components and are common to every port, and one or more files that are
|
||||
specific to a particular microcontroller and/or compiler.
|
||||
|
||||
|
||||
+ The FreeRTOS/Source/Portable/MemMang directory contains the five sample
|
||||
memory allocators as described on the http://www.FreeRTOS.org WEB site.
|
||||
|
||||
+ The other directories each contain files specific to a particular
|
||||
microcontroller or compiler, where the directory name denotes the compiler
|
||||
specific files the directory contains.
|
||||
|
||||
|
||||
|
||||
For example, if you are interested in the [compiler] port for the [architecture]
|
||||
microcontroller, then the port specific files are contained in
|
||||
FreeRTOS/Source/Portable/[compiler]/[architecture] directory. If this is the
|
||||
only port you are interested in then all the other directories can be
|
||||
ignored.
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -255,6 +255,16 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseT
|
|||
static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
#if( configUSE_MUTEXES == 1 )
|
||||
/*
|
||||
* If a task waiting for a mutex causes the mutex holder to inherit a
|
||||
* priority, but the waiting task times out, then the holder should
|
||||
* disinherit the priority - but only down to the highest priority of any
|
||||
* other tasks that are waiting for the same mutex. This function returns
|
||||
* that priority.
|
||||
*/
|
||||
static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
@ -374,6 +384,10 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
|
||||
prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
|
||||
}
|
||||
else
|
||||
{
|
||||
traceQUEUE_CREATE_FAILED( ucQueueType );
|
||||
}
|
||||
|
||||
return pxNewQueue;
|
||||
}
|
||||
|
@ -422,6 +436,10 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
|
||||
prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
|
||||
}
|
||||
else
|
||||
{
|
||||
traceQUEUE_CREATE_FAILED( ucQueueType );
|
||||
}
|
||||
|
||||
return pxNewQueue;
|
||||
}
|
||||
|
@ -567,6 +585,32 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseT
|
|||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
|
||||
|
||||
void* xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore )
|
||||
{
|
||||
void *pxReturn;
|
||||
|
||||
configASSERT( xSemaphore );
|
||||
|
||||
/* Mutexes cannot be used in interrupt service routines, so the mutex
|
||||
holder should not change in an ISR, and therefore a critical section is
|
||||
not required here. */
|
||||
if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
|
||||
{
|
||||
pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxReturn = NULL;
|
||||
}
|
||||
|
||||
return pxReturn;
|
||||
} /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_RECURSIVE_MUTEXES == 1 )
|
||||
|
||||
BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
|
||||
|
@ -643,7 +687,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseT
|
|||
}
|
||||
else
|
||||
{
|
||||
xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE );
|
||||
xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait );
|
||||
|
||||
/* pdPASS will only be returned if the mutex was successfully
|
||||
obtained. The calling task may have entered the Blocked state
|
||||
|
@ -855,7 +899,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
{
|
||||
/* The queue was full and a block time was specified so
|
||||
configure the timeout structure. */
|
||||
vTaskSetTimeOutState( &xTimeOut );
|
||||
vTaskInternalSetTimeOutState( &xTimeOut );
|
||||
xEntryTimeSet = pdTRUE;
|
||||
}
|
||||
else
|
||||
|
@ -1127,7 +1171,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
can be assumed there is no mutex holder and no need to determine if
|
||||
priority disinheritance is needed. Simply increase the count of
|
||||
messages (semaphores) available. */
|
||||
pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1;
|
||||
pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;
|
||||
|
||||
/* The event list is not altered if the queue is locked. This will
|
||||
be done when the queue is unlocked later. */
|
||||
|
@ -1234,21 +1278,27 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking )
|
||||
BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )
|
||||
{
|
||||
BaseType_t xEntryTimeSet = pdFALSE;
|
||||
TimeOut_t xTimeOut;
|
||||
int8_t *pcOriginalReadPosition;
|
||||
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||
|
||||
configASSERT( pxQueue );
|
||||
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
|
||||
/* Check the pointer is not NULL. */
|
||||
configASSERT( ( pxQueue ) );
|
||||
|
||||
/* The buffer into which data is received can only be NULL if the data size
|
||||
is zero (so no data is copied into the buffer. */
|
||||
configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
|
||||
|
||||
/* Cannot block if the scheduler is suspended. */
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* This function relaxes the coding standard somewhat to allow return
|
||||
statements within the function itself. This is done in the interest
|
||||
of execution time efficiency. */
|
||||
|
@ -1263,44 +1313,19 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
must be the highest priority task wanting to access the queue. */
|
||||
if( uxMessagesWaiting > ( UBaseType_t ) 0 )
|
||||
{
|
||||
/* Remember the read position in case the queue is only being
|
||||
peeked. */
|
||||
pcOriginalReadPosition = pxQueue->u.pcReadFrom;
|
||||
|
||||
/* Data available, remove one item. */
|
||||
prvCopyDataFromQueue( pxQueue, pvBuffer );
|
||||
traceQUEUE_RECEIVE( pxQueue );
|
||||
pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
|
||||
|
||||
if( xJustPeeking == pdFALSE )
|
||||
/* There is now space in the queue, were any tasks waiting to
|
||||
post to the queue? If so, unblock the highest priority waiting
|
||||
task. */
|
||||
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
|
||||
{
|
||||
traceQUEUE_RECEIVE( pxQueue );
|
||||
|
||||
/* Actually removing data, not just peeking. */
|
||||
pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1;
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
|
||||
{
|
||||
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
|
||||
{
|
||||
/* Record the information required to implement
|
||||
priority inheritance should it become necessary. */
|
||||
pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* configUSE_MUTEXES */
|
||||
|
||||
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
|
||||
{
|
||||
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
|
||||
{
|
||||
queueYIELD_IF_USING_PREEMPTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
queueYIELD_IF_USING_PREEMPTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1309,30 +1334,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
}
|
||||
else
|
||||
{
|
||||
traceQUEUE_PEEK( pxQueue );
|
||||
|
||||
/* The data is not being removed, so reset the read
|
||||
pointer. */
|
||||
pxQueue->u.pcReadFrom = pcOriginalReadPosition;
|
||||
|
||||
/* The data is being left in the queue, so see if there are
|
||||
any other tasks waiting for the data. */
|
||||
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
|
||||
{
|
||||
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
|
||||
{
|
||||
/* The task waiting has a higher priority than this task. */
|
||||
queueYIELD_IF_USING_PREEMPTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
taskEXIT_CRITICAL();
|
||||
|
@ -1352,7 +1354,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
{
|
||||
/* The queue was empty and a block time was specified so
|
||||
configure the timeout structure. */
|
||||
vTaskSetTimeOutState( &xTimeOut );
|
||||
vTaskInternalSetTimeOutState( &xTimeOut );
|
||||
xEntryTimeSet = pdTRUE;
|
||||
}
|
||||
else
|
||||
|
@ -1373,6 +1375,182 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
/* Update the timeout state to see if it has expired yet. */
|
||||
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
|
||||
{
|
||||
/* The timeout has not expired. If the queue is still empty place
|
||||
the task on the list of tasks waiting to receive from the queue. */
|
||||
if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
|
||||
{
|
||||
traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
|
||||
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
|
||||
prvUnlockQueue( pxQueue );
|
||||
if( xTaskResumeAll() == pdFALSE )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The queue contains data again. Loop back to try and read the
|
||||
data. */
|
||||
prvUnlockQueue( pxQueue );
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timed out. If there is no data in the queue exit, otherwise loop
|
||||
back and attempt to read the data. */
|
||||
prvUnlockQueue( pxQueue );
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
|
||||
{
|
||||
traceQUEUE_RECEIVE_FAILED( pxQueue );
|
||||
return errQUEUE_EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait )
|
||||
{
|
||||
BaseType_t xEntryTimeSet = pdFALSE;
|
||||
TimeOut_t xTimeOut;
|
||||
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||
|
||||
#if( configUSE_MUTEXES == 1 )
|
||||
BaseType_t xInheritanceOccurred = pdFALSE;
|
||||
#endif
|
||||
|
||||
/* Check the queue pointer is not NULL. */
|
||||
configASSERT( ( pxQueue ) );
|
||||
|
||||
/* Check this really is a semaphore, in which case the item size will be
|
||||
0. */
|
||||
configASSERT( pxQueue->uxItemSize == 0 );
|
||||
|
||||
/* Cannot block if the scheduler is suspended. */
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* This function relaxes the coding standard somewhat to allow return
|
||||
statements within the function itself. This is done in the interest
|
||||
of execution time efficiency. */
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Semaphores are queues with an item size of 0, and where the
|
||||
number of messages in the queue is the semaphore's count value. */
|
||||
const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;
|
||||
|
||||
/* Is there data in the queue now? To be running the calling task
|
||||
must be the highest priority task wanting to access the queue. */
|
||||
if( uxSemaphoreCount > ( UBaseType_t ) 0 )
|
||||
{
|
||||
traceQUEUE_RECEIVE( pxQueue );
|
||||
|
||||
/* Semaphores are queues with a data size of zero and where the
|
||||
messages waiting is the semaphore's count. Reduce the count. */
|
||||
pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1;
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
|
||||
{
|
||||
/* Record the information required to implement
|
||||
priority inheritance should it become necessary. */
|
||||
pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* configUSE_MUTEXES */
|
||||
|
||||
/* Check to see if other tasks are blocked waiting to give the
|
||||
semaphore, and if so, unblock the highest priority such task. */
|
||||
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
|
||||
{
|
||||
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
|
||||
{
|
||||
queueYIELD_IF_USING_PREEMPTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
taskEXIT_CRITICAL();
|
||||
return pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( xTicksToWait == ( TickType_t ) 0 )
|
||||
{
|
||||
/* For inheritance to have occurred there must have been an
|
||||
initial timeout, and an adjusted timeout cannot become 0, as
|
||||
if it were 0 the function would have exited. */
|
||||
#if( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
configASSERT( xInheritanceOccurred == pdFALSE );
|
||||
}
|
||||
#endif /* configUSE_MUTEXES */
|
||||
|
||||
/* The semaphore count was 0 and no block time is specified
|
||||
(or the block time has expired) so exit now. */
|
||||
taskEXIT_CRITICAL();
|
||||
traceQUEUE_RECEIVE_FAILED( pxQueue );
|
||||
return errQUEUE_EMPTY;
|
||||
}
|
||||
else if( xEntryTimeSet == pdFALSE )
|
||||
{
|
||||
/* The semaphore count was 0 and a block time was specified
|
||||
so configure the timeout structure ready to block. */
|
||||
vTaskInternalSetTimeOutState( &xTimeOut );
|
||||
xEntryTimeSet = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Entry time was already set. */
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
/* Interrupts and other tasks can give to and take from the semaphore
|
||||
now the critical section has been exited. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
prvLockQueue( pxQueue );
|
||||
|
||||
/* Update the timeout state to see if it has expired yet. */
|
||||
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
|
||||
{
|
||||
/* A block time is specified and not expired. If the semaphore
|
||||
count is 0 then enter the Blocked state to wait for a semaphore to
|
||||
become available. As semaphores are implemented with queues the
|
||||
queue being empty is equivalent to the semaphore count being 0. */
|
||||
if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
|
||||
{
|
||||
traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
|
||||
|
@ -1383,7 +1561,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
|
||||
xInheritanceOccurred = xTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
|
@ -1407,13 +1585,193 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Try again. */
|
||||
/* There was no timeout and the semaphore count was not 0, so
|
||||
attempt to take the semaphore again. */
|
||||
prvUnlockQueue( pxQueue );
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timed out. */
|
||||
prvUnlockQueue( pxQueue );
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
/* If the semaphore count is 0 exit now as the timeout has
|
||||
expired. Otherwise return to attempt to take the semaphore that is
|
||||
known to be available. As semaphores are implemented by queues the
|
||||
queue being empty is equivalent to the semaphore count being 0. */
|
||||
if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
|
||||
{
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
/* xInheritanceOccurred could only have be set if
|
||||
pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to
|
||||
test the mutex type again to check it is actually a mutex. */
|
||||
if( xInheritanceOccurred != pdFALSE )
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
UBaseType_t uxHighestWaitingPriority;
|
||||
|
||||
/* This task blocking on the mutex caused another
|
||||
task to inherit this task's priority. Now this task
|
||||
has timed out the priority should be disinherited
|
||||
again, but only as low as the next highest priority
|
||||
task that is waiting for the same mutex. */
|
||||
uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue );
|
||||
vTaskPriorityDisinheritAfterTimeout( ( void * ) pxQueue->pxMutexHolder, uxHighestWaitingPriority );
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
#endif /* configUSE_MUTEXES */
|
||||
|
||||
traceQUEUE_RECEIVE_FAILED( pxQueue );
|
||||
return errQUEUE_EMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )
|
||||
{
|
||||
BaseType_t xEntryTimeSet = pdFALSE;
|
||||
TimeOut_t xTimeOut;
|
||||
int8_t *pcOriginalReadPosition;
|
||||
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||
|
||||
/* Check the pointer is not NULL. */
|
||||
configASSERT( ( pxQueue ) );
|
||||
|
||||
/* The buffer into which data is received can only be NULL if the data size
|
||||
is zero (so no data is copied into the buffer. */
|
||||
configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
|
||||
|
||||
/* Cannot block if the scheduler is suspended. */
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* This function relaxes the coding standard somewhat to allow return
|
||||
statements within the function itself. This is done in the interest
|
||||
of execution time efficiency. */
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
|
||||
|
||||
/* Is there data in the queue now? To be running the calling task
|
||||
must be the highest priority task wanting to access the queue. */
|
||||
if( uxMessagesWaiting > ( UBaseType_t ) 0 )
|
||||
{
|
||||
/* Remember the read position so it can be reset after the data
|
||||
is read from the queue as this function is only peeking the
|
||||
data, not removing it. */
|
||||
pcOriginalReadPosition = pxQueue->u.pcReadFrom;
|
||||
|
||||
prvCopyDataFromQueue( pxQueue, pvBuffer );
|
||||
traceQUEUE_PEEK( pxQueue );
|
||||
|
||||
/* The data is not being removed, so reset the read pointer. */
|
||||
pxQueue->u.pcReadFrom = pcOriginalReadPosition;
|
||||
|
||||
/* The data is being left in the queue, so see if there are
|
||||
any other tasks waiting for the data. */
|
||||
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
|
||||
{
|
||||
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
|
||||
{
|
||||
/* The task waiting has a higher priority than this task. */
|
||||
queueYIELD_IF_USING_PREEMPTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
taskEXIT_CRITICAL();
|
||||
return pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( xTicksToWait == ( TickType_t ) 0 )
|
||||
{
|
||||
/* The queue was empty and no block time is specified (or
|
||||
the block time has expired) so leave now. */
|
||||
taskEXIT_CRITICAL();
|
||||
traceQUEUE_RECEIVE_FAILED( pxQueue );
|
||||
return errQUEUE_EMPTY;
|
||||
}
|
||||
else if( xEntryTimeSet == pdFALSE )
|
||||
{
|
||||
/* The queue was empty and a block time was specified so
|
||||
configure the timeout structure ready to enter the blocked
|
||||
state. */
|
||||
vTaskInternalSetTimeOutState( &xTimeOut );
|
||||
xEntryTimeSet = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Entry time was already set. */
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
/* Interrupts and other tasks can send to and receive from the queue
|
||||
now the critical section has been exited. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
prvLockQueue( pxQueue );
|
||||
|
||||
/* Update the timeout state to see if it has expired yet. */
|
||||
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
|
||||
{
|
||||
/* Timeout has not expired yet, check to see if there is data in the
|
||||
queue now, and if not enter the Blocked state to wait for data. */
|
||||
if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
|
||||
{
|
||||
traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
|
||||
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
|
||||
prvUnlockQueue( pxQueue );
|
||||
if( xTaskResumeAll() == pdFALSE )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is data in the queue now, so don't enter the blocked
|
||||
state, instead return to try and obtain the data. */
|
||||
prvUnlockQueue( pxQueue );
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The timeout has expired. If there is still no data in the queue
|
||||
exit, otherwise go back and try to read the data again. */
|
||||
prvUnlockQueue( pxQueue );
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
|
@ -1468,7 +1826,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
|
||||
|
||||
prvCopyDataFromQueue( pxQueue, pvBuffer );
|
||||
pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1;
|
||||
pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
|
||||
|
||||
/* If the queue is locked the event list will not be modified.
|
||||
Instead update the lock count so the task that unlocks the queue
|
||||
|
@ -1694,6 +2052,33 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
|||
#endif /* configUSE_TRACE_FACILITY */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_MUTEXES == 1 )
|
||||
|
||||
static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue )
|
||||
{
|
||||
UBaseType_t uxHighestPriorityOfWaitingTasks;
|
||||
|
||||
/* If a task waiting for a mutex causes the mutex holder to inherit a
|
||||
priority, but the waiting task times out, then the holder should
|
||||
disinherit the priority - but only down to the highest priority of any
|
||||
other tasks that are waiting for the same mutex. For this purpose,
|
||||
return the priority of the highest priority task that is waiting for the
|
||||
mutex. */
|
||||
if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0 )
|
||||
{
|
||||
uxHighestPriorityOfWaitingTasks = configMAX_PRIORITIES - listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY;
|
||||
}
|
||||
|
||||
return uxHighestPriorityOfWaitingTasks;
|
||||
}
|
||||
|
||||
#endif /* configUSE_MUTEXES */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
|
||||
{
|
||||
BaseType_t xReturn = pdFALSE;
|
||||
|
@ -1767,7 +2152,7 @@ UBaseType_t uxMessagesWaiting;
|
|||
}
|
||||
}
|
||||
|
||||
pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1;
|
||||
pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
@ -2316,7 +2701,7 @@ BaseType_t xReturn;
|
|||
}
|
||||
|
||||
return pcReturn;
|
||||
}
|
||||
} /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */
|
||||
|
||||
#endif /* configQUEUE_REGISTRY_SIZE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -2395,7 +2780,7 @@ BaseType_t xReturn;
|
|||
{
|
||||
QueueSetHandle_t pxQueue;
|
||||
|
||||
pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( Queue_t * ), queueQUEUE_TYPE_SET );
|
||||
pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET );
|
||||
|
||||
return pxQueue;
|
||||
}
|
||||
|
@ -2478,7 +2863,7 @@ BaseType_t xReturn;
|
|||
{
|
||||
QueueSetMemberHandle_t xReturn = NULL;
|
||||
|
||||
( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
|
||||
( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
Each real time kernel port consists of three files that contain the core kernel
|
||||
components and are common to every port, and one or more files that are
|
||||
specific to a particular microcontroller and or compiler.
|
||||
components and are common to every port, and one or more files that are
|
||||
specific to a particular microcontroller and/or compiler.
|
||||
|
||||
+ The FreeRTOS/Source directory contains the three files that are common to
|
||||
every port - list.c, queue.c and tasks.c. The kernel is contained within these
|
||||
three files. croutine.c implements the optional co-routine functionality - which
|
||||
is normally only used on very memory limited systems.
|
||||
|
||||
+ The FreeRTOS/Source/Portable directory contains the files that are specific to
|
||||
a particular microcontroller and or compiler.
|
||||
+ The FreeRTOS/Source/Portable/MemMang directory contains the five sample
|
||||
memory allocators as described on the http://www.FreeRTOS.org WEB site.
|
||||
|
||||
+ The FreeRTOS/Source/include directory contains the real time kernel header
|
||||
files.
|
||||
+ The other directories each contain files specific to a particular
|
||||
microcontroller or compiler, where the directory name denotes the compiler
|
||||
specific files the directory contains.
|
||||
|
||||
|
||||
|
||||
For example, if you are interested in the [compiler] port for the [architecture]
|
||||
microcontroller, then the port specific files are contained in
|
||||
FreeRTOS/Source/Portable/[compiler]/[architecture] directory. If this is the
|
||||
only port you are interested in then all the other directories can be
|
||||
ignored.
|
||||
|
||||
See the readme file in the FreeRTOS/Source/Portable directory for more
|
||||
information.
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -131,12 +131,23 @@ made to free the RAM that was allocated statically.
|
|||
tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
|
||||
task to be created using either statically or dynamically allocated RAM. Note
|
||||
that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
|
||||
a statically allocated stack and a dynamically allocated TCB. */
|
||||
#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
|
||||
a statically allocated stack and a dynamically allocated TCB.
|
||||
!!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is
|
||||
changed then the definition of StaticTask_t must also be updated. */
|
||||
#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
|
||||
#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
|
||||
#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
|
||||
|
||||
/* If any of the following are set then task stacks are filled with a known
|
||||
value so the high water mark can be determined. If none of the following are
|
||||
set then don't fill the stack so there is no unnecessary dependency on memset. */
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
|
||||
#define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1
|
||||
#else
|
||||
#define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros used by vListTask to indicate which state a task is in.
|
||||
*/
|
||||
|
@ -153,6 +164,12 @@ a statically allocated stack and a dynamically allocated TCB. */
|
|||
#define static
|
||||
#endif
|
||||
|
||||
/* The name allocated to the Idle task. This can be overridden by defining
|
||||
configIDLE_TASK_NAME in FreeRTOSConfig.h. */
|
||||
#ifndef configIDLE_TASK_NAME
|
||||
#define configIDLE_TASK_NAME "IDLE"
|
||||
#endif
|
||||
|
||||
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
|
||||
|
||||
/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
|
||||
|
@ -304,8 +321,8 @@ typedef struct tskTaskControlBlock
|
|||
StackType_t *pxStack; /*< Points to the start of the stack. */
|
||||
char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
|
||||
#if ( portSTACK_GROWTH > 0 )
|
||||
StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
|
||||
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
|
||||
StackType_t *pxEndOfStack; /*< Points to the highest valid address for the stack. */
|
||||
#endif
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
|
@ -327,7 +344,7 @@ typedef struct tskTaskControlBlock
|
|||
#endif
|
||||
|
||||
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
|
||||
void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
|
||||
void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
|
||||
#endif
|
||||
|
||||
#if( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
|
@ -352,7 +369,7 @@ typedef struct tskTaskControlBlock
|
|||
|
||||
/* See the comments above the definition of
|
||||
tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
|
||||
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
|
||||
#endif
|
||||
|
||||
|
@ -366,8 +383,8 @@ typedef struct tskTaskControlBlock
|
|||
below to enable the use of older kernel aware debuggers. */
|
||||
typedef tskTCB TCB_t;
|
||||
|
||||
/*lint -e956 A manual analysis and inspection has been used to determine which
|
||||
static variables must be declared volatile. */
|
||||
/*lint -save -e956 A manual analysis and inspection has been used to determine
|
||||
which static variables must be declared volatile. */
|
||||
|
||||
PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
|
||||
|
||||
|
@ -394,7 +411,7 @@ PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been r
|
|||
|
||||
/* Other file private variables. --------------------------------*/
|
||||
PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
|
||||
PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
|
||||
PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
|
||||
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
|
||||
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
|
||||
PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
|
||||
|
@ -421,21 +438,27 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t
|
|||
|
||||
#endif
|
||||
|
||||
/*lint +e956 */
|
||||
/*lint -restore */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Callback function prototypes. --------------------------*/
|
||||
#if( configCHECK_FOR_STACK_OVERFLOW > 0 )
|
||||
|
||||
extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
|
||||
|
||||
#endif
|
||||
|
||||
#if( configUSE_TICK_HOOK > 0 )
|
||||
|
||||
extern void vApplicationTickHook( void );
|
||||
|
||||
#endif
|
||||
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
|
||||
extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
|
||||
|
||||
#endif
|
||||
|
||||
/* File private functions. --------------------------------*/
|
||||
|
@ -446,7 +469,9 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t
|
|||
* is in any other state.
|
||||
*/
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* INCLUDE_vTaskSuspend */
|
||||
|
||||
/*
|
||||
|
@ -565,13 +590,13 @@ static void prvResetNextTaskUnblockTime( void );
|
|||
* dynamically to fill in the structure's members.
|
||||
*/
|
||||
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const uint32_t ulStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t * const pxCreatedTask,
|
||||
TCB_t *pxNewTCB,
|
||||
const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Called after a new task has been created and initialised to place the task
|
||||
|
@ -579,17 +604,28 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|||
*/
|
||||
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* freertos_tasks_c_additions_init() should only be called if the user definable
|
||||
* macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
|
||||
* called by the function.
|
||||
*/
|
||||
#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
|
||||
|
||||
static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
|
||||
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const uint32_t ulStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
StackType_t * const puxStackBuffer,
|
||||
StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
StaticTask_t * const pxTaskBuffer )
|
||||
{
|
||||
TCB_t *pxNewTCB;
|
||||
TaskHandle_t xReturn;
|
||||
|
@ -597,6 +633,17 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
configASSERT( puxStackBuffer != NULL );
|
||||
configASSERT( pxTaskBuffer != NULL );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
/* Sanity check that the size of the structure used to declare a
|
||||
variable of type StaticTask_t equals the size of the real task
|
||||
structure. */
|
||||
volatile size_t xSize = sizeof( StaticTask_t );
|
||||
configASSERT( xSize == sizeof( TCB_t ) );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
|
||||
if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
|
||||
{
|
||||
/* The memory used for the task's TCB and stack are passed into this
|
||||
|
@ -604,7 +651,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
|
||||
pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
|
||||
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
|
||||
{
|
||||
/* Tasks can be created statically or dynamically, so note this
|
||||
task was created statically in case the task is later deleted. */
|
||||
|
@ -626,7 +673,53 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
#endif /* SUPPORT_STATIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( portUSING_MPU_WRAPPERS == 1 )
|
||||
#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
||||
|
||||
BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
|
||||
{
|
||||
TCB_t *pxNewTCB;
|
||||
BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||
|
||||
configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
|
||||
configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
|
||||
|
||||
if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
|
||||
{
|
||||
/* Allocate space for the TCB. Where the memory comes from depends
|
||||
on the implementation of the port malloc function and whether or
|
||||
not static allocation is being used. */
|
||||
pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
|
||||
|
||||
/* Store the stack location in the TCB. */
|
||||
pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
|
||||
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
|
||||
{
|
||||
/* Tasks can be created statically or dynamically, so note this
|
||||
task was created statically in case the task is later deleted. */
|
||||
pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
|
||||
}
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
|
||||
prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
|
||||
pxTaskDefinition->pcName,
|
||||
( uint32_t ) pxTaskDefinition->usStackDepth,
|
||||
pxTaskDefinition->pvParameters,
|
||||
pxTaskDefinition->uxPriority,
|
||||
pxCreatedTask, pxNewTCB,
|
||||
pxTaskDefinition->xRegions );
|
||||
|
||||
prvAddNewTaskToReadyList( pxNewTCB );
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) )
|
||||
|
||||
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
|
||||
{
|
||||
|
@ -674,11 +767,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
|
||||
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const uint16_t usStackDepth,
|
||||
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const configSTACK_DEPTH_TYPE usStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
TaskHandle_t * const pxCreatedTask )
|
||||
{
|
||||
TCB_t *pxNewTCB;
|
||||
BaseType_t xReturn;
|
||||
|
@ -741,7 +834,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
|
||||
if( pxNewTCB != NULL )
|
||||
{
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
|
||||
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
|
||||
{
|
||||
/* Tasks can be created statically or dynamically, so note this
|
||||
task was created dynamically in case it is later deleted. */
|
||||
|
@ -765,13 +858,13 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
||||
const char * const pcName,
|
||||
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const uint32_t ulStackDepth,
|
||||
void * const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t * const pxCreatedTask,
|
||||
TCB_t *pxNewTCB,
|
||||
const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const MemoryRegion_t * const xRegions )
|
||||
{
|
||||
StackType_t *pxTopOfStack;
|
||||
UBaseType_t x;
|
||||
|
@ -791,12 +884,12 @@ UBaseType_t x;
|
|||
#endif /* portUSING_MPU_WRAPPERS == 1 */
|
||||
|
||||
/* Avoid dependency on memset() if it is not required. */
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
|
||||
#if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
|
||||
{
|
||||
/* Fill the stack with a known value to assist debugging. */
|
||||
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
|
||||
}
|
||||
#endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
|
||||
#endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
|
||||
|
||||
/* Calculate the top of stack address. This depends on whether the stack
|
||||
grows from high memory to low (as per the 80x86) or vice versa.
|
||||
|
@ -809,6 +902,14 @@ UBaseType_t x;
|
|||
|
||||
/* Check the alignment of the calculated top of stack is correct. */
|
||||
configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
|
||||
|
||||
#if( configRECORD_STACK_HIGH_ADDRESS == 1 )
|
||||
{
|
||||
/* Also record the stack's high address, which may assist
|
||||
debugging. */
|
||||
pxNewTCB->pxEndOfStack = pxTopOfStack;
|
||||
}
|
||||
#endif /* configRECORD_STACK_HIGH_ADDRESS */
|
||||
}
|
||||
#else /* portSTACK_GROWTH */
|
||||
{
|
||||
|
@ -936,7 +1037,7 @@ UBaseType_t x;
|
|||
/* Initialize the TCB stack to look as if the task was already running,
|
||||
but had been interrupted by the scheduler. The return address is set
|
||||
to the start of the task function. Once the stack has been initialised
|
||||
the top of stack variable is updated. */
|
||||
the top of stack variable is updated. */
|
||||
#if( portUSING_MPU_WRAPPERS == 1 )
|
||||
{
|
||||
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
|
||||
|
@ -1515,14 +1616,14 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
|
|||
}
|
||||
|
||||
/* If the task is in the blocked or suspended list we need do
|
||||
nothing more than change it's priority variable. However, if
|
||||
nothing more than change its priority variable. However, if
|
||||
the task is in a ready list it needs to be removed and placed
|
||||
in the list appropriate to its new priority. */
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
|
||||
{
|
||||
/* The task is currently in its ready list - remove before adding
|
||||
it to it's new ready list. As we are in a critical section we
|
||||
can do this even if the scheduler is suspended. */
|
||||
/* The task is currently in its ready list - remove before
|
||||
adding it to it's new ready list. As we are in a critical
|
||||
section we can do this even if the scheduler is suspended. */
|
||||
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
||||
{
|
||||
/* It is known that the task is in its ready list so
|
||||
|
@ -1597,6 +1698,17 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
|
|||
}
|
||||
|
||||
vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
|
||||
|
||||
#if( configUSE_TASK_NOTIFICATIONS == 1 )
|
||||
{
|
||||
if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION )
|
||||
{
|
||||
/* The task was blocked to wait for a notification, but is
|
||||
now suspended, so no notification was received. */
|
||||
pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
|
@ -1672,7 +1784,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
|
|||
{
|
||||
/* Is it in the suspended list because it is in the Suspended
|
||||
state, or because is is blocked with no timeout? */
|
||||
if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
|
||||
if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
@ -1716,12 +1828,12 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
|
|||
{
|
||||
traceTASK_RESUME( pxTCB );
|
||||
|
||||
/* As we are in a critical section we can access the ready
|
||||
lists even if the scheduler is suspended. */
|
||||
/* The ready list can be accessed even if the scheduler is
|
||||
suspended because this is inside a critical section. */
|
||||
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
|
||||
prvAddTaskToReadyList( pxTCB );
|
||||
|
||||
/* We may have just resumed a higher priority task. */
|
||||
/* A higher priority task may have just been resumed. */
|
||||
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
|
||||
{
|
||||
/* This yield may not cause the task just resumed to run,
|
||||
|
@ -1838,9 +1950,9 @@ BaseType_t xReturn;
|
|||
address of the RAM then create the idle task. */
|
||||
vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
|
||||
xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,
|
||||
"IDLE",
|
||||
configIDLE_TASK_NAME,
|
||||
ulIdleTaskStackSize,
|
||||
( void * ) NULL,
|
||||
( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */
|
||||
( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
|
||||
pxIdleTaskStackBuffer,
|
||||
pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
||||
|
@ -1858,7 +1970,8 @@ BaseType_t xReturn;
|
|||
{
|
||||
/* The Idle task is being created using dynamically allocated RAM. */
|
||||
xReturn = xTaskCreate( prvIdleTask,
|
||||
"IDLE", configMINIMAL_STACK_SIZE,
|
||||
configIDLE_TASK_NAME,
|
||||
configMINIMAL_STACK_SIZE,
|
||||
( void * ) NULL,
|
||||
( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
|
||||
&xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
|
||||
|
@ -1880,6 +1993,15 @@ BaseType_t xReturn;
|
|||
|
||||
if( xReturn == pdPASS )
|
||||
{
|
||||
/* freertos_tasks_c_additions_init() should only be called if the user
|
||||
definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
|
||||
the only macro called by the function. */
|
||||
#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
|
||||
{
|
||||
freertos_tasks_c_additions_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Interrupts are turned off here, to ensure a tick does not occur
|
||||
before or during the call to xPortStartScheduler(). The stacks of
|
||||
the created tasks contain a status word with interrupts switched on
|
||||
|
@ -1901,7 +2023,10 @@ BaseType_t xReturn;
|
|||
|
||||
/* If configGENERATE_RUN_TIME_STATS is defined then the following
|
||||
macro must be defined to configure the timer/counter used to generate
|
||||
the run time counter time base. */
|
||||
the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS
|
||||
is set to 0 and the following line fails to build then ensure you do not
|
||||
have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
|
||||
FreeRTOSConfig.h file. */
|
||||
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
|
||||
|
||||
/* Setting up the timer tick is hardware specific and thus in the
|
||||
|
@ -2427,7 +2552,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
|
|||
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
|
||||
{
|
||||
TCB_t *pxTCB = ( TCB_t * ) xTask;
|
||||
BaseType_t xReturn = pdFALSE;
|
||||
BaseType_t xReturn;
|
||||
|
||||
configASSERT( pxTCB );
|
||||
|
||||
|
@ -2437,6 +2562,8 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
|
|||
it is actually in the Blocked state. */
|
||||
if( eTaskGetState( xTask ) == eBlocked )
|
||||
{
|
||||
xReturn = pdPASS;
|
||||
|
||||
/* Remove the reference to the task from the blocked list. An
|
||||
interrupt won't touch the xStateListItem because the
|
||||
scheduler is suspended. */
|
||||
|
@ -2485,10 +2612,10 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
|
|||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
}
|
||||
xTaskResumeAll();
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
@ -2510,13 +2637,13 @@ BaseType_t xSwitchRequired = pdFALSE;
|
|||
{
|
||||
/* Minor optimisation. The tick count cannot change in this
|
||||
block. */
|
||||
const TickType_t xConstTickCount = xTickCount + 1;
|
||||
const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
|
||||
|
||||
/* Increment the RTOS tick, switching the delayed and overflowed
|
||||
delayed lists if it wraps to 0. */
|
||||
xTickCount = xConstTickCount;
|
||||
|
||||
if( xConstTickCount == ( TickType_t ) 0U )
|
||||
if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
|
||||
{
|
||||
taskSWITCH_DELAYED_LISTS();
|
||||
}
|
||||
|
@ -2959,10 +3086,9 @@ BaseType_t xReturn;
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
|
||||
void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
|
||||
{
|
||||
TCB_t *pxUnblockedTCB;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
|
||||
the event flags implementation. */
|
||||
|
@ -2985,28 +3111,30 @@ BaseType_t xReturn;
|
|||
|
||||
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
|
||||
{
|
||||
/* Return true if the task removed from the event list has
|
||||
a higher priority than the calling task. This allows
|
||||
the calling task to know if it should force a context
|
||||
switch now. */
|
||||
xReturn = pdTRUE;
|
||||
|
||||
/* Mark that a yield is pending in case the user is not using the
|
||||
"xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
|
||||
/* The unblocked task has a priority above that of the calling task, so
|
||||
a context switch is required. This function is called with the
|
||||
scheduler suspended so xYieldPending is set so the context switch
|
||||
occurs immediately that the scheduler is resumed (unsuspended). */
|
||||
xYieldPending = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
|
||||
{
|
||||
configASSERT( pxTimeOut );
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
pxTimeOut->xOverflowCount = xNumOfOverflows;
|
||||
pxTimeOut->xTimeOnEntering = xTickCount;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
|
||||
{
|
||||
/* For internal use only as it does not use a critical section. */
|
||||
pxTimeOut->xOverflowCount = xNumOfOverflows;
|
||||
pxTimeOut->xTimeOnEntering = xTickCount;
|
||||
}
|
||||
|
@ -3023,6 +3151,7 @@ BaseType_t xReturn;
|
|||
{
|
||||
/* Minor optimisation. The tick count cannot change in this block. */
|
||||
const TickType_t xConstTickCount = xTickCount;
|
||||
const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
|
||||
|
||||
#if( INCLUDE_xTaskAbortDelay == 1 )
|
||||
if( pxCurrentTCB->ucDelayAborted != pdFALSE )
|
||||
|
@ -3055,11 +3184,11 @@ BaseType_t xReturn;
|
|||
was called. */
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
|
||||
else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
|
||||
{
|
||||
/* Not a genuine timeout. Adjust parameters for time remaining. */
|
||||
*pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
|
||||
vTaskSetTimeOutState( pxTimeOut );
|
||||
*pxTicksToWait -= xElapsedTime;
|
||||
vTaskInternalSetTimeOutState( pxTimeOut );
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
|
@ -3136,6 +3265,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
|
|||
/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
|
||||
SCHEDULER IS STARTED. **/
|
||||
|
||||
/* In case a task that has a secure context deletes itself, in which case
|
||||
the idle task is responsible for deleting the task's secure context, if
|
||||
any. */
|
||||
portTASK_CALLS_SECURE_FUNCTIONS();
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* See if any tasks have deleted themselves - if so then the idle task
|
||||
|
@ -3212,6 +3346,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
|
|||
configASSERT( xNextTaskUnblockTime >= xTickCount );
|
||||
xExpectedIdleTime = prvGetExpectedIdleTime();
|
||||
|
||||
/* Define the following macro to set xExpectedIdleTime to 0
|
||||
if the application does not want
|
||||
portSUPPRESS_TICKS_AND_SLEEP() to be called. */
|
||||
configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||
|
||||
if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
|
||||
{
|
||||
traceLOW_POWER_IDLE_BEGIN();
|
||||
|
@ -3369,37 +3508,22 @@ static void prvCheckTasksWaitingTermination( void )
|
|||
|
||||
#if ( INCLUDE_vTaskDelete == 1 )
|
||||
{
|
||||
BaseType_t xListIsEmpty;
|
||||
TCB_t *pxTCB;
|
||||
|
||||
/* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
|
||||
too often in the idle task. */
|
||||
/* uxDeletedTasksWaitingCleanUp is used to prevent vTaskSuspendAll()
|
||||
being called too often in the idle task. */
|
||||
while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
|
||||
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
|
||||
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
|
||||
--uxCurrentNumberOfTasks;
|
||||
--uxDeletedTasksWaitingCleanUp;
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
if( xListIsEmpty == pdFALSE )
|
||||
{
|
||||
TCB_t *pxTCB;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
|
||||
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
|
||||
--uxCurrentNumberOfTasks;
|
||||
--uxDeletedTasksWaitingCleanUp;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
prvDeleteTCB( pxTCB );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
prvDeleteTCB( pxTCB );
|
||||
}
|
||||
}
|
||||
#endif /* INCLUDE_vTaskDelete */
|
||||
|
@ -3421,25 +3545,6 @@ static void prvCheckTasksWaitingTermination( void )
|
|||
pxTaskStatus->pxStackBase = pxTCB->pxStack;
|
||||
pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
{
|
||||
/* If the task is in the suspended list then there is a chance it is
|
||||
actually just blocked indefinitely - so really it should be reported as
|
||||
being in the Blocked state. */
|
||||
if( pxTaskStatus->eCurrentState == eSuspended )
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
||||
{
|
||||
pxTaskStatus->eCurrentState = eBlocked;
|
||||
}
|
||||
}
|
||||
xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
#endif /* INCLUDE_vTaskSuspend */
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
|
||||
|
@ -3460,12 +3565,38 @@ static void prvCheckTasksWaitingTermination( void )
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Obtaining the task state is a little fiddly, so is only done if the value
|
||||
of eState passed into this function is eInvalid - otherwise the state is
|
||||
just set to whatever is passed in. */
|
||||
/* Obtaining the task state is a little fiddly, so is only done if the
|
||||
value of eState passed into this function is eInvalid - otherwise the
|
||||
state is just set to whatever is passed in. */
|
||||
if( eState != eInvalid )
|
||||
{
|
||||
pxTaskStatus->eCurrentState = eState;
|
||||
if( pxTCB == pxCurrentTCB )
|
||||
{
|
||||
pxTaskStatus->eCurrentState = eRunning;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxTaskStatus->eCurrentState = eState;
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
{
|
||||
/* If the task is in the suspended list then there is a
|
||||
chance it is actually just blocked indefinitely - so really
|
||||
it should be reported as being in the Blocked state. */
|
||||
if( eState == eSuspended )
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
|
||||
{
|
||||
pxTaskStatus->eCurrentState = eBlocked;
|
||||
}
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
#endif /* INCLUDE_vTaskSuspend */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3499,7 +3630,7 @@ static void prvCheckTasksWaitingTermination( void )
|
|||
|
||||
static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
|
||||
{
|
||||
volatile TCB_t *pxNextTCB, *pxFirstTCB;
|
||||
configLIST_VOLATILE TCB_t *pxNextTCB, *pxFirstTCB;
|
||||
UBaseType_t uxTask = 0;
|
||||
|
||||
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
|
||||
|
@ -3600,7 +3731,7 @@ static void prvCheckTasksWaitingTermination( void )
|
|||
vPortFree( pxTCB->pxStack );
|
||||
vPortFree( pxTCB );
|
||||
}
|
||||
#elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
|
||||
#elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
|
||||
{
|
||||
/* The task could have been allocated statically or dynamically, so
|
||||
check what was statically allocated before trying to free the
|
||||
|
@ -3622,7 +3753,7 @@ static void prvCheckTasksWaitingTermination( void )
|
|||
{
|
||||
/* Neither the stack nor the TCB were allocated dynamically, so
|
||||
nothing needs to be freed. */
|
||||
configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
|
||||
configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
|
@ -3703,25 +3834,27 @@ TCB_t *pxTCB;
|
|||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
||||
void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
|
||||
BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
|
||||
{
|
||||
TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
|
||||
TCB_t * const pxMutexHolderTCB = ( TCB_t * ) pxMutexHolder;
|
||||
BaseType_t xReturn = pdFALSE;
|
||||
|
||||
/* If the mutex was given back by an interrupt while the queue was
|
||||
locked then the mutex holder might now be NULL. */
|
||||
locked then the mutex holder might now be NULL. _RB_ Is this still
|
||||
needed as interrupts can no longer use mutexes? */
|
||||
if( pxMutexHolder != NULL )
|
||||
{
|
||||
/* If the holder of the mutex has a priority below the priority of
|
||||
the task attempting to obtain the mutex then it will temporarily
|
||||
inherit the priority of the task attempting to obtain the mutex. */
|
||||
if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
|
||||
if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
|
||||
{
|
||||
/* Adjust the mutex holder state to account for its new
|
||||
priority. Only reset the event list item value if the value is
|
||||
not being used for anything else. */
|
||||
if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
||||
not being used for anything else. */
|
||||
if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
||||
{
|
||||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3730,11 +3863,11 @@ TCB_t *pxTCB;
|
|||
|
||||
/* If the task being modified is in the ready state it will need
|
||||
to be moved into a new list. */
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
|
||||
{
|
||||
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
||||
if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
||||
{
|
||||
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
||||
taskRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3742,26 +3875,45 @@ TCB_t *pxTCB;
|
|||
}
|
||||
|
||||
/* Inherit the priority before being moved into the new list. */
|
||||
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
prvAddTaskToReadyList( pxTCB );
|
||||
pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
prvAddTaskToReadyList( pxMutexHolderTCB );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just inherit the priority. */
|
||||
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
}
|
||||
|
||||
traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
|
||||
traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
|
||||
|
||||
/* Inheritance occurred. */
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
|
||||
{
|
||||
/* The base priority of the mutex holder is lower than the
|
||||
priority of the task attempting to take the mutex, but the
|
||||
current priority of the mutex holder is not lower than the
|
||||
priority of the task attempting to take the mutex.
|
||||
Therefore the mutex holder must have already inherited a
|
||||
priority, but inheritance would have occurred if that had
|
||||
not been the case. */
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* configUSE_MUTEXES */
|
||||
|
@ -3781,7 +3933,6 @@ TCB_t *pxTCB;
|
|||
interrupt, and if a mutex is given by the holding task then it must
|
||||
be the running state task. */
|
||||
configASSERT( pxTCB == pxCurrentTCB );
|
||||
|
||||
configASSERT( pxTCB->uxMutexesHeld );
|
||||
( pxTCB->uxMutexesHeld )--;
|
||||
|
||||
|
@ -3795,8 +3946,8 @@ TCB_t *pxTCB;
|
|||
/* A task can only have an inherited priority if it holds
|
||||
the mutex. If the mutex is held by a task then it cannot be
|
||||
given from an interrupt, and if a mutex is given by the
|
||||
holding task then it must be the running state task. Remove
|
||||
the holding task from the ready list. */
|
||||
holding task then it must be the running state task. Remove
|
||||
the holding task from the ready list. */
|
||||
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
||||
{
|
||||
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
||||
|
@ -3848,6 +3999,108 @@ TCB_t *pxTCB;
|
|||
#endif /* configUSE_MUTEXES */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
||||
void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask )
|
||||
{
|
||||
TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
|
||||
UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
|
||||
const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
|
||||
|
||||
if( pxMutexHolder != NULL )
|
||||
{
|
||||
/* If pxMutexHolder is not NULL then the holder must hold at least
|
||||
one mutex. */
|
||||
configASSERT( pxTCB->uxMutexesHeld );
|
||||
|
||||
/* Determine the priority to which the priority of the task that
|
||||
holds the mutex should be set. This will be the greater of the
|
||||
holding task's base priority and the priority of the highest
|
||||
priority task that is waiting to obtain the mutex. */
|
||||
if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
|
||||
{
|
||||
uxPriorityToUse = uxHighestPriorityWaitingTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
uxPriorityToUse = pxTCB->uxBasePriority;
|
||||
}
|
||||
|
||||
/* Does the priority need to change? */
|
||||
if( pxTCB->uxPriority != uxPriorityToUse )
|
||||
{
|
||||
/* Only disinherit if no other mutexes are held. This is a
|
||||
simplification in the priority inheritance implementation. If
|
||||
the task that holds the mutex is also holding other mutexes then
|
||||
the other mutexes may have caused the priority inheritance. */
|
||||
if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
|
||||
{
|
||||
/* If a task has timed out because it already holds the
|
||||
mutex it was trying to obtain then it cannot of inherited
|
||||
its own priority. */
|
||||
configASSERT( pxTCB != pxCurrentTCB );
|
||||
|
||||
/* Disinherit the priority, remembering the previous
|
||||
priority to facilitate determining the subject task's
|
||||
state. */
|
||||
traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
|
||||
uxPriorityUsedOnEntry = pxTCB->uxPriority;
|
||||
pxTCB->uxPriority = uxPriorityToUse;
|
||||
|
||||
/* Only reset the event list item value if the value is not
|
||||
being used for anything else. */
|
||||
if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
||||
{
|
||||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* If the running task is not the task that holds the mutex
|
||||
then the task that holds the mutex could be in either the
|
||||
Ready, Blocked or Suspended states. Only remove the task
|
||||
from its current state list if it is in the Ready state as
|
||||
the task's priority is going to change and there is one
|
||||
Ready list per priority. */
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
|
||||
{
|
||||
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
||||
{
|
||||
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
prvAddTaskToReadyList( pxTCB );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* configUSE_MUTEXES */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
|
||||
void vTaskEnterCritical( void )
|
||||
|
@ -3937,7 +4190,7 @@ TCB_t *pxTCB;
|
|||
#endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
|
||||
void vTaskList( char * pcWriteBuffer )
|
||||
{
|
||||
|
@ -4029,10 +4282,10 @@ TCB_t *pxTCB;
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
|
||||
#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
|
||||
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
|
||||
void vTaskGetRunTimeStats( char *pcWriteBuffer )
|
||||
{
|
||||
|
@ -4156,7 +4409,7 @@ TCB_t *pxTCB;
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
|
||||
#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
TickType_t uxTaskResetEventItemValue( void )
|
||||
|
@ -4240,7 +4493,7 @@ TickType_t uxReturn;
|
|||
}
|
||||
else
|
||||
{
|
||||
pxCurrentTCB->ulNotifiedValue = ulReturn - 1;
|
||||
pxCurrentTCB->ulNotifiedValue = ulReturn - ( uint32_t ) 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -4315,7 +4568,7 @@ TickType_t uxReturn;
|
|||
blocked state (because a notification was already pending) or the
|
||||
task unblocked because of a notification. Otherwise the task
|
||||
unblocked because of a timeout. */
|
||||
if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )
|
||||
if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
|
||||
{
|
||||
/* A notification was not received. */
|
||||
xReturn = pdFALSE;
|
||||
|
@ -4800,8 +5053,24 @@ const TickType_t xConstTickCount = xTickCount;
|
|||
#endif /* INCLUDE_vTaskSuspend */
|
||||
}
|
||||
|
||||
/* Code below here allows additional code to be inserted into this source file,
|
||||
especially where access to file scope functions and data is needed (for example
|
||||
when performing module tests). */
|
||||
|
||||
#ifdef FREERTOS_MODULE_TEST
|
||||
#include "tasks_test_access_functions.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
|
||||
|
||||
#include "freertos_tasks_c_additions.h"
|
||||
|
||||
static void freertos_tasks_c_additions_init( void )
|
||||
{
|
||||
#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
|
||||
FREERTOS_TASKS_C_ADDITIONS_INIT();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
@ -100,6 +100,12 @@ configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
|
|||
/* Misc definitions. */
|
||||
#define tmrNO_DELAY ( TickType_t ) 0U
|
||||
|
||||
/* The name assigned to the timer service task. This can be overridden by
|
||||
defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */
|
||||
#ifndef configTIMER_SERVICE_TASK_NAME
|
||||
#define configTIMER_SERVICE_TASK_NAME "Tmr Svc"
|
||||
#endif
|
||||
|
||||
/* The definition of the timers themselves. */
|
||||
typedef struct tmrTimerControl
|
||||
{
|
||||
|
@ -158,8 +164,8 @@ typedef struct tmrTimerQueueMessage
|
|||
} u;
|
||||
} DaemonTaskMessage_t;
|
||||
|
||||
/*lint -e956 A manual analysis and inspection has been used to determine which
|
||||
static variables must be declared volatile. */
|
||||
/*lint -save -e956 A manual analysis and inspection has been used to determine
|
||||
which static variables must be declared volatile. */
|
||||
|
||||
/* The list in which active timers are stored. Timers are referenced in expire
|
||||
time order, with the nearest expiry time at the front of the list. Only the
|
||||
|
@ -173,7 +179,7 @@ PRIVILEGED_DATA static List_t *pxOverflowTimerList;
|
|||
PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
|
||||
PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
|
||||
|
||||
/*lint +e956 */
|
||||
/*lint -restore */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -248,12 +254,12 @@ static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseTy
|
|||
* Called after a Timer_t structure has been allocated either statically or
|
||||
* dynamically to fill in the structure's members.
|
||||
*/
|
||||
static void prvInitialiseNewTimer( const char * const pcTimerName,
|
||||
static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const TickType_t xTimerPeriodInTicks,
|
||||
const UBaseType_t uxAutoReload,
|
||||
void * const pvTimerID,
|
||||
TimerCallbackFunction_t pxCallbackFunction,
|
||||
Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xTimerCreateTimerTask( void )
|
||||
|
@ -276,7 +282,7 @@ BaseType_t xReturn = pdFAIL;
|
|||
|
||||
vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );
|
||||
xTimerTaskHandle = xTaskCreateStatic( prvTimerTask,
|
||||
"Tmr Svc",
|
||||
configTIMER_SERVICE_TASK_NAME,
|
||||
ulTimerTaskStackSize,
|
||||
NULL,
|
||||
( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
|
||||
|
@ -291,7 +297,7 @@ BaseType_t xReturn = pdFAIL;
|
|||
#else
|
||||
{
|
||||
xReturn = xTaskCreate( prvTimerTask,
|
||||
"Tmr Svc",
|
||||
configTIMER_SERVICE_TASK_NAME,
|
||||
configTIMER_TASK_STACK_DEPTH,
|
||||
NULL,
|
||||
( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
|
||||
|
@ -311,11 +317,11 @@ BaseType_t xReturn = pdFAIL;
|
|||
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
|
||||
TimerHandle_t xTimerCreate( const char * const pcTimerName,
|
||||
TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const TickType_t xTimerPeriodInTicks,
|
||||
const UBaseType_t uxAutoReload,
|
||||
void * const pvTimerID,
|
||||
TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
TimerCallbackFunction_t pxCallbackFunction )
|
||||
{
|
||||
Timer_t *pxNewTimer;
|
||||
|
||||
|
@ -343,12 +349,12 @@ BaseType_t xReturn = pdFAIL;
|
|||
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
|
||||
TimerHandle_t xTimerCreateStatic( const char * const pcTimerName,
|
||||
TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const TickType_t xTimerPeriodInTicks,
|
||||
const UBaseType_t uxAutoReload,
|
||||
void * const pvTimerID,
|
||||
TimerCallbackFunction_t pxCallbackFunction,
|
||||
StaticTimer_t *pxTimerBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
StaticTimer_t *pxTimerBuffer )
|
||||
{
|
||||
Timer_t *pxNewTimer;
|
||||
|
||||
|
@ -356,7 +362,7 @@ BaseType_t xReturn = pdFAIL;
|
|||
{
|
||||
/* Sanity check that the size of the structure used to declare a
|
||||
variable of type StaticTimer_t equals the size of the real timer
|
||||
structures. */
|
||||
structure. */
|
||||
volatile size_t xSize = sizeof( StaticTimer_t );
|
||||
configASSERT( xSize == sizeof( Timer_t ) );
|
||||
}
|
||||
|
@ -385,12 +391,12 @@ BaseType_t xReturn = pdFAIL;
|
|||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInitialiseNewTimer( const char * const pcTimerName,
|
||||
static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
const TickType_t xTimerPeriodInTicks,
|
||||
const UBaseType_t uxAutoReload,
|
||||
void * const pvTimerID,
|
||||
TimerCallbackFunction_t pxCallbackFunction,
|
||||
Timer_t *pxNewTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||
Timer_t *pxNewTimer )
|
||||
{
|
||||
/* 0 is not a valid value for xTimerPeriodInTicks. */
|
||||
configASSERT( ( xTimerPeriodInTicks > 0 ) );
|
||||
|
@ -760,7 +766,7 @@ TickType_t xTimeNow;
|
|||
software timer. */
|
||||
pxTimer = xMessage.u.xTimerParameters.pxTimer;
|
||||
|
||||
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
|
||||
if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */
|
||||
{
|
||||
/* The timer is in a list, remove it. */
|
||||
( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
|
||||
|
@ -945,10 +951,10 @@ static void prvCheckForValidListAndQueue( void )
|
|||
{
|
||||
/* The timer queue is allocated statically in case
|
||||
configSUPPORT_DYNAMIC_ALLOCATION is 0. */
|
||||
static StaticQueue_t xStaticTimerQueue;
|
||||
static uint8_t ucStaticTimerQueueStorage[ configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ];
|
||||
static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */
|
||||
static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */
|
||||
|
||||
xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue );
|
||||
xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue );
|
||||
}
|
||||
#else
|
||||
{
|
||||
|
@ -991,7 +997,7 @@ Timer_t *pxTimer = ( Timer_t * ) xTimer;
|
|||
/* Checking to see if it is in the NULL list in effect checks to see if
|
||||
it is referenced from either the current or the overflow timer lists in
|
||||
one go, but the logic has to be reversed, hence the '!'. */
|
||||
xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) );
|
||||
xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); /*lint !e961. Cast is only redundant when NULL is passed into the macro. */
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
|
|
|
@ -78,8 +78,8 @@ Current status is alpha quality, actively developed. AP STATION mode (ie wifi cl
|
|||
## Open Source Components
|
||||
|
||||
* [FreeRTOS](http://www.freertos.org/) V9.0.0
|
||||
* [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki) v1.4.1, modified via the [esp-lwip project](https://github.com/kadamski/esp-lwip) by @kadamski.
|
||||
* [newlib](https://github.com/projectgus/newlib-xtensa) v2.2.0, with patches for xtensa support and locking stubs for thread-safe operation on FreeRTOS.
|
||||
* [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki) v2.0.3, with [some modifications](https://github.com/ourairquality/lwip/).
|
||||
* [newlib](https://github.com/ourairquality/newlib) v2.5.0, with patches for xtensa support and locking stubs for thread-safe operation on FreeRTOS.
|
||||
|
||||
For details of how third party libraries are integrated, [see the wiki page](https://github.com/SuperHouse/esp-open-rtos/wiki/Third-Party-Libraries).
|
||||
|
||||
|
|
|
@ -214,8 +214,8 @@ void IRAM sdk_user_start(void) {
|
|||
memcpy(&sdk_g_ic.s, buf32, sizeof(struct sdk_g_ic_saved_st));
|
||||
|
||||
// By default, put the sysparam region just below the config sectors at the
|
||||
// top of the flash space
|
||||
sysparam_addr = flash_size - (4 + DEFAULT_SYSPARAM_SECTORS) * sdk_flashchip.sector_size;
|
||||
// top of the flash space, and allowing one extra sector spare.
|
||||
sysparam_addr = flash_size - (5 + DEFAULT_SYSPARAM_SECTORS) * sdk_flashchip.sector_size;
|
||||
status = sysparam_init(sysparam_addr, flash_size);
|
||||
if (status == SYSPARAM_NOTFOUND) {
|
||||
status = sysparam_create_area(sysparam_addr, DEFAULT_SYSPARAM_SECTORS, false);
|
||||
|
@ -311,8 +311,8 @@ static void init_g_ic(void) {
|
|||
if (sdk_g_ic.s._unknown310 > 4) {
|
||||
sdk_g_ic.s._unknown310 = 4;
|
||||
}
|
||||
if (sdk_g_ic.s._unknown1e4._unknown1e4 == 0xffffffff) {
|
||||
bzero(&sdk_g_ic.s._unknown1e4, sizeof(sdk_g_ic.s._unknown1e4));
|
||||
if (sdk_g_ic.s.sta_ssid.ssid_length == 0xffffffff) {
|
||||
bzero(&sdk_g_ic.s.sta_ssid, sizeof(sdk_g_ic.s.sta_ssid));
|
||||
bzero(&sdk_g_ic.s.sta_password, sizeof(sdk_g_ic.s.sta_password));
|
||||
}
|
||||
sdk_g_ic.s.wifi_led_enable = 0;
|
||||
|
|
|
@ -58,17 +58,17 @@ void gpio_set_pullup(uint8_t gpio_num, bool enabled, bool enabled_during_sleep)
|
|||
|
||||
static gpio_interrupt_handler_t gpio_interrupt_handlers[16] = { 0 };
|
||||
|
||||
void __attribute__((weak)) IRAM gpio_interrupt_handler(void)
|
||||
void __attribute__((weak)) IRAM gpio_interrupt_handler(void *arg)
|
||||
{
|
||||
uint32_t status_reg = GPIO.STATUS;
|
||||
GPIO.STATUS_CLEAR = status_reg;
|
||||
|
||||
uint8_t gpio_idx;
|
||||
while((gpio_idx = __builtin_ffs(status_reg)))
|
||||
while ((gpio_idx = __builtin_ffs(status_reg)))
|
||||
{
|
||||
gpio_idx--;
|
||||
status_reg &= ~BIT(gpio_idx);
|
||||
if(FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx])) {
|
||||
if (FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx])) {
|
||||
gpio_interrupt_handler_t handler = gpio_interrupt_handlers[gpio_idx];
|
||||
if (handler) {
|
||||
handler(gpio_idx);
|
||||
|
@ -82,8 +82,8 @@ void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type, g
|
|||
gpio_interrupt_handlers[gpio_num] = handler;
|
||||
|
||||
GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type);
|
||||
if(int_type != GPIO_INTTYPE_NONE) {
|
||||
_xt_isr_attach(INUM_GPIO, gpio_interrupt_handler);
|
||||
if (int_type != GPIO_INTTYPE_NONE) {
|
||||
_xt_isr_attach(INUM_GPIO, gpio_interrupt_handler, NULL);
|
||||
_xt_isr_unmask(1<<INUM_GPIO);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,19 @@
|
|||
*/
|
||||
#include <esp/interrupts.h>
|
||||
|
||||
_xt_isr isr[16];
|
||||
typedef struct _xt_isr_entry_ {
|
||||
_xt_isr handler;
|
||||
void *arg;
|
||||
} _xt_isr_entry;
|
||||
|
||||
_xt_isr_entry isr[16];
|
||||
|
||||
bool esp_in_isr;
|
||||
|
||||
void IRAM _xt_isr_attach(uint8_t i, _xt_isr func)
|
||||
void IRAM _xt_isr_attach(uint8_t i, _xt_isr func, void *arg)
|
||||
{
|
||||
isr[i] = func;
|
||||
isr[i].handler = func;
|
||||
isr[i].arg = arg;
|
||||
}
|
||||
|
||||
/* Generic ISR handler.
|
||||
|
@ -25,17 +31,20 @@ uint16_t IRAM _xt_isr_handler(uint16_t intset)
|
|||
esp_in_isr = true;
|
||||
|
||||
/* WDT has highest priority (occasional WDT resets otherwise) */
|
||||
if(intset & BIT(INUM_WDT)) {
|
||||
if (intset & BIT(INUM_WDT)) {
|
||||
_xt_clear_ints(BIT(INUM_WDT));
|
||||
isr[INUM_WDT]();
|
||||
isr[INUM_WDT].handler(NULL);
|
||||
intset -= BIT(INUM_WDT);
|
||||
}
|
||||
|
||||
while(intset) {
|
||||
while (intset) {
|
||||
uint8_t index = __builtin_ffs(intset) - 1;
|
||||
uint16_t mask = BIT(index);
|
||||
_xt_clear_ints(mask);
|
||||
isr[index]();
|
||||
_xt_isr handler = isr[index].handler;
|
||||
if (handler) {
|
||||
handler(isr[index].arg);
|
||||
}
|
||||
intset -= mask;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ typedef void (* gpio_interrupt_handler_t)(uint8_t gpio_num);
|
|||
*
|
||||
* Example:
|
||||
*
|
||||
* void IRAM gpio_interrupt_handler(void) {
|
||||
* void IRAM gpio_interrupt_handler(void *arg) {
|
||||
* // check GPIO.STATUS
|
||||
* // write GPIO.STATUS_CLEAR
|
||||
* // Do something when GPIO changes
|
||||
|
|
|
@ -35,19 +35,37 @@ typedef enum {
|
|||
INUM_TIMER_FRC2 = 10,
|
||||
} xt_isr_num_t;
|
||||
|
||||
void sdk__xt_int_exit (void);
|
||||
void _xt_user_exit (void);
|
||||
void sdk__xt_tick_timer_init (void);
|
||||
void sdk__xt_timer_int(void);
|
||||
void sdk__xt_int_exit(void);
|
||||
void _xt_user_exit(void);
|
||||
void sdk__xt_tick_timer_init(void);
|
||||
void sdk__xt_timer_int(void *);
|
||||
void sdk__xt_timer_int1(void);
|
||||
|
||||
/* The normal running level is 0.
|
||||
* The system tick isr, timer frc2_isr, sv_isr etc run at level 1.
|
||||
* Debug exceptions run at level 2?
|
||||
* The wdev nmi runs at level 3.
|
||||
*/
|
||||
static inline uint32_t _xt_get_intlevel(void)
|
||||
{
|
||||
uint32_t level;
|
||||
__asm__ volatile("rsr %0, intlevel" : "=a"(level));
|
||||
return level;
|
||||
__asm__ volatile("rsr %0, ps" : "=a"(level));
|
||||
return level & 0xf;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are conflicting definitions for XCHAL_EXCM_LEVEL. Newlib
|
||||
* defines it to be 1 and xtensa_rtos.h defines it to be 3. Don't want
|
||||
* 3 as that is for the NMI and might want to check that the OS apis
|
||||
* are not entered in level 3. Setting the interrupt level to 3 does
|
||||
* not disable the NMI anyway. So set the level to 2.
|
||||
*/
|
||||
|
||||
#ifdef XCHAL_EXCM_LEVEL
|
||||
#undef XCHAL_EXCM_LEVEL
|
||||
#define XCHAL_EXCM_LEVEL 2
|
||||
#endif
|
||||
|
||||
/* Disable interrupts and return the old ps value, to pass into
|
||||
_xt_restore_interrupts later.
|
||||
|
||||
|
@ -68,25 +86,27 @@ static inline void _xt_restore_interrupts(uint32_t new_ps)
|
|||
__asm__ volatile ("wsr %0, ps; rsync" :: "a" (new_ps));
|
||||
}
|
||||
|
||||
/* ESPTODO: the mask/unmask functions aren't thread safe */
|
||||
|
||||
static inline void _xt_isr_unmask(uint32_t unmask)
|
||||
static inline uint32_t _xt_isr_unmask(uint32_t unmask)
|
||||
{
|
||||
uint32_t old_level = _xt_disable_interrupts();
|
||||
uint32_t intenable;
|
||||
asm volatile ("rsr %0, intenable" : "=a" (intenable));
|
||||
intenable |= unmask;
|
||||
asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
|
||||
asm volatile ("wsr %0, intenable;" :: "a" (intenable | unmask));
|
||||
_xt_restore_interrupts(old_level);
|
||||
return intenable;
|
||||
}
|
||||
|
||||
static inline void _xt_isr_mask (uint32_t mask)
|
||||
static inline uint32_t _xt_isr_mask(uint32_t mask)
|
||||
{
|
||||
uint32_t old_level = _xt_disable_interrupts();
|
||||
uint32_t intenable;
|
||||
asm volatile ("rsr %0, intenable" : "=a" (intenable));
|
||||
intenable &= ~mask;
|
||||
asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
|
||||
asm volatile ("wsr %0, intenable;" :: "a" (intenable & ~mask));
|
||||
_xt_restore_interrupts(old_level);
|
||||
return intenable;
|
||||
}
|
||||
|
||||
static inline uint32_t _xt_read_ints (void)
|
||||
static inline uint32_t _xt_read_ints(void)
|
||||
{
|
||||
uint32_t interrupt;
|
||||
asm volatile ("rsr %0, interrupt" : "=a" (interrupt));
|
||||
|
@ -98,9 +118,7 @@ static inline void _xt_clear_ints(uint32_t mask)
|
|||
asm volatile ("wsr %0, intclear; esync" :: "a" (mask));
|
||||
}
|
||||
|
||||
typedef void (* _xt_isr)(void);
|
||||
/* This function is implemeneted in FreeRTOS port.c at the moment,
|
||||
should be moved or converted to an inline */
|
||||
void _xt_isr_attach (uint8_t i, _xt_isr func);
|
||||
typedef void (* _xt_isr)(void *arg);
|
||||
void _xt_isr_attach (uint8_t i, _xt_isr func, void *arg);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,25 +14,25 @@
|
|||
// 'info' is declared in app_main.o at .bss+0x4
|
||||
|
||||
struct sdk_info_st {
|
||||
ip_addr_t softap_ipaddr; // 0x00
|
||||
ip_addr_t softap_netmask; // 0x04
|
||||
ip_addr_t softap_gw; // 0x08
|
||||
ip_addr_t sta_ipaddr; // 0x0c
|
||||
ip_addr_t sta_netmask; // 0x10
|
||||
ip_addr_t sta_gw; // 0x14
|
||||
ip4_addr_t softap_ipaddr; // 0x00
|
||||
ip4_addr_t softap_netmask; // 0x04
|
||||
ip4_addr_t softap_gw; // 0x08
|
||||
ip4_addr_t sta_ipaddr; // 0x0c
|
||||
ip4_addr_t sta_netmask; // 0x10
|
||||
ip4_addr_t sta_gw; // 0x14
|
||||
uint8_t softap_mac_addr[6]; // 0x18
|
||||
uint8_t sta_mac_addr[6]; // 0x1e
|
||||
};
|
||||
|
||||
|
||||
struct _unknown_info1 {
|
||||
struct wl_channel {
|
||||
uint8_t _unknown00;
|
||||
uint8_t _unknown01;
|
||||
uint8_t _unknown02;
|
||||
uint8_t _unknown03;
|
||||
uint8_t _unknown04;
|
||||
uint8_t _unknown05;
|
||||
uint8_t channel; // eagle_auth_done
|
||||
uint8_t num; // eagle_auth_done
|
||||
};
|
||||
|
||||
|
||||
|
@ -83,7 +83,7 @@ struct _unknown_wpa1 {
|
|||
};
|
||||
|
||||
|
||||
struct sdk_netif_conninfo {
|
||||
struct sdk_cnx_node {
|
||||
uint8_t mac_addr[6];
|
||||
uint8_t _unknown07[2];
|
||||
|
||||
|
@ -98,17 +98,19 @@ struct sdk_netif_conninfo {
|
|||
|
||||
uint32_t _unknown1c[23];
|
||||
|
||||
struct _unknown_info1 *_unknown78; // eagle_auth_done
|
||||
struct wl_channel *channel; // 0x78 eagle_auth_done
|
||||
|
||||
uint32_t _unknown7c[8];
|
||||
|
||||
uint16_t _unknown9c; // ieee80211_hostap. increases by one one each timer func called.
|
||||
uint16_t _unknown9e;
|
||||
|
||||
uint32_t _unknowna0[18];
|
||||
uint32_t _unknowna0[17];
|
||||
|
||||
int8_t _unknowne8; //
|
||||
int8_t _unknowne9; // ppInstallKey
|
||||
void *_unknowne4;
|
||||
|
||||
uint8_t _unknowne8; //
|
||||
uint8_t _unknowne9; // ppInstallKey
|
||||
int8_t _unknownea;
|
||||
int8_t _unknowneb;
|
||||
|
||||
|
@ -128,9 +130,9 @@ struct sdk_g_ic_netif_info {
|
|||
uint32_t _unknown48; // 0x48
|
||||
uint8_t _unknown4c; // 0x4c
|
||||
uint8_t _unknown4d[59]; // 0x4d - 0x88
|
||||
struct sdk_netif_conninfo *_unknown88; // 0x88
|
||||
struct sdk_cnx_node *_unknown88; // 0x88
|
||||
uint32_t _unknown8c; // 0x8c
|
||||
struct sdk_netif_conninfo *conninfo[6]; // 0x90 - 0xa8
|
||||
struct sdk_cnx_node *cnx_nodes[6]; // 0x90 - 0xa8
|
||||
uint8_t _unknowna8[12]; // 0xa8 - 0xb4
|
||||
struct _unknown_softap1 *_unknownb4;
|
||||
uint8_t statusb8; // 0xb8 (arg of sta_status_set)
|
||||
|
@ -206,10 +208,9 @@ struct sdk_g_ic_volatile_st {
|
|||
};
|
||||
|
||||
|
||||
struct sdk_g_ic_unk0_st {
|
||||
uint16_t _unknown1e4; // sdk_wpa_config_profile
|
||||
uint16_t _unknown1e6; // sdk_wpa_config_profile
|
||||
uint8_t sta_ssid[32]; // 0x1e8 Station ssid. Null terminated string.
|
||||
struct sdk_g_ic_ssid_with_length {
|
||||
uint32_t ssid_length; // 0x1e4 sdk_wpa_config_profile
|
||||
uint8_t ssid[32]; // 0x1e8 Station ssid. Null terminated string.
|
||||
};
|
||||
|
||||
// This is the portion of g_ic which is loaded/saved to the flash ROM, and thus
|
||||
|
@ -224,7 +225,8 @@ struct sdk_g_ic_saved_st {
|
|||
uint8_t wifi_led_gpio;
|
||||
uint8_t wifi_led_state; // 0 or 1.
|
||||
|
||||
struct sdk_g_ic_unk0_st _unknown1e4;
|
||||
// Current station ap config ssid and length.
|
||||
struct sdk_g_ic_ssid_with_length sta_ssid; // 0x1e4
|
||||
|
||||
uint8_t _unknown208;
|
||||
uint8_t _unknown209; // sdk_wpa_config_profile
|
||||
|
@ -260,7 +262,7 @@ struct sdk_g_ic_saved_st {
|
|||
uint8_t _unknown30d; // result of ieee80211_chan2ieee
|
||||
uint8_t _unknown30e;
|
||||
uint8_t _unknown30f;
|
||||
uint8_t _unknown310; // count of entries in the softap conninfo array, less two.
|
||||
uint8_t _unknown310; // count of entries in the softap cnx_node array, less two.
|
||||
|
||||
uint8_t _unknown311[3];
|
||||
|
||||
|
@ -320,7 +322,7 @@ struct esf_buf {
|
|||
_Static_assert(sizeof(struct sdk_info_st) == 0x24, "info_st is the wrong size!");
|
||||
_Static_assert(offsetof(struct sdk_info_st, sta_mac_addr) == 0x1e, "bad struct");
|
||||
|
||||
_Static_assert(offsetof(struct _unknown_info1, channel) == 0x06, "bad struct");
|
||||
_Static_assert(offsetof(struct wl_channel, num) == 0x06, "bad struct");
|
||||
|
||||
_Static_assert(sizeof(struct _unknown_softap2) == 0xcc, "_unknown_softap2 is the wrong size!");
|
||||
_Static_assert(offsetof(struct _unknown_softap2, _unknownb8) == 0xb8, "bad struct");
|
||||
|
@ -331,8 +333,8 @@ _Static_assert(offsetof(struct _unknown_softap1, _unknown18) == 0x18, "bad struc
|
|||
_Static_assert(sizeof(struct _unknown_wpa1) == 0x4c, "_unknown_wpa1 is the wrong size!");
|
||||
_Static_assert(offsetof(struct _unknown_wpa1, _unknown48) == 0x48, "bad struct");
|
||||
|
||||
_Static_assert(offsetof(struct sdk_netif_conninfo, _unknown78) == 0x78, "bad struct");
|
||||
_Static_assert(offsetof(struct sdk_netif_conninfo, _unknown108) == 0x108, "bad struct");
|
||||
_Static_assert(offsetof(struct sdk_cnx_node, channel) == 0x78, "bad struct");
|
||||
_Static_assert(offsetof(struct sdk_cnx_node, _unknown108) == 0x108, "bad struct");
|
||||
|
||||
_Static_assert(offsetof(struct sdk_g_ic_netif_info, started) == 0xbb, "bad struct");
|
||||
|
||||
|
@ -340,7 +342,7 @@ _Static_assert(sizeof(struct sdk_g_ic_volatile_st) == 0x1d8, "sdk_g_ic_volatile_
|
|||
_Static_assert(offsetof(struct sdk_g_ic_volatile_st, _unknown1d5) == 0x1d5, "bad struct");
|
||||
|
||||
_Static_assert(sizeof(struct sdk_g_ic_saved_st) == 0x370, "sdk_g_ic_saved_st is the wrong size!");
|
||||
_Static_assert(offsetof(struct sdk_g_ic_saved_st, _unknown1e4) == 0x1e4 - 0x1d8, "bad struct");
|
||||
_Static_assert(offsetof(struct sdk_g_ic_saved_st, sta_ssid) == 0x1e4 - 0x1d8, "bad struct");
|
||||
_Static_assert(offsetof(struct sdk_g_ic_saved_st, _unknown546) == 0x546 - 0x1d8, "bad struct");
|
||||
|
||||
_Static_assert(sizeof(struct sdk_g_ic_st) == 0x548, "sdk_g_ic_st is the wrong size!");
|
||||
|
@ -357,21 +359,16 @@ _Static_assert(offsetof(struct esf_buf, length) == 0x16, "bad struct");
|
|||
// ieee80211_output_pbuf and perhaps elsewhere. The value is just passed through
|
||||
// lwip and and not used by lwip so just ensure this slot is at the expected
|
||||
// offset.
|
||||
_Static_assert(offsetof(struct netif, state) == 28, "netif->state offset wrong!");
|
||||
_Static_assert(offsetof(struct netif, state) == 4, "netif->state offset wrong!");
|
||||
|
||||
// Some sdk uses of netif->hwaddr have been converted to source code, but many
|
||||
// remain, but the content of this slot should not change in future versions of
|
||||
// lwip, so just ensure it is at the expected offset.
|
||||
_Static_assert(offsetof(struct netif, hwaddr) == 41, "netif->hwaddr offset wrong!");
|
||||
// lwip, so just ensure it is at the expected offset. Note the sdk binary
|
||||
// libraries have been patched to move this offset from 41 to 42 to keep it
|
||||
// 16-bit aligned to keep lwip v2 happy.
|
||||
_Static_assert(offsetof(struct netif, hwaddr) == 8, "netif->hwaddr offset wrong!");
|
||||
|
||||
// Most sdk uses of the netif->flags have been converted to source code. One
|
||||
// known sdk binary read of the flags remains in wl_cnx.o:sdk_cnx_sta_leave
|
||||
// which checks the NETIF_FLAG_DHCP flag. The NETIF_FLAG_DHCP has been removed
|
||||
// in lwip v2, so some lwip hacks are needed to handle this for now until
|
||||
// wl_cnx.o is converted so source code too.
|
||||
_Static_assert(offsetof(struct netif, flags) == 47, "netif->flags offset wrong!");
|
||||
|
||||
_Static_assert(offsetof(struct pbuf, eb) == 16, "pbuf->eb offset wrong!");
|
||||
_Static_assert(offsetof(struct pbuf, esf_buf) == 16, "pbuf->esf_buf offset wrong!");
|
||||
|
||||
|
||||
/// Misc.
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <esp/uart.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdout_redirect.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
extern void *xPortSupervisorStackPointer;
|
||||
|
||||
|
@ -135,6 +136,14 @@ int _stat_r(struct _reent *r, const char *pathname, void *buf);
|
|||
__attribute__((weak, alias("syscall_returns_enosys")))
|
||||
off_t _lseek_r(struct _reent *r, int fd, off_t offset, int whence);
|
||||
|
||||
__attribute__((weak, alias("_gettimeofday_r")))
|
||||
int _gettimeofday_r _PARAMS ((struct _reent *r, struct timeval *now, void *p)) {
|
||||
now->tv_sec = 0;
|
||||
now->tv_usec = 0;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generic stub for any newlib syscall that fails with errno ENOSYS
|
||||
("Function not implemented") and a return value equivalent to
|
||||
(int)-1. */
|
||||
|
|
|
@ -133,7 +133,7 @@ static bool IRAM spi_write(uint32_t addr, uint8_t *dst, uint32_t size)
|
|||
|
||||
uint32_t offset = write_bytes_to_page;
|
||||
uint32_t pages_to_write = (size - offset) / sdk_flashchip.page_size;
|
||||
for (uint8_t i = 0; i != pages_to_write; i++) {
|
||||
for (uint32_t i = 0; i < pages_to_write; i++) {
|
||||
if (!spi_write_page(&sdk_flashchip, addr + offset,
|
||||
dst + offset, sdk_flashchip.page_size)) {
|
||||
return false;
|
||||
|
|
|
@ -801,9 +801,13 @@ sysparam_status_t sysparam_get_bool(const char *key, bool *result) {
|
|||
do {
|
||||
if (binary) {
|
||||
if (data_len == 1) { // int8 value
|
||||
*result = (int8_t)(*buf) ? true : false;
|
||||
uint8_t value;
|
||||
memcpy(&value, buf, sizeof(value));
|
||||
*result = value ? true : false;
|
||||
} else if (data_len == 4) { // int32 value
|
||||
*result = (int32_t)(*buf) ? true : false;
|
||||
uint32_t value;
|
||||
memcpy(&value, buf, sizeof(value));
|
||||
*result = value ? true : false;
|
||||
} else {
|
||||
status = SYSPARAM_PARSEFAILED;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ void user_init(void)
|
|||
};
|
||||
sdk_wifi_softap_set_config(&ap_config);
|
||||
|
||||
ip_addr_t first_client_ip;
|
||||
ip4_addr_t first_client_ip;
|
||||
IP4_ADDR(&first_client_ip, 172, 16, 0, 2);
|
||||
dhcpserver_start(&first_client_ip, 4);
|
||||
|
||||
|
@ -65,14 +65,14 @@ static void telnetTask(void *pvParameters)
|
|||
printf("Status monitor: Failed to allocate socket.\r\n");
|
||||
return;
|
||||
}
|
||||
netconn_bind(nc, IP_ADDR_ANY, TELNET_PORT);
|
||||
netconn_bind(nc, IP_ANY_TYPE, TELNET_PORT);
|
||||
netconn_listen(nc);
|
||||
|
||||
while(1) {
|
||||
struct netconn *client = NULL;
|
||||
err_t err = netconn_accept(nc, &client);
|
||||
|
||||
if ( err != ERR_OK ) {
|
||||
if (err != ERR_OK) {
|
||||
if(client)
|
||||
netconn_delete(client);
|
||||
continue;
|
||||
|
@ -88,9 +88,8 @@ static void telnetTask(void *pvParameters)
|
|||
netconn_write(client, buf, strlen(buf), NETCONN_COPY);
|
||||
snprintf(buf, sizeof(buf), "Free heap %d bytes\r\n", (int)xPortGetFreeHeapSize());
|
||||
netconn_write(client, buf, strlen(buf), NETCONN_COPY);
|
||||
snprintf(buf, sizeof(buf), "Your address is %d.%d.%d.%d\r\n\r\n",
|
||||
ip4_addr1(&client_addr), ip4_addr2(&client_addr),
|
||||
ip4_addr3(&client_addr), ip4_addr4(&client_addr));
|
||||
char abuf[40];
|
||||
snprintf(buf, sizeof(buf), "Your address is %s\r\n\r\n", ipaddr_ntoa_r(&client_addr, abuf, sizeof(abuf)));
|
||||
netconn_write(client, buf, strlen(buf), NETCONN_COPY);
|
||||
netconn_delete(client);
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@ const int freq_frc2 = 10;
|
|||
static volatile uint32_t frc1_count;
|
||||
static volatile uint32_t frc2_count;
|
||||
|
||||
void frc1_interrupt_handler(void)
|
||||
void frc1_interrupt_handler(void *arg)
|
||||
{
|
||||
frc1_count++;
|
||||
gpio_toggle(gpio_frc1);
|
||||
}
|
||||
|
||||
void frc2_interrupt_handler(void)
|
||||
void frc2_interrupt_handler(void *arg)
|
||||
{
|
||||
/* FRC2 needs the match register updated on each timer interrupt */
|
||||
timer_set_frequency(FRC2, freq_frc2);
|
||||
|
@ -47,8 +47,8 @@ void user_init(void)
|
|||
timer_set_run(FRC2, false);
|
||||
|
||||
/* set up ISRs */
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
|
||||
_xt_isr_attach(INUM_TIMER_FRC2, frc2_interrupt_handler);
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
|
||||
_xt_isr_attach(INUM_TIMER_FRC2, frc2_interrupt_handler, NULL);
|
||||
|
||||
/* configure timer frequencies */
|
||||
timer_set_frequency(FRC1, freq_frc1);
|
||||
|
|
|
@ -97,7 +97,7 @@ void timerRegTask(void *pvParameters)
|
|||
}
|
||||
}
|
||||
|
||||
IRAM void frc1_handler(void)
|
||||
IRAM void frc1_handler(void *arg)
|
||||
{
|
||||
frc1_handler_call_count++;
|
||||
frc1_last_count_val = TIMER(0).COUNT;
|
||||
|
@ -106,7 +106,7 @@ IRAM void frc1_handler(void)
|
|||
//TIMER_FRC1_MATCH_REG = frc1_last_count_val + 0x100000;
|
||||
}
|
||||
|
||||
void frc2_handler(void)
|
||||
void frc2_handler(void *arg)
|
||||
{
|
||||
frc2_handler_call_count++;
|
||||
frc2_last_count_val = TIMER(1).COUNT;
|
||||
|
@ -127,9 +127,9 @@ void user_init(void)
|
|||
TIMER(1).LOAD = VAL2FIELD(TIMER_CTRL_CLKDIV, TIMER_CLKDIV_256);
|
||||
|
||||
DPORT.INT_ENABLE |= DPORT_INT_ENABLE_TIMER0 | DPORT_INT_ENABLE_TIMER1;
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_handler);
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_handler, NULL);
|
||||
_xt_isr_unmask(1<<INUM_TIMER_FRC1);
|
||||
_xt_isr_attach(INUM_TIMER_FRC2, frc2_handler);
|
||||
_xt_isr_attach(INUM_TIMER_FRC2, frc2_handler, NULL);
|
||||
_xt_isr_unmask(1<<INUM_TIMER_FRC2);
|
||||
|
||||
TIMER(0).CTRL |= TIMER_CTRL_RUN;
|
||||
|
|
|
@ -237,7 +237,7 @@ static volatile bool frc1_ran;
|
|||
static volatile bool frc1_finished;
|
||||
static volatile char frc1_buf[80];
|
||||
|
||||
static void frc1_interrupt_handler(void)
|
||||
static void frc1_interrupt_handler(void *arg)
|
||||
{
|
||||
frc1_ran = true;
|
||||
timer_set_run(FRC1, false);
|
||||
|
@ -250,7 +250,7 @@ static void test_isr()
|
|||
printf("Testing behaviour inside ISRs...\r\n");
|
||||
timer_set_interrupts(FRC1, false);
|
||||
timer_set_run(FRC1, false);
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
|
||||
timer_set_frequency(FRC1, 1000);
|
||||
timer_set_interrupts(FRC1, true);
|
||||
timer_set_run(FRC1, true);
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
|
||||
#include "ssid_config.h"
|
||||
|
||||
#define WEB_SERVER "chainxor.org"
|
||||
#define WEB_SERVER "ipv6.google.com"
|
||||
#define WEB_PORT 80
|
||||
#define WEB_URL "http://chainxor.org/"
|
||||
#define WEB_PATH "/"
|
||||
|
||||
void http_get_task(void *pvParameters)
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ void http_get_task(void *pvParameters)
|
|||
|
||||
while(1) {
|
||||
const struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
};
|
||||
struct addrinfo *res;
|
||||
|
@ -39,7 +39,7 @@ void http_get_task(void *pvParameters)
|
|||
printf("Running DNS lookup for %s...\r\n", WEB_SERVER);
|
||||
int err = getaddrinfo(WEB_SERVER, "80", &hints, &res);
|
||||
|
||||
if(err != 0 || res == NULL) {
|
||||
if (err != 0 || res == NULL) {
|
||||
printf("DNS lookup failed err=%d res=%p\r\n", err, res);
|
||||
if(res)
|
||||
freeaddrinfo(res);
|
||||
|
@ -47,9 +47,28 @@ void http_get_task(void *pvParameters)
|
|||
failures++;
|
||||
continue;
|
||||
}
|
||||
/* Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
|
||||
struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
|
||||
printf("DNS lookup succeeded. IP=%s\r\n", inet_ntoa(*addr));
|
||||
|
||||
#if LWIP_IPV6
|
||||
{
|
||||
struct netif *netif = sdk_system_get_netif(0);
|
||||
int i;
|
||||
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
printf(" ip6 %d state %x\n", i, netif_ip6_addr_state(netif, i));
|
||||
if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)))
|
||||
printf(" ip6 addr %d = %s\n", i, ip6addr_ntoa(netif_ip6_addr(netif, i)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct sockaddr *sa = res->ai_addr;
|
||||
if (sa->sa_family == AF_INET) {
|
||||
printf("DNS lookup succeeded. IP=%s\r\n", inet_ntoa(((struct sockaddr_in *)sa)->sin_addr));
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
printf("DNS lookup succeeded. IP=%s\r\n", inet6_ntoa(((struct sockaddr_in6 *)sa)->sin6_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
int s = socket(res->ai_family, res->ai_socktype, 0);
|
||||
if(s < 0) {
|
||||
|
@ -75,8 +94,10 @@ void http_get_task(void *pvParameters)
|
|||
freeaddrinfo(res);
|
||||
|
||||
const char *req =
|
||||
"GET "WEB_URL"\r\n"
|
||||
"GET "WEB_PATH" HTTP/1.1\r\n"
|
||||
"Host: "WEB_SERVER"\r\n"
|
||||
"User-Agent: esp-open-rtos/0.1 esp8266\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n";
|
||||
if (write(s, req, strlen(req)) < 0) {
|
||||
printf("... socket send failed\r\n");
|
||||
|
@ -126,6 +147,6 @@ void user_init(void)
|
|||
sdk_wifi_set_opmode(STATION_MODE);
|
||||
sdk_wifi_station_set_config(&config);
|
||||
|
||||
xTaskCreate(&http_get_task, "get_task", 256, NULL, 2, NULL);
|
||||
xTaskCreate(&http_get_task, "get_task", 384, NULL, 2, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ static inline void init_descriptors_list()
|
|||
}
|
||||
|
||||
// DMA interrupt handler. It is called each time a DMA block is finished processing.
|
||||
static void dma_isr_handler(void)
|
||||
static void dma_isr_handler(void *args)
|
||||
{
|
||||
portBASE_TYPE task_awoken = pdFALSE;
|
||||
|
||||
|
@ -168,7 +168,7 @@ void play_task(void *pvParameters)
|
|||
|
||||
i2s_pins_t i2s_pins = {.data = true, .clock = true, .ws = true};
|
||||
|
||||
i2s_dma_init(dma_isr_handler, clock_div, i2s_pins);
|
||||
i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins);
|
||||
|
||||
while (1) {
|
||||
init_descriptors_list();
|
||||
|
|
|
@ -8,7 +8,7 @@ include ../../common.mk
|
|||
# `make dump-flash` can be used to view the current contents of the sysparam
|
||||
# regions in flash.
|
||||
dump-flash:
|
||||
esptool.py read_flash 0x1f8000 8192 r1.bin
|
||||
esptool.py read_flash 0x1f7000 8192 r1.bin
|
||||
hexdump -C r1.bin
|
||||
esptool.py read_flash 0x1fa000 8192 r2.bin
|
||||
esptool.py read_flash 0x1f9000 8192 r2.bin
|
||||
hexdump -C r2.bin
|
||||
|
|
|
@ -45,7 +45,7 @@ size_t tty_readline(char *buffer, size_t buf_size, bool echo) {
|
|||
|
||||
while (true) {
|
||||
c = getchar();
|
||||
if (c == '\r') {
|
||||
if (c == '\r' || c == '\n') {
|
||||
if (echo) putchar('\n');
|
||||
break;
|
||||
} else if (c == '\b' || c == 0x7f) {
|
||||
|
@ -173,7 +173,7 @@ void sysparam_editor_task(void *pvParameters) {
|
|||
// stuff, so if the user uses this utility to reformat it, it will put
|
||||
// it somewhere the system will find it later
|
||||
num_sectors = DEFAULT_SYSPARAM_SECTORS;
|
||||
base_addr = sdk_flashchip.chip_size - (4 + num_sectors) * sdk_flashchip.sector_size;
|
||||
base_addr = sdk_flashchip.chip_size - (5 + num_sectors) * sdk_flashchip.sector_size;
|
||||
}
|
||||
while (true) {
|
||||
printf("==> ");
|
||||
|
@ -246,5 +246,7 @@ void user_init(void)
|
|||
{
|
||||
uart_set_baud(0, 115200);
|
||||
|
||||
sdk_wifi_set_opmode(NULL_MODE);
|
||||
|
||||
xTaskCreate(sysparam_editor_task, "sysparam_editor_task", 512, NULL, 2, NULL);
|
||||
}
|
||||
|
|
|
@ -202,9 +202,8 @@ void tls_server_task(void *pvParameters)
|
|||
socklen_t peer_addr_len = sizeof(struct sockaddr_in);
|
||||
getpeername(client_ctx.fd, (struct sockaddr *)&peer_addr, &peer_addr_len);
|
||||
unsigned char buf[256];
|
||||
int len = sprintf((char *) buf, "O hai, client %d.%d.%d.%d:%d\nFree heap size is %d bytes\n",
|
||||
ip4_addr1(&peer_addr.sin_addr), ip4_addr2(&peer_addr.sin_addr),
|
||||
ip4_addr3(&peer_addr.sin_addr), ip4_addr4(&peer_addr.sin_addr),
|
||||
int len = sprintf((char *) buf, "O hai, client " IPSTR ":%d\nFree heap size is %d bytes\n",
|
||||
IP2STR((ip4_addr_t *)&peer_addr.sin_addr.s_addr),
|
||||
peer_addr.sin_port, xPortGetFreeHeapSize());
|
||||
while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0)
|
||||
{
|
||||
|
|
|
@ -146,9 +146,8 @@ void tls_server_task(void *pvParameters)
|
|||
|
||||
/* Prepare a message to the client */
|
||||
unsigned char buf[100];
|
||||
int len = sprintf((char *) buf, "O hai, client %d.%d.%d.%d:%d\r\nFree heap size is %d bytes\r\n",
|
||||
ip4_addr1(&sa.sin_addr), ip4_addr2(&sa.sin_addr),
|
||||
ip4_addr3(&sa.sin_addr), ip4_addr4(&sa.sin_addr),
|
||||
int len = sprintf((char *) buf, "O hai, client " IPSTR ":%d\r\nFree heap size is %d bytes\r\n",
|
||||
IP2STR((ip4_addr_t *)&sa.sin_addr.s_addr),
|
||||
ntohs(sa.sin_port), xPortGetFreeHeapSize());
|
||||
|
||||
/* Send the message and close the connection */
|
||||
|
|
|
@ -1,464 +1,5 @@
|
|||
/*
|
||||
* 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: Simon Goldschmidt
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIPOPTS_H__
|
||||
#define __LWIPOPTS_H__
|
||||
|
||||
#define LWIP_ESP 1
|
||||
#define ESP_RTOS 1
|
||||
#define PBUF_RSV_FOR_WLAN 1
|
||||
#define EBUF_LWIP 1
|
||||
#define ESP_TIMEWAIT_THRESHOLD 10000
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
|
||||
#define TCP_WND (TCP_MSS * 2)
|
||||
|
||||
#define LWIP_IGMP 1
|
||||
#include <stdint.h>
|
||||
#include <esp/hwrand.h>
|
||||
#define LWIP_RAND hwrand
|
||||
|
||||
/*
|
||||
-----------------------------------------------
|
||||
---------- Platform specific locking ----------
|
||||
-----------------------------------------------
|
||||
*/
|
||||
/**
|
||||
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
|
||||
* critical regions during buffer allocation, deallocation and memory
|
||||
* allocation and deallocation.
|
||||
*/
|
||||
#define SYS_LIGHTWEIGHT_PROT 1
|
||||
|
||||
/**
|
||||
* MEMCPY: override this if you have a faster implementation at hand than the
|
||||
* one included in your C library
|
||||
*/
|
||||
#define MEMCPY(dst,src,len) memcpy(dst,src,len)
|
||||
|
||||
/**
|
||||
* SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a
|
||||
* call to memcpy() if the length is known at compile time and is small.
|
||||
*/
|
||||
#define SMEMCPY(dst,src,len) memcpy(dst,src,len)
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- Memory options ----------
|
||||
------------------------------------
|
||||
*/
|
||||
/**
|
||||
* MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library
|
||||
* instead of the lwip internal allocator. Can save code size if you
|
||||
* already use it.
|
||||
*/
|
||||
#define MEM_LIBC_MALLOC 1
|
||||
|
||||
/**
|
||||
* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator.
|
||||
* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution
|
||||
* speed and usage from interrupts!
|
||||
*/
|
||||
#define MEMP_MEM_MALLOC 1
|
||||
|
||||
/**
|
||||
* MEM_ALIGNMENT: should be set to the alignment of the CPU
|
||||
* 4 byte alignment -> #define MEM_ALIGNMENT 4
|
||||
* 2 byte alignment -> #define MEM_ALIGNMENT 2
|
||||
*/
|
||||
#define MEM_ALIGNMENT 4
|
||||
|
||||
/*
|
||||
------------------------------------------------
|
||||
---------- Internal Memory Pool Sizes ----------
|
||||
------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
--------------------------------
|
||||
---------- ARP options -------
|
||||
--------------------------------
|
||||
*/
|
||||
/**
|
||||
* ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address
|
||||
* resolution. By default, only the most recent packet is queued per IP address.
|
||||
* This is sufficient for most protocols and mainly reduces TCP connection
|
||||
* startup time. Set this to 1 if you know your application sends more than one
|
||||
* packet in a row to an IP address that is not in the ARP cache.
|
||||
*/
|
||||
#define ARP_QUEUEING 1
|
||||
|
||||
/*
|
||||
--------------------------------
|
||||
---------- IP options ----------
|
||||
--------------------------------
|
||||
*/
|
||||
/**
|
||||
* IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that
|
||||
* this option does not affect outgoing packet sizes, which can be controlled
|
||||
* via IP_FRAG.
|
||||
*/
|
||||
#define IP_REASSEMBLY 0
|
||||
|
||||
/**
|
||||
* IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note
|
||||
* that this option does not affect incoming packet sizes, which can be
|
||||
* controlled via IP_REASSEMBLY.
|
||||
*/
|
||||
#define IP_FRAG 1
|
||||
|
||||
/**
|
||||
* IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally)
|
||||
* a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived
|
||||
* in this time, the whole packet is discarded.
|
||||
*/
|
||||
#define IP_REASS_MAXAGE 3
|
||||
|
||||
/**
|
||||
* IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled.
|
||||
* Since the received pbufs are enqueued, be sure to configure
|
||||
* PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive
|
||||
* packets even if the maximum amount of fragments is enqueued for reassembly!
|
||||
*/
|
||||
#define IP_REASS_MAX_PBUFS 10
|
||||
|
||||
/*
|
||||
----------------------------------
|
||||
---------- ICMP options ----------
|
||||
----------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
---------- RAW options ----------
|
||||
---------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
----------------------------------
|
||||
---------- DHCP options ----------
|
||||
----------------------------------
|
||||
*/
|
||||
/**
|
||||
* LWIP_DHCP==1: Enable DHCP module.
|
||||
*/
|
||||
#define LWIP_DHCP 1
|
||||
|
||||
#define LWIP_DHCP_BOOTP_FILE 0
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- AUTOIP options ----------
|
||||
------------------------------------
|
||||
*/
|
||||
/*
|
||||
----------------------------------
|
||||
---------- SNMP options ----------
|
||||
----------------------------------
|
||||
*/
|
||||
/*
|
||||
----------------------------------
|
||||
---------- IGMP options ----------
|
||||
----------------------------------
|
||||
*/
|
||||
/*
|
||||
----------------------------------
|
||||
---------- DNS options -----------
|
||||
----------------------------------
|
||||
*/
|
||||
/**
|
||||
* LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS
|
||||
* transport.
|
||||
*/
|
||||
#define LWIP_DNS 1
|
||||
|
||||
#define DNS_TABLE_SIZE 1
|
||||
#define DNS_MAX_NAME_LENGTH 128
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
---------- UDP options ----------
|
||||
---------------------------------
|
||||
*/
|
||||
/*
|
||||
---------------------------------
|
||||
---------- TCP options ----------
|
||||
---------------------------------
|
||||
*/
|
||||
/**
|
||||
* TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order.
|
||||
* Define to 0 if your device is low on memory.
|
||||
*/
|
||||
#define TCP_QUEUE_OOSEQ 0
|
||||
|
||||
/*
|
||||
* LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all
|
||||
* events (accept, sent, etc) that happen in the system.
|
||||
* LWIP_CALLBACK_API==1: The PCB callback function is called directly
|
||||
* for the event. This is the default.
|
||||
*/
|
||||
#define TCP_MSS 1460
|
||||
|
||||
/**
|
||||
* TCP_MAXRTX: Maximum number of retransmissions of data segments.
|
||||
*/
|
||||
#define TCP_MAXRTX 6
|
||||
|
||||
|
||||
/**
|
||||
* TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments.
|
||||
*/
|
||||
#define TCP_SYNMAXRTX 3
|
||||
|
||||
/*
|
||||
----------------------------------
|
||||
---------- Pbuf options ----------
|
||||
----------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
------------------------------------------------
|
||||
---------- Network Interfaces options ----------
|
||||
------------------------------------------------
|
||||
*/
|
||||
/**
|
||||
* LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data
|
||||
* to be sent into one single pbuf. This is for compatibility with DMA-enabled
|
||||
* MACs that do not support scatter-gather.
|
||||
* Beware that this might involve CPU-memcpy before transmitting that would not
|
||||
* be needed without this flag! Use this only if you need to!
|
||||
*
|
||||
* @todo: TCP and IP-frag do not work with this, yet:
|
||||
*/
|
||||
#define LWIP_NETIF_TX_SINGLE_PBUF 1
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- LOOPIF options ----------
|
||||
------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- SLIPIF options ----------
|
||||
------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- Thread options ----------
|
||||
------------------------------------
|
||||
*/
|
||||
/**
|
||||
* TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread.
|
||||
* The stack size value itself is platform-dependent, but is passed to
|
||||
* sys_thread_new() when the thread is created.
|
||||
*/
|
||||
#define TCPIP_THREAD_STACKSIZE 512 //not ok:384
|
||||
|
||||
/**
|
||||
* TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread.
|
||||
* The priority value itself is platform-dependent, but is passed to
|
||||
* sys_thread_new() when the thread is created.
|
||||
*/
|
||||
#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES-5)
|
||||
|
||||
/**
|
||||
* TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages
|
||||
* The queue size value itself is platform-dependent, but is passed to
|
||||
* sys_mbox_new() when tcpip_init is called.
|
||||
*/
|
||||
#define TCPIP_MBOX_SIZE 16
|
||||
|
||||
/**
|
||||
* DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
|
||||
* NETCONN_UDP. The queue size value itself is platform-dependent, but is passed
|
||||
* to sys_mbox_new() when the recvmbox is created.
|
||||
*/
|
||||
#define DEFAULT_UDP_RECVMBOX_SIZE 6
|
||||
|
||||
/**
|
||||
* DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
|
||||
* NETCONN_TCP. The queue size value itself is platform-dependent, but is passed
|
||||
* to sys_mbox_new() when the recvmbox is created.
|
||||
*/
|
||||
#define DEFAULT_TCP_RECVMBOX_SIZE 6
|
||||
|
||||
/**
|
||||
* DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections.
|
||||
* The queue size value itself is platform-dependent, but is passed to
|
||||
* sys_mbox_new() when the acceptmbox is created.
|
||||
*/
|
||||
#define DEFAULT_ACCEPTMBOX_SIZE 6
|
||||
|
||||
/*
|
||||
----------------------------------------------
|
||||
---------- Sequential layer options ----------
|
||||
----------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- Socket options ----------
|
||||
------------------------------------
|
||||
*/
|
||||
/**
|
||||
* LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and
|
||||
* SO_SNDTIMEO processing.
|
||||
*/
|
||||
#define LWIP_SO_SNDTIMEO 1
|
||||
|
||||
/**
|
||||
* LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and
|
||||
* SO_RCVTIMEO processing.
|
||||
*/
|
||||
#define LWIP_SO_RCVTIMEO 1
|
||||
|
||||
/**
|
||||
* LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT
|
||||
* options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set
|
||||
* in seconds. (does not require sockets.c, and will affect tcp.c)
|
||||
*/
|
||||
#define LWIP_TCP_KEEPALIVE 1
|
||||
|
||||
/**
|
||||
* LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing.
|
||||
*/
|
||||
#define LWIP_SO_RCVBUF 0
|
||||
|
||||
/**
|
||||
* SO_REUSE==1: Enable SO_REUSEADDR option.
|
||||
*/
|
||||
#define SO_REUSE 1
|
||||
|
||||
/*
|
||||
----------------------------------------
|
||||
---------- Statistics options ----------
|
||||
----------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
---------------------------------
|
||||
---------- PPP options ----------
|
||||
---------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
--------------------------------------
|
||||
---------- Checksum options ----------
|
||||
--------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
---------------------------------------
|
||||
---------- IPv6 options ---------------
|
||||
---------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
---------------------------------------
|
||||
---------- Hook options ---------------
|
||||
---------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
---------------------------------------
|
||||
---------- Debugging options ----------
|
||||
---------------------------------------
|
||||
*/
|
||||
|
||||
// Uncomment this line, and set the individual debug options you want, for IP stack debug output
|
||||
//#define LWIP_DEBUG
|
||||
|
||||
/**
|
||||
* ETHARP_DEBUG: Enable debugging in etharp.c.
|
||||
*/
|
||||
#define ETHARP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* PBUF_DEBUG: Enable debugging in pbuf.c.
|
||||
*/
|
||||
#define PBUF_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* API_LIB_DEBUG: Enable debugging in api_lib.c.
|
||||
*/
|
||||
#define API_LIB_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* SOCKETS_DEBUG: Enable debugging in sockets.c.
|
||||
*/
|
||||
#define SOCKETS_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* IP_DEBUG: Enable debugging for IP.
|
||||
*/
|
||||
#define IP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* MEMP_DEBUG: Enable debugging in memp.c.
|
||||
*/
|
||||
#define MEMP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug.
|
||||
*/
|
||||
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions.
|
||||
*/
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* UDP_DEBUG: Enable debugging in udp.c.
|
||||
*/
|
||||
#define UDP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* ICMP_DEBUG: Enable debugging in udp.c.
|
||||
*/
|
||||
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* TCPIP_DEBUG: Enable debugging in tcpip.c.
|
||||
*/
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
|
||||
/**
|
||||
* DHCP_DEBUG: Enable debugging in dhcp.c.
|
||||
*/
|
||||
#define DHCP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
#define LWIP_POSIX_SOCKETS_IO_NAMES 0
|
||||
|
||||
#endif /* __LWIPOPTS_H__ */
|
||||
/* Use the defaults for everything else */
|
||||
#include_next <lwipopts.h>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <string.h>
|
||||
#include <lwip/udp.h>
|
||||
#include <lwip/igmp.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
#include <espressif/esp_common.h>
|
||||
#include "upnp.h"
|
||||
|
||||
|
@ -18,13 +19,13 @@ static const char* get_my_ip(void)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief This function joins a multicast group witht he specified ip/port
|
||||
* @brief This function joins a multicast group with the specified ip/port
|
||||
* @param group_ip the specified multicast group ip
|
||||
* @param group_port the specified multicast port number
|
||||
* @param recv the lwip UDP callback
|
||||
* @retval udp_pcb* or NULL if joining failed
|
||||
*/
|
||||
static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, void (* recv)(void * arg, struct udp_pcb * upcb, struct pbuf * p, struct ip_addr * addr, u16_t port))
|
||||
static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port))
|
||||
{
|
||||
bool status = false;
|
||||
struct udp_pcb *upcb;
|
||||
|
@ -36,7 +37,7 @@ static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, voi
|
|||
printf("Error, udp_new failed");
|
||||
break;
|
||||
}
|
||||
udp_bind(upcb, IP_ADDR_ANY, group_port);
|
||||
udp_bind(upcb, IP4_ADDR_ANY, group_port);
|
||||
struct netif* netif = sdk_system_get_netif(STATION_IF);
|
||||
if (!netif) {
|
||||
printf("Error, netif is null");
|
||||
|
@ -46,10 +47,10 @@ static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, voi
|
|||
netif->flags |= NETIF_FLAG_IGMP;
|
||||
igmp_start(netif);
|
||||
}
|
||||
ip_addr_t ipgroup;
|
||||
ipaddr_aton(group_ip, &ipgroup);
|
||||
err_t err = igmp_joingroup(&netif->ip_addr, &ipgroup);
|
||||
if(ERR_OK != err) {
|
||||
ip4_addr_t ipgroup;
|
||||
ip4addr_aton(group_ip, &ipgroup);
|
||||
err_t err = igmp_joingroup_netif(netif, &ipgroup);
|
||||
if (ERR_OK != err) {
|
||||
printf("Failed to join multicast group: %d", err);
|
||||
break;
|
||||
}
|
||||
|
@ -68,7 +69,7 @@ static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, voi
|
|||
return upcb;
|
||||
}
|
||||
|
||||
static void send(struct udp_pcb *upcb, struct ip_addr *addr, u16_t port)
|
||||
static void send_udp(struct udp_pcb *upcb, const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
struct pbuf *p;
|
||||
char msg[500];
|
||||
|
@ -110,14 +111,14 @@ static void send(struct udp_pcb *upcb, struct ip_addr *addr, u16_t port)
|
|||
* @param port the remote port from which the packet was received
|
||||
* @retval None
|
||||
*/
|
||||
static void receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
|
||||
static void receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
if (p) {
|
||||
printf("Msg received port:%d len:%d\n", port, p->len);
|
||||
uint8_t *buf = (uint8_t*) p->payload;
|
||||
printf("Msg received port:%d len:%d\nbuf: %s\n", port, p->len, buf);
|
||||
|
||||
send(upcb, addr, port);
|
||||
send_udp(upcb, addr, port);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
|
1
examples/wificfg/.gitignore
vendored
Normal file
1
examples/wificfg/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
!local.mk
|
7
examples/wificfg/FreeRTOSConfig.h
Normal file
7
examples/wificfg/FreeRTOSConfig.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#define configUSE_TRACE_FACILITY 1
|
||||
#define configGENERATE_RUN_TIME_STATS 1
|
||||
#define portGET_RUN_TIME_COUNTER_VALUE() (RTC.COUNTER)
|
||||
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() {}
|
||||
|
||||
/* Use the defaults for everything else */
|
||||
#include_next<FreeRTOSConfig.h>
|
5
examples/wificfg/Makefile
Normal file
5
examples/wificfg/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Makefile for wificfg example
|
||||
PROGRAM=wificfg
|
||||
EXTRA_COMPONENTS=extras/dhcpserver extras/wificfg
|
||||
|
||||
include ../../common.mk
|
18
examples/wificfg/content/index.html
Normal file
18
examples/wificfg/content/index.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li class=\"active\"><a href=\"/\">Home</a></li>"
|
||||
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li><a href=\"/tasks.html\">Tasks</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>",
|
||||
"</body></html>"
|
1
examples/wificfg/local.mk
Normal file
1
examples/wificfg/local.mk
Normal file
|
@ -0,0 +1 @@
|
|||
FLASH_SIZE ?= 32
|
94
examples/wificfg/wificfg.c
Normal file
94
examples/wificfg/wificfg.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Example Wifi configuration via an access point.
|
||||
*
|
||||
* Copyright (C) 2016 OurAirQuality.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0, January 2004 (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/
|
||||
*
|
||||
* 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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <espressif/esp_common.h>
|
||||
#include <espressif/user_interface.h>
|
||||
#include <esp/uart.h>
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#include "wificfg/wificfg.h"
|
||||
|
||||
#include "sysparam.h"
|
||||
|
||||
static const char http_success_header[] = "HTTP/1.1 200 \r\n"
|
||||
"Content-Type: text/html; charset=utf-8\r\n"
|
||||
"Cache-Control: no-store\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n";
|
||||
static const char *http_index_content[] = {
|
||||
#include "content/index.html"
|
||||
};
|
||||
|
||||
static int handle_index(int s, wificfg_method method,
|
||||
uint32_t content_length,
|
||||
wificfg_content_type content_type,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
if (wificfg_write_string(s, http_success_header) < 0) return -1;
|
||||
|
||||
if (method != HTTP_METHOD_HEAD) {
|
||||
if (wificfg_write_string_chunk(s, http_index_content[0], buf, len) < 0) return -1;
|
||||
if (wificfg_write_html_title(s, buf, len, "Home") < 0) return -1;
|
||||
if (wificfg_write_string_chunk(s, http_index_content[1], buf, len) < 0) return -1;
|
||||
|
||||
socklen_t addr_len;
|
||||
struct sockaddr addr;
|
||||
addr_len = sizeof(addr);
|
||||
getpeername(s, (struct sockaddr*)&addr, &addr_len);
|
||||
|
||||
if (wificfg_write_string_chunk(s, "<dl class=\"dlh\">", buf, len) < 0) return -1;
|
||||
if (addr.sa_family == AF_INET) {
|
||||
struct sockaddr_in *sa = (struct sockaddr_in *)&addr;
|
||||
if (wificfg_write_string_chunk(s, "<dt>Peer address</dt>", buf, len) < 0) return -1;
|
||||
snprintf(buf, len, "<dd>" IPSTR " : %d</dd>",
|
||||
IP2STR((ip4_addr_t *)&sa->sin_addr.s_addr), ntohs(sa->sin_port));
|
||||
if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1;
|
||||
}
|
||||
|
||||
if (wificfg_write_string_chunk(s, "</dl>", buf, len) < 0) return -1;
|
||||
if (wificfg_write_string_chunk(s, http_index_content[2], buf, len) < 0) return -1;
|
||||
if (wificfg_write_chunk_end(s) < 0) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const wificfg_dispatch dispatch_list[] = {
|
||||
{"/", HTTP_METHOD_GET, handle_index, false},
|
||||
{"/index.html", HTTP_METHOD_GET, handle_index, false},
|
||||
{NULL, HTTP_METHOD_ANY, NULL}
|
||||
};
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
uart_set_baud(0, 115200);
|
||||
printf("SDK version:%s\n", sdk_system_get_sdk_version());
|
||||
|
||||
sdk_wifi_set_sleep_type(WIFI_SLEEP_MODEM);
|
||||
|
||||
wificfg_init(80, dispatch_list);
|
||||
}
|
|
@ -152,7 +152,7 @@ bool bmp180_measure(i2c_dev_t *dev, bmp180_constants_t *c, int32_t *temperature,
|
|||
if (!temperature && !pressure)
|
||||
return false;
|
||||
|
||||
// Temperature is always needed, allso required for pressure only.
|
||||
// Temperature is always needed, also required for pressure only.
|
||||
//
|
||||
// Calculation taken from BMP180 Datasheet
|
||||
int32_t UT, X1, X2, B5;
|
||||
|
|
|
@ -14,18 +14,22 @@
|
|||
* BSD Licensed as described in the file LICENSE
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/api.h>
|
||||
#include "esplibs/libmain.h"
|
||||
|
||||
/* Grow the size of the lwip dhcp_msg struct's options field, as LWIP
|
||||
defaults to a 68 octet options field for its DHCP client, and most
|
||||
full-sized clients send us more than this. */
|
||||
#define DHCP_OPTIONS_LEN 312
|
||||
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/ip.h>
|
||||
#include <lwip/prot/dhcp.h>
|
||||
#include <lwip/prot/iana.h>
|
||||
|
||||
_Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 312, "dhcp_msg_t should have extended options size");
|
||||
|
||||
|
@ -35,15 +39,20 @@ _Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 3
|
|||
|
||||
typedef struct {
|
||||
uint8_t hwaddr[NETIF_MAX_HWADDR_LEN];
|
||||
uint8_t active;
|
||||
uint32_t expires;
|
||||
} dhcp_lease_t;
|
||||
|
||||
typedef struct {
|
||||
struct netconn *nc;
|
||||
uint8_t max_leases;
|
||||
ip_addr_t first_client_addr;
|
||||
ip4_addr_t first_client_addr;
|
||||
struct netif *server_if;
|
||||
dhcp_lease_t *leases; /* length max_leases */
|
||||
/* Optional router */
|
||||
ip4_addr_t router;
|
||||
/* Optional DNS server */
|
||||
ip4_addr_t dns;
|
||||
} server_state_t;
|
||||
|
||||
/* Only one DHCP server task can run at once, so we have global state
|
||||
|
@ -68,51 +77,67 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u
|
|||
static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr);
|
||||
|
||||
/* Copy IP address as dotted decimal to 'dest', must be at least 16 bytes long */
|
||||
inline static void sprintf_ipaddr(const ip_addr_t *addr, char *dest)
|
||||
inline static void sprintf_ipaddr(const ip4_addr_t *addr, char *dest)
|
||||
{
|
||||
if(addr == NULL)
|
||||
if (addr == NULL)
|
||||
sprintf(dest, "NULL");
|
||||
else
|
||||
sprintf(dest, "%d.%d.%d.%d", ip4_addr1(addr),
|
||||
ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr));
|
||||
}
|
||||
|
||||
void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases)
|
||||
void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases)
|
||||
{
|
||||
/* Stop any existing running dhcpserver */
|
||||
if(dhcpserver_task_handle)
|
||||
if (dhcpserver_task_handle)
|
||||
dhcpserver_stop();
|
||||
|
||||
state = malloc(sizeof(server_state_t));
|
||||
state->max_leases = max_leases;
|
||||
state->leases = calloc(max_leases, sizeof(dhcp_lease_t));
|
||||
bzero(state->leases, max_leases * sizeof(dhcp_lease_t));
|
||||
// state->server_if is assigned once the task is running - see comment in dhcpserver_task()
|
||||
ip_addr_copy(state->first_client_addr, *first_client_addr);
|
||||
ip4_addr_copy(state->first_client_addr, *first_client_addr);
|
||||
|
||||
xTaskCreate(dhcpserver_task, "DHCPServer", 768, NULL, 8, &dhcpserver_task_handle);
|
||||
/* Clear options */
|
||||
ip4_addr_set_zero(&state->router);
|
||||
ip4_addr_set_zero(&state->dns);
|
||||
|
||||
xTaskCreate(dhcpserver_task, "DHCP Server", 448, NULL, 2, &dhcpserver_task_handle);
|
||||
}
|
||||
|
||||
void dhcpserver_stop(void)
|
||||
{
|
||||
if(dhcpserver_task_handle) {
|
||||
if (dhcpserver_task_handle) {
|
||||
vTaskDelete(dhcpserver_task_handle);
|
||||
free(state);
|
||||
dhcpserver_task_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void dhcpserver_set_router(const ip4_addr_t *router)
|
||||
{
|
||||
ip4_addr_copy(state->router, *router);
|
||||
}
|
||||
|
||||
void dhcpserver_set_dns(const ip4_addr_t *dns)
|
||||
{
|
||||
ip4_addr_copy(state->dns, *dns);
|
||||
}
|
||||
|
||||
static void dhcpserver_task(void *pxParameter)
|
||||
{
|
||||
/* netif_list isn't assigned until after user_init completes, which is why we do it inside the task */
|
||||
state->server_if = netif_list; /* TODO: Make this configurable */
|
||||
|
||||
state->nc = netconn_new (NETCONN_UDP);
|
||||
if(!state->nc) {
|
||||
if (!state->nc) {
|
||||
printf("DHCP Server Error: Failed to allocate socket.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
netconn_bind(state->nc, IP_ADDR_ANY, DHCP_SERVER_PORT);
|
||||
netconn_bind(state->nc, IP4_ADDR_ANY, LWIP_IANA_PORT_DHCP_SERVER);
|
||||
netconn_bind_if (state->nc, netif_get_index(state->server_if));
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
@ -121,29 +146,32 @@ static void dhcpserver_task(void *pxParameter)
|
|||
|
||||
/* Receive a DHCP packet */
|
||||
err_t err = netconn_recv(state->nc, &netbuf);
|
||||
if(err != ERR_OK) {
|
||||
if (err != ERR_OK) {
|
||||
printf("DHCP Server Error: Failed to receive DHCP packet. err=%d\r\n", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* expire any leases that have passed */
|
||||
uint32_t now = xTaskGetTickCount();
|
||||
for(int i = 0; i < state->max_leases; i++) {
|
||||
uint32_t expires = state->leases[i].expires;
|
||||
if(expires && expires < now)
|
||||
state->leases[i].expires = 0;
|
||||
for (int i = 0; i < state->max_leases; i++) {
|
||||
if (state->leases[i].active) {
|
||||
uint32_t expires = state->leases[i].expires - now;
|
||||
if (expires >= 0x80000000) {
|
||||
state->leases[i].active = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ip_addr_t received_ip;
|
||||
u16_t port;
|
||||
netconn_addr(state->nc, &received_ip, &port);
|
||||
|
||||
if(netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) {
|
||||
if (netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) {
|
||||
/* too short to be a valid DHCP client message */
|
||||
netbuf_delete(netbuf);
|
||||
continue;
|
||||
}
|
||||
if(netbuf_len(netbuf) >= sizeof(struct dhcp_msg)) {
|
||||
if (netbuf_len(netbuf) >= sizeof(struct dhcp_msg)) {
|
||||
printf("DHCP Server Warning: Client sent more options than we know how to parse. len=%d\r\n", netbuf_len(netbuf));
|
||||
}
|
||||
|
||||
|
@ -152,18 +180,18 @@ static void dhcpserver_task(void *pxParameter)
|
|||
|
||||
uint8_t *message_type = find_dhcp_option(&received, DHCP_OPTION_MESSAGE_TYPE,
|
||||
DHCP_OPTION_MESSAGE_TYPE_LEN, NULL);
|
||||
if(!message_type) {
|
||||
if (!message_type) {
|
||||
printf("DHCP Server Error: No message type field found");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
printf("State dump. Message type %d\n", *message_type);
|
||||
for(int i = 0; i < state->max_leases; i++) {
|
||||
for (int i = 0; i < state->max_leases; i++) {
|
||||
dhcp_lease_t *lease = &state->leases[i];
|
||||
printf("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i, lease->expires, lease->hwaddr[0],
|
||||
lease->hwaddr[1], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
|
||||
lease->hwaddr[5]);
|
||||
printf("lease slot %d active %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i,
|
||||
lease->active, lease->expires - now,
|
||||
lease->hwaddr[0], lease->hwaddr[1], lease->hwaddr[2],
|
||||
lease->hwaddr[3], lease->hwaddr[4], lease->hwaddr[5]);
|
||||
}
|
||||
|
||||
switch(*message_type) {
|
||||
|
@ -184,13 +212,13 @@ static void dhcpserver_task(void *pxParameter)
|
|||
|
||||
static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
|
||||
{
|
||||
if(dhcpmsg->htype != DHCP_HTYPE_ETH)
|
||||
if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET)
|
||||
return;
|
||||
if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
|
||||
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
|
||||
return;
|
||||
|
||||
dhcp_lease_t *freelease = find_lease_slot(dhcpmsg->chaddr);
|
||||
if(!freelease) {
|
||||
if (!freelease) {
|
||||
printf("DHCP Server: All leases taken.\r\n");
|
||||
return; /* Nothing available, so do nothing */
|
||||
}
|
||||
|
@ -199,13 +227,19 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
|
|||
dhcpmsg->op = DHCP_BOOTREPLY;
|
||||
bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
|
||||
|
||||
ip_addr_copy(dhcpmsg->yiaddr, state->first_client_addr);
|
||||
ip4_addr4(&(dhcpmsg->yiaddr)) += (freelease - state->leases);
|
||||
dhcpmsg->yiaddr.addr = lwip_htonl(lwip_ntohl(state->first_client_addr.addr) + (freelease - state->leases));
|
||||
|
||||
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
|
||||
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_OFFER);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4);
|
||||
if (!ip4_addr_isany_val(state->router)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
|
||||
}
|
||||
if (!ip4_addr_isany_val(state->dns)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
|
||||
}
|
||||
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
|
||||
|
||||
struct netbuf *netbuf = netbuf_new();
|
||||
|
@ -218,17 +252,17 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
|
|||
static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
||||
{
|
||||
static char ipbuf[16];
|
||||
if(dhcpmsg->htype != DHCP_HTYPE_ETH)
|
||||
if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET)
|
||||
return;
|
||||
if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
|
||||
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
|
||||
return;
|
||||
|
||||
ip_addr_t requested_ip;
|
||||
ip4_addr_t requested_ip;
|
||||
uint8_t *requested_ip_opt = find_dhcp_option(dhcpmsg, DHCP_OPTION_REQUESTED_IP, 4, NULL);
|
||||
if(requested_ip_opt) {
|
||||
memcpy(&requested_ip.addr, requested_ip_opt, 4);
|
||||
} else if(ip_addr_cmp(&requested_ip, IP_ADDR_ANY)) {
|
||||
ip_addr_copy(requested_ip, dhcpmsg->ciaddr);
|
||||
if (requested_ip_opt) {
|
||||
memcpy(&requested_ip.addr, requested_ip_opt, 4);
|
||||
} else if (ip4_addr_cmp(&requested_ip, IP4_ADDR_ANY4)) {
|
||||
ip4_addr_copy(requested_ip, dhcpmsg->ciaddr);
|
||||
} else {
|
||||
printf("DHCP Server Error: No requested IP\r\n");
|
||||
send_dhcp_nak(dhcpmsg);
|
||||
|
@ -236,7 +270,7 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
}
|
||||
|
||||
/* Test the first 4 octets match */
|
||||
if(ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
|
||||
if (ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
|
||||
|| ip4_addr2(&requested_ip) != ip4_addr2(&state->first_client_addr)
|
||||
|| ip4_addr3(&requested_ip) != ip4_addr3(&state->first_client_addr)) {
|
||||
sprintf_ipaddr(&requested_ip, ipbuf);
|
||||
|
@ -246,14 +280,14 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
}
|
||||
/* Test the last octet is in the MAXCLIENTS range */
|
||||
int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&state->first_client_addr);
|
||||
if(octet_offs < 0 || octet_offs >= state->max_leases) {
|
||||
if (octet_offs < 0 || octet_offs >= state->max_leases) {
|
||||
printf("DHCP Server Error: Address out of range\r\n");
|
||||
send_dhcp_nak(dhcpmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp_lease_t *requested_lease = state->leases + octet_offs;
|
||||
if(requested_lease->expires != 0 && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
|
||||
if (requested_lease->active && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
|
||||
{
|
||||
printf("DHCP Server Error: Lease for address already taken\r\n");
|
||||
send_dhcp_nak(dhcpmsg);
|
||||
|
@ -265,13 +299,17 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
printf("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", ipbuf, requested_lease->hwaddr[0],
|
||||
requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4],
|
||||
requested_lease->hwaddr[5]);
|
||||
requested_lease->expires = DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
|
||||
uint32_t now = xTaskGetTickCount();
|
||||
requested_lease->expires = now + DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
|
||||
requested_lease->active = 1;
|
||||
|
||||
sdk_wifi_softap_set_station_info(requested_lease->hwaddr, &requested_ip);
|
||||
|
||||
/* Reuse the REQUEST message as the ACK message */
|
||||
dhcpmsg->op = DHCP_BOOTREPLY;
|
||||
bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);
|
||||
|
||||
ip_addr_copy(dhcpmsg->yiaddr, requested_ip);
|
||||
ip4_addr_copy(dhcpmsg->yiaddr, requested_ip);
|
||||
|
||||
uint8_t *opt = (uint8_t *)&dhcpmsg->options;
|
||||
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_ACK);
|
||||
|
@ -279,6 +317,13 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4);
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4);
|
||||
if (!ip4_addr_isany_val(state->router)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4);
|
||||
}
|
||||
if (!ip4_addr_isany_val(state->dns)) {
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4);
|
||||
}
|
||||
|
||||
opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0);
|
||||
|
||||
struct netbuf *netbuf = netbuf_new();
|
||||
|
@ -291,7 +336,8 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
|
|||
static void handle_dhcp_release(struct dhcp_msg *dhcpmsg)
|
||||
{
|
||||
dhcp_lease_t *lease = find_lease_slot(dhcpmsg->chaddr);
|
||||
if(lease) {
|
||||
if (lease) {
|
||||
lease->active = 0;
|
||||
lease->expires = 0;
|
||||
}
|
||||
}
|
||||
|
@ -319,17 +365,17 @@ static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8
|
|||
uint8_t *start = (uint8_t *)&msg->options;
|
||||
uint8_t *msg_end = (uint8_t *)msg + sizeof(struct dhcp_msg);
|
||||
|
||||
for(uint8_t *p = start; p < msg_end-2;) {
|
||||
for (uint8_t *p = start; p < msg_end-2;) {
|
||||
uint8_t type = *p++;
|
||||
uint8_t len = *p++;
|
||||
if(type == DHCP_OPTION_END)
|
||||
if (type == DHCP_OPTION_END)
|
||||
return NULL;
|
||||
if(p+len >= msg_end)
|
||||
if (p+len >= msg_end)
|
||||
break; /* We've overrun our valid DHCP message size, or this isn't a valid option */
|
||||
if(type == option_num) {
|
||||
if(len < min_length)
|
||||
if (type == option_num) {
|
||||
if (len < min_length)
|
||||
break;
|
||||
if(length)
|
||||
if (length)
|
||||
*length = len;
|
||||
return p; /* start of actual option data */
|
||||
}
|
||||
|
@ -349,7 +395,7 @@ static uint8_t *add_dhcp_option_byte(uint8_t *opt, uint8_t type, uint8_t value)
|
|||
static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, uint8_t len)
|
||||
{
|
||||
*opt++ = type;
|
||||
if(len) {
|
||||
if (len) {
|
||||
*opt++ = len;
|
||||
memcpy(opt, value, len);
|
||||
}
|
||||
|
@ -360,8 +406,8 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u
|
|||
static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr)
|
||||
{
|
||||
dhcp_lease_t *empty_lease = NULL;
|
||||
for(int i = 0; i < state->max_leases; i++) {
|
||||
if(state->leases[i].expires == 0 && !empty_lease)
|
||||
for (int i = 0; i < state->max_leases; i++) {
|
||||
if (!state->leases[i].active && !empty_lease)
|
||||
empty_lease = &state->leases[i];
|
||||
else if (memcmp(hwaddr, state->leases[i].hwaddr, 6) == 0)
|
||||
return &state->leases[i];
|
||||
|
|
|
@ -26,14 +26,20 @@ extern "C" {
|
|||
to a client. Subsequent lease addresses are calculated by
|
||||
incrementing the final octet of the IPv4 address, up to max_leases.
|
||||
*/
|
||||
void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases);
|
||||
void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases);
|
||||
|
||||
void dhcpserver_get_lease(const ip_addr_t *first_client_addr, uint8_t max_leases);
|
||||
void dhcpserver_get_lease(const ip4_addr_t *first_client_addr, uint8_t max_leases);
|
||||
|
||||
/* Stop DHCP server.
|
||||
*/
|
||||
void dhcpserver_stop(void);
|
||||
|
||||
/* Set a router address to send as an option. */
|
||||
void dhcpserver_set_router(const ip4_addr_t *router);
|
||||
|
||||
/* Set a DNS address to send as an option. */
|
||||
void dhcpserver_set_dns(const ip4_addr_t *dns);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
/* Convert normal decimal to binary coded decimal */
|
||||
static inline uint8_t decToBcd(uint8_t dec)
|
||||
{
|
||||
return(((dec / 10) * 16) + (dec % 10));
|
||||
return (dec / 10) * 16 + dec % 10;
|
||||
}
|
||||
|
||||
/* Convert binary coded decimal to normal decimal */
|
||||
static inline uint8_t bcdToDec(uint8_t bcd)
|
||||
{
|
||||
return(((bcd / 16) * 10) + (bcd % 16));
|
||||
return (bcd / 16) * 10 + bcd % 16;
|
||||
}
|
||||
|
||||
/* Send a number of bytes to the rtc over i2c
|
||||
|
@ -48,6 +48,8 @@ int ds3231_setTime(i2c_dev_t *dev, struct tm *time)
|
|||
data[0] = decToBcd(time->tm_sec);
|
||||
data[1] = decToBcd(time->tm_min);
|
||||
data[2] = decToBcd(time->tm_hour);
|
||||
/* The week data must be in the range 1 to 7, and to keep the start on the
|
||||
* same day as for tm_wday have it start at 1 on Sunday. */
|
||||
data[3] = decToBcd(time->tm_wday + 1);
|
||||
data[4] = decToBcd(time->tm_mday);
|
||||
data[5] = decToBcd(time->tm_mon + 1);
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
|
||||
/** Set this to 1 on platforms where strnstr is not available */
|
||||
#ifndef LWIP_HTTPD_STRNSTR_PRIVATE
|
||||
#define LWIP_HTTPD_STRNSTR_PRIVATE 1
|
||||
#define LWIP_HTTPD_STRNSTR_PRIVATE 0
|
||||
#endif
|
||||
|
||||
/** Set this to one to show error pages when parsing a request fails instead
|
||||
|
@ -2675,7 +2675,7 @@ http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
|
|||
* Initialize the httpd with the specified local address.
|
||||
*/
|
||||
static void
|
||||
httpd_init_addr(ip_addr_t *local_addr)
|
||||
httpd_init_addr(const ip_addr_t *local_addr)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
err_t err;
|
||||
|
|
|
@ -62,7 +62,7 @@ void sdk_rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id,
|
|||
reg_add##_lsb, indata)
|
||||
|
||||
|
||||
void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins)
|
||||
void i2s_dma_init(i2s_dma_isr_t isr, void *arg, i2s_clock_div_t clock_div, i2s_pins_t pins)
|
||||
{
|
||||
// reset DMA
|
||||
SET_MASK_BITS(SLC.CONF0, SLC_CONF0_RX_LINK_RESET);
|
||||
|
@ -83,7 +83,7 @@ void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins)
|
|||
SLC_RX_DESCRIPTOR_CONF_RX_EOF_MODE | SLC_RX_DESCRIPTOR_CONF_RX_FILL_MODE);
|
||||
|
||||
if (isr) {
|
||||
_xt_isr_attach(INUM_SLC, isr);
|
||||
_xt_isr_attach(INUM_SLC, isr, arg);
|
||||
SET_MASK_BITS(SLC.INT_ENABLE, SLC_INT_ENABLE_RX_EOF);
|
||||
SLC.INT_CLEAR = 0xFFFFFFFF;
|
||||
_xt_isr_unmask(1<<INUM_SLC);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*i2s_dma_isr_t)(void);
|
||||
typedef void (*i2s_dma_isr_t)(void *);
|
||||
|
||||
typedef struct dma_descriptor {
|
||||
uint32_t blocksize:12;
|
||||
|
@ -61,10 +61,11 @@ typedef struct {
|
|||
* Initialize I2S and DMA subsystems.
|
||||
*
|
||||
* @param isr ISR handler. Can be NULL if interrupt handling is not needed.
|
||||
* @param arg ISR handler arg.
|
||||
* @param clock_div I2S clock configuration.
|
||||
* @param pins I2S pin configuration. Specifies which pins are enabled in I2S.
|
||||
*/
|
||||
void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins);
|
||||
void i2s_dma_init(i2s_dma_isr_t isr, void *arg, i2s_clock_div_t clock_div, i2s_pins_t pins);
|
||||
|
||||
/**
|
||||
* Calculate I2S dividers for the specified frequency.
|
||||
|
|
|
@ -43,7 +43,7 @@ typedef struct pwmInfoDefinition
|
|||
|
||||
static PWMInfo pwmInfo;
|
||||
|
||||
static void frc1_interrupt_handler(void)
|
||||
static void frc1_interrupt_handler(void *arg)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
bool out = true;
|
||||
|
@ -97,7 +97,7 @@ void pwm_init(uint8_t npins, const uint8_t* pins)
|
|||
pwm_stop();
|
||||
|
||||
/* set up ISRs */
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
|
||||
|
||||
/* Flag not running */
|
||||
pwmInfo.running = 0;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include "sntp.h"
|
||||
|
||||
#include "lwip/timers.h"
|
||||
#include "lwip/timeouts.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
@ -136,12 +136,12 @@
|
|||
#define SNTP_STARTUP_DELAY 0
|
||||
#endif
|
||||
|
||||
/** SNTP receive timeout - in milliseconds
|
||||
/** SNTP receive timeout - in seconds
|
||||
* Also used as retry timeout - this shouldn't be too low.
|
||||
* Default is 3 seconds.
|
||||
*/
|
||||
#ifndef SNTP_RECV_TIMEOUT
|
||||
#define SNTP_RECV_TIMEOUT 3000
|
||||
#define SNTP_RECV_TIMEOUT 3
|
||||
#endif
|
||||
|
||||
/** SNTP update delay - in milliseconds
|
||||
|
@ -384,8 +384,8 @@ sntp_request(void *arg)
|
|||
/* bind to local address */
|
||||
if (lwip_bind(sock, (struct sockaddr *)&local, sizeof(local)) == 0) {
|
||||
/* set recv timeout */
|
||||
timeout = SNTP_RECV_TIMEOUT;
|
||||
lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
const struct timeval timeout = { SNTP_RECV_TIMEOUT, 0 };
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
/* prepare SNTP request */
|
||||
sntp_initialize_request(&sntpmsg);
|
||||
|
@ -511,7 +511,7 @@ sntp_try_next_server(void* arg)
|
|||
|
||||
/** UDP recv callback for the sntp pcb */
|
||||
static void
|
||||
sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
|
||||
sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
u8_t mode;
|
||||
u8_t stratum;
|
||||
|
@ -597,7 +597,7 @@ sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, ip_addr_t *addr, u16_t
|
|||
* @param server_addr resolved IP address of the SNTP server
|
||||
*/
|
||||
static void
|
||||
sntp_send_request(ip_addr_t *server_addr)
|
||||
sntp_send_request(const ip_addr_t *server_addr)
|
||||
{
|
||||
struct pbuf* p;
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM);
|
||||
|
@ -611,7 +611,7 @@ sntp_send_request(ip_addr_t *server_addr)
|
|||
pbuf_free(p);
|
||||
|
||||
/* set up receive timeout: try next server or retry on timeout */
|
||||
sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
|
||||
sys_timeout((u32_t)SNTP_RECV_TIMEOUT * 1000, sntp_try_next_server, NULL);
|
||||
#if SNTP_CHECK_RESPONSE >= 1
|
||||
/* save server address to verify it in sntp_recv */
|
||||
ip_addr_set(&sntp_last_server_address, server_addr);
|
||||
|
@ -629,7 +629,7 @@ sntp_send_request(ip_addr_t *server_addr)
|
|||
* DNS found callback when using DNS names as server address.
|
||||
*/
|
||||
static void
|
||||
sntp_dns_found(const char* hostname, ip_addr_t *ipaddr, void *arg)
|
||||
sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(hostname);
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
|
|
@ -102,7 +102,7 @@ void sntp_update_rtc(time_t t, uint32_t us) {
|
|||
// DEBUG: Compute and print drift
|
||||
int64_t sntp_current = sntp_base + TIMER_COUNT - tim_ref;
|
||||
int64_t sntp_correct = (((uint64_t)us + (uint64_t)t * 1000000U)<<12) / cal;
|
||||
printf("\nRTC Adjust: drift = %ld ticks, cal = %d\n", (time_t)(sntp_correct - sntp_current), cal);
|
||||
printf("\nRTC Adjust: drift = %lld ticks, cal = %d\n", (time_t)(sntp_correct - sntp_current), (uint32_t)cal);
|
||||
|
||||
tim_ref = TIMER_COUNT;
|
||||
cal = sdk_system_rtc_clock_cali_proc();
|
||||
|
|
|
@ -44,7 +44,7 @@ static SemaphoreHandle_t uart0_sem = NULL;
|
|||
static bool inited = false;
|
||||
static void uart0_rx_init(void);
|
||||
|
||||
IRAM void uart0_rx_handler(void)
|
||||
IRAM void uart0_rx_handler(void *arg)
|
||||
{
|
||||
// TODO: Handle UART1, see reg 0x3ff20020, bit2, bit0 represents uart1 and uart0 respectively
|
||||
if (!UART(UART0).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) {
|
||||
|
@ -97,7 +97,7 @@ static void uart0_rx_init(void)
|
|||
int trig_lvl = 1;
|
||||
uart0_sem = xSemaphoreCreateCounting(UART0_RX_SIZE, 0);
|
||||
|
||||
_xt_isr_attach(INUM_UART, uart0_rx_handler);
|
||||
_xt_isr_attach(INUM_UART, uart0_rx_handler, NULL);
|
||||
_xt_isr_unmask(1 << INUM_UART);
|
||||
|
||||
// reset the rx fifo
|
||||
|
|
10
extras/wificfg/component.mk
Normal file
10
extras/wificfg/component.mk
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Component makefile for extras/wificfg
|
||||
|
||||
# Expected anyone using wificfg includes it as 'wificfg/wificfg.h'
|
||||
INC_DIRS += $(wificfg_ROOT)..
|
||||
|
||||
# args for passing into compile rule generation
|
||||
wificfg_INC_DIR =
|
||||
wificfg_SRC_DIR = $(wificfg_ROOT)
|
||||
|
||||
$(eval $(call component_compile_rules,wificfg))
|
30
extras/wificfg/content/challenge.html
Normal file
30
extras/wificfg/content/challenge.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li class=\"active\"><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
|
||||
"<li><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>"
|
||||
"<form action=\"/challenge.html\" method=\"post\">"
|
||||
"<fieldset>"
|
||||
"<legend>Unlock the configuration interface</legend>"
|
||||
"<dl class=\"dlh\">"
|
||||
"<dt><label for=\"pw\">Password</label></dt>"
|
||||
"<dd><input id=\"pw\" type=\"text\" maxlength=\"32\" name=\"cfg_password\" "
|
||||
"placeholder=\"unlock-password\" value=\"\"></dd>"
|
||||
"</dl>"
|
||||
"<center><input type=\"submit\" value=\"Unlock\"></center>"
|
||||
"</fieldset>"
|
||||
"</form>"
|
||||
"</body></html>"
|
11
extras/wificfg/content/favicon.ico
Normal file
11
extras/wificfg/content/favicon.ico
Normal file
|
@ -0,0 +1,11 @@
|
|||
"HTTP/1.1 200 \r\n"
|
||||
"Content-Type: image/svg+xml\r\n"
|
||||
"Cache-Control: max-age=900\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n",
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
|
||||
"<svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\" version=\"1.1\">"
|
||||
"<defs><linearGradient id=\"g1\" y2=\"248.63\" gradientUnits=\"userSpaceOnUse\" x2=\"153\" gradientTransform=\"matrix(.20068 0 0 .20068 -54.336 -1.0508)\" y1=\"15.424\" x1=\"99.777\"><stop style=\"stop-color:#0088FF\" offset=\"0\"/><stop style=\"stop-color:#b2dbff\" offset=\"1\"/></linearGradient></defs>"
|
||||
"<path style=\"stroke-linejoin:round;color:#000000;stroke:#aaaaaa;stroke-linecap:round;fill:url(#g1)\" d=\"m22.7 0.94747c-0.474 0.03238-0.934 0.10563-1.398 0.15883h-0.032l-1.112 6.068c-1.812 0.4127-3.517 1.1132-5.051 2.065l-4.988-3.59c-1.3485 1.0468-2.5754 2.2677-3.6536 3.59l3.4628 5.0517c-1.0514 1.606-1.842 3.441-2.2874 5.369v0.031l-6.0361 0.953c-0.1104 0.902-0.1589 1.833-0.1589 2.764 0 0.762 0.021 1.514 0.0953 2.256l6.0362 1.08c0.4293 2.096 1.2448 4.054 2.3827 5.782l-3.5899 4.924c1.0281 1.277 2.2151 2.439 3.4946 3.463l5.0833-3.494c1.776 1.133 3.759 1.928 5.909 2.319l0.953 6.004c0.677 0.062 1.372 0.064 2.065 0.064 0.979 0 1.914-0.037 2.859-0.159l1.144-6.132c2.041-0.507 3.958-1.389 5.623-2.573l4.893 3.558c1.268-1.079 2.429-2.32 3.431-3.653l-3.558-5.147c0.963-1.664 1.631-3.5 1.969-5.464l6.005-0.953c0.052-0.627 0.063-1.234 0.063-1.875 0-1.112-0.129-2.203-0.286-3.272l-6.099-1.112c-0.478-1.765-1.263-3.412-2.256-4.892l3.59-4.9245c-1.113-1.3608-2.382-2.618-3.781-3.6852l-5.178 3.5581c-1.488-0.8802-3.09-1.5556-4.829-1.9379l-0.953-6.0362c-0.868-0.102-1.742-0.15883-2.637-0.15883-0.242 0-0.491-0.00761-0.731 0-0.117 0.00371-0.232-0.00681-0.349 0-0.032 0.00184-0.064-0.00216-0.095 0zm0.826 15.44c0.116-0.006 0.231 0 0.349 0 3.761 0 6.83 3.07 6.83 6.831 0 3.76-3.069 6.798-6.83 6.798s-6.799-3.038-6.799-6.798c0-3.643 2.852-6.648 6.45-6.831z\"/>"
|
||||
"</svg>"
|
8
extras/wificfg/content/script.js
Normal file
8
extras/wificfg/content/script.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
"HTTP/1.1 200 \r\n"
|
||||
"Content-Type: text/javascript\r\n"
|
||||
"Cache-Control: max-age=900\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n",
|
||||
"function myFunction() { var x = document.getElementById(\"myTopnav\");"
|
||||
"if (x.className === \"topnav\") { x.className += \" responsive\"; } else { x.className = \"topnav\"; } }"
|
19
extras/wificfg/content/style.css
Normal file
19
extras/wificfg/content/style.css
Normal file
|
@ -0,0 +1,19 @@
|
|||
"HTTP/1.1 200 \r\n"
|
||||
"Content-Type: text/css\r\n"
|
||||
"Cache-Control: max-age=900\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"\r\n",
|
||||
".dlh dd,h1{font-weight:300}.dlh{font-size:0;text-align:center}"
|
||||
".dlh dd,.dlh dt{width:48%;width:calc(50% - 10px);margin:8px 0;display:inline-block;font-size:16px;vertical-align:middle}"
|
||||
".dlh dt{text-align:right;padding-right:10px}"
|
||||
".dlh dd{font-size:18px;text-align:left;padding-left:10px}"
|
||||
"ul.topnav{list-style-type:none;margin:0;padding:0;overflow:hidden;background-color:#bbb}"
|
||||
"ul.topnav li{float:left}"
|
||||
"ul.topnav li a{display:inline-block;color:#444;text-align:center;padding:14px 16px;text-decoration:none;transition:.3s;font-size:17px}"
|
||||
"ul.topnav li a:hover{background-color:#ddd}ul.topnav li.icon{display:none}"
|
||||
"@media screen and (max-width:680px){ul.topnav li:not(.active){display:none}ul.topnav li.icon{float:right;display:inline-block}ul.topnav.responsive{position:relative}ul.topnav.responsive li.icon{position:absolute;right:0;top:0}ul.topnav.responsive li{float:none;display:inline}ul.topnav.responsive li a{display:block;text-align:left}}"
|
||||
"html{min-height:100%}"
|
||||
"body{background:#d0e4f7;background:-moz-linear-gradient(top, #d0e4f7 0%, #73b1e7 24%, #0a77d5 50%, #539fe1 79%, #87bcea 100%);background:-webkit-linear-gradient(top, #d0e4f7 0%,#73b1e7 24%,#0a77d5 50%,#539fe1 79%,#87bcea 100%);background:linear-gradient(to bottom, #d0e4f7 0%,#73b1e7 24%,#0a77d5 50%,#539fe1 79%,#87bcea 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d0e4f7', endColorstr='#87bcea',GradientType=0)}"
|
||||
"body{font-family:helvetica,arial,sans-serif;font-size:16px}"
|
||||
"h1{font-size:26px}"
|
||||
"p{font-size:14px}"
|
18
extras/wificfg/content/tasks.html
Normal file
18
extras/wificfg/content/tasks.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li class=\"active\"><a href=\"/tasks.html\">Tasks</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>",
|
||||
"</body></html>"
|
90
extras/wificfg/content/wificfg/ap.html
Normal file
90
extras/wificfg/content/wificfg/ap.html
Normal file
|
@ -0,0 +1,90 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
|
||||
"<li class=\"active\"><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>"
|
||||
"<form action=\"/wificfg/ap.html\" method=\"post\">"
|
||||
"<fieldset>"
|
||||
"<legend>WiFi Access Point configuration</legend>"
|
||||
"<dl class=\"dlh\">"
|
||||
"<dt><label for=\"enable\">Enable AP mode</label></dt>"
|
||||
"<dd><input id=\"enable\" type=\"checkbox\" name=\"ap_enable\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"disable_if_sta\">Auto disable if station connection</label></dt>"
|
||||
"<dd><input id=\"hidden\" type=\"checkbox\" name=\"ap_disable_if_sta\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"disabled_restarts\">Disabled restarts</label></dt>"
|
||||
"<dd><input id=\"disabled_restarts\" type=\"number\" size=\"2\" min=\"0\" step=\"1\" "
|
||||
"name=\"ap_disabled_restarts\" placeholder=\"0\" value=\"",
|
||||
"\"/></dd>"
|
||||
"<dt><label for=\"ssid\">SSID</label></dt>"
|
||||
"<dd><input id=\"ssid\" type=\"text\" minlength=\"1\" maxlength=\"31\" name=\"ap_ssid\" "
|
||||
"placeholder=\"my access point\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"ap\">Password</label></dt>"
|
||||
"<dd><input id=\"ap\" type=\"text\" minlength=\"8\" maxlength=\"63\" name=\"ap_password\" "
|
||||
"placeholder=\"password\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"hidden\">SSID Hidden</label></dt>"
|
||||
"<dd><input id=\"hidden\" type=\"checkbox\" name=\"ap_ssid_hidden\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"ch\">Channel</label></dt>"
|
||||
"<dd><input id=\"ch\" type=\"number\" size=\"2\" min=\"1\" max=\"14\" step=\"1\" "
|
||||
"name=\"ap_channel\" placeholder=\"6\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"am\">Authentication Mode</label></dt>"
|
||||
"<dd><select id=\"am\" name=\"ap_authmode\">"
|
||||
"<option value=\"0\"",
|
||||
">Open</option>"
|
||||
"<option value=\"1\"",
|
||||
">WEP</option>"
|
||||
"<option value=\"2\"",
|
||||
">WPA_PSK</option>"
|
||||
"<option value=\"3\"",
|
||||
">WPA2_PSK</option>"
|
||||
"<option value=\"4\"",
|
||||
">WPA_WPA2_PSK</option></select></dd>"
|
||||
"<dt><label for=\"mc\">Max connections</label></dt>"
|
||||
"<dd><input id=\"mc\" type=\"number\" size=\"2\" min=\"1\" max=\"8\" step=\"1\" "
|
||||
"name=\"ap_max_conn\" placeholder=\"3\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"bi\">Beacon interval</label></dt>"
|
||||
"<dd><input id=\"bi\" type=\"number\" size=\"6\" min=\"0\" max=\"10000\" step=\"1\" "
|
||||
"name=\"ap_beacon_interval\" placeholder=\"100\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"ip\">IP Address</label></dt>"
|
||||
"<dd><input id=\"ip\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"ap_ip_addr\" placeholder=\"192.168.4.1\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"nm\">Netmask</label></dt>"
|
||||
"<dd><input id=\"nm\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"ap_netmask\" placeholder=\"255.255.255.0\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"dhcp\">DHCP Server Max Leases</label></dt>"
|
||||
"<dd><input id=\"dhcp\" type=\"number\" size=\"2\" min=\"0\" max=\"16\" step=\"1\" "
|
||||
"name=\"ap_dhcp_leases\" placeholder=\"4\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"dns_en\">DNS enabled</label></dt>"
|
||||
"<dd><input id=\"dns_en\" type=\"checkbox\" name=\"ap_dns\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"</dl>"
|
||||
"<center><input type=\"reset\"> <input type=\"submit\" value=\"Save\"></center>"
|
||||
"</fieldset>"
|
||||
"<input type=\"hidden\" name=\"done\">"
|
||||
"</form>"
|
||||
"</body></html>"
|
52
extras/wificfg/content/wificfg/index.html
Normal file
52
extras/wificfg/content/wificfg/index.html
Normal file
|
@ -0,0 +1,52 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li class=\"active\"><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
|
||||
"<li><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>"
|
||||
"<h1>WiFi Status</h1>"
|
||||
"<dl class=\"dlh\">",
|
||||
"</dl>"
|
||||
"<br>"
|
||||
"<form action=\"/wificfg/\" method=\"post\" onsubmit=\"return confirm('Are you sure you want to lock the configuration interface, and have you noted the password?');\">"
|
||||
"<fieldset>"
|
||||
"<legend>Lock the configuration interface</legend>"
|
||||
"<p>These WiFi configuration pages can be disabled for security on a shared network. If a password is supplied then they can be unlocked. Warning: if no password is supplied then it will not be possible to unlock these pages via this interface.</p>"
|
||||
"<dl class=\"dlh\">"
|
||||
"<dt><label for=\"pw\">Password</label></dt>"
|
||||
"<dd><input id=\"pw\" type=\"text\" maxlength=\"32\" name=\"cfg_password\" "
|
||||
"placeholder=\"unlock-password\" value=\"",
|
||||
"\"></dd>"
|
||||
"</dl>"
|
||||
"<input type=\"hidden\" name=\"cfg_enable\" value=\"0\">"
|
||||
"<center><input type=\"submit\" value=\"Lock\"></center>"
|
||||
"</fieldset>"
|
||||
"</form>"
|
||||
"<form action=\"/wificfg/restart.html\" method=\"post\" onsubmit=\"return confirm('Are you sure you want to restart the device?');\">"
|
||||
"<fieldset>"
|
||||
"<legend>Restart device</legend>"
|
||||
"<p>A restart is necessary for some changes to take effect.</p>"
|
||||
"<center><button>Restart</button></center>"
|
||||
"</fieldset></form>"
|
||||
"<form action=\"/wificfg/erase.html\" method=\"post\" onsubmit=\"return confirm('Are you sure you want to erase the configuration?');\">"
|
||||
"<fieldset>"
|
||||
"<legend>Erase configuration</legend>"
|
||||
"<p>Erases the device configuration stored in the flash memory and restarts the device. "
|
||||
"This might be useful to clear stored passwords and private configuration information."
|
||||
"</p>"
|
||||
"<center><button>Erase Configuration</button></center>"
|
||||
"</fieldset>"
|
||||
"</form>",
|
||||
"</body></html>"
|
68
extras/wificfg/content/wificfg/sta.html
Normal file
68
extras/wificfg/content/wificfg/sta.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
"<!DOCTYPE html><html lang=\"en\">"
|
||||
"<head>"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">"
|
||||
"<script src=\"/script.js\"></script>"
|
||||
"<title>",
|
||||
"</title>"
|
||||
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<ul class=\"topnav\" id=\"myTopnav\">"
|
||||
"<li><a href=\"/\">Home</a></li>"
|
||||
"<li><a href=\"/wificfg/\">WiFi Config</a></li>"
|
||||
"<li class=\"active\"><a href=\"/wificfg/sta.html\">WiFi Station</a></li>"
|
||||
"<li><a href=\"/wificfg/ap.html\">WiFi Access Point</a></li>"
|
||||
"<li class=\"icon\">"
|
||||
"<a href=\"javascript:void(0);\" onclick=\"myFunction()\">☰</a>"
|
||||
"</li>"
|
||||
"</ul>"
|
||||
"<form action=\"/wificfg/sta.html\" method=\"post\">"
|
||||
"<fieldset>"
|
||||
"<legend>WiFi Station configuration</legend>"
|
||||
"<dl class=\"dlh\">"
|
||||
"<dt><label for=\"enable\">Enable Station mode</label></dt>"
|
||||
"<dd><input id=\"enable\" type=\"checkbox\" name=\"sta_enable\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"disabled_restarts\">Disabled restarts</label></dt>"
|
||||
"<dd><input id=\"disabled_restarts\" type=\"number\" size=\"2\" min=\"0\" step=\"1\" "
|
||||
"name=\"sta_disabled_restarts\" placeholder=\"0\" value=\"",
|
||||
"\" /></dd>"
|
||||
"<dt><label for=\"ssid\">SSID</label></dt>"
|
||||
"<dd><input id=\"ssid\" minlength=\"1\" maxlength=\"31\" type=\"text\" name=\"sta_ssid\" "
|
||||
"placeholder=\"my access point\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"pw\">Password</label></dt>"
|
||||
"<dd><input id=\"pw\" type=\"text\" minlength=\"8\" maxlength=\"63\" name=\"sta_password\" "
|
||||
"placeholder=\"password\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"hostname\">Hostname</label></dt>"
|
||||
"<dd><input id=\"hostname\" type=\"text\" maxlength=\"63\" name=\"hostname\" "
|
||||
"placeholder=\"device-hostname\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"dhcp\">Enable DHCP</label></dt>"
|
||||
"<dd><input id=\"dhcp\" type=\"radio\" name=\"sta_dhcp\" value=\"1\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"static\">Disable DHCP (static address below)</label></dt>"
|
||||
"<dd><input id=\"static\" type=\"radio\" name=\"sta_dhcp\" value=\"0\" ",
|
||||
" /></dd>"
|
||||
"<dt><label for=\"ip\">Static IP Address</label></dt>"
|
||||
"<dd><input id=\"ip\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"sta_ip_addr\" placeholder=\"192.168.1.50\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"nm\">Static Netmask</label></dt>"
|
||||
"<dd><input id=\"nm\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"sta_netmask\" placeholder=\"255.255.255.0\" value=\"",
|
||||
"\"></dd>"
|
||||
"<dt><label for=\"gw\">Static Gateway</label></dt>"
|
||||
"<dd><input id=\"gw\" type=\"text\" maxlength=\"15\" size=\"15\" "
|
||||
"pattern=\"(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)_*){3}\" "
|
||||
"name=\"sta_gateway\" placeholder=\"192.168.1.1\" value=\"",
|
||||
"\"></dd>"
|
||||
"</dl>"
|
||||
"<center><input type=\"reset\"> <input type=\"submit\" value=\"Save\"></center>"
|
||||
"</fieldset>"
|
||||
"<input type=\"hidden\" name=\"done\">"
|
||||
"</form>"
|
||||
"</body></html>"
|
2022
extras/wificfg/wificfg.c
Normal file
2022
extras/wificfg/wificfg.c
Normal file
File diff suppressed because it is too large
Load diff
137
extras/wificfg/wificfg.h
Normal file
137
extras/wificfg/wificfg.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* WiFi configuration via a simple web server.
|
||||
*
|
||||
* Copyright (C) 2016 OurAirQuality.org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0, January 2004 (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/
|
||||
*
|
||||
* 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 CONTRIBUTORS 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 WITH THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WIFICFG_H__
|
||||
#define __WIFICFG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Printf format used to initialize a default AP ssid. It is passed the last
|
||||
* three bytes of the mac address. This may be NULL to not default the ssid,
|
||||
* but the AP network will not run without a ssid.
|
||||
*/
|
||||
extern char *wificfg_default_ssid;
|
||||
|
||||
/*
|
||||
* A default password for the AP interface. This may be NULL to not default the
|
||||
* password, but the AP network will not run without a password. The minimum
|
||||
* length is 8 characters.
|
||||
*/
|
||||
extern char *wificfg_default_password;
|
||||
|
||||
/*
|
||||
* A default hostname printf format string. This may be NULL to not default the
|
||||
* hostname.
|
||||
*/
|
||||
extern char *wificfg_default_hostname;
|
||||
|
||||
/*
|
||||
* The web server parses the http method string in these enums. The ANY method
|
||||
* is only use for dispatch. The method enum is passed to the handler functions.
|
||||
*/
|
||||
typedef enum {
|
||||
HTTP_METHOD_GET,
|
||||
HTTP_METHOD_POST,
|
||||
HTTP_METHOD_HEAD,
|
||||
HTTP_METHOD_OTHER,
|
||||
HTTP_METHOD_ANY,
|
||||
} wificfg_method;
|
||||
|
||||
/*
|
||||
* The web server parses these content-type header values. This is passed to the
|
||||
* dispatch function.
|
||||
*/
|
||||
typedef enum {
|
||||
HTTP_CONTENT_TYPE_WWW_FORM_URLENCODED,
|
||||
HTTP_CONTENT_TYPE_OTHER
|
||||
} wificfg_content_type;
|
||||
|
||||
/*
|
||||
* The function signature for the http server request handler functions.
|
||||
*
|
||||
* The buffer, with its length, is usable by the handler.
|
||||
*/
|
||||
typedef int (* wificfg_handler)(int s, wificfg_method method,
|
||||
uint32_t content_length,
|
||||
wificfg_content_type content_type,
|
||||
char *buf, size_t len);
|
||||
|
||||
typedef struct {
|
||||
const char *path;
|
||||
wificfg_method method;
|
||||
wificfg_handler handler;
|
||||
bool secure;
|
||||
} wificfg_dispatch;
|
||||
|
||||
|
||||
/*
|
||||
* Start the Wifi Configuration http server task. The IP port number
|
||||
* and a path dispatch list are needed. The dispatch list can not be
|
||||
* stack allocated as it is passed to another task.
|
||||
*/
|
||||
void wificfg_init(uint32_t port, const wificfg_dispatch *dispatch);
|
||||
|
||||
/*
|
||||
* Support for reading a form name or value from the socket. The name or value
|
||||
* is truncated to the buffer length. The number of characters read is limited
|
||||
* to the remainder which is updated. The 'valp' flag is set if a value follows.
|
||||
*/
|
||||
int wificfg_form_name_value(int s, bool *valp, size_t *rem, char *buf, size_t len);
|
||||
|
||||
/* Support for form url-encoding decoder. */
|
||||
void wificfg_form_url_decode(char *string);
|
||||
|
||||
/* Support for html-escaping of form values. */
|
||||
void wificfg_html_escape(char *string, char *buf, size_t len);
|
||||
|
||||
/* Support for writing a string in a response. */
|
||||
int wificfg_write_string(int s, const char *str);
|
||||
|
||||
/* Support for writing a string in a response, with chunk transfer encoding.
|
||||
* An optional buffer may be supplied to use to construct a chunk with the
|
||||
* header and trailer, reducing the number of write() calls, and the str may be
|
||||
* at the start of this buffer.
|
||||
*/
|
||||
int wificfg_write_string_chunk(int s, const char *str, char *buf, size_t len);
|
||||
|
||||
/* Write a chunk transfer encoding end marker. */
|
||||
int wificfg_write_chunk_end(int s);
|
||||
|
||||
/* Write a chunk offset 4 bytes into the buffer. */
|
||||
int wificfg_write_buffer_chunk(int s, char *buf);
|
||||
|
||||
/* Write a html title meta data, using the hostname or AP SSI. */
|
||||
int wificfg_write_html_title(int s, char *buf, size_t len, const char *str);
|
||||
|
||||
/* Callback to notify the wificfg logic that a station connection has been
|
||||
* successfully established. It might use this to disable the AP interface after
|
||||
* a restart.
|
||||
*/
|
||||
void wificfg_got_sta_connect(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __WIFICFG_H__
|
|
@ -60,7 +60,7 @@ volatile uint32_t dma_isr_counter = 0;
|
|||
|
||||
static volatile bool i2s_dma_processing = false;
|
||||
|
||||
static void dma_isr_handler(void)
|
||||
static void dma_isr_handler(void *arg)
|
||||
{
|
||||
if (i2s_dma_is_eof_interrupt()) {
|
||||
#ifdef WS2812_I2S_DEBUG
|
||||
|
@ -145,7 +145,7 @@ void ws2812_i2s_init(uint32_t pixels_number)
|
|||
debug("i2s clock dividers, bclk=%d, clkm=%d\n",
|
||||
clock_div.bclk_div, clock_div.clkm_div);
|
||||
|
||||
i2s_dma_init(dma_isr_handler, clock_div, i2s_pins);
|
||||
i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins);
|
||||
}
|
||||
|
||||
const IRAM_DATA int16_t bitpatterns[16] =
|
||||
|
|
|
@ -44,9 +44,9 @@ enum {
|
|||
};
|
||||
|
||||
struct ip_info {
|
||||
struct ip_addr ip;
|
||||
struct ip_addr netmask;
|
||||
struct ip_addr gw;
|
||||
struct ip4_addr ip;
|
||||
struct ip4_addr netmask;
|
||||
struct ip4_addr gw;
|
||||
};
|
||||
|
||||
bool sdk_wifi_get_ip_info(uint8_t if_index, struct ip_info *info);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ip_addr;
|
||||
struct ip4_addr;
|
||||
|
||||
/*********************************************
|
||||
* Defined in libmain.a
|
||||
|
@ -43,17 +43,6 @@ int sdk_uart_rx_one_char(char *buf);
|
|||
*/
|
||||
void sdk_os_putc(char c);
|
||||
|
||||
/* Called when an IP gets set on the "station" (client) interface.
|
||||
*/
|
||||
void sdk_system_station_got_ip_set(struct ip_addr *ip_addr, struct ip_addr *sn_mask, struct ip_addr *gw_addr);
|
||||
|
||||
/* This is a no-op wrapper around ppRecycleRxPkt, which is defined in libpp.a
|
||||
|
||||
It's called when a pbuf is freed, and allows pp to reuse the 'eb' pointer to ESP-specific
|
||||
pbuf data. (See esp-lwip pbuf.h)
|
||||
*/
|
||||
void sdk_system_pp_recycle_rx_pkt(void *eb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -289,6 +289,7 @@ os_timer_disarm sdk_os_timer_disarm
|
|||
os_timer_setfn sdk_os_timer_setfn
|
||||
os_update_cpu_frequency sdk_os_update_cpu_frequency
|
||||
pbkdf2_sha1 sdk_pbkdf2_sha1
|
||||
pbuf_alloc sdk_pbuf_alloc
|
||||
pbus_set_rxbbgain sdk_pbus_set_rxbbgain
|
||||
pend_flag_noise_check sdk_pend_flag_noise_check
|
||||
pend_flag_periodic_cal sdk_pend_flag_periodic_cal
|
||||
|
|
BIN
lib/libmain.a
BIN
lib/libmain.a
Binary file not shown.
|
@ -3,3 +3,4 @@ printf-stdarg.o
|
|||
libc.o
|
||||
xtensa_vectors.o
|
||||
app_main.o
|
||||
ets_timer.o
|
||||
|
|
Binary file not shown.
BIN
lib/libpp.a
BIN
lib/libpp.a
Binary file not shown.
BIN
lib/libwpa.a
BIN
lib/libwpa.a
Binary file not shown.
|
@ -1,3 +1 @@
|
|||
Newlib 2.2.0 with xtensa & locking patches, built from commit daa6ae40cdc8099f54c3e68a586fc1b906169c5a
|
||||
|
||||
For details on newlib in esp-open-rtos, see https://github.com/SuperHouse/esp-open-rtos/wiki/libc-configuration
|
||||
Newlib from git://sourceware.org/git/newlib-cygwin.git with xtensa & locking patches see https://github.com/ourairquality/newlib and built from commit 7bcbbff5f7e3600806f352e88ec23ae0300edc29
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
12
libc/xtensa-lx106-elf/include/_newlib_version.h
Normal file
12
libc/xtensa-lx106-elf/include/_newlib_version.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* _newlib_version.h. Generated from _newlib_version.hin by configure. */
|
||||
/* Version macros for internal and downstream use. */
|
||||
#ifndef _NEWLIB_VERSION_H__
|
||||
#define _NEWLIB_VERSION_H__ 1
|
||||
|
||||
#define _NEWLIB_VERSION "2.5.0"
|
||||
#define __NEWLIB__ 2
|
||||
#define __NEWLIB_MINOR__ 5
|
||||
#define __NEWLIB_PATCHLEVEL__ 0
|
||||
|
||||
#endif /* !_NEWLIB_VERSION_H__ */
|
||||
|
|
@ -24,10 +24,12 @@ float complex cacosf(float complex);
|
|||
/* 7.3.5.2 The casin functions */
|
||||
double complex casin(double complex);
|
||||
float complex casinf(float complex);
|
||||
long double complex casinl(long double complex);
|
||||
|
||||
/* 7.3.5.1 The catan functions */
|
||||
double complex catan(double complex);
|
||||
float complex catanf(float complex);
|
||||
long double complex catanl(long double complex);
|
||||
|
||||
/* 7.3.5.1 The ccos functions */
|
||||
double complex ccos(double complex);
|
||||
|
@ -74,6 +76,7 @@ float complex cexpf(float complex);
|
|||
/* 7.3.7.2 The clog functions */
|
||||
double complex clog(double complex);
|
||||
float complex clogf(float complex);
|
||||
long double complex clogl(long double complex);
|
||||
|
||||
/* 7.3.8 Power and absolute-value functions */
|
||||
/* 7.3.8.1 The cabs functions */
|
||||
|
@ -83,6 +86,7 @@ float complex clogf(float complex);
|
|||
float cabsf(float complex) __RENAME(__c99_cabsf);
|
||||
#endif
|
||||
*/
|
||||
long double cabsl(long double complex) ;
|
||||
double cabs(double complex) ;
|
||||
float cabsf(float complex) ;
|
||||
|
||||
|
@ -93,31 +97,56 @@ float complex cpowf(float complex, float complex);
|
|||
/* 7.3.8.3 The csqrt functions */
|
||||
double complex csqrt(double complex);
|
||||
float complex csqrtf(float complex);
|
||||
long double complex csqrtl(long double complex);
|
||||
|
||||
/* 7.3.9 Manipulation functions */
|
||||
/* 7.3.9.1 The carg functions */
|
||||
double carg(double complex);
|
||||
float cargf(float complex);
|
||||
long double cargl(long double complex);
|
||||
|
||||
/* 7.3.9.2 The cimag functions */
|
||||
double cimag(double complex);
|
||||
float cimagf(float complex);
|
||||
/*long double cimagl(long double complex); */
|
||||
long double cimagl(long double complex);
|
||||
|
||||
/* 7.3.9.3 The conj functions */
|
||||
double complex conj(double complex);
|
||||
float complex conjf(float complex);
|
||||
/*long double complex conjl(long double complex); */
|
||||
|
||||
/* 7.3.9.4 The cproj functions */
|
||||
double complex cproj(double complex);
|
||||
float complex cprojf(float complex);
|
||||
/*long double complex cprojl(long double complex); */
|
||||
|
||||
/* 7.3.9.5 The creal functions */
|
||||
double creal(double complex);
|
||||
float crealf(float complex);
|
||||
/*long double creall(long double complex); */
|
||||
long double creall(long double complex);
|
||||
|
||||
#if __GNU_VISIBLE
|
||||
double complex clog10(double complex);
|
||||
float complex clog10f(float complex);
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
long double complex cacosl(long double complex);
|
||||
long double complex ccosl(long double complex);
|
||||
long double complex csinl(long double complex);
|
||||
long double complex ctanl(long double complex);
|
||||
long double complex cacoshl(long double complex);
|
||||
long double complex casinhl(long double complex);
|
||||
long double complex catanhl(long double complex);
|
||||
long double complex ccoshl(long double complex);
|
||||
long double complex csinhl(long double complex);
|
||||
long double complex ctanhl(long double complex);
|
||||
long double complex cexpl(long double complex);
|
||||
long double complex cpowl(long double complex, long double complex);
|
||||
long double complex conjl(long double complex);
|
||||
long double complex cprojl(long double complex);
|
||||
#if __GNU_VISIBLE
|
||||
long double complex clog10l(long double complex);
|
||||
#endif
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
30
libc/xtensa-lx106-elf/include/cpio.h
Normal file
30
libc/xtensa-lx106-elf/include/cpio.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* POSIX.1 symbolic constants for c_mode field of cpio archive format */
|
||||
|
||||
#ifndef _CPIO_H
|
||||
#define _CPIO_H
|
||||
|
||||
#define C_IRUSR 0000400 /* Read by owner */
|
||||
#define C_IWUSR 0000200 /* Write by owner */
|
||||
#define C_IXUSR 0000100 /* Execute by owner */
|
||||
#define C_IRGRP 0000040 /* Read by group */
|
||||
#define C_IWGRP 0000020 /* Write by group */
|
||||
#define C_IXGRP 0000010 /* Execute by group */
|
||||
#define C_IROTH 0000004 /* Read by others */
|
||||
#define C_IWOTH 0000002 /* Write by others */
|
||||
#define C_IXOTH 0000001 /* Execute by others */
|
||||
#define C_ISUID 0004000 /* Set user ID */
|
||||
#define C_ISGID 0002000 /* Set group ID */
|
||||
#define C_ISVTX 0001000 /* On directories, restricted deletion flag */
|
||||
|
||||
#define C_ISDIR 0040000 /* Directory */
|
||||
#define C_ISFIFO 0010000 /* FIFO */
|
||||
#define C_ISREG 0100000 /* Regular file */
|
||||
#define C_ISBLK 0060000 /* Block special */
|
||||
#define C_ISCHR 0020000 /* Character special */
|
||||
#define C_ISCTG 0110000 /* Reserved */
|
||||
#define C_ISLNK 0120000 /* Symbolic link */
|
||||
#define C_ISSOCK 0140000 /* Socket */
|
||||
|
||||
#define MAGIC "070707"
|
||||
|
||||
#endif /* _CPIO_H */
|
|
@ -2,6 +2,11 @@
|
|||
#define _CTYPE_H_
|
||||
|
||||
#include "_ansi.h"
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#if __POSIX_VISIBLE >= 200809 || __MISC_VISIBLE || defined (_COMPILING_NEWLIB)
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
_BEGIN_STD_C
|
||||
|
||||
|
@ -19,17 +24,39 @@ int _EXFUN(isxdigit,(int __c));
|
|||
int _EXFUN(tolower, (int __c));
|
||||
int _EXFUN(toupper, (int __c));
|
||||
|
||||
#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L
|
||||
#if __ISO_C_VISIBLE >= 1999
|
||||
int _EXFUN(isblank, (int __c));
|
||||
#endif
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#if __MISC_VISIBLE || __XSI_VISIBLE
|
||||
int _EXFUN(isascii, (int __c));
|
||||
int _EXFUN(toascii, (int __c));
|
||||
#define _tolower(__c) ((unsigned char)(__c) - 'A' + 'a')
|
||||
#define _toupper(__c) ((unsigned char)(__c) - 'a' + 'A')
|
||||
#endif
|
||||
|
||||
#if __POSIX_VISIBLE >= 200809
|
||||
extern int isalnum_l (int __c, locale_t __l);
|
||||
extern int isalpha_l (int __c, locale_t __l);
|
||||
extern int isblank_l (int __c, locale_t __l);
|
||||
extern int iscntrl_l (int __c, locale_t __l);
|
||||
extern int isdigit_l (int __c, locale_t __l);
|
||||
extern int isgraph_l (int __c, locale_t __l);
|
||||
extern int islower_l (int __c, locale_t __l);
|
||||
extern int isprint_l (int __c, locale_t __l);
|
||||
extern int ispunct_l (int __c, locale_t __l);
|
||||
extern int isspace_l (int __c, locale_t __l);
|
||||
extern int isupper_l (int __c, locale_t __l);
|
||||
extern int isxdigit_l(int __c, locale_t __l);
|
||||
extern int tolower_l (int __c, locale_t __l);
|
||||
extern int toupper_l (int __c, locale_t __l);
|
||||
#endif
|
||||
|
||||
#if __MISC_VISIBLE
|
||||
extern int isascii_l (int __c, locale_t __l);
|
||||
extern int toascii_l (int __c, locale_t __l);
|
||||
#endif
|
||||
|
||||
#define _U 01
|
||||
#define _L 02
|
||||
#define _N 04
|
||||
|
@ -39,22 +66,20 @@ int _EXFUN(toascii, (int __c));
|
|||
#define _X 0100
|
||||
#define _B 0200
|
||||
|
||||
#ifndef _MB_CAPABLE
|
||||
_CONST
|
||||
#endif
|
||||
extern __IMPORT char *__ctype_ptr__;
|
||||
const char *__locale_ctype_ptr (void);
|
||||
# define __CTYPE_PTR (__locale_ctype_ptr ())
|
||||
|
||||
#ifndef __cplusplus
|
||||
/* These macros are intentionally written in a manner that will trigger
|
||||
a gcc -Wall warning if the user mistakenly passes a 'char' instead
|
||||
of an int containing an 'unsigned char'. Note that the sizeof will
|
||||
always be 1, which is what we want for mapping EOF to __ctype_ptr__[0];
|
||||
always be 1, which is what we want for mapping EOF to __CTYPE_PTR[0];
|
||||
the use of a raw index inside the sizeof triggers the gcc warning if
|
||||
__c was of type char, and sizeof masks side effects of the extra __c.
|
||||
Meanwhile, the real index to __ctype_ptr__+1 must be cast to int,
|
||||
Meanwhile, the real index to __CTYPE_PTR+1 must be cast to int,
|
||||
since isalpha(0x100000001LL) must equal isalpha(1), rather than being
|
||||
an out-of-bounds reference on a 64-bit machine. */
|
||||
#define __ctype_lookup(__c) ((__ctype_ptr__+sizeof(""[__c]))[(int)(__c)])
|
||||
#define __ctype_lookup(__c) ((__CTYPE_PTR+sizeof(""[__c]))[(int)(__c)])
|
||||
|
||||
#define isalpha(__c) (__ctype_lookup(__c)&(_U|_L))
|
||||
#define isupper(__c) ((__ctype_lookup(__c)&(_U|_L))==_U)
|
||||
|
@ -68,13 +93,45 @@ extern __IMPORT char *__ctype_ptr__;
|
|||
#define isgraph(__c) (__ctype_lookup(__c)&(_P|_U|_L|_N))
|
||||
#define iscntrl(__c) (__ctype_lookup(__c)&_C)
|
||||
|
||||
#if defined(__GNUC__) && \
|
||||
(!defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901L)
|
||||
#if defined(__GNUC__) && __ISO_C_VISIBLE >= 1999
|
||||
#define isblank(__c) \
|
||||
__extension__ ({ __typeof__ (__c) __x = (__c); \
|
||||
(__ctype_lookup(__x)&_B) || (int) (__x) == '\t';})
|
||||
#endif
|
||||
|
||||
#if __POSIX_VISIBLE >= 200809
|
||||
const char *__locale_ctype_ptr_l (locale_t);
|
||||
#define __ctype_lookup_l(__c,__l) ((__locale_ctype_ptr_l(__l)+sizeof(""[__c]))[(int)(__c)])
|
||||
|
||||
#define isalpha_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_U|_L))
|
||||
#define isupper_l(__c,__l) ((__ctype_lookup_l(__c,__l)&(_U|_L))==_U)
|
||||
#define islower_l(__c,__l) ((__ctype_lookup_l(__c,__l)&(_U|_L))==_L)
|
||||
#define isdigit_l(__c,__l) (__ctype_lookup_l(__c,__l)&_N)
|
||||
#define isxdigit_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_X|_N))
|
||||
#define isspace_l(__c,__l) (__ctype_lookup_l(__c,__l)&_S)
|
||||
#define ispunct_l(__c,__l) (__ctype_lookup_l(__c,__l)&_P)
|
||||
#define isalnum_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_U|_L|_N))
|
||||
#define isprint_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_P|_U|_L|_N|_B))
|
||||
#define isgraph_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_P|_U|_L|_N))
|
||||
#define iscntrl_l(__c,__l) (__ctype_lookup_l(__c,__l)&_C)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define isblank_l(__c, __l) \
|
||||
__extension__ ({ __typeof__ (__c) __x = (__c); \
|
||||
(__ctype_lookup_l(__x,__l)&_B) || (int) (__x) == '\t';})
|
||||
#endif
|
||||
|
||||
#endif /* __POSIX_VISIBLE >= 200809 */
|
||||
|
||||
#if __MISC_VISIBLE || __XSI_VISIBLE
|
||||
#define isascii(__c) ((unsigned)(__c)<=0177)
|
||||
#define toascii(__c) ((__c)&0177)
|
||||
#endif
|
||||
|
||||
#if __MISC_VISIBLE
|
||||
#define isascii_l(__c,__l) ((__l),(unsigned)(__c)<=0177)
|
||||
#define toascii_l(__c,__l) ((__l),(__c)&0177)
|
||||
#endif
|
||||
|
||||
/* Non-gcc versions will get the library versions, and will be
|
||||
slightly slower. These macros are not NLS-aware so they are
|
||||
|
@ -92,18 +149,17 @@ extern __IMPORT char *__ctype_ptr__;
|
|||
function. */
|
||||
# define toupper(__c) \
|
||||
__extension__ ({ __typeof__ (__c) __x = (__c); \
|
||||
(void) __ctype_ptr__[__x]; (toupper) (__x);})
|
||||
(void) __CTYPE_PTR[__x]; (toupper) (__x);})
|
||||
# define tolower(__c) \
|
||||
__extension__ ({ __typeof__ (__c) __x = (__c); \
|
||||
(void) __ctype_ptr__[__x]; (tolower) (__x);})
|
||||
(void) __CTYPE_PTR[__x]; (tolower) (__x);})
|
||||
# endif /* _MB_EXTENDED_CHARSETS* */
|
||||
# endif /* __GNUC__ */
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define isascii(__c) ((unsigned)(__c)<=0177)
|
||||
#define toascii(__c) ((__c)&0177)
|
||||
#endif
|
||||
#if __POSIX_VISIBLE >= 200809
|
||||
#endif /* __POSIX_VISIBLE >= 200809 */
|
||||
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
/* For C++ backward-compatibility only. */
|
||||
extern __IMPORT _CONST char _ctype_[];
|
||||
|
|
51
libc/xtensa-lx106-elf/include/devctl.h
Normal file
51
libc/xtensa-lx106-elf/include/devctl.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Joel Sherrill <joel@rtems.org>. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
|
||||
*/
|
||||
|
||||
#ifndef _POSIX_DEVCTL_h_
|
||||
#define _POSIX_DEVCTL_h_
|
||||
|
||||
/*
|
||||
* The posix_devctl() method is defined by POSIX 1003.26-2003. Aside
|
||||
* from the single method, it adds the following requirements:
|
||||
*
|
||||
* + define _POSIX_26_VERSION to 200312L
|
||||
* + add _SC_POSIX_26_VERSION in <unistd.h>. Return _POSIX_26_VERSION
|
||||
* + application must define _POSIX_26_C_SOURCE to use posix_devctl().
|
||||
* + posix_devctl() is prototyped in <devctl.h>
|
||||
*/
|
||||
|
||||
#ifdef _POSIX_26_C_SOURCE
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
int posix_devctl(
|
||||
int fd,
|
||||
int dcmd,
|
||||
void *__restrict dev_data_ptr,
|
||||
size_t nbyte,
|
||||
int *__restrict dev_info_ptr
|
||||
);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -3,9 +3,10 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/dirent.h>
|
||||
|
||||
#if !defined(MAXNAMLEN) && !defined(_POSIX_SOURCE)
|
||||
#if !defined(MAXNAMLEN) && __BSD_VISIBLE
|
||||
#define MAXNAMLEN 1024
|
||||
#endif
|
||||
|
||||
|
|
|
@ -33,21 +33,21 @@
|
|||
#ifndef _FNMATCH_H_
|
||||
#define _FNMATCH_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#define FNM_NOMATCH 1 /* Match failed. */
|
||||
|
||||
#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
|
||||
#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
|
||||
#define FNM_PERIOD 0x04 /* Period must be matched by period. */
|
||||
|
||||
#if defined(_GNU_SOURCE) || !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
|
||||
#if __GNU_VISIBLE
|
||||
#define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */
|
||||
#define FNM_CASEFOLD 0x10 /* Case insensitive search. */
|
||||
#define FNM_IGNORECASE FNM_CASEFOLD
|
||||
#define FNM_FILE_NAME FNM_PATHNAME
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
int fnmatch(const char *, const char *, int);
|
||||
__END_DECLS
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#include <cygwin/grp.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
|
||||
#if __BSD_VISIBLE
|
||||
#define _PATH_GROUP "/etc/group"
|
||||
#endif
|
||||
|
||||
|
@ -67,25 +67,20 @@ extern "C" {
|
|||
#ifndef __INSIDE_CYGWIN__
|
||||
struct group *getgrgid (gid_t);
|
||||
struct group *getgrnam (const char *);
|
||||
#if __MISC_VISIBLE || __POSIX_VISIBLE
|
||||
int getgrnam_r (const char *, struct group *,
|
||||
char *, size_t, struct group **);
|
||||
int getgrgid_r (gid_t, struct group *,
|
||||
char *, size_t, struct group **);
|
||||
#ifndef _POSIX_SOURCE
|
||||
#endif /* __MISC_VISIBLE || __POSIX_VISIBLE */
|
||||
#if __MISC_VISIBLE || __XSI_VISIBLE >= 4
|
||||
struct group *getgrent (void);
|
||||
void setgrent (void);
|
||||
void endgrent (void);
|
||||
#ifndef __CYGWIN__
|
||||
void setgrfile (const char *);
|
||||
#endif /* !__CYGWIN__ */
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#ifndef __CYGWIN__
|
||||
char *group_from_gid (gid_t, int);
|
||||
int setgroupent (int);
|
||||
#endif /* !__CYGWIN__ */
|
||||
#endif /* __MISC_VISIBLE || __XSI_VISIBLE >= 4 */
|
||||
#if __BSD_VISIBLE
|
||||
int initgroups (const char *, gid_t);
|
||||
#endif /* !_XOPEN_SOURCE */
|
||||
#endif /* !_POSIX_SOURCE */
|
||||
#endif /* __BSD_VISIBLE */
|
||||
#endif /* !__INSIDE_CYGWIN__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
#include "_ansi.h"
|
||||
|
||||
#include <machine/ieeefp.h>
|
||||
#include <float.h>
|
||||
|
||||
_BEGIN_STD_C
|
||||
|
||||
/* FIXME FIXME FIXME:
|
||||
Neither of __ieee_{float,double}_shape_tape seem to be used anywhere
|
||||
Neither of __ieee_{float,double}_shape_type seem to be used anywhere
|
||||
except in libm/test. If that is the case, please delete these from here.
|
||||
If that is not the case, please insert documentation here describing why
|
||||
they're needed. */
|
||||
|
@ -46,9 +47,7 @@ typedef union
|
|||
long aslong[2];
|
||||
} __ieee_double_shape_type;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __IEEE_LITTLE_ENDIAN
|
||||
#elif defined __IEEE_LITTLE_ENDIAN
|
||||
|
||||
typedef union
|
||||
{
|
||||
|
@ -92,7 +91,7 @@ typedef union
|
|||
|
||||
} __ieee_double_shape_type;
|
||||
|
||||
#endif
|
||||
#endif /* __IEEE_LITTLE_ENDIAN */
|
||||
|
||||
#ifdef __IEEE_BIG_ENDIAN
|
||||
|
||||
|
@ -118,9 +117,7 @@ typedef union
|
|||
|
||||
} __ieee_float_shape_type;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __IEEE_LITTLE_ENDIAN
|
||||
#elif defined __IEEE_LITTLE_ENDIAN
|
||||
|
||||
typedef union
|
||||
{
|
||||
|
@ -144,10 +141,70 @@ typedef union
|
|||
|
||||
} __ieee_float_shape_type;
|
||||
|
||||
#endif /* __IEEE_LITTLE_ENDIAN */
|
||||
|
||||
#ifndef _LDBL_EQ_DBL
|
||||
|
||||
#ifndef LDBL_MANT_DIG
|
||||
#error "LDBL_MANT_DIG not defined - should be found in float.h"
|
||||
|
||||
#elif LDBL_MANT_DIG == DBL_MANT_DIG
|
||||
#error "double and long double are the same size but LDBL_EQ_DBL is not defined"
|
||||
|
||||
#elif LDBL_MANT_DIG == 53
|
||||
/* This happens when doubles are 32-bits and long doubles are 64-bits. */
|
||||
#define EXT_EXPBITS 11
|
||||
#define EXT_FRACHBITS 20
|
||||
#define EXT_FRACLBITS 32
|
||||
#define __ieee_ext_field_type unsigned long
|
||||
|
||||
#elif LDBL_MANT_DIG == 64
|
||||
#define EXT_EXPBITS 15
|
||||
#define EXT_FRACHBITS 32
|
||||
#define EXT_FRACLBITS 32
|
||||
#define __ieee_ext_field_type unsigned int
|
||||
|
||||
#elif LDBL_MANT_DIG == 65
|
||||
#define EXT_EXPBITS 15
|
||||
#define EXT_FRACHBITS 32
|
||||
#define EXT_FRACLBITS 32
|
||||
#define __ieee_ext_field_type unsigned int
|
||||
|
||||
#elif LDBL_MANT_DIG == 112
|
||||
#define EXT_EXPBITS 15
|
||||
#define EXT_FRACHBITS 48
|
||||
#define EXT_FRACLBITS 64
|
||||
#define __ieee_ext_field_type unsigned long long
|
||||
|
||||
#elif LDBL_MANT_DIG == 113
|
||||
#define EXT_EXPBITS 15
|
||||
#define EXT_FRACHBITS 48
|
||||
#define EXT_FRACLBITS 64
|
||||
#define __ieee_ext_field_type unsigned long long
|
||||
|
||||
#else
|
||||
#error Unsupported value for LDBL_MANT_DIG
|
||||
#endif
|
||||
|
||||
#define EXT_EXP_INFNAN ((1 << EXT_EXPBITS) - 1) /* 32767 */
|
||||
#define EXT_EXP_BIAS ((1 << (EXT_EXPBITS - 1)) - 1) /* 16383 */
|
||||
#define EXT_FRACBITS (EXT_FRACLBITS + EXT_FRACHBITS)
|
||||
|
||||
typedef struct ieee_ext
|
||||
{
|
||||
__ieee_ext_field_type ext_fracl : EXT_FRACLBITS;
|
||||
__ieee_ext_field_type ext_frach : EXT_FRACHBITS;
|
||||
__ieee_ext_field_type ext_exp : EXT_EXPBITS;
|
||||
__ieee_ext_field_type ext_sign : 1;
|
||||
} ieee_ext;
|
||||
|
||||
typedef union ieee_ext_u
|
||||
{
|
||||
long double extu_ld;
|
||||
struct ieee_ext extu_ext;
|
||||
} ieee_ext_u;
|
||||
|
||||
#endif /* ! _LDBL_EQ_DBL */
|
||||
|
||||
|
||||
/* FLOATING ROUNDING */
|
||||
|
@ -184,19 +241,6 @@ typedef int fp_rdi;
|
|||
fp_rdi _EXFUN(fpgetroundtoi,(void));
|
||||
fp_rdi _EXFUN(fpsetroundtoi,(fp_rdi));
|
||||
|
||||
#undef isnan
|
||||
#undef isinf
|
||||
|
||||
int _EXFUN(isnan, (double));
|
||||
int _EXFUN(isinf, (double));
|
||||
int _EXFUN(finite, (double));
|
||||
|
||||
|
||||
|
||||
int _EXFUN(isnanf, (float));
|
||||
int _EXFUN(isinff, (float));
|
||||
int _EXFUN(finitef, (float));
|
||||
|
||||
#define __IEEE_DBL_EXPBIAS 1023
|
||||
#define __IEEE_FLT_EXPBIAS 127
|
||||
|
||||
|
@ -213,22 +257,17 @@ int _EXFUN(finitef, (float));
|
|||
#define __IEEE_DBL_NAN_EXP 0x7ff
|
||||
#define __IEEE_FLT_NAN_EXP 0xff
|
||||
|
||||
#ifndef __ieeefp_isnanf
|
||||
#define __ieeefp_isnanf(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \
|
||||
((*(long *)&(x) & 0x007fffffL)!=0000000000L))
|
||||
#endif
|
||||
#ifdef __ieeefp_isnanf
|
||||
#define isnanf(x) __ieeefp_isnanf(x)
|
||||
|
||||
#ifndef __ieeefp_isinff
|
||||
#define __ieeefp_isinff(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \
|
||||
((*(long *)&(x) & 0x007fffffL)==0000000000L))
|
||||
#endif
|
||||
|
||||
#ifdef __ieeefp_isinff
|
||||
#define isinff(x) __ieeefp_isinff(x)
|
||||
|
||||
#ifndef __ieeefp_finitef
|
||||
#define __ieeefp_finitef(x) (((*(long *)&(x) & 0x7f800000L)!=0x7f800000L))
|
||||
#endif
|
||||
|
||||
#ifdef __ieeefp_finitef
|
||||
#define finitef(x) __ieeefp_finitef(x)
|
||||
#endif
|
||||
|
||||
#ifdef _DOUBLE_IS_32BITS
|
||||
#undef __IEEE_DBL_EXPBIAS
|
||||
|
|
|
@ -14,15 +14,23 @@
|
|||
#define _INTTYPES_H
|
||||
|
||||
#include <newlib.h>
|
||||
#include <sys/config.h>
|
||||
#include <sys/_intsup.h>
|
||||
#include "_ansi.h"
|
||||
#include <stdint.h>
|
||||
#define __need_wchar_t
|
||||
#include <stddef.h>
|
||||
|
||||
#if __BSD_VISIBLE
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#define __STRINGIFY(a) #a
|
||||
|
||||
/* 8-bit types */
|
||||
#define __PRI8(x) __STRINGIFY(x)
|
||||
#define __PRI8(x) __INT8 __STRINGIFY(x)
|
||||
#define __PRI8LEAST(x) __LEAST8 __STRINGIFY(x)
|
||||
#define __PRI8FAST(x) __FAST8 __STRINGIFY(x)
|
||||
|
||||
/* NOTICE: scanning 8-bit types requires use of the hh specifier
|
||||
* which is only supported on newlib platforms that
|
||||
|
@ -35,7 +43,9 @@
|
|||
*/
|
||||
|
||||
#if defined(_WANT_IO_C99_FORMATS)
|
||||
#define __SCN8(x) __STRINGIFY(hh##x)
|
||||
#define __SCN8(x) __INT8 __STRINGIFY(x)
|
||||
#define __SCN8LEAST(x) __LEAST8 __STRINGIFY(x)
|
||||
#define __SCN8FAST(x) __FAST8 __STRINGIFY(x)
|
||||
#endif /* _WANT_IO_C99_FORMATS */
|
||||
|
||||
|
||||
|
@ -58,45 +68,49 @@
|
|||
#endif /* _WANT_IO_C99_FORMATS */
|
||||
|
||||
|
||||
#define PRIdLEAST8 __PRI8(d)
|
||||
#define PRIiLEAST8 __PRI8(i)
|
||||
#define PRIoLEAST8 __PRI8(o)
|
||||
#define PRIuLEAST8 __PRI8(u)
|
||||
#define PRIxLEAST8 __PRI8(x)
|
||||
#define PRIXLEAST8 __PRI8(X)
|
||||
#define PRIdLEAST8 __PRI8LEAST(d)
|
||||
#define PRIiLEAST8 __PRI8LEAST(i)
|
||||
#define PRIoLEAST8 __PRI8LEAST(o)
|
||||
#define PRIuLEAST8 __PRI8LEAST(u)
|
||||
#define PRIxLEAST8 __PRI8LEAST(x)
|
||||
#define PRIXLEAST8 __PRI8LEAST(X)
|
||||
|
||||
/* Macros below are only enabled for a newlib built with C99 I/O format support. */
|
||||
#if defined(_WANT_IO_C99_FORMATS)
|
||||
|
||||
#define SCNdLEAST8 __SCN8(d)
|
||||
#define SCNiLEAST8 __SCN8(i)
|
||||
#define SCNoLEAST8 __SCN8(o)
|
||||
#define SCNuLEAST8 __SCN8(u)
|
||||
#define SCNxLEAST8 __SCN8(x)
|
||||
#define SCNdLEAST8 __SCN8LEAST(d)
|
||||
#define SCNiLEAST8 __SCN8LEAST(i)
|
||||
#define SCNoLEAST8 __SCN8LEAST(o)
|
||||
#define SCNuLEAST8 __SCN8LEAST(u)
|
||||
#define SCNxLEAST8 __SCN8LEAST(x)
|
||||
|
||||
#endif /* _WANT_IO_C99_FORMATS */
|
||||
|
||||
#define PRIdFAST8 __PRI8(d)
|
||||
#define PRIiFAST8 __PRI8(i)
|
||||
#define PRIoFAST8 __PRI8(o)
|
||||
#define PRIuFAST8 __PRI8(u)
|
||||
#define PRIxFAST8 __PRI8(x)
|
||||
#define PRIXFAST8 __PRI8(X)
|
||||
#define PRIdFAST8 __PRI8FAST(d)
|
||||
#define PRIiFAST8 __PRI8FAST(i)
|
||||
#define PRIoFAST8 __PRI8FAST(o)
|
||||
#define PRIuFAST8 __PRI8FAST(u)
|
||||
#define PRIxFAST8 __PRI8FAST(x)
|
||||
#define PRIXFAST8 __PRI8FAST(X)
|
||||
|
||||
/* Macros below are only enabled for a newlib built with C99 I/O format support. */
|
||||
#if defined(_WANT_IO_C99_FORMATS)
|
||||
|
||||
#define SCNdFAST8 __SCN8(d)
|
||||
#define SCNiFAST8 __SCN8(i)
|
||||
#define SCNoFAST8 __SCN8(o)
|
||||
#define SCNuFAST8 __SCN8(u)
|
||||
#define SCNxFAST8 __SCN8(x)
|
||||
#define SCNdFAST8 __SCN8FAST(d)
|
||||
#define SCNiFAST8 __SCN8FAST(i)
|
||||
#define SCNoFAST8 __SCN8FAST(o)
|
||||
#define SCNuFAST8 __SCN8FAST(u)
|
||||
#define SCNxFAST8 __SCN8FAST(x)
|
||||
|
||||
#endif /* _WANT_IO_C99_FORMATS */
|
||||
|
||||
/* 16-bit types */
|
||||
#define __PRI16(x) __STRINGIFY(x)
|
||||
#define __SCN16(x) __STRINGIFY(h##x)
|
||||
#define __PRI16(x) __INT16 __STRINGIFY(x)
|
||||
#define __PRI16LEAST(x) __LEAST16 __STRINGIFY(x)
|
||||
#define __PRI16FAST(x) __FAST16 __STRINGIFY(x)
|
||||
#define __SCN16(x) __INT16 __STRINGIFY(x)
|
||||
#define __SCN16LEAST(x) __LEAST16 __STRINGIFY(x)
|
||||
#define __SCN16FAST(x) __FAST16 __STRINGIFY(x)
|
||||
|
||||
|
||||
#define PRId16 __PRI16(d)
|
||||
|
@ -113,41 +127,40 @@
|
|||
#define SCNx16 __SCN16(x)
|
||||
|
||||
|
||||
#define PRIdLEAST16 __PRI16(d)
|
||||
#define PRIiLEAST16 __PRI16(i)
|
||||
#define PRIoLEAST16 __PRI16(o)
|
||||
#define PRIuLEAST16 __PRI16(u)
|
||||
#define PRIxLEAST16 __PRI16(x)
|
||||
#define PRIXLEAST16 __PRI16(X)
|
||||
#define PRIdLEAST16 __PRI16LEAST(d)
|
||||
#define PRIiLEAST16 __PRI16LEAST(i)
|
||||
#define PRIoLEAST16 __PRI16LEAST(o)
|
||||
#define PRIuLEAST16 __PRI16LEAST(u)
|
||||
#define PRIxLEAST16 __PRI16LEAST(x)
|
||||
#define PRIXLEAST16 __PRI16LEAST(X)
|
||||
|
||||
#define SCNdLEAST16 __SCN16(d)
|
||||
#define SCNiLEAST16 __SCN16(i)
|
||||
#define SCNoLEAST16 __SCN16(o)
|
||||
#define SCNuLEAST16 __SCN16(u)
|
||||
#define SCNxLEAST16 __SCN16(x)
|
||||
#define SCNdLEAST16 __SCN16LEAST(d)
|
||||
#define SCNiLEAST16 __SCN16LEAST(i)
|
||||
#define SCNoLEAST16 __SCN16LEAST(o)
|
||||
#define SCNuLEAST16 __SCN16LEAST(u)
|
||||
#define SCNxLEAST16 __SCN16LEAST(x)
|
||||
|
||||
|
||||
#define PRIdFAST16 __PRI16(d)
|
||||
#define PRIiFAST16 __PRI16(i)
|
||||
#define PRIoFAST16 __PRI16(o)
|
||||
#define PRIuFAST16 __PRI16(u)
|
||||
#define PRIxFAST16 __PRI16(x)
|
||||
#define PRIXFAST16 __PRI16(X)
|
||||
#define PRIdFAST16 __PRI16FAST(d)
|
||||
#define PRIiFAST16 __PRI16FAST(i)
|
||||
#define PRIoFAST16 __PRI16FAST(o)
|
||||
#define PRIuFAST16 __PRI16FAST(u)
|
||||
#define PRIxFAST16 __PRI16FAST(x)
|
||||
#define PRIXFAST16 __PRI16FAST(X)
|
||||
|
||||
#define SCNdFAST16 __SCN16(d)
|
||||
#define SCNiFAST16 __SCN16(i)
|
||||
#define SCNoFAST16 __SCN16(o)
|
||||
#define SCNuFAST16 __SCN16(u)
|
||||
#define SCNxFAST16 __SCN16(x)
|
||||
#define SCNdFAST16 __SCN16FAST(d)
|
||||
#define SCNiFAST16 __SCN16FAST(i)
|
||||
#define SCNoFAST16 __SCN16FAST(o)
|
||||
#define SCNuFAST16 __SCN16FAST(u)
|
||||
#define SCNxFAST16 __SCN16FAST(x)
|
||||
|
||||
/* 32-bit types */
|
||||
#if __have_long32
|
||||
#define __PRI32(x) __STRINGIFY(l##x)
|
||||
#define __SCN32(x) __STRINGIFY(l##x)
|
||||
#else
|
||||
#define __PRI32(x) __STRINGIFY(x)
|
||||
#define __SCN32(x) __STRINGIFY(x)
|
||||
#endif
|
||||
#define __PRI32(x) __INT32 __STRINGIFY(x)
|
||||
#define __SCN32(x) __INT32 __STRINGIFY(x)
|
||||
#define __PRI32LEAST(x) __LEAST32 __STRINGIFY(x)
|
||||
#define __SCN32LEAST(x) __LEAST32 __STRINGIFY(x)
|
||||
#define __PRI32FAST(x) __FAST32 __STRINGIFY(x)
|
||||
#define __SCN32FAST(x) __FAST32 __STRINGIFY(x)
|
||||
|
||||
#define PRId32 __PRI32(d)
|
||||
#define PRIi32 __PRI32(i)
|
||||
|
@ -163,46 +176,44 @@
|
|||
#define SCNx32 __SCN32(x)
|
||||
|
||||
|
||||
#define PRIdLEAST32 __PRI32(d)
|
||||
#define PRIiLEAST32 __PRI32(i)
|
||||
#define PRIoLEAST32 __PRI32(o)
|
||||
#define PRIuLEAST32 __PRI32(u)
|
||||
#define PRIxLEAST32 __PRI32(x)
|
||||
#define PRIXLEAST32 __PRI32(X)
|
||||
#define PRIdLEAST32 __PRI32LEAST(d)
|
||||
#define PRIiLEAST32 __PRI32LEAST(i)
|
||||
#define PRIoLEAST32 __PRI32LEAST(o)
|
||||
#define PRIuLEAST32 __PRI32LEAST(u)
|
||||
#define PRIxLEAST32 __PRI32LEAST(x)
|
||||
#define PRIXLEAST32 __PRI32LEAST(X)
|
||||
|
||||
#define SCNdLEAST32 __SCN32(d)
|
||||
#define SCNiLEAST32 __SCN32(i)
|
||||
#define SCNoLEAST32 __SCN32(o)
|
||||
#define SCNuLEAST32 __SCN32(u)
|
||||
#define SCNxLEAST32 __SCN32(x)
|
||||
#define SCNdLEAST32 __SCN32LEAST(d)
|
||||
#define SCNiLEAST32 __SCN32LEAST(i)
|
||||
#define SCNoLEAST32 __SCN32LEAST(o)
|
||||
#define SCNuLEAST32 __SCN32LEAST(u)
|
||||
#define SCNxLEAST32 __SCN32LEAST(x)
|
||||
|
||||
|
||||
#define PRIdFAST32 __PRI32(d)
|
||||
#define PRIiFAST32 __PRI32(i)
|
||||
#define PRIoFAST32 __PRI32(o)
|
||||
#define PRIuFAST32 __PRI32(u)
|
||||
#define PRIxFAST32 __PRI32(x)
|
||||
#define PRIXFAST32 __PRI32(X)
|
||||
#define PRIdFAST32 __PRI32FAST(d)
|
||||
#define PRIiFAST32 __PRI32FAST(i)
|
||||
#define PRIoFAST32 __PRI32FAST(o)
|
||||
#define PRIuFAST32 __PRI32FAST(u)
|
||||
#define PRIxFAST32 __PRI32FAST(x)
|
||||
#define PRIXFAST32 __PRI32FAST(X)
|
||||
|
||||
#define SCNdFAST32 __SCN32(d)
|
||||
#define SCNiFAST32 __SCN32(i)
|
||||
#define SCNoFAST32 __SCN32(o)
|
||||
#define SCNuFAST32 __SCN32(u)
|
||||
#define SCNxFAST32 __SCN32(x)
|
||||
#define SCNdFAST32 __SCN32FAST(d)
|
||||
#define SCNiFAST32 __SCN32FAST(i)
|
||||
#define SCNoFAST32 __SCN32FAST(o)
|
||||
#define SCNuFAST32 __SCN32FAST(u)
|
||||
#define SCNxFAST32 __SCN32FAST(x)
|
||||
|
||||
|
||||
/* 64-bit types */
|
||||
#if __have_long64
|
||||
#define __PRI64(x) __STRINGIFY(l##x)
|
||||
#define __SCN64(x) __STRINGIFY(l##x)
|
||||
#elif __have_longlong64
|
||||
#define __PRI64(x) __STRINGIFY(ll##x)
|
||||
#define __SCN64(x) __STRINGIFY(ll##x)
|
||||
#else
|
||||
#define __PRI64(x) __STRINGIFY(x)
|
||||
#define __SCN64(x) __STRINGIFY(x)
|
||||
#endif
|
||||
#define __PRI64(x) __INT64 __STRINGIFY(x)
|
||||
#define __SCN64(x) __INT64 __STRINGIFY(x)
|
||||
|
||||
#define __PRI64LEAST(x) __LEAST64 __STRINGIFY(x)
|
||||
#define __SCN64LEAST(x) __LEAST64 __STRINGIFY(x)
|
||||
#define __PRI64FAST(x) __FAST64 __STRINGIFY(x)
|
||||
#define __SCN64FAST(x) __FAST64 __STRINGIFY(x)
|
||||
|
||||
#if __int64_t_defined
|
||||
#define PRId64 __PRI64(d)
|
||||
#define PRIi64 __PRI64(i)
|
||||
#define PRIo64 __PRI64(o)
|
||||
|
@ -215,34 +226,36 @@
|
|||
#define SCNo64 __SCN64(o)
|
||||
#define SCNu64 __SCN64(u)
|
||||
#define SCNx64 __SCN64(x)
|
||||
#endif
|
||||
|
||||
#if __int64_t_defined
|
||||
#define PRIdLEAST64 __PRI64(d)
|
||||
#define PRIiLEAST64 __PRI64(i)
|
||||
#define PRIoLEAST64 __PRI64(o)
|
||||
#define PRIuLEAST64 __PRI64(u)
|
||||
#define PRIxLEAST64 __PRI64(x)
|
||||
#define PRIXLEAST64 __PRI64(X)
|
||||
#if __int_least64_t_defined
|
||||
#define PRIdLEAST64 __PRI64LEAST(d)
|
||||
#define PRIiLEAST64 __PRI64LEAST(i)
|
||||
#define PRIoLEAST64 __PRI64LEAST(o)
|
||||
#define PRIuLEAST64 __PRI64LEAST(u)
|
||||
#define PRIxLEAST64 __PRI64LEAST(x)
|
||||
#define PRIXLEAST64 __PRI64LEAST(X)
|
||||
|
||||
#define SCNdLEAST64 __SCN64(d)
|
||||
#define SCNiLEAST64 __SCN64(i)
|
||||
#define SCNoLEAST64 __SCN64(o)
|
||||
#define SCNuLEAST64 __SCN64(u)
|
||||
#define SCNxLEAST64 __SCN64(x)
|
||||
#define SCNdLEAST64 __SCN64LEAST(d)
|
||||
#define SCNiLEAST64 __SCN64LEAST(i)
|
||||
#define SCNoLEAST64 __SCN64LEAST(o)
|
||||
#define SCNuLEAST64 __SCN64LEAST(u)
|
||||
#define SCNxLEAST64 __SCN64LEAST(x)
|
||||
#endif
|
||||
|
||||
#if __int_fast64_t_defined
|
||||
#define PRIdFAST64 __PRI64FAST(d)
|
||||
#define PRIiFAST64 __PRI64FAST(i)
|
||||
#define PRIoFAST64 __PRI64FAST(o)
|
||||
#define PRIuFAST64 __PRI64FAST(u)
|
||||
#define PRIxFAST64 __PRI64FAST(x)
|
||||
#define PRIXFAST64 __PRI64FAST(X)
|
||||
|
||||
#define PRIdFAST64 __PRI64(d)
|
||||
#define PRIiFAST64 __PRI64(i)
|
||||
#define PRIoFAST64 __PRI64(o)
|
||||
#define PRIuFAST64 __PRI64(u)
|
||||
#define PRIxFAST64 __PRI64(x)
|
||||
#define PRIXFAST64 __PRI64(X)
|
||||
|
||||
#define SCNdFAST64 __SCN64(d)
|
||||
#define SCNiFAST64 __SCN64(i)
|
||||
#define SCNoFAST64 __SCN64(o)
|
||||
#define SCNuFAST64 __SCN64(u)
|
||||
#define SCNxFAST64 __SCN64(x)
|
||||
#define SCNdFAST64 __SCN64FAST(d)
|
||||
#define SCNiFAST64 __SCN64FAST(i)
|
||||
#define SCNoFAST64 __SCN64FAST(o)
|
||||
#define SCNuFAST64 __SCN64FAST(u)
|
||||
#define SCNxFAST64 __SCN64FAST(x)
|
||||
#endif
|
||||
|
||||
/* max-bit types */
|
||||
|
@ -271,10 +284,10 @@
|
|||
#define SCNxMAX __SCNMAX(x)
|
||||
|
||||
/* ptr types */
|
||||
#if defined(_UINTPTR_EQ_ULONGLONG)
|
||||
#if defined (_INTPTR_EQ_LONGLONG)
|
||||
# define __PRIPTR(x) __STRINGIFY(ll##x)
|
||||
# define __SCNPTR(x) __STRINGIFY(ll##x)
|
||||
#elif defined(_UINTPTR_EQ_ULONG)
|
||||
#elif defined (_INTPTR_EQ_LONG)
|
||||
# define __PRIPTR(x) __STRINGIFY(l##x)
|
||||
# define __SCNPTR(x) __STRINGIFY(l##x)
|
||||
#else
|
||||
|
@ -301,6 +314,8 @@ typedef struct {
|
|||
intmax_t rem;
|
||||
} imaxdiv_t;
|
||||
|
||||
struct _reent;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -308,9 +323,20 @@ extern "C" {
|
|||
extern intmax_t imaxabs(intmax_t j);
|
||||
extern imaxdiv_t imaxdiv(intmax_t numer, intmax_t denomer);
|
||||
extern intmax_t strtoimax(const char *__restrict, char **__restrict, int);
|
||||
extern intmax_t _strtoimax_r(struct _reent *, const char *__restrict, char **__restrict, int);
|
||||
extern uintmax_t strtoumax(const char *__restrict, char **__restrict, int);
|
||||
extern uintmax_t _strtoumax_r(struct _reent *, const char *__restrict, char **__restrict, int);
|
||||
extern intmax_t wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int);
|
||||
extern intmax_t _wcstoimax_r(struct _reent *, const wchar_t *__restrict, wchar_t **__restrict, int);
|
||||
extern uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int);
|
||||
extern uintmax_t _wcstoumax_r(struct _reent *, const wchar_t *__restrict, wchar_t **__restrict, int);
|
||||
|
||||
#if __BSD_VISIBLE
|
||||
extern intmax_t strtoimax_l(const char *__restrict, char **_restrict, int, locale_t);
|
||||
extern uintmax_t strtoumax_l(const char *__restrict, char **_restrict, int, locale_t);
|
||||
extern intmax_t wcstoimax_l(const wchar_t *__restrict, wchar_t **_restrict, int, locale_t);
|
||||
extern uintmax_t wcstoumax_l(const wchar_t *__restrict, wchar_t **_restrict, int, locale_t);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
#include <newlib.h>
|
||||
#include <sys/config.h>
|
||||
#include <sys/cdefs.h>
|
||||
#if __POSIX_VISIBLE >= 200809
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
typedef int nl_item;
|
||||
|
||||
|
@ -301,7 +304,7 @@ enum __nl_item
|
|||
_NL_COLLATE_CODESET,
|
||||
|
||||
/* This MUST be the last entry since it's used to check for an array
|
||||
index in nl_langinfo(). */
|
||||
index in nl_langinfo(). It also must not exceed _NL_LOCALE_NAME_BASE. */
|
||||
_NL_LOCALE_EXTENDED_LAST_ENTRY
|
||||
|
||||
#endif /* __HAVE_LOCALE_INFO_EXTENDED__ */
|
||||
|
@ -309,8 +312,19 @@ enum __nl_item
|
|||
|
||||
};
|
||||
|
||||
/* As an extension, nl_langinfo can retrive the name of a locale
|
||||
category, with this mapping from setlocale() category (other than
|
||||
LC_ALL) to nl_item. */
|
||||
#define _NL_LOCALE_NAME_BASE 100000
|
||||
#if __GNU_VISIBLE
|
||||
#define NL_LOCALE_NAME(category) (_NL_LOCALE_NAME_BASE + (category))
|
||||
#endif
|
||||
|
||||
__BEGIN_DECLS
|
||||
char *nl_langinfo(nl_item);
|
||||
char *nl_langinfo (nl_item);
|
||||
#if __POSIX_VISIBLE >= 200809
|
||||
char *nl_langinfo_l (nl_item, locale_t);
|
||||
#endif
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_LANGINFO_H_ */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue