mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-08-06 09:39:44 +08:00
Update cellular comm interface to generate interrupt from windows thread (#1221)
* Make use of vPortGenerateSimulatedInterruptFromWindowsThread to generate interrupt from windows thread
This commit is contained in:
@ -48,37 +48,23 @@
|
||||
#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 CELLULAR_COMM_PATH "\\\\.\\"CELLULAR_COMM_INTERFACE_PORT
|
||||
|
||||
/* Define the simulated UART interrupt number. */
|
||||
#define portINTERRUPT_UART ( 2UL )
|
||||
#define appINTERRUPT_UART portINTERRUPT_APPLICATION_DEFINED_START
|
||||
|
||||
/* Define the read write buffer size. */
|
||||
#define COMM_TX_BUFFER_SIZE ( 8192 )
|
||||
#define COMM_RX_BUFFER_SIZE ( 8192 )
|
||||
#define COMM_TX_BUFFER_SIZE ( 8192 )
|
||||
#define COMM_RX_BUFFER_SIZE ( 8192 )
|
||||
|
||||
/* Receive thread timeout in ms. */
|
||||
#define COMM_RECV_THREAD_TIMEOUT ( 5000 )
|
||||
#define COMM_RECV_THREAD_TIMEOUT ( 5000 )
|
||||
|
||||
/* Write operation timeout in ms. */
|
||||
#define COMM_WRITE_OPERATION_TIMEOUT ( 500 )
|
||||
#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 )
|
||||
#define CELLULAR_COMM_OPEN_BIT ( 0x01U )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
@ -91,7 +77,6 @@ typedef struct cellularCommContext
|
||||
HANDLE commFileHandle;
|
||||
CellularCommInterface_t * pCommInterface;
|
||||
bool commTaskThreadStarted;
|
||||
EventGroupHandle_t pCommTaskEvent;
|
||||
} cellularCommContext_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
@ -126,14 +111,6 @@ static CellularCommInterfaceError_t prvCommIntfReceive( CellularCommInterfaceHan
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@ -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
|
||||
* in CellularCommInterfaceError_t is returned.
|
||||
*/
|
||||
static CellularCommInterfaceError_t prvSetupCommSettings( 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 );
|
||||
static CellularCommInterfaceError_t prvSetupCommState( HANDLE hComm );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
@ -215,28 +165,14 @@ static cellularCommContext_t uxCellularCommContext =
|
||||
.commFileHandle = NULL,
|
||||
.pUserData = NULL,
|
||||
.commStatus = 0U,
|
||||
.commTaskThreadStarted = false,
|
||||
.pCommTaskEvent = NULL
|
||||
.commTaskThreadStarted = false
|
||||
};
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
cellularCommContext_t * pCellularCommContext = prvGetCellularCommContext();
|
||||
cellularCommContext_t * pCellularCommContext = &uxCellularCommContext;
|
||||
CellularCommInterfaceError_t callbackRet = IOT_COMM_INTERFACE_FAILURE;
|
||||
uint32_t retUartInt = pdTRUE;
|
||||
|
||||
@ -271,35 +207,35 @@ static DWORD WINAPI prvCellularCommReceiveCBThreadFunc( LPVOID pArgument )
|
||||
{
|
||||
retValue = ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
while( retValue == 0 )
|
||||
else
|
||||
{
|
||||
retWait = WaitCommEvent( hComm, &dwCommStatus, NULL );
|
||||
for( ; ; )
|
||||
{
|
||||
retWait = WaitCommEvent( hComm, &dwCommStatus, NULL );
|
||||
|
||||
if( ( retWait != FALSE ) && ( ( dwCommStatus & EV_RXCHAR ) != 0 ) )
|
||||
{
|
||||
if( ( dwCommStatus & EV_RXCHAR ) != 0 )
|
||||
if( ( retWait != FALSE ) && ( ( dwCommStatus & EV_RXCHAR ) != 0 ) )
|
||||
{
|
||||
WaitForSingleObject( pvRxEventMutex, INFINITE );
|
||||
rxEvent = true;
|
||||
ReleaseMutex( pvRxEventMutex );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ( GetLastError() == ERROR_INVALID_HANDLE ) || ( GetLastError() == ERROR_OPERATION_ABORTED ) )
|
||||
{
|
||||
/* COM port closed. */
|
||||
LogInfo( ( "Cellular COM port %p closed", hComm ) );
|
||||
/* Generate a simulated interrupt when data is received in the input buffer in driver.
|
||||
* The interrupt handler prvProcessUartInt() will be called in prvProcessSimulatedInterrupts().
|
||||
* This ensures no other task or ISR is running. */
|
||||
vPortGenerateSimulatedInterruptFromWindowsThread( appINTERRUPT_UART );
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "Cellular receiver thread wait comm error %p %d", hComm, GetLastError() ) );
|
||||
retValue = GetLastError();
|
||||
|
||||
if( ( retValue == ERROR_INVALID_HANDLE ) || ( retValue == ERROR_OPERATION_ABORTED ) )
|
||||
{
|
||||
/* COM port closed. */
|
||||
LogInfo( ( "Cellular COM port %p closed", hComm ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "Cellular receiver thread wait comm error %p %d", hComm, retValue ) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
retValue = GetLastError();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
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,
|
||||
void * pUserData,
|
||||
CellularCommInterfaceHandle_t * pCommInterfaceHandle )
|
||||
@ -514,7 +310,7 @@ static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiv
|
||||
CellularCommInterfaceError_t commIntRet = IOT_COMM_INTERFACE_SUCCESS;
|
||||
HANDLE hComm = ( HANDLE ) INVALID_HANDLE_VALUE;
|
||||
BOOL Status = TRUE;
|
||||
cellularCommContext_t * pCellularCommContext = prvGetCellularCommContext();
|
||||
cellularCommContext_t * pCellularCommContext = &uxCellularCommContext;
|
||||
DWORD dwRes = 0;
|
||||
|
||||
if( pCellularCommContext == NULL )
|
||||
@ -543,7 +339,7 @@ static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiv
|
||||
}
|
||||
|
||||
/* 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 ) );
|
||||
hComm = CreateFile( TEXT( CELLULAR_COMM_PATH ),
|
||||
@ -578,7 +374,7 @@ static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiv
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
commIntRet = prvSetupCommSettings( hComm );
|
||||
commIntRet = prvSetupCommState( hComm );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
pCellularCommContext->commReceiveCallback = receiveCallback;
|
||||
commIntRet = prvSetupCommTaskThread( pCellularCommContext );
|
||||
}
|
||||
|
||||
if( commIntRet == IOT_COMM_INTERFACE_SUCCESS )
|
||||
{
|
||||
vPortSetInterruptHandler( portINTERRUPT_UART, prvProcessUartInt );
|
||||
vPortSetInterruptHandler( appINTERRUPT_UART, prvProcessUartInt );
|
||||
pCellularCommContext->commReceiveCallbackThread =
|
||||
CreateThread( NULL, 0, prvCellularCommReceiveCBThreadFunc, hComm, 0, NULL );
|
||||
|
||||
@ -653,16 +434,6 @@ static CellularCommInterfaceError_t prvCommIntfOpen( CellularCommInterfaceReceiv
|
||||
}
|
||||
|
||||
pCellularCommContext->commReceiveCallbackThread = NULL;
|
||||
|
||||
/* Wait for the commTaskThreadStarted exit. */
|
||||
( void ) prvCleanCommTaskThread( pCellularCommContext );
|
||||
|
||||
/* Clean the rxEvent mutex. */
|
||||
if( pvRxEventMutex != NULL )
|
||||
{
|
||||
CloseHandle( pvRxEventMutex );
|
||||
pvRxEventMutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return commIntRet;
|
||||
@ -731,16 +502,6 @@ static CellularCommInterfaceError_t prvCommIntfClose( CellularCommInterfaceHandl
|
||||
|
||||
pCellularCommContext->commReceiveCallbackThread = NULL;
|
||||
|
||||
/* Clean the commTaskThread. */
|
||||
( void ) prvCleanCommTaskThread( pCellularCommContext );
|
||||
|
||||
/* Clean the rxEvent mutex. */
|
||||
if( pvRxEventMutex != NULL )
|
||||
{
|
||||
CloseHandle( pvRxEventMutex );
|
||||
pvRxEventMutex = NULL;
|
||||
}
|
||||
|
||||
/* clean the data structure. */
|
||||
pCellularCommContext->commStatus &= ~( CELLULAR_COMM_OPEN_BIT );
|
||||
}
|
||||
|
Reference in New Issue
Block a user