mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-20 19:57:44 -04:00
Add cellular library submodule path and demo (#695)
* [Cellular] Add cellulr lib submodule and demo app * [Cellular] Fix memory violation in transport layer and add using LoggingPrintf * Update FreeRTOS Cellular Interface * Change the mbedtls usage in FreeRTOS-Plus * [Cellular] Fix missing spell * [Cellular] Add manifest.yml * Fix missing spell * Update manifest.yml * [Cellular] Add integration test * Modify the demo log level to LOG_INFO * Update cellular interface * The modification of the folder structure for cellular library * Rename the naming of demo * Adjust the location of using_mbedtls and socket_wrapper * Adjust project setting for relocating using_mbedtls and socket_wrapper * Turn off PSM mode * Add start marker for CI validation. * The modification for mbedtls platform send/recv function for cellular * Change the project file due to the changes of mbedtls platform send/recv function for cellular * Fix missing newline and remove unused file * Add missing configuration. * Make cellular and freertos tcp plus use the same transport implementation * Add comment for the macro MBEDTLS_SSL_SEND and MBEDTLS_SSL_RECV * Make changes from the github comment.
This commit is contained in:
parent
223d2d0e21
commit
957fb26dbe
142 changed files with 45928 additions and 14758 deletions
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* FreeRTOS V202107.00
|
||||
* Copyright (C) 2020 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.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "cellular_platform.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
typedef QueueHandle_t SemaphoreHandle_t;
|
||||
|
||||
typedef struct threadInfo
|
||||
{
|
||||
void * pArgument; /**< @brief Argument to `threadRoutine`. */
|
||||
void ( * threadRoutine )( void * ); /**< @brief Thread function to run. */
|
||||
} threadInfo_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Sends provided buffer to network using transport send.
|
||||
*
|
||||
* @param[in] pArgument Argument passed to threadRoutine function.
|
||||
*
|
||||
*/
|
||||
static void prvThreadRoutineWrapper( void * pArgument );
|
||||
|
||||
/**
|
||||
* @brief Lock mutex with timeout.
|
||||
*
|
||||
* @param[in] pMutex Mutex to lock.
|
||||
* @param[in] timeout Timeout value to lock mutex.
|
||||
*
|
||||
* @return true if mutex is locked successfully. Otherwise false.
|
||||
*/
|
||||
static bool prIotMutexTimedLock( PlatformMutex_t * pMutex,
|
||||
TickType_t timeout );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvThreadRoutineWrapper( void * pArgument )
|
||||
{
|
||||
threadInfo_t * pThreadInfo = ( threadInfo_t * ) pArgument;
|
||||
|
||||
/* Run the thread routine. */
|
||||
pThreadInfo->threadRoutine( pThreadInfo->pArgument );
|
||||
Platform_Free( pThreadInfo );
|
||||
|
||||
vTaskDelete( NULL );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static bool prIotMutexTimedLock( PlatformMutex_t * pMutex,
|
||||
TickType_t timeout )
|
||||
{
|
||||
BaseType_t lockResult = pdTRUE;
|
||||
|
||||
configASSERT( pMutex != NULL );
|
||||
|
||||
LogDebug( ( "Locking mutex %p.", pMutex ) );
|
||||
|
||||
/* Call the correct FreeRTOS mutex take function based on mutex type. */
|
||||
if( pMutex->recursive == pdTRUE )
|
||||
{
|
||||
lockResult = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) &pMutex->xMutex, timeout );
|
||||
}
|
||||
else
|
||||
{
|
||||
lockResult = xSemaphoreTake( ( SemaphoreHandle_t ) &pMutex->xMutex, timeout );
|
||||
}
|
||||
|
||||
return( lockResult == pdTRUE );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool Platform_CreateDetachedThread( void ( * threadRoutine )( void * ),
|
||||
void * pArgument,
|
||||
int32_t priority,
|
||||
size_t stackSize )
|
||||
{
|
||||
bool status = true;
|
||||
threadInfo_t * pThreadInfo = NULL;
|
||||
|
||||
configASSERT( threadRoutine != NULL );
|
||||
|
||||
LogDebug( ( "Creating new thread." ) );
|
||||
|
||||
pThreadInfo = Platform_Malloc( sizeof( threadInfo_t ) );
|
||||
|
||||
if( pThreadInfo == NULL )
|
||||
{
|
||||
LogDebug( ( "Unable to allocate memory for threadRoutine %p.", threadRoutine ) );
|
||||
status = false;
|
||||
}
|
||||
|
||||
/* Create the FreeRTOS task that will run the thread. */
|
||||
if( status == true )
|
||||
{
|
||||
pThreadInfo->threadRoutine = threadRoutine;
|
||||
pThreadInfo->pArgument = pArgument;
|
||||
|
||||
if( xTaskCreate( prvThreadRoutineWrapper,
|
||||
"Cellular_Thread",
|
||||
( configSTACK_DEPTH_TYPE ) stackSize,
|
||||
pThreadInfo,
|
||||
priority,
|
||||
NULL ) != pdPASS )
|
||||
{
|
||||
/* Task creation failed. */
|
||||
LogWarn( ( "Failed to create thread." ) );
|
||||
Platform_Free( pThreadInfo );
|
||||
status = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug( ( "New thread created." ) );
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool PlatformMutex_Create( PlatformMutex_t * pNewMutex,
|
||||
bool recursive )
|
||||
{
|
||||
SemaphoreHandle_t xSemaphore = NULL;
|
||||
bool retMutexCreate = false;
|
||||
|
||||
configASSERT( pNewMutex != NULL );
|
||||
|
||||
LogDebug( ( "Creating new mutex %p.", pNewMutex ) );
|
||||
|
||||
if( recursive == true )
|
||||
{
|
||||
xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &pNewMutex->xMutex );
|
||||
}
|
||||
else
|
||||
{
|
||||
xSemaphore = xSemaphoreCreateMutexStatic( &pNewMutex->xMutex );
|
||||
}
|
||||
|
||||
/* Remember the type of mutex. */
|
||||
if( recursive == true )
|
||||
{
|
||||
pNewMutex->recursive = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pNewMutex->recursive = pdFALSE;
|
||||
}
|
||||
|
||||
/* Check the handle value returned by the mutex create function. */
|
||||
if( xSemaphore == NULL )
|
||||
{
|
||||
retMutexCreate = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
retMutexCreate = true;
|
||||
}
|
||||
|
||||
return retMutexCreate;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PlatformMutex_Destroy( PlatformMutex_t * pMutex )
|
||||
{
|
||||
configASSERT( pMutex != NULL );
|
||||
|
||||
vSemaphoreDelete( ( SemaphoreHandle_t ) &pMutex->xMutex );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PlatformMutex_Lock( PlatformMutex_t * pMutex )
|
||||
{
|
||||
prIotMutexTimedLock( pMutex, portMAX_DELAY );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool PlatformMutex_TryLock( PlatformMutex_t * pMutex )
|
||||
{
|
||||
return prIotMutexTimedLock( pMutex, 0 );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PlatformMutex_Unlock( PlatformMutex_t * pMutex )
|
||||
{
|
||||
configASSERT( pMutex != NULL );
|
||||
|
||||
LogDebug( ( "Unlocking mutex %p.", pMutex ) );
|
||||
|
||||
/* Call the correct FreeRTOS mutex unlock function based on mutex type. */
|
||||
if( pMutex->recursive == pdTRUE )
|
||||
{
|
||||
( void ) xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) &pMutex->xMutex );
|
||||
}
|
||||
else
|
||||
{
|
||||
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pMutex->xMutex );
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* FreeRTOS V202107.00
|
||||
* Copyright (C) 2020 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.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*/
|
||||
|
||||
#ifndef __CELLULAR_PLATFORM_H__
|
||||
#define __CELLULAR_PLATFORM_H__
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
#include "event_groups.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Cellular library log configuration.
|
||||
*
|
||||
* Cellular library use CellularLogLevel macro for logging.
|
||||
* The prototye of these logging function is similar with printf with return type ignored.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "logging_levels.h"
|
||||
#ifndef LIBRARY_LOG_NAME
|
||||
#define LIBRARY_LOG_NAME "CELLULAR"
|
||||
#endif
|
||||
|
||||
|
||||
/* Prototype for the function used to print to console on Windows simulator
|
||||
* of FreeRTOS.
|
||||
* The function prints to the console before the network is connected;
|
||||
* then a UDP port after the network has connected. */
|
||||
extern void vLoggingPrintf( const char * pcFormatString,
|
||||
... );
|
||||
|
||||
/* Map the SdkLog macro to the logging function to enable logging
|
||||
* on Windows simulator. */
|
||||
#ifndef SdkLog
|
||||
#define SdkLog( message ) vLoggingPrintf message
|
||||
#endif
|
||||
|
||||
#ifndef LIBRARY_LOG_LEVEL
|
||||
#define LIBRARY_LOG_LEVEL LOG_ERROR
|
||||
#endif
|
||||
#include "logging_stack.h"
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Cellular library platform thread API and configuration.
|
||||
*
|
||||
* Cellular library create a detached thread by this API.
|
||||
* The threadRoutine should be called with pArgument in the created thread.
|
||||
*
|
||||
* PLATFORM_THREAD_DEFAULT_STACK_SIZE and PLATFORM_THREAD_DEFAULT_PRIORITY defines
|
||||
* the platform related stack size and priority.
|
||||
*/
|
||||
|
||||
bool Platform_CreateDetachedThread( void ( * threadRoutine )( void * ),
|
||||
void * pArgument,
|
||||
int32_t priority,
|
||||
size_t stackSize );
|
||||
|
||||
#define PLATFORM_THREAD_DEFAULT_STACK_SIZE ( 2048U )
|
||||
#define PLATFORM_THREAD_DEFAULT_PRIORITY ( tskIDLE_PRIORITY + 5U )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Cellular library platform mutex APIs.
|
||||
*
|
||||
* Cellular library use platform mutex to protect resource.
|
||||
*
|
||||
* The IotMutex_ functions can be referenced as function prototype for
|
||||
* PlatfromMutex_ prefix function in the following link.
|
||||
* https://docs.aws.amazon.com/freertos/latest/lib-ref/c-sdk/platform/platform_threads_functions.html
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct PlatformMutex
|
||||
{
|
||||
StaticSemaphore_t xMutex; /**< FreeRTOS mutex. */
|
||||
BaseType_t recursive; /**< Type; used for indicating if this is reentrant or normal. */
|
||||
} PlatformMutex_t;
|
||||
|
||||
bool PlatformMutex_Create( PlatformMutex_t * pNewMutex,
|
||||
bool recursive );
|
||||
void PlatformMutex_Destroy( PlatformMutex_t * pMutex );
|
||||
void PlatformMutex_Lock( PlatformMutex_t * pMutex );
|
||||
bool PlatformMutex_TryLock( PlatformMutex_t * pMutex );
|
||||
void PlatformMutex_Unlock( PlatformMutex_t * pMutex );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Cellular library platform memory allocation APIs.
|
||||
*
|
||||
* Cellular library use platform memory allocation APIs to allocate memory dynamically.
|
||||
* The FreeRTOS memory management document can be referenced for these APIs.
|
||||
* https://www.freertos.org/a00111.html
|
||||
*
|
||||
*/
|
||||
|
||||
#define Platform_Malloc pvPortMalloc
|
||||
#define Platform_Free vPortFree
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Cellular library platform event group APIs.
|
||||
*
|
||||
* Cellular library use platform event group for process synchronization.
|
||||
*
|
||||
* The EventGroup functions in the following link can be referenced as function prototype.
|
||||
* https://www.freertos.org/event-groups-API.html
|
||||
*
|
||||
*/
|
||||
|
||||
#define PlatformEventGroupHandle_t EventGroupHandle_t
|
||||
#define PlatformEventGroup_Delete vEventGroupDelete
|
||||
#define PlatformEventGroup_ClearBits xEventGroupClearBits
|
||||
#define PlatformEventGroup_Create xEventGroupCreate
|
||||
#define PlatformEventGroup_GetBits xEventGroupGetBits
|
||||
#define PlatformEventGroup_SetBits xEventGroupSetBits
|
||||
#define PlatformEventGroup_SetBitsFromISR xEventGroupSetBitsFromISR
|
||||
#define PlatformEventGroup_WaitBits xEventGroupWaitBits
|
||||
#define PlatformEventGroup_EventBits EventBits_t
|
||||
#define PlatformTickType TickType_t
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Cellular library platform delay function.
|
||||
*
|
||||
* Cellular library use platform delay function for waiting events.
|
||||
*
|
||||
* The delay functions in the following link can be referenced as function prototype.
|
||||
* https://www.freertos.org/a00127.html
|
||||
*
|
||||
*/
|
||||
#define Platform_Delay( delayMs ) vTaskDelay( pdMS_TO_TICKS( delayMs ) )
|
||||
|
||||
#endif /* __CELLULAR_PLATFORM_H__ */
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* FreeRTOS V202107.00
|
||||
* Copyright (C) 2020 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.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cellular_setup.c
|
||||
* @brief Setup cellular connectivity for board with cellular module.
|
||||
*/
|
||||
|
||||
/* FreeRTOS include. */
|
||||
#include <FreeRTOS.h>
|
||||
#include "task.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Demo Specific configs. */
|
||||
#include "demo_config.h"
|
||||
|
||||
/* The config header is always included first. */
|
||||
#ifndef CELLULAR_DO_NOT_USE_CUSTOM_CONFIG
|
||||
/* Include custom config file before other headers. */
|
||||
#include "cellular_config.h"
|
||||
#endif
|
||||
#include "cellular_config_defaults.h"
|
||||
#include "cellular_types.h"
|
||||
#include "cellular_api.h"
|
||||
#include "cellular_comm_interface.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifndef CELLULAR_APN
|
||||
#error "CELLULAR_APN is not defined in cellular_config.h"
|
||||
#endif
|
||||
|
||||
#define CELLULAR_SIM_CARD_WAIT_INTERVAL_MS ( 500UL )
|
||||
#define CELLULAR_MAX_SIM_RETRY ( 5U )
|
||||
|
||||
#define CELLULAR_PDN_CONNECT_WAIT_INTERVAL_MS ( 1000UL )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* the default Cellular comm interface in system. */
|
||||
extern CellularCommInterface_t CellularCommInterface;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Secure socket needs application to provide the cellular handle and pdn context id. */
|
||||
/* User of secure sockets cellular should provide this variable. */
|
||||
CellularHandle_t CellularHandle = NULL;
|
||||
|
||||
/* User of secure sockets cellular should provide this variable. */
|
||||
uint8_t CellularSocketPdnContextId = CELLULAR_PDN_CONTEXT_ID;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool setupCellular( void )
|
||||
{
|
||||
bool cellularRet = true;
|
||||
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
||||
CellularSimCardStatus_t simStatus = { 0 };
|
||||
CellularServiceStatus_t serviceStatus = { 0 };
|
||||
CellularCommInterface_t * pCommIntf = &CellularCommInterface;
|
||||
uint8_t tries = 0;
|
||||
CellularPdnConfig_t pdnConfig = { CELLULAR_PDN_CONTEXT_IPV4, CELLULAR_PDN_AUTH_NONE, CELLULAR_APN, "", "" };
|
||||
CellularPdnStatus_t PdnStatusBuffers = { 0 };
|
||||
char localIP[ CELLULAR_IP_ADDRESS_MAX_SIZE ] = { '\0' };
|
||||
uint32_t timeoutCountLimit = ( CELLULAR_PDN_CONNECT_TIMEOUT / CELLULAR_PDN_CONNECT_WAIT_INTERVAL_MS ) + 1U;
|
||||
uint32_t timeoutCount = 0;
|
||||
uint8_t NumStatus = 1;
|
||||
CellularPsmSettings_t psmSettings = { 0 };
|
||||
|
||||
/* Initialize Cellular Comm Interface. */
|
||||
cellularStatus = Cellular_Init( &CellularHandle, pCommIntf );
|
||||
|
||||
if( cellularStatus == CELLULAR_SUCCESS )
|
||||
{
|
||||
/* wait until SIM is ready */
|
||||
for( tries = 0; tries < CELLULAR_MAX_SIM_RETRY; tries++ )
|
||||
{
|
||||
cellularStatus = Cellular_GetSimCardStatus( CellularHandle, &simStatus );
|
||||
|
||||
if( ( cellularStatus == CELLULAR_SUCCESS ) &&
|
||||
( ( simStatus.simCardState == CELLULAR_SIM_CARD_INSERTED ) &&
|
||||
( simStatus.simCardLockState == CELLULAR_SIM_CARD_READY ) ) )
|
||||
{
|
||||
/* Turn of PSM because this is demo to showcase MQTT instead of PSM mode. */
|
||||
psmSettings.mode = 0;
|
||||
cellularStatus = cellularStatus = Cellular_SetPsmSettings( CellularHandle, &psmSettings );
|
||||
|
||||
if( cellularStatus != CELLULAR_SUCCESS )
|
||||
{
|
||||
configPRINTF( ( ">>> Cellular_SetPsmSettings failure <<<\r\n" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
configPRINTF( ( ">>> Cellular SIM okay <<<\r\n" ) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
configPRINTF( ( ">>> Cellular SIM card state %d, Lock State %d <<<\r\n",
|
||||
simStatus.simCardState,
|
||||
simStatus.simCardLockState ) );
|
||||
}
|
||||
|
||||
vTaskDelay( pdMS_TO_TICKS( CELLULAR_SIM_CARD_WAIT_INTERVAL_MS ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the PDN config. */
|
||||
if( cellularStatus == CELLULAR_SUCCESS )
|
||||
{
|
||||
cellularStatus = Cellular_SetPdnConfig( CellularHandle, CellularSocketPdnContextId, &pdnConfig );
|
||||
}
|
||||
else
|
||||
{
|
||||
configPRINTF( ( ">>> Cellular SIM failure <<<\r\n" ) );
|
||||
}
|
||||
|
||||
/* Rescan network. */
|
||||
if( cellularStatus == CELLULAR_SUCCESS )
|
||||
{
|
||||
cellularStatus = Cellular_RfOff( CellularHandle );
|
||||
}
|
||||
|
||||
if( cellularStatus == CELLULAR_SUCCESS )
|
||||
{
|
||||
cellularStatus = Cellular_RfOn( CellularHandle );
|
||||
}
|
||||
|
||||
/* Get service status. */
|
||||
if( cellularStatus == CELLULAR_SUCCESS )
|
||||
{
|
||||
while( timeoutCount < timeoutCountLimit )
|
||||
{
|
||||
cellularStatus = Cellular_GetServiceStatus( CellularHandle, &serviceStatus );
|
||||
|
||||
if( ( cellularStatus == CELLULAR_SUCCESS ) &&
|
||||
( ( serviceStatus.psRegistrationStatus == REGISTRATION_STATUS_REGISTERED_HOME ) ||
|
||||
( serviceStatus.psRegistrationStatus == REGISTRATION_STATUS_ROAMING_REGISTERED ) ) )
|
||||
{
|
||||
configPRINTF( ( ">>> Cellular module registered <<<\r\n" ) );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
configPRINTF( ( ">>> Cellular GetServiceStatus failed %d, ps registration status %d <<<\r\n",
|
||||
cellularStatus, serviceStatus.psRegistrationStatus ) );
|
||||
}
|
||||
|
||||
timeoutCount++;
|
||||
|
||||
if( timeoutCount >= timeoutCountLimit )
|
||||
{
|
||||
cellularStatus = CELLULAR_INVALID_HANDLE;
|
||||
configPRINTF( ( ">>> Cellular module can't be registered <<<\r\n" ) );
|
||||
}
|
||||
|
||||
vTaskDelay( pdMS_TO_TICKS( CELLULAR_PDN_CONNECT_WAIT_INTERVAL_MS ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( cellularStatus == CELLULAR_SUCCESS )
|
||||
{
|
||||
cellularStatus = Cellular_ActivatePdn( CellularHandle, CellularSocketPdnContextId );
|
||||
}
|
||||
|
||||
if( cellularStatus == CELLULAR_SUCCESS )
|
||||
{
|
||||
cellularStatus = Cellular_GetIPAddress( CellularHandle, CellularSocketPdnContextId, localIP, sizeof( localIP ) );
|
||||
}
|
||||
|
||||
if( cellularStatus == CELLULAR_SUCCESS )
|
||||
{
|
||||
cellularStatus = Cellular_GetPdnStatus( CellularHandle, &PdnStatusBuffers, CellularSocketPdnContextId, &NumStatus );
|
||||
}
|
||||
|
||||
if( ( cellularStatus == CELLULAR_SUCCESS ) && ( PdnStatusBuffers.state == 1 ) )
|
||||
{
|
||||
configPRINTF( ( ">>> Cellular module registered, IP address %s <<<\r\n", localIP ) );
|
||||
cellularRet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellularRet = false;
|
||||
}
|
||||
|
||||
return cellularRet;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
|
@ -0,0 +1,912 @@
|
|||
/*
|
||||
* FreeRTOS V202107.00
|
||||
* Copyright (C) 2020 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.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @file comm_if_windows.c
|
||||
* @brief Windows Simulator file for cellular comm interface
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Windows include file for COM port I/O. */
|
||||
#include <windows.h>
|
||||
|
||||
/* Platform layer includes. */
|
||||
#include "cellular_platform.h"
|
||||
|
||||
/* Cellular comm interface include file. */
|
||||
#include "cellular_config.h"
|
||||
#include "cellular_config_defaults.h"
|
||||
#include "cellular_comm_interface.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Define the COM port used as comm interface. */
|
||||
#ifndef CELLULAR_COMM_INTERFACE_PORT
|
||||
#error "Define CELLULAR_COMM_INTERFACE_PORT in cellular_config.h"
|
||||
#endif
|
||||
#define CELLULAR_COMM_PATH "\\\\.\\"CELLULAR_COMM_INTERFACE_PORT
|
||||
|
||||
/* Define the simulated UART interrupt number. */
|
||||
#define portINTERRUPT_UART ( 2UL )
|
||||
|
||||
/* Define the read write buffer size. */
|
||||
#define COMM_TX_BUFFER_SIZE ( 8192 )
|
||||
#define COMM_RX_BUFFER_SIZE ( 8192 )
|
||||
|
||||
/* Receive thread timeout in ms. */
|
||||
#define COMM_RECV_THREAD_TIMEOUT ( 5000 )
|
||||
|
||||
/* Write operation timeout in ms. */
|
||||
#define COMM_WRITE_OPERATION_TIMEOUT ( 500 )
|
||||
|
||||
/* Comm status. */
|
||||
#define CELLULAR_COMM_OPEN_BIT ( 0x01U )
|
||||
|
||||
/* Comm task event. */
|
||||
#define COMMTASK_EVT_MASK_STARTED ( 0x0001UL )
|
||||
#define COMMTASK_EVT_MASK_ABORT ( 0x0002UL )
|
||||
#define COMMTASK_EVT_MASK_ABORTED ( 0x0004UL )
|
||||
#define COMMTASK_EVT_MASK_ALL_EVENTS \
|
||||
( COMMTASK_EVT_MASK_STARTED \
|
||||
| COMMTASK_EVT_MASK_ABORT \
|
||||
| COMMTASK_EVT_MASK_ABORTED )
|
||||
#define COMMTASK_POLLING_TIME_MS ( 1UL )
|
||||
|
||||
/* Platform thread stack size and priority. */
|
||||
#define COMM_IF_THREAD_DEFAULT_STACK_SIZE ( 2048U )
|
||||
#define COMM_IF_THREAD_DEFAULT_PRIORITY ( tskIDLE_PRIORITY + 5U )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
typedef struct _cellularCommContext
|
||||
{
|
||||
CellularCommInterfaceReceiveCallback_t commReceiveCallback;
|
||||
HANDLE commReceiveCallbackThread;
|
||||
uint8_t commStatus;
|
||||
void * pUserData;
|
||||
HANDLE commFileHandle;
|
||||
CellularCommInterface_t * pCommInterface;
|
||||
bool commTaskThreadStarted;
|
||||
EventGroupHandle_t pCommTaskEvent;
|
||||
} _cellularCommContext_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief CellularCommInterfaceOpen_t implementation.
|
||||
*/
|
||||
static CellularCommInterfaceError_t _prvCommIntfOpen( CellularCommInterfaceReceiveCallback_t receiveCallback,
|
||||
void * pUserData,
|
||||
CellularCommInterfaceHandle_t * pCommInterfaceHandle );
|
||||
|
||||
/**
|
||||
* @brief CellularCommInterfaceSend_t implementation.
|
||||
*/
|
||||
static CellularCommInterfaceError_t _prvCommIntfSend( CellularCommInterfaceHandle_t commInterfaceHandle,
|
||||
const uint8_t * pData,
|
||||
uint32_t dataLength,
|
||||
uint32_t timeoutMilliseconds,
|
||||
uint32_t * pDataSentLength );
|
||||
|
||||
/**
|
||||
* @brief CellularCommInterfaceRecv_t implementation.
|
||||
*/
|
||||
static CellularCommInterfaceError_t _prvCommIntfReceive( CellularCommInterfaceHandle_t commInterfaceHandle,
|
||||
uint8_t * pBuffer,
|
||||
uint32_t bufferLength,
|
||||
uint32_t timeoutMilliseconds,
|
||||
uint32_t * pDataReceivedLength );
|
||||
|
||||
/**
|
||||
* @brief CellularCommInterfaceClose_t implementation.
|
||||
*/
|
||||
static CellularCommInterfaceError_t _prvCommIntfClose( CellularCommInterfaceHandle_t commInterfaceHandle );
|
||||
|
||||
/**
|
||||
* @brief Get default comm interface context.
|
||||
*
|
||||
* @return On success, SOCKETS_ERROR_NONE is returned. If an error occurred, error code defined
|
||||
* in sockets_wrapper.h is returned.
|
||||
*/
|
||||
static _cellularCommContext_t * _getCellularCommContext( void );
|
||||
|
||||
/**
|
||||
* @brief UART interrupt handler.
|
||||
*
|
||||
* @return pdTRUE if the operation is successful, otherwise
|
||||
* an error code indicating the cause of the error.
|
||||
*/
|
||||
static uint32_t prvProcessUartInt( void );
|
||||
|
||||
/**
|
||||
* @brief Set COM port timeout settings.
|
||||
*
|
||||
* @param[in] hComm COM handle returned by CreateFile.
|
||||
*
|
||||
* @return On success, IOT_COMM_INTERFACE_SUCCESS is returned. If an error occurred, error code defined
|
||||
* in CellularCommInterfaceError_t is returned.
|
||||
*/
|
||||
static CellularCommInterfaceError_t _setupCommTimeout( HANDLE hComm );
|
||||
|
||||
/**
|
||||
* @brief Set COM port control settings.
|
||||
*
|
||||
* @param[in] hComm COM handle returned by CreateFile.
|
||||
*
|
||||
* @return On success, IOT_COMM_INTERFACE_SUCCESS is returned. If an error occurred, error code defined
|
||||
* in CellularCommInterfaceError_t is returned.
|
||||
*/
|
||||
static CellularCommInterfaceError_t _setupCommSettings( HANDLE hComm );
|
||||
|
||||
/**
|
||||
* @brief Thread routine to generate simulated interrupt.
|
||||
*
|
||||
* @param[in] pUserData Pointer to _cellularCommContext_t allocated in comm interface open.
|
||||
*/
|
||||
static void commTaskThread( void * pUserData );
|
||||
|
||||
/**
|
||||
* @brief Helper function to setup and create commTaskThread.
|
||||
*
|
||||
* @param[in] pCellularCommContext Cellular comm interface context allocated in open.
|
||||
*
|
||||
* @return On success, IOT_COMM_INTERFACE_SUCCESS is returned. If an error occurred, error code defined
|
||||
* in CellularCommInterfaceError_t is returned.
|
||||
*/
|
||||
static CellularCommInterfaceError_t setupCommTaskThread( _cellularCommContext_t * pCellularCommContext );
|
||||
|
||||
/**
|
||||
* @brief Helper function to clean commTaskThread.
|
||||
*
|
||||
* @param[in] pCellularCommContext Cellular comm interface context allocated in open.
|
||||
*
|
||||
* @return On success, IOT_COMM_INTERFACE_SUCCESS is returned. If an error occurred, error code defined
|
||||
* in CellularCommInterfaceError_t is returned.
|
||||
*/
|
||||
static CellularCommInterfaceError_t cleanCommTaskThread( _cellularCommContext_t * pCellularCommContext );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
CellularCommInterface_t CellularCommInterface =
|
||||
{
|
||||
.open = _prvCommIntfOpen,
|
||||
.send = _prvCommIntfSend,
|
||||
.recv = _prvCommIntfReceive,
|
||||
.close = _prvCommIntfClose
|
||||
};
|
||||
|
||||
static _cellularCommContext_t _iotCellularCommContext =
|
||||
{
|
||||
.commReceiveCallback = NULL,
|
||||
.commReceiveCallbackThread = NULL,
|
||||
.pCommInterface = &CellularCommInterface,
|
||||
.commFileHandle = NULL,
|
||||
.pUserData = NULL,
|
||||
.commStatus = 0U,
|
||||
.commTaskThreadStarted = false,
|
||||
.pCommTaskEvent = NULL
|
||||
};
|
||||
|
||||
/* Indicate RX event is received in comm driver. */
|
||||
static bool rxEvent = false;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static _cellularCommContext_t * _getCellularCommContext( void )
|
||||
{
|
||||
return &_iotCellularCommContext;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t prvProcessUartInt( void )
|
||||
{
|
||||
_cellularCommContext_t * pCellularCommContext = _getCellularCommContext();
|
||||
CellularCommInterfaceError_t callbackRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
uint32_t retUartInt = pdTRUE;
|
||||
|
||||
if( pCellularCommContext->commReceiveCallback != NULL )
|
||||
{
|
||||
callbackRet = pCellularCommContext->commReceiveCallback( pCellularCommContext->pUserData,
|
||||
( CellularCommInterfaceHandle_t ) pCellularCommContext );
|
||||
}
|
||||
|
||||
if( callbackRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
retUartInt = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
retUartInt = pdFALSE;
|
||||
}
|
||||
|
||||
return retUartInt;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Communication receiver thread function.
|
||||
*
|
||||
* @param[in] pArgument windows COM port handle.
|
||||
* @return 0 if thread function exit without error. Others for error.
|
||||
*/
|
||||
DWORD WINAPI _CellularCommReceiveCBThreadFunc( LPVOID pArgument )
|
||||
{
|
||||
DWORD dwCommStatus = 0;
|
||||
HANDLE hComm = ( HANDLE ) pArgument;
|
||||
BOOL retWait = FALSE;
|
||||
DWORD retValue = 0;
|
||||
|
||||
if( hComm == ( HANDLE ) INVALID_HANDLE_VALUE )
|
||||
{
|
||||
retValue = ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
while( retValue == 0 )
|
||||
{
|
||||
retWait = WaitCommEvent( hComm, &dwCommStatus, NULL );
|
||||
|
||||
if( ( retWait != FALSE ) && ( ( dwCommStatus & EV_RXCHAR ) != 0 ) )
|
||||
{
|
||||
if( ( dwCommStatus & EV_RXCHAR ) != 0 )
|
||||
{
|
||||
rxEvent = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ( GetLastError() == ERROR_INVALID_HANDLE ) || ( GetLastError() == ERROR_OPERATION_ABORTED ) )
|
||||
{
|
||||
/* COM port closed. */
|
||||
LogInfo( ( "Cellular COM port %p closed", hComm ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "Cellular receiver thread wait comm error %p %d", hComm, GetLastError() ) );
|
||||
}
|
||||
|
||||
retValue = GetLastError();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static CellularCommInterfaceError_t _setupCommTimeout( HANDLE hComm )
|
||||
{
|
||||
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
|
||||
COMMTIMEOUTS xCommTimeouts = { 0 };
|
||||
BOOL Status = TRUE;
|
||||
|
||||
/* Set ReadIntervalTimeout to MAXDWORD and zero values for both
|
||||
* ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier to return
|
||||
* immediately with the bytes that already been received. */
|
||||
xCommTimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
xCommTimeouts.ReadTotalTimeoutConstant = 0;
|
||||
xCommTimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
xCommTimeouts.WriteTotalTimeoutConstant = COMM_WRITE_OPERATION_TIMEOUT;
|
||||
xCommTimeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
Status = SetCommTimeouts( hComm, &xCommTimeouts );
|
||||
|
||||
if( Status == FALSE )
|
||||
{
|
||||
LogError( ( "Cellular SetCommTimeouts fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
return commIntRet;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static CellularCommInterfaceError_t _setupCommSettings( HANDLE hComm )
|
||||
{
|
||||
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
|
||||
DCB dcbSerialParams = { 0 };
|
||||
BOOL Status = TRUE;
|
||||
|
||||
( void ) memset( &dcbSerialParams, 0, sizeof( dcbSerialParams ) );
|
||||
dcbSerialParams.DCBlength = sizeof( dcbSerialParams );
|
||||
dcbSerialParams.BaudRate = CBR_115200;
|
||||
dcbSerialParams.fBinary = 1;
|
||||
dcbSerialParams.ByteSize = 8;
|
||||
dcbSerialParams.StopBits = ONESTOPBIT;
|
||||
dcbSerialParams.Parity = NOPARITY;
|
||||
|
||||
dcbSerialParams.fOutxCtsFlow = FALSE;
|
||||
dcbSerialParams.fOutxDsrFlow = FALSE;
|
||||
dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
|
||||
dcbSerialParams.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
|
||||
Status = SetCommState( hComm, &dcbSerialParams );
|
||||
|
||||
if( Status == FALSE )
|
||||
{
|
||||
LogError( ( "Cellular SetCommState fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
return commIntRet;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void commTaskThread( void * pUserData )
|
||||
{
|
||||
_cellularCommContext_t * pCellularCommContext = ( _cellularCommContext_t * ) pUserData;
|
||||
EventBits_t uxBits = 0;
|
||||
|
||||
/* Inform thread ready. */
|
||||
LogInfo( ( "Cellular commTaskThread started" ) );
|
||||
|
||||
if( pCellularCommContext != NULL )
|
||||
{
|
||||
( void ) xEventGroupSetBits( pCellularCommContext->pCommTaskEvent,
|
||||
COMMTASK_EVT_MASK_STARTED );
|
||||
}
|
||||
|
||||
while( true )
|
||||
{
|
||||
/* Wait for notification from eventqueue. */
|
||||
uxBits = xEventGroupWaitBits( ( pCellularCommContext->pCommTaskEvent ),
|
||||
( ( EventBits_t ) COMMTASK_EVT_MASK_ABORT ),
|
||||
pdTRUE,
|
||||
pdFALSE,
|
||||
pdMS_TO_TICKS( COMMTASK_POLLING_TIME_MS ) );
|
||||
|
||||
if( ( uxBits & ( EventBits_t ) COMMTASK_EVT_MASK_ABORT ) != 0U )
|
||||
{
|
||||
LogDebug( ( "Abort received, cleaning up!" ) );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Polling the global share variable to trigger the interrupt. */
|
||||
if( rxEvent == true )
|
||||
{
|
||||
rxEvent = false;
|
||||
vPortGenerateSimulatedInterrupt( portINTERRUPT_UART );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Inform thread ready. */
|
||||
if( pCellularCommContext != NULL )
|
||||
{
|
||||
( void ) xEventGroupSetBits( pCellularCommContext->pCommTaskEvent, COMMTASK_EVT_MASK_ABORTED );
|
||||
}
|
||||
|
||||
LogInfo( ( "Cellular commTaskThread exit" ) );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static CellularCommInterfaceError_t setupCommTaskThread( _cellularCommContext_t * pCellularCommContext )
|
||||
{
|
||||
BOOL Status = TRUE;
|
||||
EventBits_t uxBits = 0;
|
||||
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
|
||||
|
||||
pCellularCommContext->pCommTaskEvent = xEventGroupCreate();
|
||||
|
||||
if( pCellularCommContext->pCommTaskEvent != NULL )
|
||||
{
|
||||
/* Create the FreeRTOS thread to generate the simulated interrupt. */
|
||||
Status = Platform_CreateDetachedThread( commTaskThread,
|
||||
( void * ) pCellularCommContext,
|
||||
COMM_IF_THREAD_DEFAULT_PRIORITY,
|
||||
COMM_IF_THREAD_DEFAULT_STACK_SIZE );
|
||||
|
||||
if( Status != true )
|
||||
{
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
uxBits = xEventGroupWaitBits( ( pCellularCommContext->pCommTaskEvent ),
|
||||
( ( EventBits_t ) COMMTASK_EVT_MASK_STARTED | ( EventBits_t ) COMMTASK_EVT_MASK_ABORTED ),
|
||||
pdTRUE,
|
||||
pdFALSE,
|
||||
portMAX_DELAY );
|
||||
|
||||
if( ( uxBits & ( EventBits_t ) COMMTASK_EVT_MASK_STARTED ) == COMMTASK_EVT_MASK_STARTED )
|
||||
{
|
||||
pCellularCommContext->commTaskThreadStarted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
pCellularCommContext->commTaskThreadStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
return commIntRet;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static CellularCommInterfaceError_t cleanCommTaskThread( _cellularCommContext_t * pCellularCommContext )
|
||||
{
|
||||
EventBits_t uxBits = 0;
|
||||
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
|
||||
|
||||
/* Wait for the commTaskThreadStarted exit. */
|
||||
if( ( pCellularCommContext->commTaskThreadStarted == true ) && ( pCellularCommContext->pCommTaskEvent != NULL ) )
|
||||
{
|
||||
( void ) xEventGroupSetBits( pCellularCommContext->pCommTaskEvent,
|
||||
COMMTASK_EVT_MASK_ABORT );
|
||||
uxBits = xEventGroupWaitBits( ( pCellularCommContext->pCommTaskEvent ),
|
||||
( ( EventBits_t ) COMMTASK_EVT_MASK_ABORTED ),
|
||||
pdTRUE,
|
||||
pdFALSE,
|
||||
portMAX_DELAY );
|
||||
|
||||
if( ( uxBits & ( EventBits_t ) COMMTASK_EVT_MASK_ABORTED ) != COMMTASK_EVT_MASK_ABORTED )
|
||||
{
|
||||
LogDebug( ( "Cellular close wait commTaskThread fail" ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
pCellularCommContext->commTaskThreadStarted = false;
|
||||
}
|
||||
|
||||
/* Clean the event group. */
|
||||
if( pCellularCommContext->pCommTaskEvent != NULL )
|
||||
{
|
||||
vEventGroupDelete( pCellularCommContext->pCommTaskEvent );
|
||||
pCellularCommContext->pCommTaskEvent = NULL;
|
||||
}
|
||||
|
||||
return commIntRet;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static CellularCommInterfaceError_t _prvCommIntfOpen( CellularCommInterfaceReceiveCallback_t receiveCallback,
|
||||
void * pUserData,
|
||||
CellularCommInterfaceHandle_t * pCommInterfaceHandle )
|
||||
{
|
||||
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
|
||||
HANDLE hComm = ( HANDLE ) INVALID_HANDLE_VALUE;
|
||||
BOOL Status = TRUE;
|
||||
_cellularCommContext_t * pCellularCommContext = _getCellularCommContext();
|
||||
DWORD dwRes = 0;
|
||||
|
||||
if( pCellularCommContext == NULL )
|
||||
{
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
else if( ( pCellularCommContext->commStatus & CELLULAR_COMM_OPEN_BIT ) != 0 )
|
||||
{
|
||||
LogError( ( "Cellular comm interface opened already" ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear the context. */
|
||||
memset( pCellularCommContext, 0, sizeof( _cellularCommContext_t ) );
|
||||
pCellularCommContext->pCommInterface = &CellularCommInterface;
|
||||
|
||||
/* If CreateFile fails, the return value is INVALID_HANDLE_VALUE. */
|
||||
hComm = CreateFile( TEXT( CELLULAR_COMM_PATH ),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
NULL );
|
||||
}
|
||||
|
||||
/* Comm port is just closed. Wait 1 second and retry. */
|
||||
if( ( hComm == ( HANDLE ) INVALID_HANDLE_VALUE ) && ( GetLastError() == 5 ) )
|
||||
{
|
||||
vTaskDelay( pdMS_TO_TICKS( 1000UL ) );
|
||||
hComm = CreateFile( TEXT( CELLULAR_COMM_PATH ),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
NULL );
|
||||
}
|
||||
|
||||
if( hComm == ( HANDLE ) INVALID_HANDLE_VALUE )
|
||||
{
|
||||
LogError( ( "Cellular open COM port fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = SetupComm( hComm, COMM_TX_BUFFER_SIZE, COMM_RX_BUFFER_SIZE );
|
||||
|
||||
if( Status == FALSE )
|
||||
{
|
||||
LogError( ( "Cellular setup COM port fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
commIntRet = _setupCommTimeout( hComm );
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
commIntRet = _setupCommSettings( hComm );
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
Status = SetCommMask( hComm, EV_RXCHAR );
|
||||
|
||||
if( Status == FALSE )
|
||||
{
|
||||
LogError( ( "Cellular SetCommMask fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
pCellularCommContext->commReceiveCallback = receiveCallback;
|
||||
commIntRet = setupCommTaskThread( pCellularCommContext );
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
vPortSetInterruptHandler( portINTERRUPT_UART, prvProcessUartInt );
|
||||
pCellularCommContext->commReceiveCallbackThread =
|
||||
CreateThread( NULL, 0, _CellularCommReceiveCBThreadFunc, hComm, 0, NULL );
|
||||
|
||||
/* CreateThread return NULL for error. */
|
||||
if( pCellularCommContext->commReceiveCallbackThread == NULL )
|
||||
{
|
||||
LogError( ( "Cellular CreateThread fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
pCellularCommContext->pUserData = pUserData;
|
||||
pCellularCommContext->commFileHandle = hComm;
|
||||
*pCommInterfaceHandle = ( CellularCommInterfaceHandle_t ) pCellularCommContext;
|
||||
pCellularCommContext->commStatus |= CELLULAR_COMM_OPEN_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Comm interface open fail. Clean the data. */
|
||||
if( hComm != ( HANDLE ) INVALID_HANDLE_VALUE )
|
||||
{
|
||||
( void ) CloseHandle( hComm );
|
||||
hComm = INVALID_HANDLE_VALUE;
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
/* Wait for the commReceiveCallbackThread exit. */
|
||||
if( pCellularCommContext->commReceiveCallbackThread != NULL )
|
||||
{
|
||||
dwRes = WaitForSingleObject( pCellularCommContext->commReceiveCallbackThread, COMM_RECV_THREAD_TIMEOUT );
|
||||
|
||||
if( dwRes != WAIT_OBJECT_0 )
|
||||
{
|
||||
LogDebug( ( "Cellular close wait receiveCallbackThread %p fail %d",
|
||||
pCellularCommContext->commReceiveCallbackThread, dwRes ) );
|
||||
}
|
||||
}
|
||||
|
||||
pCellularCommContext->commReceiveCallbackThread = NULL;
|
||||
|
||||
/* Wait for the commTaskThreadStarted exit. */
|
||||
( void ) cleanCommTaskThread( pCellularCommContext );
|
||||
}
|
||||
|
||||
return commIntRet;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static CellularCommInterfaceError_t _prvCommIntfClose( CellularCommInterfaceHandle_t commInterfaceHandle )
|
||||
{
|
||||
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
|
||||
_cellularCommContext_t * pCellularCommContext = ( _cellularCommContext_t * ) commInterfaceHandle;
|
||||
HANDLE hComm = NULL;
|
||||
BOOL Status = TRUE;
|
||||
DWORD dwRes = 0;
|
||||
|
||||
if( pCellularCommContext == NULL )
|
||||
{
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
else if( ( pCellularCommContext->commStatus & CELLULAR_COMM_OPEN_BIT ) == 0 )
|
||||
{
|
||||
LogError( ( "Cellular close comm interface is not opened before." ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clean the receive callback. */
|
||||
pCellularCommContext->commReceiveCallback = NULL;
|
||||
|
||||
/* Close the COM port. */
|
||||
hComm = pCellularCommContext->commFileHandle;
|
||||
|
||||
if( hComm != ( HANDLE ) INVALID_HANDLE_VALUE )
|
||||
{
|
||||
Status = CloseHandle( hComm );
|
||||
|
||||
if( Status == FALSE )
|
||||
{
|
||||
LogDebug( ( "Cellular close CloseHandle %p fail", hComm ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
pCellularCommContext->commFileHandle = NULL;
|
||||
|
||||
/* Wait for the thread exit. */
|
||||
if( pCellularCommContext->commReceiveCallbackThread != NULL )
|
||||
{
|
||||
dwRes = WaitForSingleObject( pCellularCommContext->commReceiveCallbackThread, COMM_RECV_THREAD_TIMEOUT );
|
||||
|
||||
if( dwRes != WAIT_OBJECT_0 )
|
||||
{
|
||||
LogDebug( ( "Cellular close wait receiveCallbackThread %p fail %d",
|
||||
pCellularCommContext->commReceiveCallbackThread, dwRes ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle( pCellularCommContext->commReceiveCallbackThread );
|
||||
}
|
||||
}
|
||||
|
||||
pCellularCommContext->commReceiveCallbackThread = NULL;
|
||||
|
||||
/* Clean the commTaskThread. */
|
||||
( void ) cleanCommTaskThread( pCellularCommContext );
|
||||
|
||||
/* clean the data structure. */
|
||||
pCellularCommContext->commStatus &= ~( CELLULAR_COMM_OPEN_BIT );
|
||||
}
|
||||
|
||||
return commIntRet;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static CellularCommInterfaceError_t _prvCommIntfSend( CellularCommInterfaceHandle_t commInterfaceHandle,
|
||||
const uint8_t * pData,
|
||||
uint32_t dataLength,
|
||||
uint32_t timeoutMilliseconds,
|
||||
uint32_t * pDataSentLength )
|
||||
{
|
||||
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
|
||||
_cellularCommContext_t * pCellularCommContext = ( _cellularCommContext_t * ) commInterfaceHandle;
|
||||
HANDLE hComm = NULL;
|
||||
OVERLAPPED osWrite = { 0 };
|
||||
DWORD dwRes = 0;
|
||||
DWORD dwWritten = 0;
|
||||
BOOL Status = TRUE;
|
||||
|
||||
if( pCellularCommContext == NULL )
|
||||
{
|
||||
commIntRet = IOT_COMM_INTERFACE_BAD_PARAMETER;
|
||||
}
|
||||
else if( ( pCellularCommContext->commStatus & CELLULAR_COMM_OPEN_BIT ) == 0 )
|
||||
{
|
||||
LogError( ( "Cellular send comm interface is not opened before." ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hComm = pCellularCommContext->commFileHandle;
|
||||
osWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||||
|
||||
if( osWrite.hEvent == NULL )
|
||||
{
|
||||
LogError( ( "Cellular CreateEvent fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
Status = WriteFile( hComm, pData, dataLength, &dwWritten, &osWrite );
|
||||
|
||||
/* WriteFile fail and error is not the ERROR_IO_PENDING. */
|
||||
if( ( Status == FALSE ) && ( GetLastError() != ERROR_IO_PENDING ) )
|
||||
{
|
||||
LogError( ( "Cellular WriteFile fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
if( Status == TRUE )
|
||||
{
|
||||
*pDataSentLength = ( uint32_t ) dwWritten;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle pending I/O. */
|
||||
if( ( commIntRet == IOT_COMM_INTERFACE_SUCCESS ) && ( Status == FALSE ) )
|
||||
{
|
||||
dwRes = WaitForSingleObject( osWrite.hEvent, timeoutMilliseconds );
|
||||
|
||||
switch( dwRes )
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
|
||||
if( GetOverlappedResult( hComm, &osWrite, &dwWritten, FALSE ) == FALSE )
|
||||
{
|
||||
LogError( ( "Cellular GetOverlappedResult fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STATUS_TIMEOUT:
|
||||
LogError( ( "Cellular WaitForSingleObject timeout" ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_TIMEOUT;
|
||||
break;
|
||||
|
||||
default:
|
||||
LogError( ( "Cellular WaitForSingleObject fail %d", dwRes ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
*pDataSentLength = ( uint32_t ) dwWritten;
|
||||
}
|
||||
|
||||
if( osWrite.hEvent != NULL )
|
||||
{
|
||||
Status = CloseHandle( osWrite.hEvent );
|
||||
|
||||
if( Status == FALSE )
|
||||
{
|
||||
LogDebug( ( "Cellular send CloseHandle fail" ) );
|
||||
}
|
||||
}
|
||||
|
||||
return commIntRet;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static CellularCommInterfaceError_t _prvCommIntfReceive( CellularCommInterfaceHandle_t commInterfaceHandle,
|
||||
uint8_t * pBuffer,
|
||||
uint32_t bufferLength,
|
||||
uint32_t timeoutMilliseconds,
|
||||
uint32_t * pDataReceivedLength )
|
||||
{
|
||||
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
|
||||
_cellularCommContext_t * pCellularCommContext = ( _cellularCommContext_t * ) commInterfaceHandle;
|
||||
HANDLE hComm = NULL;
|
||||
OVERLAPPED osRead = { 0 };
|
||||
BOOL Status = TRUE;
|
||||
DWORD dwRes = 0;
|
||||
DWORD dwRead = 0;
|
||||
|
||||
if( pCellularCommContext == NULL )
|
||||
{
|
||||
commIntRet = IOT_COMM_INTERFACE_BAD_PARAMETER;
|
||||
}
|
||||
else if( ( pCellularCommContext->commStatus & CELLULAR_COMM_OPEN_BIT ) == 0 )
|
||||
{
|
||||
LogError( ( "Cellular read comm interface is not opened before." ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hComm = pCellularCommContext->commFileHandle;
|
||||
osRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||||
|
||||
if( osRead.hEvent == NULL )
|
||||
{
|
||||
LogError( ( "Cellular CreateEvent fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
Status = ReadFile( hComm, pBuffer, bufferLength, &dwRead, &osRead );
|
||||
|
||||
if( ( Status == FALSE ) && ( GetLastError() != ERROR_IO_PENDING ) )
|
||||
{
|
||||
LogError( ( "Cellular ReadFile fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
if( Status == TRUE )
|
||||
{
|
||||
*pDataReceivedLength = ( uint32_t ) dwRead;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle pending I/O. */
|
||||
if( ( commIntRet == IOT_COMM_INTERFACE_SUCCESS ) && ( Status == FALSE ) )
|
||||
{
|
||||
dwRes = WaitForSingleObject( osRead.hEvent, timeoutMilliseconds );
|
||||
|
||||
switch( dwRes )
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
|
||||
if( GetOverlappedResult( hComm, &osRead, &dwRead, FALSE ) == FALSE )
|
||||
{
|
||||
LogError( ( "Cellular receive GetOverlappedResult fail %d", GetLastError() ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STATUS_TIMEOUT:
|
||||
LogError( ( "Cellular receive WaitForSingleObject timeout" ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_TIMEOUT;
|
||||
break;
|
||||
|
||||
default:
|
||||
LogError( ( "Cellular receive WaitForSingleObject fail %d", dwRes ) );
|
||||
commIntRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
*pDataReceivedLength = ( uint32_t ) dwRead;
|
||||
}
|
||||
|
||||
if( osRead.hEvent != NULL )
|
||||
{
|
||||
Status = CloseHandle( osRead.hEvent );
|
||||
|
||||
if( Status == FALSE )
|
||||
{
|
||||
LogDebug( ( "Cellular recv CloseHandle fail" ) );
|
||||
}
|
||||
}
|
||||
|
||||
return commIntRet;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* FreeRTOS V202107.00
|
||||
* Copyright (C) 2020 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.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/***
|
||||
* See https://www.FreeRTOS.org/coremqtt for configuration and usage instructions.
|
||||
***/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
/* Visual studio intrinsics used so the __debugbreak() function is available
|
||||
* should an assert get hit. */
|
||||
#include <intrin.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include <FreeRTOS.h>
|
||||
#include "task.h"
|
||||
|
||||
/* TCP/IP stack includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
/* Demo logging includes. */
|
||||
#include "logging.h"
|
||||
|
||||
/* Demo Specific configs. */
|
||||
#include "demo_config.h"
|
||||
|
||||
/* FreeRTOS Cellular Library init and setup cellular network registration. */
|
||||
extern bool setupCellular( void );
|
||||
|
||||
/* The MQTT demo entry function. */
|
||||
extern void vStartSimpleMQTTDemo( void );
|
||||
|
||||
/* The task function to setup cellular with thread ready environment. */
|
||||
static void CellularDemoTask( void * pvParameters );
|
||||
|
||||
/*
|
||||
* Just seeds the simple pseudo random number generator.
|
||||
*
|
||||
* !!! NOTE !!!
|
||||
* This is not a secure method of generating random numbers and production
|
||||
* devices should use a true random number generator (TRNG).
|
||||
*/
|
||||
static void prvSRand( UBaseType_t ulSeed );
|
||||
|
||||
/*
|
||||
* Miscellaneous initialization including preparing the logging and seeding the
|
||||
* random number generator.
|
||||
*/
|
||||
static void prvMiscInitialisation( void );
|
||||
|
||||
/* Set the following constant to pdTRUE to log using the method indicated by the
|
||||
* name of the constant, or pdFALSE to not log using the method indicated by the
|
||||
* name of the constant. Options include to standard out (xLogToStdout), to a disk
|
||||
* file (xLogToFile), and to a UDP port (xLogToUDP). If xLogToUDP is set to pdTRUE
|
||||
* then UDP messages are sent to the IP address configured as the UDP logging server
|
||||
* address (see the configUDP_LOGGING_ADDR0 definitions in FreeRTOSConfig.h) and
|
||||
* the port number set by configPRINT_PORT in FreeRTOSConfig.h. */
|
||||
const BaseType_t xLogToStdout = pdTRUE, xLogToFile = pdFALSE, xLogToUDP = pdFALSE;
|
||||
|
||||
/* Used by the pseudo random number generator. */
|
||||
static UBaseType_t ulNextRand;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
int main( void )
|
||||
{
|
||||
/***
|
||||
* See https://www.FreeRTOS.org/iot-device-shadow for configuration and usage instructions.
|
||||
***/
|
||||
|
||||
/* Miscellaneous initialization including preparing the logging and seeding
|
||||
* the random number generator. */
|
||||
prvMiscInitialisation();
|
||||
|
||||
/* Start the RTOS scheduler. */
|
||||
vTaskStartScheduler();
|
||||
|
||||
/* If all is well, the scheduler will now be running, and the following
|
||||
* line will never be reached. If the following line does execute, then
|
||||
* there was insufficient FreeRTOS heap memory available for the idle and/or
|
||||
* timer tasks to be created. See the memory management section on the
|
||||
* FreeRTOS web site for more details (this is standard text that is not
|
||||
* really applicable to the Win32 simulator port). */
|
||||
for( ; ; )
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Called by FreeRTOS+TCP when the network connects or disconnects. Disconnect
|
||||
* events are only received if implemented in the MAC driver. */
|
||||
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
|
||||
{
|
||||
( void ) eNetworkEvent;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vAssertCalled( const char * pcFile,
|
||||
uint32_t ulLine )
|
||||
{
|
||||
volatile uint32_t ulBlockVariable = 0UL;
|
||||
volatile char * pcFileName = ( volatile char * ) pcFile;
|
||||
volatile uint32_t ulLineNumber = ulLine;
|
||||
|
||||
( void ) pcFileName;
|
||||
( void ) ulLineNumber;
|
||||
|
||||
printf( "vAssertCalled( %s, %u\n", pcFile, ulLine );
|
||||
|
||||
/* Setting ulBlockVariable to a non-zero value in the debugger will allow
|
||||
* this function to be exited. */
|
||||
taskDISABLE_INTERRUPTS();
|
||||
{
|
||||
while( ulBlockVariable == 0UL )
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
}
|
||||
taskENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxRand( void )
|
||||
{
|
||||
const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
|
||||
|
||||
/*
|
||||
* Utility function to generate a pseudo random number.
|
||||
*
|
||||
* !!!NOTE!!!
|
||||
* This is not a secure method of generating a random number. Production
|
||||
* devices should use a True Random Number Generator (TRNG).
|
||||
*/
|
||||
ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
|
||||
return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSRand( UBaseType_t ulSeed )
|
||||
{
|
||||
/* Utility function to seed the pseudo random number generator. */
|
||||
ulNextRand = ulSeed;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void CellularDemoTask( void * pvParameters )
|
||||
{
|
||||
bool retCellular = true;
|
||||
|
||||
( void ) pvParameters;
|
||||
/* Setup cellular. */
|
||||
retCellular = setupCellular();
|
||||
|
||||
if( retCellular == false )
|
||||
{
|
||||
configPRINTF( ( "Cellular failed to initialize.\r\n" ) );
|
||||
}
|
||||
|
||||
/* Stop here if we fail to initialize cellular. */
|
||||
configASSERT( retCellular == true );
|
||||
|
||||
/* Run the MQTT demo. */
|
||||
/* Demos that use the network are created after the network is
|
||||
* up. */
|
||||
LogInfo( ( "---------STARTING DEMO---------\r\n" ) );
|
||||
vStartSimpleMQTTDemo();
|
||||
|
||||
vTaskDelete( NULL );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvMiscInitialisation( void )
|
||||
{
|
||||
vLoggingInit( xLogToStdout, xLogToFile, xLogToUDP, 0U, configPRINT_PORT );
|
||||
|
||||
/* FreeRTOS Cellular Library init needs thread ready environment.
|
||||
* CellularDemoTask invoke setupCellular to init FreeRTOS Cellular Library and register network.
|
||||
* Then it runs the MQTT demo. */
|
||||
xTaskCreate( CellularDemoTask, /* Function that implements the task. */
|
||||
"CellularDemo", /* Text name for the task - only used for debugging. */
|
||||
democonfigDEMO_STACKSIZE, /* Size of stack (in words, not bytes) to allocate for the task. */
|
||||
NULL, /* Task parameter - not used in this case. */
|
||||
democonfigDEMO_PRIORITY, /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */
|
||||
NULL ); /* Used to pass out a handle to the created task - not used in this case. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) || ( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
|
||||
|
||||
const char * pcApplicationHostnameHook( void )
|
||||
{
|
||||
/* Assign the name "FreeRTOS" to this network node. This function will
|
||||
* be called during the DHCP: the machine will be registered with an IP
|
||||
* address plus this name. */
|
||||
return mainHOST_NAME;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 )
|
||||
|
||||
BaseType_t xApplicationDNSQueryHook( const char * pcName )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Determine if a name lookup is for this node. Two names are given
|
||||
* to this node: that returned by pcApplicationHostnameHook() and that set
|
||||
* by mainDEVICE_NICK_NAME. */
|
||||
if( _stricmp( pcName, pcApplicationHostnameHook() ) == 0 )
|
||||
{
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else if( _stricmp( pcName, mainDEVICE_NICK_NAME ) == 0 )
|
||||
{
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Callback that provides the inputs necessary to generate a randomized TCP
|
||||
* Initial Sequence Number per RFC 6528. THIS IS ONLY A DUMMY IMPLEMENTATION
|
||||
* THAT RETURNS A PSEUDO RANDOM NUMBER SO IS NOT INTENDED FOR USE IN PRODUCTION
|
||||
* SYSTEMS.
|
||||
*/
|
||||
extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
|
||||
uint16_t usSourcePort,
|
||||
uint32_t ulDestinationAddress,
|
||||
uint16_t usDestinationPort )
|
||||
{
|
||||
( void ) ulSourceAddress;
|
||||
( void ) usSourcePort;
|
||||
( void ) ulDestinationAddress;
|
||||
( void ) usDestinationPort;
|
||||
|
||||
return uxRand();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Set *pulNumber to a random number, and return pdTRUE. When the random number
|
||||
* generator is broken, it shall return pdFALSE.
|
||||
* The macros ipconfigRAND32() and configRAND32() are not in use
|
||||
* anymore in FreeRTOS+TCP.
|
||||
*
|
||||
* THIS IS ONLY A DUMMY IMPLEMENTATION THAT RETURNS A PSEUDO RANDOM NUMBER SO IS
|
||||
* NOT INTENDED FOR USE IN PRODUCTION SYSTEMS.
|
||||
*/
|
||||
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
|
||||
{
|
||||
*pulNumber = uxRand();
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
|
||||
* implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
|
||||
* used by the Idle task. */
|
||||
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
|
||||
StackType_t ** ppxIdleTaskStackBuffer,
|
||||
uint32_t * pulIdleTaskStackSize )
|
||||
{
|
||||
/* If the buffers to be provided to the Idle task are declared inside this
|
||||
* function then they must be declared static - otherwise they will be allocated on
|
||||
* the stack and so not exists after this function exits. */
|
||||
static StaticTask_t xIdleTaskTCB;
|
||||
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
|
||||
|
||||
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
|
||||
* state will be stored. */
|
||||
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
|
||||
|
||||
/* Pass out the array that will be used as the Idle task's stack. */
|
||||
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
|
||||
|
||||
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
|
||||
* Note that, as the array is necessarily of type StackType_t,
|
||||
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
|
||||
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
|
||||
* application must provide an implementation of vApplicationGetTimerTaskMemory()
|
||||
* to provide the memory that is used by the Timer service task. */
|
||||
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
|
||||
StackType_t ** ppxTimerTaskStackBuffer,
|
||||
uint32_t * pulTimerTaskStackSize )
|
||||
{
|
||||
/* If the buffers to be provided to the Timer task are declared inside this
|
||||
* function then they must be declared static - otherwise they will be allocated on
|
||||
* the stack and so not exists after this function exits. */
|
||||
static StaticTask_t xTimerTaskTCB;
|
||||
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
|
||||
|
||||
/* Pass out a pointer to the StaticTask_t structure in which the Timer
|
||||
* task's state will be stored. */
|
||||
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
|
||||
|
||||
/* Pass out the array that will be used as the Timer task's stack. */
|
||||
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
|
||||
|
||||
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
|
||||
* Note that, as the array is necessarily of type StackType_t,
|
||||
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
|
||||
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
Loading…
Add table
Add a link
Reference in a new issue