Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Philippe Kehl 2018-06-17 13:45:21 +02:00
commit 59cb689a45
54 changed files with 968 additions and 233 deletions

View file

@ -826,6 +826,13 @@ extern "C" {
#define configSTACK_DEPTH_TYPE uint16_t
#endif
#ifndef configMESSAGE_BUFFER_LENGTH_TYPE
/* Defaults to size_t for backward compatibility, but can be overridden
in FreeRTOSConfig.h if lengths will always be less than the number of bytes
in a size_t. */
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
#endif
/* Sanity check the configuration. */
#if( configUSE_TICKLESS_IDLE != 0 )
#if( INCLUDE_vTaskSuspend != 1 )
@ -1019,7 +1026,7 @@ typedef struct xSTATIC_TCB
uint32_t ulDummy18;
uint8_t ucDummy19;
#endif
#if( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t uxDummy20;
#endif
@ -1122,13 +1129,14 @@ typedef struct xSTATIC_TIMER
StaticListItem_t xDummy2;
TickType_t xDummy3;
UBaseType_t uxDummy4;
void *pvDummy5[ 2 ];
void *pvDummy5;
TaskFunction_t pvDummy6;
#if( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy6;
UBaseType_t uxDummy7;
#endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucDummy7;
uint8_t ucDummy8;
#endif
} StaticTimer_t;

View file

@ -693,6 +693,25 @@ size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) );
*/
#define xMessageBufferSpaceAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer )
/**
* message_buffer.h
<pre>
size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer ) );
</pre>
* Returns the length (in bytes) of the next message in a message buffer.
* Useful if xMessageBufferReceive() returned 0 because the size of the buffer
* passed into xMessageBufferReceive() was too small to hold the next message.
*
* @param xMessageBuffer The handle of the message buffer being queried.
*
* @return The length (in bytes) of the next message in the message buffer, or 0
* if the message buffer is empty.
*
* \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes
* \ingroup MessageBufferManagement
*/
#define xMessageBufferNextLengthBytes( xMessageBuffer ) xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer ) PRIVILEGED_FUNCTION;
/**
* message_buffer.h
*

View file

@ -138,6 +138,7 @@ UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup );
size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t xTicksToWait );
size_t MPU_xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, BaseType_t * const pxHigherPriorityTaskWoken );
size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait );
size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer );
size_t MPU_xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, BaseType_t * const pxHigherPriorityTaskWoken );
void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );
BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );

View file

@ -142,6 +142,7 @@ only for ports that are using the MPU. */
#define xStreamBufferSend MPU_xStreamBufferSend
#define xStreamBufferSendFromISR MPU_xStreamBufferSendFromISR
#define xStreamBufferReceive MPU_xStreamBufferReceive
#define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes
#define xStreamBufferReceiveFromISR MPU_xStreamBufferReceiveFromISR
#define vStreamBufferDelete MPU_vStreamBufferDelete
#define xStreamBufferIsFull MPU_xStreamBufferIsFull

View file

@ -233,7 +233,7 @@ typedef void * QueueSetMemberHandle_t;
/**
* queue. h
* <pre>
BaseType_t xQueueSendToToFront(
BaseType_t xQueueSendToFront(
QueueHandle_t xQueue,
const void *pvItemToQueue,
TickType_t xTicksToWait

View file

@ -839,6 +839,8 @@ StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION;
size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
#if( configUSE_TRACE_FACILITY == 1 )
void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION;
UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;

View file

@ -135,7 +135,7 @@ typedef struct xTASK_STATUS
UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */
uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */
uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
} TaskStatus_t;
/* Possible return values for eTaskConfirmSleepModeStatus(). */

View file

@ -114,7 +114,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Insert the new list item into the list, sorted in xItemValue order.
If the list already contains a list item with the same item value then the
new list item should be placed after it. This ensures that TCB's which are
new list item should be placed after it. This ensures that TCBs which are
stored in ready lists (all of which have the same xItemValue value) get a
share of the CPU. However, if the xItemValue is the same as the back marker
the iteration loop below will not end. Therefore the value is checked

View file

