blob: e1d8119f63806b8a8ea577615fb87c528d300e1f [file] [log] [blame]
/*
* Amazon FreeRTOS Platform V1.1.0
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file iot_threads_freertos.c
* @brief Implementation of the platform specific functions in iot_threads.h for
* FreeRTOS.
*/
/* The config header is always included first. */
#include "iot_config.h"
#include "semphr.h"
/* Platform threads include. */
#include "platform/iot_platform_types_freertos.h"
#include "platform/iot_threads.h"
#include "types/iot_platform_types.h"
/* Configure logs for the functions in this file. */
#ifdef IOT_LOG_LEVEL_PLATFORM
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_PLATFORM
#else
#ifdef IOT_LOG_LEVEL_GLOBAL
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL
#else
#define LIBRARY_LOG_LEVEL IOT_LOG_NONE
#endif
#endif
#define LIBRARY_LOG_NAME ( "THREAD" )
#include "iot_logging_setup.h"
/*
* Provide default values for undefined memory allocation functions based on
* the usage of dynamic memory allocation.
*/
#ifndef IotThreads_Malloc
#include <stdlib.h>
/**
* @brief Memory allocation. This function should have the same signature
* as [malloc](http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html).
*/
#define IotThreads_Malloc malloc
#endif
#ifndef IotThreads_Free
#include <stdlib.h>
/**
* @brief Free memory. This function should have the same signature as
* [free](http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html).
*/
#define IotThreads_Free free
#endif
/*-----------------------------------------------------------*/
static void _threadRoutineWrapper( void * pArgument )
{
threadInfo_t * pThreadInfo = ( threadInfo_t * ) pArgument;
/* Run the thread routine. */
pThreadInfo->threadRoutine( pThreadInfo->pArgument );
IotThreads_Free( pThreadInfo );
vTaskDelete( NULL );
}
/*-----------------------------------------------------------*/
bool Iot_CreateDetachedThread( IotThreadRoutine_t threadRoutine,
void * pArgument,
int32_t priority,
size_t stackSize )
{
bool status = true;
configASSERT( threadRoutine != NULL );
IotLogDebug( "Creating new thread." );
threadInfo_t * pThreadInfo = IotThreads_Malloc( sizeof( threadInfo_t ) );
if( pThreadInfo == NULL )
{
IotLogDebug( "Unable to allocate memory for threadRoutine %p.", threadRoutine );
status = false;
}
/* Create the FreeRTOS task that will run the thread. */
if( status )
{
pThreadInfo->threadRoutine = threadRoutine;
pThreadInfo->pArgument = pArgument;
if( xTaskCreate( _threadRoutineWrapper,
"iot_thread",
( configSTACK_DEPTH_TYPE ) stackSize,
pThreadInfo,
priority,
NULL ) != pdPASS )
{
/* Task creation failed. */
IotLogWarn( "Failed to create thread." );
IotThreads_Free( pThreadInfo );
status = false;
}
}
return status;
}
/*-----------------------------------------------------------*/
bool IotMutex_Create( IotMutex_t * pNewMutex,
bool recursive )
{
_IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pNewMutex;
configASSERT( internalMutex != NULL );
IotLogDebug( "Creating new mutex %p.", pNewMutex );
if( recursive )
{
( void ) xSemaphoreCreateRecursiveMutexStatic( &internalMutex->xMutex );
}
else
{
( void ) xSemaphoreCreateMutexStatic( &internalMutex->xMutex );
}
/* remember the type of mutex */
if( recursive )
{
internalMutex->recursive = pdTRUE;
}
else
{
internalMutex->recursive = pdFALSE;
}
return true;
}
/*-----------------------------------------------------------*/
void IotMutex_Destroy( IotMutex_t * pMutex )
{
_IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex;
configASSERT( internalMutex != NULL );
vSemaphoreDelete( ( SemaphoreHandle_t ) &internalMutex->xMutex );
}
/*-----------------------------------------------------------*/
bool prIotMutexTimedLock( IotMutex_t * pMutex,
TickType_t timeout )
{
_IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex;
BaseType_t lockResult;
configASSERT( internalMutex != NULL );
IotLogDebug( "Locking mutex %p.", internalMutex );
/* Call the correct FreeRTOS mutex take function based on mutex type. */
if( internalMutex->recursive == pdTRUE )
{
lockResult = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) &internalMutex->xMutex, timeout );
}
else
{
lockResult = xSemaphoreTake( ( SemaphoreHandle_t ) &internalMutex->xMutex, timeout );
}
return( lockResult == pdTRUE );
}
/*-----------------------------------------------------------*/
void IotMutex_Lock( IotMutex_t * pMutex )
{
prIotMutexTimedLock( pMutex, portMAX_DELAY );
}
/*-----------------------------------------------------------*/
bool IotMutex_TryLock( IotMutex_t * pMutex )
{
return prIotMutexTimedLock( pMutex, 0 );
}
/*-----------------------------------------------------------*/
void IotMutex_Unlock( IotMutex_t * pMutex )
{
_IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex;
configASSERT( internalMutex != NULL );
IotLogDebug( "Unlocking mutex %p.", internalMutex );
/* Call the correct FreeRTOS mutex unlock function based on mutex type. */
if( internalMutex->recursive == pdTRUE )
{
( void ) xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) &internalMutex->xMutex );
}
else
{
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &internalMutex->xMutex );
}
}
/*-----------------------------------------------------------*/
bool IotSemaphore_Create( IotSemaphore_t * pNewSemaphore,
uint32_t initialValue,
uint32_t maxValue )
{
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pNewSemaphore;
configASSERT( internalSemaphore != NULL );
IotLogDebug( "Creating new semaphore %p.", pNewSemaphore );
( void ) xSemaphoreCreateCountingStatic( maxValue, initialValue, &internalSemaphore->xSemaphore );
return true;
}
/*-----------------------------------------------------------*/
uint32_t IotSemaphore_GetCount( IotSemaphore_t * pSemaphore )
{
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
UBaseType_t count = 0;
configASSERT( internalSemaphore != NULL );
count = uxSemaphoreGetCount( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore );
IotLogDebug( "Semaphore %p has count %d.", pSemaphore, count );
return ( uint32_t ) count;
}
/*-----------------------------------------------------------*/
void IotSemaphore_Destroy( IotSemaphore_t * pSemaphore )
{
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
configASSERT( internalSemaphore != NULL );
IotLogDebug( "Destroying semaphore %p.", internalSemaphore );
vSemaphoreDelete( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore );
}
/*-----------------------------------------------------------*/
void IotSemaphore_Wait( IotSemaphore_t * pSemaphore )
{
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
configASSERT( internalSemaphore != NULL );
IotLogDebug( "Waiting on semaphore %p.", internalSemaphore );
/* Take the semaphore using the FreeRTOS API. */
if( xSemaphoreTake( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore,
portMAX_DELAY ) != pdTRUE )
{
IotLogWarn( "Failed to wait on semaphore %p.",
pSemaphore );
/* There is an assert here because during debugging we could falsely
* believe that we are waiting successfully on a semaphore. */
configASSERT( false );
}
}
/*-----------------------------------------------------------*/
bool IotSemaphore_TryWait( IotSemaphore_t * pSemaphore )
{
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
configASSERT( internalSemaphore != NULL );
IotLogDebug( "Attempting to wait on semaphore %p.", internalSemaphore );
return IotSemaphore_TimedWait( pSemaphore, 0 );
}
/*-----------------------------------------------------------*/
bool IotSemaphore_TimedWait( IotSemaphore_t * pSemaphore,
uint32_t timeoutMs )
{
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
configASSERT( internalSemaphore != NULL );
/* Take the semaphore using the FreeRTOS API. Cast the calculation to 64 bit to avoid overflows. */
if( xSemaphoreTake( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore,
pdMS_TO_TICKS( timeoutMs ) ) != pdTRUE )
{
/* Only warn if timeout > 0. */
if( timeoutMs > 0 )
{
IotLogWarn( "Timeout waiting on semaphore %p.",
internalSemaphore );
}
return false;
}
return true;
}
/*-----------------------------------------------------------*/
void IotSemaphore_Post( IotSemaphore_t * pSemaphore )
{
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
configASSERT( internalSemaphore != NULL );
IotLogDebug( "Posting to semaphore %p.", internalSemaphore );
/* Give the semaphore using the FreeRTOS API. */
BaseType_t result = xSemaphoreGive( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore );
if( result == pdFALSE )
{
IotLogDebug( "Unable to give semaphore over maximum", internalSemaphore );
}
}
/*-----------------------------------------------------------*/