Update cellular comm interface to generate interrupt from windows thread (#1221)

* Make use of vPortGenerateSimulatedInterruptFromWindowsThread to generate interrupt from windows thread
pull/1224/head
chinglee-iot 9 months ago committed by GitHub
parent a3f42a78e7
commit 6518cb153d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -51,7 +51,7 @@
#define CELLULAR_COMM_PATH "\\\\.\\"CELLULAR_COMM_INTERFACE_PORT #define CELLULAR_COMM_PATH "\\\\.\\"CELLULAR_COMM_INTERFACE_PORT
/* Define the simulated UART interrupt number. */ /* Define the simulated UART interrupt number. */
#define portINTERRUPT_UART ( 2UL ) #define appINTERRUPT_UART portINTERRUPT_APPLICATION_DEFINED_START
/* Define the read write buffer size. */ /* Define the read write buffer size. */
#define COMM_TX_BUFFER_SIZE ( 8192 ) #define COMM_TX_BUFFER_SIZE ( 8192 )
@ -66,20 +66,6 @@
/* Comm status. */ /* Comm status. */
#define CELLULAR_COMM_OPEN_BIT ( 0x01U ) #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 typedef struct cellularCommContext
@ -91,7 +77,6 @@ typedef struct cellularCommContext
HANDLE commFileHandle; HANDLE commFileHandle;
CellularCommInterface_t * pCommInterface; CellularCommInterface_t * pCommInterface;
bool commTaskThreadStarted; bool commTaskThreadStarted;
EventGroupHandle_t pCommTaskEvent;
} cellularCommContext_t; } cellularCommContext_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -126,14 +111,6 @@ static CellularCommInterfaceError_t prvCommIntfReceive( CellularCommInterfaceHan
*/ */
static CellularCommInterfaceError_t prvCommIntfClose( CellularCommInterfaceHandle_t commInterfaceHandle ); 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 * prvGetCellularCommContext( void );
/** /**
* @brief UART interrupt handler. * @brief UART interrupt handler.
* *
@ -168,34 +145,7 @@ static CellularCommInterfaceError_t prvSetupCommTimeout( HANDLE hComm );
* @return On success, IOT_COMM_INTERFACE_SUCCESS is returned. If an error occurred, error code defined * @return On success, IOT_COMM_INTERFACE_SUCCESS is returned. If an error occurred, error code defined
* in CellularCommInterfaceError_t is returned. * in CellularCommInterfaceError_t is returned.
*/ */
static CellularCommInterfaceError_t prvSetupCommSettings( HANDLE hComm ); static CellularCommInterfaceError_t prvSetupCommState( HANDLE hComm );
/**
* @brief Thread routine to generate simulated interrupt.
*
* @param[in] pUserData Pointer to cellularCommContext_t allocated in comm interface open.
*/
static void prvCommTaskThread( 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 prvSetupCommTaskThread( 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 prvCleanCommTaskThread( cellularCommContext_t * pCellularCommContext );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -215,28 +165,14 @@ static cellularCommContext_t uxCellularCommContext =
.commFileHandle = NULL, .commFileHandle = NULL,
.pUserData = NULL, .pUserData = NULL,
.commStatus = 0U, .commStatus = 0U,
.commTaskThreadStarted = false, .commTaskThreadStarted = false
.pCommTaskEvent = NULL
}; };
/* Mutex used to protect rxEvent variables that are accessed by multiple threads. */
static void * pvRxEventMutex = NULL;
/* Indicate RX event is received in comm driver. */
static bool rxEvent = false;
/*-----------------------------------------------------------*/
static cellularCommContext_t * prvGetCellularCommContext( void )
{
return &uxCellularCommContext;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static uint32_t prvProcessUartInt( void ) static uint32_t prvProcessUartInt( void )
{ {
cellularCommContext_t * pCellularCommContext = prvGetCellularCommContext(); cellularCommContext_t * pCellularCommContext = &uxCellularCommContext;
CellularCommInterfaceError_t callbackRet = IOT_COMM_INTERFACE_FAILURE; CellularCommInterfaceError_t callbackRet = IOT_COMM_INTERFACE_FAILURE;
uint32_t retUartInt = pdTRUE; uint32_t retUartInt = pdTRUE;
@ -271,37 +207,37 @@ static DWORD WINAPI prvCellularCommReceiveCBThreadFunc( LPVOID pArgument )
{ {
retValue = ERROR_INVALID_HANDLE; retValue = ERROR_INVALID_HANDLE;
} }
else
while( retValue == 0 ) {
for( ; ; )
{ {
retWait = WaitCommEvent( hComm, &dwCommStatus, NULL ); retWait = WaitCommEvent( hComm, &dwCommStatus, NULL );
if( ( retWait != FALSE ) && ( ( dwCommStatus & EV_RXCHAR ) != 0 ) ) if( ( retWait != FALSE ) && ( ( dwCommStatus & EV_RXCHAR ) != 0 ) )
{ {
if( ( dwCommStatus & EV_RXCHAR ) != 0 ) /* Generate a simulated interrupt when data is received in the input buffer in driver.
{ * The interrupt handler prvProcessUartInt() will be called in prvProcessSimulatedInterrupts().
WaitForSingleObject( pvRxEventMutex, INFINITE ); * This ensures no other task or ISR is running. */
rxEvent = true; vPortGenerateSimulatedInterruptFromWindowsThread( appINTERRUPT_UART );
ReleaseMutex( pvRxEventMutex );
}
} }
else else
{ {
if( ( GetLastError() == ERROR_INVALID_HANDLE ) || ( GetLastError() == ERROR_OPERATION_ABORTED ) ) retValue = GetLastError();
if( ( retValue == ERROR_INVALID_HANDLE ) || ( retValue == ERROR_OPERATION_ABORTED ) )
{ {
/* COM port closed. */ /* COM port closed. */
LogInfo( ( "Cellular COM port %p closed", hComm ) ); LogInfo( ( "Cellular COM port %p closed", hComm ) );
} }
else else
{ {
LogInfo( ( "Cellular receiver thread wait comm error %p %d", hComm, GetLastError() ) ); LogInfo( ( "Cellular receiver thread wait comm error %p %d", hComm, retValue ) );
} }
retValue = GetLastError();
break; break;
} }
} }
}
return retValue; return retValue;
} }
@ -335,7 +271,7 @@ static CellularCommInterfaceError_t prvSetupCommTimeout( HANDLE hComm )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static CellularCommInterfaceError_t prvSetupCommSettings( HANDLE hComm ) static CellularCommInterfaceError_t prvSetupCommState( HANDLE hComm )
{ {
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS; CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
DCB dcbSerialParams = { 0 }; DCB dcbSerialParams = { 0 };
@ -367,146 +303,6 @@ static CellularCommInterfaceError_t prvSetupCommSettings( HANDLE hComm )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCommTaskThread( 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 )
{
WaitForSingleObject( pvRxEventMutex, INFINITE );
rxEvent = false;
ReleaseMutex( pvRxEventMutex );
vPortGenerateSimulatedInterrupt( portINTERRUPT_UART );
}
}
}
/* Inform thread ready. */
if( pCellularCommContext != NULL )
{
( void ) xEventGroupSetBits( pCellularCommContext->pCommTaskEvent, COMMTASK_EVT_MASK_ABORTED );
}
LogInfo( ( "Cellular commTaskThread exit" ) );
}
/*-----------------------------------------------------------*/
static CellularCommInterfaceError_t prvSetupCommTaskThread( 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( prvCommTaskThread,
( 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 prvCleanCommTaskThread( 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, static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiveCallback_t receiveCallback,
void * pUserData, void * pUserData,
CellularCommInterfaceHandle_t * pCommInterfaceHandle ) CellularCommInterfaceHandle_t * pCommInterfaceHandle )
@ -514,7 +310,7 @@ static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiv
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS; CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
HANDLE hComm = ( HANDLE ) INVALID_HANDLE_VALUE; HANDLE hComm = ( HANDLE ) INVALID_HANDLE_VALUE;
BOOL Status = TRUE; BOOL Status = TRUE;
cellularCommContext_t * pCellularCommContext = prvGetCellularCommContext(); cellularCommContext_t * pCellularCommContext = &uxCellularCommContext;
DWORD dwRes = 0; DWORD dwRes = 0;
if( pCellularCommContext == NULL ) if( pCellularCommContext == NULL )
@ -543,7 +339,7 @@ static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiv
} }
/* Comm port is just closed. Wait 1 second and retry. */ /* Comm port is just closed. Wait 1 second and retry. */
if( ( hComm == ( HANDLE ) INVALID_HANDLE_VALUE ) && ( GetLastError() == 5 ) ) if( ( hComm == ( HANDLE ) INVALID_HANDLE_VALUE ) && ( GetLastError() == ERROR_ACCESS_DENIED ) )
{ {
vTaskDelay( pdMS_TO_TICKS( 1000UL ) ); vTaskDelay( pdMS_TO_TICKS( 1000UL ) );
hComm = CreateFile( TEXT( CELLULAR_COMM_PATH ), hComm = CreateFile( TEXT( CELLULAR_COMM_PATH ),
@ -578,7 +374,7 @@ static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiv
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS ) if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
{ {
commIntRet = prvSetupCommSettings( hComm ); commIntRet = prvSetupCommState( hComm );
} }
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS ) if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
@ -592,26 +388,11 @@ static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiv
} }
} }
/* Create RX event mutex to protect rxEvent. */
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
{
pvRxEventMutex = CreateMutex( NULL, FALSE, NULL );
if( pvRxEventMutex == NULL )
{
commIntRet = IOT_COMM_INTERFACE_FAILURE;
}
}
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS ) if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
{ {
pCellularCommContext->commReceiveCallback = receiveCallback; pCellularCommContext->commReceiveCallback = receiveCallback;
commIntRet = prvSetupCommTaskThread( pCellularCommContext );
}
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS ) vPortSetInterruptHandler( appINTERRUPT_UART, prvProcessUartInt );
{
vPortSetInterruptHandler( portINTERRUPT_UART, prvProcessUartInt );
pCellularCommContext->commReceiveCallbackThread = pCellularCommContext->commReceiveCallbackThread =
CreateThread( NULL, 0, prvCellularCommReceiveCBThreadFunc, hComm, 0, NULL ); CreateThread( NULL, 0, prvCellularCommReceiveCBThreadFunc, hComm, 0, NULL );
@ -653,16 +434,6 @@ static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiv
} }
pCellularCommContext->commReceiveCallbackThread = NULL; pCellularCommContext->commReceiveCallbackThread = NULL;
/* Wait for the commTaskThreadStarted exit. */
( void ) prvCleanCommTaskThread( pCellularCommContext );
/* Clean the rxEvent mutex. */
if( pvRxEventMutex != NULL )
{
CloseHandle( pvRxEventMutex );
pvRxEventMutex = NULL;
}
} }
return commIntRet; return commIntRet;
@ -731,16 +502,6 @@ static CellularCommInterfaceError_t prvCommIntfClose( CellularCommInterfaceHandl
pCellularCommContext->commReceiveCallbackThread = NULL; pCellularCommContext->commReceiveCallbackThread = NULL;
/* Clean the commTaskThread. */
( void ) prvCleanCommTaskThread( pCellularCommContext );
/* Clean the rxEvent mutex. */
if( pvRxEventMutex != NULL )
{
CloseHandle( pvRxEventMutex );
pvRxEventMutex = NULL;
}
/* clean the data structure. */ /* clean the data structure. */
pCellularCommContext->commStatus &= ~( CELLULAR_COMM_OPEN_BIT ); pCellularCommContext->commStatus &= ~( CELLULAR_COMM_OPEN_BIT );
} }

@ -1 +1 @@
Subproject commit 4d4f8d0d50bedc37e1d07c96aded7d2bc20f0d6c Subproject commit 29b202a41e0e2810272b5765805d9fa4af247736

@ -5,7 +5,7 @@ license: "MIT"
dependencies: dependencies:
- name: "FreeRTOS-Kernel" - name: "FreeRTOS-Kernel"
version: "4d4f8d0d5" version: "29b202a41"
repository: repository:
type: "git" type: "git"
url: "https://github.com/FreeRTOS/FreeRTOS-Kernel.git" url: "https://github.com/FreeRTOS/FreeRTOS-Kernel.git"

Loading…
Cancel
Save