@ -301,7 +301,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType )
{
Queue_t *pxNewQueue;
Queue_t *pxNewQueue = NULL;
configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
@ -345,6 +345,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
else
{
traceQUEUE_CREATE_FAILED( ucQueueType );
mtCOVERAGE_TEST_MARKER();
}
return pxNewQueue;
@ -397,6 +398,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
else
{
traceQUEUE_CREATE_FAILED( ucQueueType );
mtCOVERAGE_TEST_MARKER();
}
return pxNewQueue;
@ -752,13 +754,23 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
{
traceQUEUE_SEND( pxQueue );
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
#if ( configUSE_QUEUE_SETS == 1 )
{
UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
if( pxQueue->pxQueueSetContainer != NULL )
{
if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )
if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) )
{
/* Do not notify the queue set as an existing item
was overwritten in the queue so the number of items
in the queue has not changed. */
mtCOVERAGE_TEST_MARKER();
}
else if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )
{
/* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to
@ -805,6 +817,8 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
}
#else /* configUSE_QUEUE_SETS */
{
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
/* If there was a task waiting for data to arrive on the
queue then unblock it now. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )

View file

@ -129,7 +129,7 @@ that uses task notifications. */
/*lint -restore (9026) */
/* The number of bytes used to hold the length of a message in the buffer. */
#define sbBYTES_TO_STORE_MESSAGE_LENGTH ( sizeof( size_t ) )
#define sbBYTES_TO_STORE_MESSAGE_LENGTH ( sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) )
/* Bits stored in the ucFlags field of the stream buffer. */
#define sbFLAGS_IS_MESSAGE_BUFFER ( ( uint8_t ) 1 ) /* Set if the stream buffer was created as a message buffer, in which case it holds discrete messages rather than a stream. */
@ -200,7 +200,7 @@ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer,
static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer,
uint8_t *pucData,
size_t xMaxCount,
size_t xBytesAvailable ); PRIVILEGED_FUNCTION
size_t xBytesAvailable ) PRIVILEGED_FUNCTION;
/*
* Called by both pxStreamBufferCreate() and pxStreamBufferCreateStatic() to
@ -504,6 +504,9 @@ TimeOut_t xTimeOut;
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{
xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
/* Overflow? */
configASSERT( xRequiredSpace > xDataLengthBytes );
}
else
{
@ -540,7 +543,7 @@ TimeOut_t xTimeOut;
taskEXIT_CRITICAL();
traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer );
( void ) xTaskNotifyWait( ( uint32_t ) 0, UINT32_MAX, NULL, xTicksToWait );
( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
pxStreamBuffer->xTaskWaitingToSend = NULL;
} while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE );
@ -746,7 +749,7 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
{
/* Wait for data to be available. */
traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer );
( void ) xTaskNotifyWait( ( uint32_t ) 0, UINT32_MAX, NULL, xTicksToWait );
( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait );
pxStreamBuffer->xTaskWaitingToReceive = NULL;
/* Recheck the data available after blocking. */
@ -792,6 +795,50 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength;
}
/*-----------------------------------------------------------*/
size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer )
{
StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */
size_t xReturn, xBytesAvailable, xOriginalTail;
configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn;
configASSERT( pxStreamBuffer );
/* Ensure the stream buffer is being used as a message buffer. */
if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 )
{
xBytesAvailable = prvBytesInBuffer( pxStreamBuffer );
if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH )
{
/* The number of bytes available is greater than the number of bytes
required to hold the length of the next message, so another message
is available. Return its length without removing the length bytes
from the buffer. A copy of the tail is stored so the buffer can be
returned to its prior state as the message is not actually being
removed from the buffer. */
xOriginalTail = pxStreamBuffer->xTail;
( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable );
xReturn = ( size_t ) xTempReturn;
pxStreamBuffer->xTail = xOriginalTail;
}
else
{
/* The minimum amount of bytes in a message buffer is
( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is
less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid
value is 0. */
configASSERT( xBytesAvailable == 0 );
xReturn = 0;
}
}
else
{
xReturn = 0;
}
return xReturn;
}
/*-----------------------------------------------------------*/
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer,
void *pvRxData,
size_t xBufferLengthBytes,
@ -856,6 +903,7 @@ static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer,
size_t xBytesToStoreMessageLength )
{
size_t xOriginalTail, xReceivedLength, xNextMessageLength;
configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength;
if( xBytesToStoreMessageLength != ( size_t ) 0 )
{
@ -864,7 +912,8 @@ size_t xOriginalTail, xReceivedLength, xNextMessageLength;
returned to its prior state if the length of the message is too
large for the provided buffer. */
xOriginalTail = pxStreamBuffer->xTail;
( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable );
( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable );
xNextMessageLength = ( size_t ) xTempNextMessageLength;
/* Reduce the number of bytes available by the number of bytes just
read out. */
@ -1192,7 +1241,7 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer )
{
return ( ( StreamBuffer_t * )xStreamBuffer )->ucFlags | sbFLAGS_IS_MESSAGE_BUFFER;
return ( ( StreamBuffer_t * )xStreamBuffer )->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER;
}
#endif /* configUSE_TRACE_FACILITY */

View file

@ -509,7 +509,7 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseT
*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
#endif
@ -846,6 +846,8 @@ UBaseType_t x;
uxPriority &= ~portPRIVILEGE_BIT;
#endif /* portUSING_MPU_WRAPPERS == 1 */
configASSERT( pcName );
/* Avoid dependency on memset() if it is not required. */
#if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
{
@ -1362,11 +1364,30 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
else if( pxStateList == &xSuspendedTaskList )
{
/* The task being queried is referenced from the suspended
list. Is it genuinely suspended or is it block
list. Is it genuinely suspended or is it blocked
indefinitely? */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
{
eReturn = eSuspended;
#if( configUSE_TASK_NOTIFICATIONS == 1 )
{
/* The task does not appear on the event list item of
and of the RTOS objects, but could still be in the
blocked state if it is waiting on its notification
rather than waiting on an object. */
if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION )
{
eReturn = eBlocked;
}
else
{
eReturn = eSuspended;
}
}
#else
{
eReturn = eSuspended;
}
#endif
}
else
{
@ -1982,7 +2003,7 @@ BaseType_t xReturn;
xNextTaskUnblockTime = portMAX_DELAY;
xSchedulerRunning = pdTRUE;
xTickCount = ( TickType_t ) 0U;
xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
/* If configGENERATE_RUN_TIME_STATS is defined then the following
macro must be defined to configure the timer/counter used to generate
@ -1992,6 +2013,8 @@ BaseType_t xReturn;
FreeRTOSConfig.h file. */
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
traceTASK_SWITCHED_IN();
/* Setting up the timer tick is hardware specific and thus in the
portable interface. */
if( xPortStartScheduler() != pdFALSE )
@ -2778,7 +2801,9 @@ BaseType_t xSwitchRequired = pdFALSE;
/* Save the hook function in the TCB. A critical section is required as
the value can be accessed from an interrupt. */
taskENTER_CRITICAL();
{
xTCB->pxTaskTag = pxHookFunction;
}
taskEXIT_CRITICAL();
}
@ -3474,7 +3499,7 @@ static void prvCheckTasksWaitingTermination( void )
{
TCB_t *pxTCB;
/* uxDeletedTasksWaitingCleanUp is used to prevent vTaskSuspendAll()
/* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
being called too often in the idle task. */
while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
{
@ -3625,7 +3650,7 @@ static void prvCheckTasksWaitingTermination( void )
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
{
uint32_t ulCount = 0U;
@ -3637,7 +3662,7 @@ static void prvCheckTasksWaitingTermination( void )
ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
return ( uint16_t ) ulCount;
return ( configSTACK_DEPTH_TYPE ) ulCount;
}
#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
@ -4766,13 +4791,11 @@ TickType_t uxReturn;
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
else
{
/* Mark that a yield is pending in case the user is not
using the "xHigherPriorityTaskWoken" parameter to an ISR
safe FreeRTOS function. */
xYieldPending = pdTRUE;
}
/* Mark that a yield is pending in case the user is not
using the "xHigherPriorityTaskWoken" parameter to an ISR
safe FreeRTOS function. */
xYieldPending = pdTRUE;
}
else
{
@ -4856,13 +4879,11 @@ TickType_t uxReturn;
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
else
{
/* Mark that a yield is pending in case the user is not
using the "xHigherPriorityTaskWoken" parameter in an ISR
safe FreeRTOS function. */
xYieldPending = pdTRUE;
}
/* Mark that a yield is pending in case the user is not
using the "xHigherPriorityTaskWoken" parameter in an ISR
safe FreeRTOS function. */
xYieldPending = pdTRUE;
}
else
{

10
bootloader/c_types.h Normal file
View file

@ -0,0 +1,10 @@
/* rboot type definitions */
typedef int int32;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned char uint8;
#define TRUE 1
#define FALSE 0

@ -1 +1 @@
Subproject commit 30afbaa777e00abf9d7d469fb3345f118c4975c1
Subproject commit 3b067a8686a07474c5f722953d3b2f0e71db681f

View file

@ -174,25 +174,32 @@ void IRAM sdk_user_start(void) {
}
switch (buf8[3] >> 4) {
case 0x0: // 4 Mbit (512 KByte)
flash_sectors = 128;
flash_size = 524288;
break;
case 0x1: // 2 Mbit (256 Kbyte)
flash_sectors = 64;
flash_size = 262144;
break;
case 0x2: // 8 Mbit (1 Mbyte)
flash_sectors = 256;
flash_size = 1048576;
break;
case 0x3: // 16 Mbit (2 Mbyte)
flash_sectors = 512;
case 0x5: // 16 Mbit (2 Mbyte)
flash_size = 2097152;
break;
case 0x4: // 32 Mbit (4 Mbyte)
flash_sectors = 1024;
case 0x6: // 32 Mbit (4 Mbyte)
flash_size = 4194304;
break;
case 0x8: // 64 Mbit (8 Mbyte)
flash_size = 8388608;
break;
case 0x9: // 128 Mbit (16 Mbyte)
flash_size = 16777216;
break;
default: // Invalid -- Assume 4 Mbit (512 KByte)
flash_sectors = 128;
flash_size = 524288;
}
//FIXME: we should probably calculate flash_sectors by starting with flash_size and dividing by sdk_flashchip.sector_size instead of vice-versa.
flash_size = flash_sectors * 4096;
flash_sectors = flash_size / sdk_flashchip.sector_size;
sdk_flashchip.chip_size = flash_size;
set_spi0_divisor(flash_speed_divisor);
sdk_SPIRead(flash_size - 4096, buf32, BOOT_INFO_SIZE);
@ -431,8 +438,6 @@ static __attribute__((noinline)) void user_start_phase2(void) {
memcpy(&phy_info, &default_phy_info, sizeof(sdk_phy_info_t));
}
// Disable default buffering on stdout
setbuf(stdout, NULL);
// Wait for UARTs to finish sending anything in their queues.
uart_flush_txfifo(0);
uart_flush_txfifo(1);

View file

@ -4,22 +4,22 @@
#include <stdio.h>
#include <stdlib.h>
void *operator new(size_t size)
void * __attribute__((weak)) operator new(size_t size)
{
return malloc(size);
}
void *operator new[](size_t size)
void * __attribute__((weak)) operator new[](size_t size)
{
return malloc(size);
}
void operator delete(void * ptr)
void __attribute__((weak)) operator delete(void * ptr)
{
free(ptr);
}
void operator delete[](void * ptr)
void __attribute__((weak)) operator delete[](void * ptr)
{
free(ptr);
}

View file

@ -70,7 +70,7 @@ struct GPIO_REGS {
uint32_t volatile STATUS_SET; // 0x20
uint32_t volatile STATUS_CLEAR; // 0x24
uint32_t volatile CONF[16]; // 0x28 - 0x64
uint32_t volatile PWM; // 0x68
uint32_t volatile DSM; // 0x68
uint32_t volatile RTC_CALIB; // 0x6c
uint32_t volatile RTC_CALIB_RESULT; // 0x70
};
@ -117,9 +117,9 @@ _Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size");
* GPIO_CONF_OPEN_DRAIN does not appear to work on all pins.
*
*
* GPIO_CONF_SOURCE_PWM (boolean)
* When set, GPIO pin output will be connected to the sigma-delta PWM
* generator (controlled by the GPIO.PWM register). When cleared, pin
* GPIO_CONF_SOURCE_DSM (boolean)
* When set, GPIO pin output will be connected to the sigma-delta
* generator (controlled by the GPIO.DSM register). When cleared, pin
* output will function as a normal GPIO output (controlled by the
* GPIO.OUT* registers).
*/
@ -130,7 +130,7 @@ _Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size");
#define GPIO_CONF_INTTYPE_M 0x00000007
#define GPIO_CONF_INTTYPE_S 7
#define GPIO_CONF_OPEN_DRAIN BIT(2)
#define GPIO_CONF_SOURCE_PWM BIT(0)
#define GPIO_CONF_SOURCE_DSM BIT(0)
/* Valid values for the GPIO_CONF_INTTYPE field */
typedef enum {
@ -142,13 +142,13 @@ typedef enum {
GPIO_INTTYPE_LEVEL_HIGH = 5,
} gpio_inttype_t;
/* Details for PWM register */
/* Details for DSM register */
#define GPIO_PWM_ENABLE BIT(16)
#define GPIO_PWM_PRESCALER_M 0x000000ff
#define GPIO_PWM_PRESCALER_S 8
#define GPIO_PWM_TARGET_M 0x000000ff
#define GPIO_PWM_TARGET_S 0
#define GPIO_DSM_ENABLE BIT(16)
#define GPIO_DSM_PRESCALER_M 0x000000ff
#define GPIO_DSM_PRESCALER_S 8
#define GPIO_DSM_TARGET_M 0x000000ff
#define GPIO_DSM_TARGET_S 0
/* Details for RTC_CALIB register */

View file

@ -160,4 +160,14 @@ static inline UART_Parity uart_get_parity(int uart_num) {
return (UART_Parity)((UART(uart_num).CONF0 & UART_CONF0_PARITY) != 0);
}
/* Set uart data bits length to the desired value */
static inline void uart_set_byte_length(int uart_num, UART_ByteLength byte_length) {
UART(uart_num).CONF0 = SET_FIELD(UART(uart_num).CONF0, UART_CONF0_BYTE_LEN, byte_length);
}
/* Returns the current data bits length for the UART */
static inline UART_ByteLength uart_get_byte_length(int uart_num) {
return (UART_ByteLength)(FIELD2VAL(UART_CONF0_BYTE_LEN, UART(uart_num).CONF0));
}
#endif /* _ESP_UART_H */

View file

@ -62,6 +62,13 @@ typedef enum {
UART_PARITY_ODD = 0b1
} UART_Parity;
typedef enum {
UART_BYTELENGTH_5 = 0b00,
UART_BYTELENGTH_6 = 0b01,
UART_BYTELENGTH_7 = 0b10,
UART_BYTELENGTH_8 = 0b11,
} UART_ByteLength;
/* Details for FIFO register */
#define UART_FIFO_DATA_M 0x000000ff

View file

@ -303,6 +303,10 @@ void _lock_acquire(_lock_t *lock) {
void _lock_acquire_recursive(_lock_t *lock) {
if (locks_initialized) {
if (sdk_NMIIrqIsOn) {
uart_putc(0, ':');
return;
}
xSemaphoreTakeRecursive((QueueHandle_t)*lock, portMAX_DELAY);
}
}
@ -321,6 +325,9 @@ void _lock_release(_lock_t *lock) {
void _lock_release_recursive(_lock_t *lock) {
if (locks_initialized) {
if (sdk_NMIIrqIsOn) {
return;
}
xSemaphoreGiveRecursive((QueueHandle_t)*lock);
}
}

View file

@ -505,6 +505,8 @@ sysparam_status_t sysparam_init(uint32_t base_addr, uint32_t top_addr) {
struct sysparam_context ctx;
uint16_t num_sectors;
_sysparam_info.sem = xSemaphoreCreateMutex();
// Make sure we're starting at the beginning of the sector
base_addr -= (base_addr % sdk_flashchip.sector_size);
@ -584,8 +586,6 @@ sysparam_status_t sysparam_init(uint32_t base_addr, uint32_t top_addr) {
_sysparam_info.end_addr = ctx.addr;
}
_sysparam_info.sem = xSemaphoreCreateMutex();
return SYSPARAM_OK;
}

View file

@ -0,0 +1,4 @@
# Simple makefile for simple example
PROGRAM=dsm_test
EXTRA_COMPONENTS = extras/dsm
include ../../common.mk

View file

@ -0,0 +1,67 @@
/* Very basic example to test the dsm library
* Led intensity from module will change over time.
*
* Part of esp-open-rtos
* Copyright (C) 2018 zaltora (https://github.com/Zaltora)
* BSD Licensed as described in the file LICENSE
*/
#include "espressif/esp_common.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "dsm.h"
#define TEST_WITH_160MHZ (0)
#define DSM_PIN (2)
void task1(void *pvParameters)
{
uint32_t const init_count = 0;
uint32_t count = init_count;
while(1)
{
vTaskDelay(100/portTICK_PERIOD_MS);
printf("Target set to %3u, ", count);
//Freq = (80,000,000/prescale) * (target / 256) HZ (0 < target < 128)
//Freq = (80,000,000/prescale) * ((256 - target) / 256) HZ (128 < target < 256)
if (count < 128)
{
printf("Freqency: %.1f Hz\r\n", (80000000.0/255.0 * (count/ 256.0)));
}
else
{
printf("Freqency: %.1f Hz\r\n", 80000000.0/255.0 * ((256.0-count)/ 256.0));
}
dsm_set_target(count);
count++;
if (count > UINT8_MAX)
count = init_count;
}
}
void user_init(void)
{
uint8_t pins[1];
uart_set_baud(0, 115200);
#if (TEST_WITH_160MHZ)
sdk_system_update_cpu_freq(160);
#endif
printf("SDK version:%s\r\n", sdk_system_get_sdk_version());
pins[0] = DSM_PIN;
/* register pin to use with DSM */
dsm_init(1, pins);
/* Set prescale to FF to get a proper signal */
dsm_set_prescale(0xFF);
/* Target initial */
dsm_set_target(0);
/* start dsm to pin */
dsm_start();
printf("dsm start\r\n");
xTaskCreate(task1, "tsk1", 256, NULL, 2, NULL);
}

View file

@ -12,6 +12,7 @@
#define CS_GPIO_PIN 2
#define TEST_FILENAME "/test_loooong_filename.txt"
#define TEST_DIRECTORYNAME "my_directory"
#define TEST_CONTENTS "Hello! It's FatFs on esp8266 with ESP Open RTOS!"
#define READBUF_SIZE 256
#define DELAY_MS 3000
@ -69,6 +70,19 @@ void check_fatfs()
if (failed(f_chdrive(vol)))
return;
// Create a directory if it not exists
FILINFO info;
if (failed(f_stat(TEST_DIRECTORYNAME, &info)) && info.fattrib & AM_DIR)
{
printf("f_mkdir (\"%s\")\n", TEST_DIRECTORYNAME);
if (failed(f_mkdir(TEST_DIRECTORYNAME)))
return;
}
else
{
printf("\"%s\" directory already exists\n", TEST_DIRECTORYNAME);
}
FIL f;
// Create test file
printf("f_open(&f, \"%s\", FA_WRITE | FA_CREATE_ALWAYS)", TEST_FILENAME);

9
extras/dsm/component.mk Normal file
View file

@ -0,0 +1,9 @@
# Component makefile for extras/dsm
INC_DIRS += $(ROOT)extras/dsm
# args for passing into compile rule generation
extras/dsm_INC_DIR = $(ROOT)extras/dsm
extras/dsm_SRC_DIR = $(ROOT)extras/dsm
$(eval $(call component_compile_rules,extras/dsm))

111
extras/dsm/dsm.c Normal file
View file

@ -0,0 +1,111 @@
/* Implementation of Delta-Sigma modulator support.
*
* Part of esp-open-rtos
* Copyright (C) 2018 ourairquality (https://github.com/ourairquality)
* Copyright (C) 2018 Zaltora (https://github.com/Zaltora)
* BSD Licensed as described in the file LICENSE
*/
#include "dsm.h"
#include <espressif/esp_common.h>
#include <esp8266.h>
#if (DSM_DEBUG)
#define debug(fmt, ...) printf("%s: " fmt "\n", "DSM", ## __VA_ARGS__)
#else
#define debug(fmt, ...)
#endif
typedef struct dsmInfoDefinition
{
uint8_t running;
uint8_t preScale;
uint8_t target;
bool output;
/* private */
uint8_t usedPins;
uint8_t pins[8];
} DSMInfo;
static DSMInfo dsmInfo;
void dsm_init(uint8_t npins, const uint8_t* pins)
{
/* Assert number of pins is correct */
if (npins > MAX_DSM_PINS)
{
debug("Incorrect number of DSM pins (%d)\n", npins);
return;
}
/* Save pins information */
dsmInfo.usedPins = npins;
for (uint8_t i = 0 ; i < npins; ++i)
{
dsmInfo.pins[i] = pins[i];
/* configure GPIOs */
gpio_enable(pins[i], GPIO_OUTPUT);
}
/* Set output to LOW */
dsm_stop();
/* Flag not running */
dsmInfo.running = 0;
}
void dsm_set_prescale(uint8_t prescale)
{
//TODO: Add a freq/prescale converter
dsmInfo.preScale = prescale;
debug("Set Prescale: %u",dsmInfo.preScale);
}
void dsm_set_target(uint8_t target)
{
dsmInfo.target = target;
if (target == 0 || target == UINT8_MAX)
{
dsmInfo.output = (target == UINT8_MAX);
}
debug("Duty set at %u",dsmInfo.target);
if (dsmInfo.running)
{
dsm_start();
}
}
void dsm_start()
{
if (dsmInfo.target > 0 && dsmInfo.target < UINT8_MAX)
{
for (uint8_t i = 0; i < dsmInfo.usedPins; ++i)
{
SET_MASK_BITS(GPIO.CONF[dsmInfo.pins[i]], GPIO_CONF_SOURCE_DSM);
}
GPIO.DSM = GPIO_DSM_ENABLE | (dsmInfo.preScale << 8) | dsmInfo.target;
}
else
{
for (uint8_t i = 0; i < dsmInfo.usedPins; ++i)
{
gpio_write(dsmInfo.pins[i], dsmInfo.output );
}
}
debug("start");
dsmInfo.running = 1;
}
void dsm_stop()
{
for (uint8_t i = 0; i < dsmInfo.usedPins; ++i)
{
CLEAR_MASK_BITS(GPIO.CONF[dsmInfo.pins[i]], GPIO_CONF_SOURCE_DSM);
gpio_write(dsmInfo.pins[i], false);
}
debug("stop");
dsmInfo.running = 0;
}

36
extras/dsm/dsm.h Normal file
View file

@ -0,0 +1,36 @@
/* Implementation of Delta-Sigma modulator support.
*
* Part of esp-open-rtos
* Copyright (C) 2018 ourairquality (https://github.com/ourairquality)
* Copyright (C) 2018 Zaltora (https://github.com/Zaltora)
* BSD Licensed as described in the file LICENSE
*/
#ifndef EXTRAS_DSM_H_
#define EXTRAS_DSM_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define MAX_DSM_PINS (8)
#define DSM_DEBUG (0)
/*
* Freq = (80,000,000/prescale) * (target / 256) HZ (0 < target < 128)
* Freq = (80,000,000/prescale) * ((256 - target) / 256) HZ (128 < target < 256)
*/
void dsm_init(uint8_t npins, const uint8_t* pins);
void dsm_set_prescale(uint8_t prescale);
void dsm_set_target(uint8_t target);
void dsm_start();
void dsm_stop();
#ifdef __cplusplus
}
#endif
#endif /* EXTRAS_DSM_H_ */

View file

@ -32,6 +32,7 @@
//#define I2C_DEBUG true
#ifdef I2C_DEBUG
#include <stdio.h>
#define debug(fmt, ...) printf("%s: " fmt "\n", "I2C", ## __VA_ARGS__)
#else
#define debug(fmt, ...)
@ -66,7 +67,7 @@ typedef struct i2c_bus_description
bool started;
bool flag;
bool force;
uint32_t clk_stretch;
TickType_t clk_stretch;
} i2c_bus_description_t;
static i2c_bus_description_t i2c_bus[I2C_MAX_BUS];
@ -183,7 +184,7 @@ int i2c_set_frequency_hz(uint8_t bus, uint32_t freq)
return not_ok ? -EINVAL : 0;
}
void i2c_set_clock_stretch(uint8_t bus, uint32_t clk_stretch)
void i2c_set_clock_stretch(uint8_t bus, TickType_t clk_stretch)
{
i2c_bus[bus].clk_stretch = clk_stretch;
}
@ -235,13 +236,46 @@ static inline void clear_sda(uint8_t bus)
#endif
}
static inline void set_scl(uint8_t bus)
#define I2C_CLK_STRETCH_SPIN 1024
static void set_scl(uint8_t bus)
{
#if I2C_USE_GPIO16 == 1
gpio_write(i2c_bus[bus].g_scl_pin, 1);
#else
GPIO.OUT_SET = i2c_bus[bus].g_scl_mask;
#endif
// Clock stretching.
// Spin sampling frequently.
uint32_t clk_stretch_spin = I2C_CLK_STRETCH_SPIN;
do {
if (read_scl(bus)) {
return;
}
clk_stretch_spin--;
} while (clk_stretch_spin);
// Fall back to a longer wait, sampling less frequently.
TickType_t clk_stretch = i2c_bus[bus].clk_stretch;
TickType_t start = xTaskGetTickCount();
do {
vTaskDelay(20 / portTICK_PERIOD_MS);
if (read_scl(bus)) {
return;
}
TickType_t elapsed = xTaskGetTickCount() - start;
if (elapsed > clk_stretch) {
break;
}
} while (1);
debug("bus %u clock stretch timeout", bus);
}
static inline void set_sda(uint8_t bus)
@ -265,10 +299,7 @@ void i2c_start(uint8_t bus)
// Set SDA to 1
set_sda(bus);
i2c_delay(bus);
uint32_t clk_stretch = i2c_bus[bus].clk_stretch;
set_scl(bus);
while (read_scl(bus) == 0 && clk_stretch--)
;
// Repeated start setup time, minimum 4.7us
i2c_delay(bus);
}
@ -286,14 +317,10 @@ void i2c_start(uint8_t bus)
// Output stop condition
bool i2c_stop(uint8_t bus)
{
uint32_t clk_stretch = i2c_bus[bus].clk_stretch;
// Set SDA to 0
clear_sda(bus);
i2c_delay(bus);
// Clock stretching
set_scl(bus);
while (read_scl(bus) == 0 && clk_stretch--)
;
// Stop bit setup time, minimum 4us
i2c_delay(bus);
// SCL is high, set SDA from 0 to 1
@ -315,17 +342,13 @@ bool i2c_stop(uint8_t bus)
// Write a bit to I2C bus
static void i2c_write_bit(uint8_t bus, bool bit)
{
uint32_t clk_stretch = i2c_bus[bus].clk_stretch;
if (bit) {
set_sda(bus);
} else {
clear_sda(bus);
}
i2c_delay(bus);
// Clock stretching
set_scl(bus);
while (read_scl(bus) == 0 && clk_stretch--)
;
// SCL is high, now data is valid
// If SDA is high, check that nobody else is driving SDA
if (bit && read_sda(bus) == 0) {
@ -338,15 +361,11 @@ static void i2c_write_bit(uint8_t bus, bool bit)
// Read a bit from I2C bus
static bool i2c_read_bit(uint8_t bus)
{
uint32_t clk_stretch = i2c_bus[bus].clk_stretch;
bool bit;
// Let the slave drive data
set_sda(bus);
i2c_delay(bus);
set_scl(bus);
// Clock stretching
while (read_scl(bus) == 0 && clk_stretch--)
;
// SCL is high, now data is valid
bit = read_sda(bus);
i2c_delay(bus);

View file

@ -32,6 +32,8 @@
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <FreeRTOS.h>
#include <task.h>
#ifdef __cplusplus
extern "C" {
@ -51,7 +53,8 @@ extern "C" {
#define I2C_USE_GPIO16 0
#endif
#define I2C_DEFAULT_CLK_STRETCH (10)
/* Default clock strech waiting time, 250 msec. */
#define I2C_DEFAULT_CLK_STRETCH (250 / portTICK_PERIOD_MS)
/* SCL speed settings. 160 MHz sysclk frequency will result in improved
* timing accuracy. Greater bitrates will have poorer accuracy. 1000K is the
@ -86,7 +89,6 @@ typedef struct i2c_dev
* @param scl_pin SCL pin for I2C
* @param sda_pin SDA pin for I2C
* @param freq frequency of bus (ex : I2C_FREQ_400K)
* @param clk_stretch I2C clock stretch. I2C_DEFAULT_CLK_STRETCH would be good in most cases
* @return Non-zero if error occured
*/
int i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq);
@ -97,7 +99,6 @@ int i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq);
* @param scl_pin SCL pin for I2C
* @param sda_pin SDA pin for I2C
* @param freq frequency of bus in hertz
* @param clk_stretch I2C clock stretch. I2C_DEFAULT_CLK_STRETCH would be good in most cases
* @return Non-zero if error occured
*/
int i2c_init_hz(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, uint32_t freq);
@ -119,9 +120,9 @@ int i2c_set_frequency_hz(uint8_t bus, uint32_t freq);
/**
* Change clock stretch
* @param bus I2C bus
* @param clk_stretch I2C clock stretch. I2C_DEFAULT_CLK_STRETCH by default
* @param clk_stretch I2C clock stretch, in ticks. I2C_DEFAULT_CLK_STRETCH by default
*/
void i2c_set_clock_stretch(uint8_t bus, uint32_t clk_stretch);
void i2c_set_clock_stretch(uint8_t bus, TickType_t clk_stretch);
/**
* Write a byte to I2C bus.

View file

@ -26,7 +26,7 @@ OBJS_CRYPTO= aes.o aesni.o arc4.o \
padlock.o pem.o pk.o \
pk_wrap.o pkcs12.o pkcs5.o \
pkparse.o pkwrite.o platform.o \
ripemd160.o rsa.o sha1.o \
ripemd160.o rsa.o rsa_internal.o sha1.o \
sha256.o sha512.o threading.o \
timing.o version.o \
version_features.o xtea.o

@ -1 +1 @@
Subproject commit f2a597fa3dd1c7b15e0fee62f6932b253295803d
Subproject commit 1bf6123fca97a9a35c2f403ab0c96495f9580db6

View file

@ -1,6 +1,7 @@
/*
* TCP/IP or UDP/IP networking functions
* modified for LWIP support on ESP8266
* Based on mbedtls/library/net_sockets.c
* Modified for LWIP support on ESP8266
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2015 Angus Gratton
@ -21,7 +22,6 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#include <fcntl.h>
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@ -30,18 +30,74 @@
#if defined(MBEDTLS_NET_C)
#define ESP_OPEN_RTOS 1
#define _SOCKLEN_T_DECLARED 1
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(ESP_OPEN_RTOS)
#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#endif
#include "mbedtls/net_sockets.h"
#include <string.h>
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
/* Enables getaddrinfo() & Co */
#define _WIN32_WINNT 0x0501
#include <ws2tcpip.h>
#include <winsock2.h>
#include <windows.h>
#if defined(_MSC_VER)
#if defined(_WIN32_WCE)
#pragma comment( lib, "ws2.lib" )
#else
#pragma comment( lib, "ws2_32.lib" )
#endif
#endif /* _MSC_VER */
#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 )
#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 )
#define close(fd) closesocket(fd)
static int wsa_init_done = 0;
#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
#include <sys/types.h>
#include <sys/socket.h>
//#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
/* Some MS functions want int and MSVC warns if we pass size_t,
* but the standard functions use socklen_t, so cast only for MSVC */
#if defined(_MSC_VER)
#define MSVC_INT_CAST (int)
#else
#define MSVC_INT_CAST
#endif
#include <stdio.h>
#include <time.h>
@ -65,6 +121,9 @@ static int net_prepare( void )
wsa_init_done = 1;
}
#else
#if !defined(EFIX64) && !defined(EFI32) && !defined(ESP_OPEN_RTOS)
signal( SIGPIPE, SIG_IGN );
#endif
#endif
return( 0 );
}
@ -80,7 +139,8 @@ void mbedtls_net_init( mbedtls_net_context *ctx )
/*
* Initiate a TCP connection with host:port and the given protocol
*/
int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host,
const char *port, int proto )
{
int ret;
struct addrinfo hints, *addr_list, *cur;
@ -109,7 +169,11 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char
continue;
}
if( connect( ctx->fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
const struct timeval timeout = { 60, 0 }; /* 60 second timeout */
setsockopt( ctx->fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout) );
setsockopt( ctx->fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout) );
if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
{
ret = 0;
break;
@ -130,14 +194,7 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char
int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
{
int n, ret;
struct addrinfo *addr_list, *cur;
/* Only request desired protocol */
const struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = (proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM),
.ai_protocol = (proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP),
};
struct addrinfo hints, *addr_list, *cur;
struct sockaddr_in sockaddr_ipaddr_any = {
.sin_len = sizeof(struct sockaddr_in),
@ -148,8 +205,8 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
struct addrinfo all_interfaces_addr = {
.ai_family = AF_INET,
.ai_socktype = hints.ai_socktype,
.ai_protocol = hints.ai_protocol,
.ai_socktype = (proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM),
.ai_protocol = (proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP),
.ai_addrlen = sizeof(struct sockaddr_in),
.ai_addr = (struct sockaddr *)&sockaddr_ipaddr_any,
};
@ -157,14 +214,22 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
if( ( ret = net_prepare() ) != 0 )
return( ret );
if(bind_ip == NULL) {
/* Bind to IPv6 and/or IPv4, but only in the desired protocol */
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
if( bind_ip == NULL )
hints.ai_flags = AI_PASSIVE;
if( bind_ip == NULL ) {
/* mbedTLS docs specify bind_ip == NULL means all interfaces, but lwip getaddrinfo() assumes NULL
means localhost. So we swap in a precreated IPADDR_ANY addrinfo result here. */
addr_list = &all_interfaces_addr;
}
else if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) {
else
if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
}
/* Try the sockaddrs until a binding succeeds */
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
@ -187,7 +252,7 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
continue;
}
if( bind( ctx->fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
{
close( ctx->fd );
ret = MBEDTLS_ERR_NET_BIND_FAILED;
@ -205,12 +270,12 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
}
}
/* I we ever get there, it's a success */
/* Bind was successful */
ret = 0;
break;
}
if(bind_ip != NULL) {
if( bind_ip != NULL ) {
freeaddrinfo( addr_list );
}
@ -218,14 +283,18 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
}
static int socket_errno( const mbedtls_net_context *ctx )
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
!defined(EFI32)
/*
* Check if the requested operation would be blocking on a non-blocking socket
* and thus 'failed' with a negative return value.
*/
static int net_would_block( const mbedtls_net_context *ctx )
{
int sock_errno = 0;
u32_t optlen = sizeof(sock_errno);
lwip_getsockopt(ctx->fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
return sock_errno;
((void) ctx);
return( WSAGetLastError() == WSAEWOULDBLOCK );
}
#else
/*
* Check if the requested operation would be blocking on a non-blocking socket
* and thus 'failed' with a negative return value.
@ -234,14 +303,18 @@ static int socket_errno( const mbedtls_net_context *ctx )
*/
static int net_would_block( const mbedtls_net_context *ctx )
{
int err = errno;
/*
* Never return 'WOULD BLOCK' on a non-blocking socket
*/
if( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK )
{
errno = err;
return( 0 );
}
switch( socket_errno(ctx) )
switch( errno = err )
{
#if defined EAGAIN
case EAGAIN:
@ -253,6 +326,7 @@ static int net_would_block( const mbedtls_net_context *ctx )
}
return( 0 );
}
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
/*
* Accept a connection from a remote client
@ -264,14 +338,20 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
int ret;
int type;
struct sockaddr_in client_addr;
struct sockaddr_storage client_addr;
#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t)
socklen_t n = (socklen_t) sizeof( client_addr );
socklen_t type_len = (socklen_t) sizeof( type );
#else
int n = (int) sizeof( client_addr );
int type_len = (int) sizeof( type );
#endif
/* Is this a TCP or UDP socket? */
if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
(void *) &type, (socklen_t *) &type_len ) != 0 ||
(void *) &type, &type_len ) != 0 ||
( type != SOCK_STREAM && type != SOCK_DGRAM ) )
{
return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
@ -288,7 +368,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
/* UDP: wait for a message, but keep it in the queue */
char buf[1] = { 0 };
ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
(struct sockaddr *) &client_addr, &n );
#if defined(_WIN32)
@ -313,7 +393,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
* then bind a new socket to accept new connections */
if( type != SOCK_STREAM )
{
struct sockaddr_in local_addr;
struct sockaddr_storage local_addr;
int one = 1;
if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
@ -322,10 +402,10 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
client_ctx->fd = bind_ctx->fd;
bind_ctx->fd = -1; /* In case we exit early */
n = sizeof( struct sockaddr_in );
n = sizeof( struct sockaddr_storage );
if( getsockname( client_ctx->fd,
(struct sockaddr *) &local_addr, &n ) != 0 ||
( bind_ctx->fd = (int) socket( AF_INET,
( bind_ctx->fd = (int) socket( local_addr.ss_family,
SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &one, sizeof( one ) ) != 0 )
@ -341,6 +421,8 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
if( client_ip != NULL )
{
if( client_addr.ss_family == AF_INET )
{
struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
*ip_len = sizeof( addr4->sin_addr.s_addr );
@ -348,6 +430,19 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
}
else
{
#if LWIP_IPV6
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
*ip_len = sizeof( addr6->sin6_addr.s6_addr );
if( buf_size < *ip_len )
return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
#endif
}
}
return( 0 );
@ -398,7 +493,9 @@ void mbedtls_net_usleep( unsigned long usec )
#endif
}
/* Read at most 'len' characters */
/*
* Read at most 'len' characters
*/
int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
{
int ret;
@ -414,13 +511,17 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
if( net_would_block( ctx ) != 0 )
return( MBEDTLS_ERR_SSL_WANT_READ );
int sock_errno = socket_errno(ctx);
if( sock_errno == EPIPE || sock_errno == ECONNRESET )
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
!defined(EFI32)
if( WSAGetLastError() == WSAECONNRESET )
return( MBEDTLS_ERR_NET_CONN_RESET );
#else
if( errno == EPIPE || errno == ECONNRESET )
return( MBEDTLS_ERR_NET_CONN_RESET );
if( sock_errno == EINTR )
if( errno == EINTR )
return( MBEDTLS_ERR_SSL_WANT_READ );
#endif
return( MBEDTLS_ERR_NET_RECV_FAILED );
}
@ -456,8 +557,14 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
if( ret < 0 )
{
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
!defined(EFI32)
if( WSAGetLastError() == WSAEINTR )
return( MBEDTLS_ERR_SSL_WANT_READ );
#else
if( errno == EINTR )
return( MBEDTLS_ERR_SSL_WANT_READ );
#endif
return( MBEDTLS_ERR_NET_RECV_FAILED );
}
@ -484,13 +591,17 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
if( net_would_block( ctx ) != 0 )
return( MBEDTLS_ERR_SSL_WANT_WRITE );
int sock_errno = socket_errno(ctx);
if( sock_errno == EPIPE || sock_errno == ECONNRESET )
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
!defined(EFI32)
if( WSAGetLastError() == WSAECONNRESET )
return( MBEDTLS_ERR_NET_CONN_RESET );
#else
if( errno == EPIPE || errno == ECONNRESET )
return( MBEDTLS_ERR_NET_CONN_RESET );
if( sock_errno == EINTR )
if( errno == EINTR )
return( MBEDTLS_ERR_SSL_WANT_WRITE );
#endif
return( MBEDTLS_ERR_NET_SEND_FAILED );
}

View file

@ -38,9 +38,11 @@
#error "LWIP_IGMP needs to be defined in lwipopts.h"
#endif
#if MDNS_RESPONDER_DEBUGGING
#define qDebugLog // Log activity generally
#define qLogIncoming // Log all arriving multicast packets
#define qLogAllTraffic // Log and decode all mDNS packets
#endif
//-------------------------------------------------------------------
@ -776,9 +778,13 @@ static void mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_a
// Sanity checks on size
if (plen > MDNS_RESPONDER_REPLY_SIZE) {
#ifdef qDebugLog
printf(">>> mdns_recv: pbuf too big\n");
#endif
} else if (plen < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + 1 + SIZEOF_DNS_ANSWER + 1)) {
#ifdef qDebugLog
printf(">>> mdns_recv: pbuf too small\n");
#endif
} else {
mdns_payload = malloc(plen);
if (!mdns_payload) {

View file

@ -21,6 +21,11 @@
#define MDNS_RESPONDER_REPLY_SIZE 320
#endif
#ifndef MDNS_RESPONDER_DEBUGGING
#define MDNS_RESPONDER_DEBUGGING 0
#endif
// Starts the mDNS responder task, call first
void mdns_init();

View file

@ -182,10 +182,6 @@ static uint8_t command(sdio_card_t *card, uint8_t cmd, uint32_t arg)
wait();
spi_transfer(BUS, buf, NULL, 6, SPI_8BIT);
// R1b response
if (cmd == CMD12 || cmd == CMD28 || cmd == CMD29)
spi_read_byte();
uint8_t res;
for (uint8_t i = 0; i < MAX_ERR_COUNT; i ++)
{
@ -193,6 +189,25 @@ static uint8_t command(sdio_card_t *card, uint8_t cmd, uint32_t arg)
if (!(res & BV(R1_BUSY)))
break;
}
/** If the response is a "busy" type (R1B), then theres some
* special handling that needs to be done. The card will
* output a continuous stream of zeros, so the end of the BUSY
* state is signaled by any nonzero response.
*/
if (cmd == CMD12 || cmd == CMD28 || cmd == CMD29)
{
for (uint8_t i = 0; i < MAX_ERR_COUNT; i ++)
{
res = spi_read_byte();
if (res != 0)
{
spi_transfer_8(BUS, 0xFF);
return SDIO_ERR_NONE;
}
}
}
return res;
}
@ -394,16 +409,10 @@ sdio_error_t sdio_write_sectors(sdio_card_t *card, uint32_t sector, uint8_t *src
if (card->type != SDIO_TYPE_SDHC)
sector <<= 9;
if (count == 1)
{
// single block
if (command(card, CMD24, sector))
return set_error(card, SDIO_ERR_IO);
return set_error(card, write_data_block(card, TOKEN_SINGLE_TRAN, src));
}
bool multi = count != 1;
// send pre-erase count
if ((card->type == SDIO_TYPE_SD1
if (multi && (card->type == SDIO_TYPE_SD1
|| card->type == SDIO_TYPE_SD2
|| card->type == SDIO_TYPE_SDHC)
&& app_command(card, ACMD23, count))
@ -411,16 +420,19 @@ sdio_error_t sdio_write_sectors(sdio_card_t *card, uint32_t sector, uint8_t *src
return set_error(card, SDIO_ERR_IO);
}
if (command(card, CMD25, sector))
if (command(card, multi ? CMD25 : CMD24, sector))
return set_error(card, SDIO_ERR_IO);
while (count--)
{
if (write_data_block(card, TOKEN_MULTI_TRAN, src) != SDIO_ERR_NONE)
return card->error;
if (write_data_block(card, multi ? TOKEN_MULTI_TRAN : TOKEN_SINGLE_TRAN, src) != SDIO_ERR_NONE){
return card->error;
}
src += SDIO_BLOCK_SIZE;
}
spi_transfer_8(BUS, TOKEN_STOP_TRAN);
if (multi && command(card, CMD12, 0))
return set_error(card, SDIO_ERR_IO);
return set_error(card, SDIO_ERR_NONE);
}
@ -449,4 +461,3 @@ sdio_error_t sdio_erase_sectors(sdio_card_t *card, uint32_t first, uint32_t last
return set_error(card, wait() ? SDIO_ERR_NONE : SDIO_ERR_TIMEOUT);
}

View file

@ -7,11 +7,13 @@ INC_DIRS += $(ssd1306_ROOT)..
SSD1306_I2C_SUPPORT ?= 1
# SPI4 support is on by default
SSD1306_SPI4_SUPPORT ?= 1
# SPI3 support is on by default
SSD1306_SPI3_SUPPORT ?= 1
# args for passing into compile rule generation
ssd1306_SRC_DIR = $(ssd1306_ROOT)
ssd1306_CFLAGS = -DSSD1306_I2C_SUPPORT=${SSD1306_I2C_SUPPORT} -DSSD1306_SPI4_SUPPORT=${SSD1306_SPI4_SUPPORT} $(CFLAGS)
ssd1306_CFLAGS = -DSSD1306_I2C_SUPPORT=${SSD1306_I2C_SUPPORT} -DSSD1306_SPI4_SUPPORT=${SSD1306_SPI4_SUPPORT} -DSSD1306_SPI3_SUPPORT=${SSD1306_SPI3_SUPPORT} $(CFLAGS)
$(eval $(call component_compile_rules,ssd1306))

View file

@ -236,7 +236,9 @@ static int sh1106_go_coordinate(const ssd1306_t *dev, uint8_t x, uint8_t y)
int ssd1306_load_frame_buffer(const ssd1306_t *dev, uint8_t buf[])
{
uint16_t i;
#if (SSD1306_SPI3_SUPPORT)
uint8_t j;
#endif
#if (SSD1306_I2C_SUPPORT)
uint8_t tab[16] = { 0 };
#endif

View file

@ -40,30 +40,55 @@
#define UART0_RX_SIZE (128) // ESP8266 UART HW FIFO size
static SemaphoreHandle_t uart0_sem = NULL;
static QueueHandle_t uart0_queue;
static bool inited = false;
static void uart0_rx_init(void);
static bool uart0_rx_init(void);
static int uart0_nonblock;
static TickType_t uart0_vtime = portMAX_DELAY;
uint32_t uart0_parity_errors;
uint32_t uart0_framing_errors;
uint32_t uart0_breaks_detected;
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) {
return;
}
// printf(" [%08x (%d)]\n", READ_PERI_REG(UART_INT_ST(UART0)), READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S));
if (UART(UART0).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) {
UART(UART0).INT_CLEAR = UART_INT_CLEAR_RXFIFO_FULL;
if (UART(UART0).STATUS & (UART_STATUS_RXFIFO_COUNT_M << UART_STATUS_RXFIFO_COUNT_S)) {
long int xHigherPriorityTaskWoken;
_xt_isr_mask(1 << INUM_UART);
_xt_clear_ints(1<<INUM_UART);
xSemaphoreGiveFromISR(uart0_sem, &xHigherPriorityTaskWoken);
if(xHigherPriorityTaskWoken) {
portYIELD();
// printf(" [%08x (%d)]\n", READ_PERI_REG(UART_INT_ST(UART0)), READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S));
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
do {
// If new data arrives and the status changes after checking here, them
// the interrupt will be re-triggered.
uint32_t int_status = UART(UART0).INT_STATUS;
if (int_status & UART_INT_STATUS_RXFIFO_FULL) {
size_t count = UART(UART0).STATUS & (UART_STATUS_RXFIFO_COUNT_M << UART_STATUS_RXFIFO_COUNT_S);
for (size_t i = 0; i < count; i++) {
char ch = UART(UART0).FIFO & (UART_FIFO_DATA_M << UART_FIFO_DATA_S);
xQueueSendToBackFromISR(uart0_queue, &ch, &xHigherPriorityTaskWoken);
}
UART(UART0).INT_CLEAR = UART_INT_CLEAR_RXFIFO_FULL;
// If new data has arrived then the interrupt status will remain set.
} else if (int_status & UART_INT_STATUS_PARITY_ERR) {
uart0_parity_errors++;
UART(UART0).INT_CLEAR = UART_INT_CLEAR_PARITY_ERR;
} else if (int_status & UART_INT_STATUS_FRAMING_ERR) {
uart0_framing_errors++;
UART(UART0).INT_CLEAR = UART_INT_CLEAR_FRAMING_ERR;
} else if (int_status & UART_INT_STATUS_BREAK_DETECTED) {
uart0_breaks_detected++;
UART(UART0).INT_CLEAR = UART_INT_CLEAR_BREAK_DETECTED;
} else if (int_status & 0xff) {
printf("Error: unexpected uart irq, INT_STATUS 0x%02x\n", int_status);
} else {
break;
}
} else {
printf("Error: unexpected uart irq, INT_STATUS 0x%02x\n", UART(UART0).INT_STATUS);
} while (1);
if(xHigherPriorityTaskWoken) {
portYIELD();
}
}
@ -71,31 +96,61 @@ uint32_t uart0_num_char(void)
{
uint32_t count;
if (!inited) uart0_rx_init();
count = UART(UART0).STATUS & (UART_STATUS_RXFIFO_COUNT_M << UART_STATUS_RXFIFO_COUNT_S);
count = uxQueueMessagesWaiting(uart0_queue);
return count;
}
int uart0_set_nonblock(int nonblock)
{
int current = uart0_nonblock;
uart0_nonblock = nonblock;
return current;
}
TickType_t uart0_set_vtime(TickType_t ticks)
{
TickType_t current = uart0_vtime;
uart0_vtime = ticks;
return current;
}
// _read_stdin_r in core/newlib_syscalls.c will be skipped by the linker in favour
// of this function
long _read_stdin_r(struct _reent *r, int fd, char *ptr, int len)
{
TickType_t vtime = uart0_vtime;
int nonblock = uart0_nonblock;
if (nonblock) {
vtime = 0;
}
if (!inited) uart0_rx_init();
for(int i = 0; i < len; i++) {
if (!(UART(UART0).STATUS & (UART_STATUS_RXFIFO_COUNT_M << UART_STATUS_RXFIFO_COUNT_S))) {
_xt_isr_unmask(1 << INUM_UART);
if (!xSemaphoreTake(uart0_sem, portMAX_DELAY)) {
printf("\nFailed to get sem\n");
for(size_t i = 0; i < len; i++, ptr++) {
if (xQueueReceive(uart0_queue, (void*)ptr, vtime) == pdFALSE) {
if (i > 0) {
return i;
}
if (nonblock) {
r->_errno = EAGAIN;
return -1;
}
return 0;
}
ptr[i] = UART(UART0).FIFO & (UART_FIFO_DATA_M << UART_FIFO_DATA_S);
}
return len;
}
static void uart0_rx_init(void)
static bool uart0_rx_init(void)
{
uart0_queue = xQueueCreate(64, sizeof(char));
if (!uart0_queue) {
return false;
}
int trig_lvl = 1;
uart0_sem = xSemaphoreCreateCounting(UART0_RX_SIZE, 0);
_xt_isr_attach(INUM_UART, uart0_rx_handler, NULL);
_xt_isr_unmask(1 << INUM_UART);
@ -112,7 +167,10 @@ static void uart0_rx_init(void)
UART(UART0).INT_CLEAR = 0x1ff;
// enable rx_interrupt
UART(UART0).INT_ENABLE = UART_INT_ENABLE_RXFIFO_FULL;
UART(UART0).INT_ENABLE = UART_INT_ENABLE_RXFIFO_FULL | UART_INT_ENABLE_PARITY_ERR |
UART_INT_ENABLE_FRAMING_ERR | UART_INT_ENABLE_BREAK_DETECTED;
inited = true;
return true;
}

View file

@ -27,6 +27,16 @@
#include <stdint.h>
// Return number of characters waiting in UART0
/* Return number of characters waiting in UART0. */
uint32_t uart0_num_char(void);
/* Set UART0 input to nonblocking or blocking, returning the old state. */
int uart0_set_nonblock(int);
/* Set the UART0 input wait time in ticks, or zero to wait indefinitely,
* returning the old wait time. The wait time is only used when the input is
* blocking.
*/
TickType_t uart0_set_vtime(TickType_t ticks);
#endif

View file

@ -1375,6 +1375,45 @@ void wificfg_got_sta_connect()
}
}
void wificfg_wait_until_sta_connected()
{
while (1) {
uint8_t connect_status = sdk_wifi_station_get_connect_status();
if (connect_status == STATION_GOT_IP)
break;
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
/*
* Notifty wificfg to disable the AP interface on the next restart
* if that option is enabled.
*/
wificfg_got_sta_connect();
}
struct shutdown_hook {
struct shutdown_hook *next;
void (*fn)(void *);
void *arg;
};
static struct shutdown_hook *shutdown_hooks;
bool wificfg_add_shutdown_hook(void (*fn)(void *), void *arg)
{
struct shutdown_hook *hook = malloc(sizeof(struct shutdown_hook));
if (!hook) {
return false;
}
hook->next = shutdown_hooks;
hook->fn = fn;
hook->arg = arg;
shutdown_hooks = hook;
return true;
}
static int handle_restart_post(int s, wificfg_method method,
uint32_t content_length,
wificfg_content_type content_type,
@ -1382,6 +1421,10 @@ static int handle_restart_post(int s, wificfg_method method,
{
wificfg_write_string(s, http_redirect_header);
close(s);
struct shutdown_hook *hook;
for (hook = shutdown_hooks; hook; hook = hook->next) {
hook->fn(hook->arg);
}
vTaskDelay(2000 / portTICK_PERIOD_MS);
sdk_system_restart();
return 0;
@ -1841,8 +1884,11 @@ static void server_task(void *pvParameters)
value = skip_whitespace(value);
switch (header) {
case HTTP_HEADER_HOST:
if (hostname_local && host_is_name(value) &&
strcmp(value, hostname_local)) {
if (!host_is_name(value)) {
break;
}
if (!hostname_local ||
(hostname_local && strcmp(value, hostname_local))) {
host_redirect = true;
}
break;
@ -2006,6 +2052,21 @@ void wificfg_init(uint32_t port, const wificfg_dispatch *dispatch)
return;
}
/* Default a hostname. */
char *hostname = NULL;
sysparam_get_string("hostname", &hostname);
if (!hostname && wificfg_default_hostname) {
uint8_t macaddr[6];
char name[32];
sdk_wifi_get_macaddr(1, macaddr);
snprintf(name, sizeof(name), wificfg_default_hostname, macaddr[3],
macaddr[4], macaddr[5]);
sysparam_set_string("hostname", name);
}
if (hostname) {
free(hostname);
}
sysparam_get_string("wifi_ap_ssid", &wifi_ap_ssid);
sysparam_get_string("wifi_ap_password", &wifi_ap_password);
sysparam_get_string("wifi_sta_ssid", &wifi_sta_ssid);
@ -2077,21 +2138,6 @@ void wificfg_init(uint32_t port, const wificfg_dispatch *dispatch)
sdk_wifi_set_opmode(wifi_mode);
if (wifi_sta_enable) {
/* Default a hostname. */
char *hostname = NULL;
sysparam_get_string("hostname", &hostname);
if (!hostname && wificfg_default_hostname) {
uint8_t macaddr[6];
char name[32];
sdk_wifi_get_macaddr(1, macaddr);
snprintf(name, sizeof(name), wificfg_default_hostname, macaddr[3],
macaddr[4], macaddr[5]);
sysparam_set_string("hostname", name);
}
if (hostname) {
free(hostname);
}
struct sdk_station_config config;
strcpy((char *)config.ssid, wifi_sta_ssid);
strcpy((char *)config.password, wifi_sta_password);

View file

@ -121,11 +121,11 @@ ssize_t wificfg_write_chunk_end(int s);
/* 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);
/* Wait until the station interface has connected to an access point,
* and obtained an IP address. */
void wificfg_wait_until_sta_connected(void);
bool wificfg_add_shutdown_hook(void (*fn)(void *), void *arg);
#ifdef __cplusplus
}

View file

@ -117,7 +117,7 @@ static inline void init_descriptors_list(uint8_t *buf, uint32_t total_dma_data_s
}
}
void ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type)
int ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type)
{
dma_buffer_size = pixels_number * type;
dma_block_list_size = dma_buffer_size / MAX_DMA_BLOCK_SIZE;
@ -130,11 +130,24 @@ void ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type)
debug("allocating %d dma blocks\n", dma_block_list_size);
dma_block_list = (dma_descriptor_t*)malloc(
dma_block_list_size * sizeof(dma_descriptor_t));
if(!dma_block_list)
{
dma_block_list = (dma_descriptor_t*)malloc(
dma_block_list_size * sizeof(dma_descriptor_t));
if(!dma_block_list)
{
return -1;
}
}
debug("allocating %d bytes for DMA buffer\n", dma_buffer_size);
dma_buffer = malloc(dma_buffer_size);
if(!dma_buffer)
{
dma_buffer = malloc(dma_buffer_size);
if(!dma_buffer)
{
return -1;
}
}
memset(dma_buffer, 0xFA, dma_buffer_size);
init_descriptors_list(dma_buffer, dma_buffer_size);
@ -146,6 +159,7 @@ void ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type)
clock_div.bclk_div, clock_div.clkm_div);
i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins);
return 0;
}
const IRAM_DATA int16_t bitpatterns[16] =

View file

@ -53,7 +53,7 @@ typedef enum {
*
* @param pixels_number Number of pixels in the strip.
*/
void ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type);
int ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type);
/**
* Update ws2812 pixels.

View file

@ -113,7 +113,11 @@ SECTIONS
*libc.a:*bzero.o(.literal .text .literal.* .text.*)
*libc.a:*lock.o(.literal .text .literal.* .text.*)
*libc.a:*printf.o(.literal .text .literal.* .text.*)
*libc.a:*-printf.o(.literal .text .literal.* .text.*)
*libc.a:*-sprintf.o(.literal .text .literal.* .text.*)
*libc.a:*-fprintf.o(.literal .text .literal.* .text.*)
*libc.a:*-svfprintf.o(.literal .text .literal.* .text.*)
*libc.a:*-vfprintf.o(.literal .text .literal.* .text.*)
*libc.a:*findfp.o(.literal .text .literal.* .text.*)
*libc.a:*fputwc.o(.literal .text .literal.* .text.*)
@ -249,10 +253,13 @@ SECTIONS
*(.gnu.linkonce.r.*)
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gcc_except_table .gcc_except_table.*)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame)
. = (. + 3) & ~ 3;
__eh_frame = ABSOLUTE(.);
KEEP(*(.eh_frame))
. = (. + 7) & ~ 3;
. = ALIGN(4);
*(.dynamic)
*(.gnu.version_d)

View file

@ -57,18 +57,18 @@ PROVIDE ( __umoddi3 = 0x4000d770 );
PROVIDE ( __umodsi3 = 0x4000e268 );
PROVIDE ( __umulsidi3 = 0x4000dcf0 );
PROVIDE ( bzero = 0x40002ae8 );
PROVIDE ( memcmp = 0x400018d4 );
PROVIDE ( memcpy = 0x400018b4 );
PROVIDE ( memmove = 0x400018c4 );
PROVIDE ( memset = 0x400018a4 );
PROVIDE ( bzero = 0x4000de84 );
PROVIDE ( memcmp = 0x4000dea8 );
PROVIDE ( memcpy = 0x4000df48 );
PROVIDE ( memmove = 0x4000e04c );
PROVIDE ( memset = 0x4000e190 );
PROVIDE ( strcmp = 0x40002aa8 );
PROVIDE ( strcpy = 0x40002a88 );
PROVIDE ( strlen = 0x40002ac8 );
PROVIDE ( strncmp = 0x40002ab8 );
PROVIDE ( strncpy = 0x40002a98 );
PROVIDE ( strstr = 0x40002ad8 );
PROVIDE ( strcmp = 0x4000bdc8 );
PROVIDE ( strcpy = 0x4000bec8 );
PROVIDE ( strlen = 0x4000bf4c );
PROVIDE ( strncmp = 0x4000bfa8 );
PROVIDE ( strncpy = 0x4000c0a0 );
PROVIDE ( strstr = 0x4000e1e0 );
PROVIDE ( ETS_INTR_LOCK = 0x40000f74 );
PROVIDE ( ETS_INTR_UNLOCK = 0x40000f80 );

View file

@ -1,9 +1,9 @@
Newlib from git://sourceware.org/git/newlib-cygwin.git with xtensa & locking patches see https://github.com/ourairquality/newlib and built from commit 7558d27f9dba58ba0e51e37a2aa3ea6be7214799
Newlib from git://sourceware.org/git/newlib-cygwin.git with xtensa & locking patches see https://github.com/ourairquality/newlib and built from commit 984b749fb223daab954060c04720933290584f00
The build commands were:
mkdir build
cd build
../configure --with-newlib --enable-multilib --disable-newlib-io-c99-formats --enable-newlib-supplied-syscalls --enable-target-optspace --program-transform-name="s&^&xtensa-lx106-elf-&" --disable-option-checking --with-target-subdir=xtensa-lx106-elf --target=xtensa-lx106-elf --enable-newlib-nano-malloc --enable-newlib-nano-formatted-io --enable-newlib-reent-small --disable-newlib-mb --prefix=/tmp/libc
../configure --with-newlib --enable-multilib --disable-newlib-io-c99-formats --enable-newlib-supplied-syscalls --enable-target-optspace --program-transform-name="s&^&xtensa-lx106-elf-&" --disable-option-checking --with-target-subdir=xtensa-lx106-elf --target=xtensa-lx106-elf --enable-newlib-nano-malloc --enable-newlib-nano-formatted-io --enable-newlib-reent-small --disable-newlib-mb --enable-newlib-global-stdio-streams --prefix=/tmp/libc
env CROSS_CFLAGS="-DSIGNAL_PROVIDED -DABORT_PROVIDED" make
make install

View file

@ -133,6 +133,10 @@ extern int malloc_trim (size_t);
extern int _malloc_trim_r (struct _reent *, size_t);
#endif
extern void __malloc_lock(struct _reent *);
extern void __malloc_unlock(struct _reent *);
/* A compatibility routine for an earlier version of the allocator. */
extern void mstats (char *);

View file

@ -83,7 +83,7 @@
/* Define to move the stdio stream FILE objects out of struct _reent and make
them global. The stdio stream pointers of struct _reent are initialized to
point to the global stdio FILE stream objects. */
/* #undef _WANT_REENT_GLOBAL_STDIO_STREAMS */
#define _WANT_REENT_GLOBAL_STDIO_STREAMS 1
/* Define if small footprint nano-formatted-IO implementation used. */
#define _NANO_FORMATTED_IO 1

View file

@ -144,7 +144,7 @@ struct __sbuf {
* _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
*/
#ifdef _REENT_SMALL
#if defined(_REENT_SMALL) && !defined(_REENT_GLOBAL_STDIO_STREAMS)
/*
* struct __sFILE_fake is the start of a struct __sFILE, with only the
* minimal fields allocated. In __sinit() we really allocate the 3
@ -418,6 +418,43 @@ struct _reent
char *_signal_buf; /* strsignal */
};
#ifdef _REENT_GLOBAL_STDIO_STREAMS
extern __FILE __sf[3];
# define _REENT_INIT(var) \
{ 0, \
&__sf[0], \
&__sf[1], \
&__sf[2], \
0, \
_NULL, \
0, \
0, \
_NULL, \
_NULL, \
_NULL, \
0, \
0, \
_NULL, \
_NULL, \
_NULL, \
_NULL, \
_NULL, \
_REENT_INIT_ATEXIT \
{_NULL, 0, _NULL}, \
_NULL, \
_NULL, \
_NULL \
}
#define _REENT_INIT_PTR_ZEROED(var) \
{ (var)->_stdin = &__sf[0]; \
(var)->_stdout = &__sf[1]; \
(var)->_stderr = &__sf[2]; \
}
#else
extern const struct __sFILE_fake __sf_fake_stdin;
extern const struct __sFILE_fake __sf_fake_stdout;
extern const struct __sFILE_fake __sf_fake_stderr;
@ -454,6 +491,8 @@ extern const struct __sFILE_fake __sf_fake_stderr;
(var)->_stderr = (__FILE *)&__sf_fake_stderr; \
}
#endif
/* Only add assert() calls if we are specified to debug. */
#ifdef _REENT_CHECK_DEBUG
#include <assert.h>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -244,9 +244,9 @@ void sdk_ets_timer_disarm(ets_timer_t *timer)
prev = curr;
curr = curr->next;
}
vPortExitCritical();
timer->next = ETS_TIMER_NOT_ARMED;
timer->period_ticks = 0;
vPortExitCritical();
}
/**

View file

@ -11,7 +11,7 @@
#include "esp/gpio_regs.h"
#include "esp/rtc_regs.h"
#include "sdk_internal.h"
#include "xtensa/hal.h"
#include "xtensa_ops.h"
static int cpu_freq = 80;
@ -28,9 +28,14 @@ void sdk_os_update_cpu_frequency(int freq) {
void sdk_ets_update_cpu_frequency(int freq) __attribute__ (( alias ("sdk_os_update_cpu_frequency") ));
void sdk_os_delay_us(uint16_t us) {
uint32_t start_ccount = xthal_get_ccount();
uint32_t start_ccount, ccount;
uint32_t delay_ccount = cpu_freq * us;
while (xthal_get_ccount() - start_ccount < delay_ccount) {}
RSR(start_ccount, ccount);
do {
RSR(ccount, ccount);
} while (ccount - start_ccount < delay_ccount);
}
void sdk_ets_delay_us(uint16_t us) __attribute__ (( alias ("sdk_os_delay_us") ));

View file

@ -563,12 +563,12 @@ bool sdk_wifi_station_dhcpc_stop(void) {
if (sdk_wifi_get_opmode() == 2) {
return false;
}
LOCK_TCPIP_CORE();
if (netif && sdk_dhcpc_flag == DHCP_STARTED) {
LOCK_TCPIP_CORE();
dhcp_stop(netif);
sdk_dhcpc_flag = DHCP_STOPPED;
UNLOCK_TCPIP_CORE();
}
sdk_dhcpc_flag = DHCP_STOPPED;
UNLOCK_TCPIP_CORE();
return true;
}