Integrating HAL into an RTOS

In general, most OSs isolate the application from the hardware. Its device drivers use data structures to pass the data from applications to the hardware devices (called I/O structures). Also, the device drivers in most cases, apart from controlling the I/O on the hardware device, also perform tasks to pass the data to the upper layers of the OS.

Inserting HAL in those OS implies removing the hardware handling of an original device driver, and converting it into a mapping layer that connects the HAL driver to the rest of the OS. The mapping layer can be linked all together with the HAL device driver.

In an RTOS with a POSIX-compliant architecture, the HAL is integrated as shown in the following figure.

Figure 1. RTOS Interface Diagram



An LDD architecture always defines an Init() function. This function, apart from initializing the device, always receives a void pointer. This pointer is the OS I/O structure for a particular device. This structure is saved into HAL's LDD device structure. At the same time, an Init() returns a pointer to its own device structure that is meant to be saved in the I/O structure of the RTOS driver.

Init() function is also capable to allocate memory for the HAL device structure, and install an ISR into the OS.

LDD_TDeviceData* ETH1_Init(LDD_TUserData *UserDataPtr)

ETH1_TDeviceData *DeviceDataPrv;

/* Allocate internal device data structure */

/* {myMQX1 RTOS Adapter} Driver memory allocation: RTOS function call is defined by

myMQX1 RTOS Adapter property */

DeviceDataPrv = (ETH1_TDeviceData *)_mem_alloc_system(sizeof(ETH1_TDeviceData));

#if MQX1_CHECK_MEMORY_ALLOCATION_ERRORS

if (DeviceDataPrv == NULL) {

return (NULL);

#endif

DeviceDataPrv->UserDataPtr = UserDataPtr; /* Store the RTOS device structure */

. . .

/* {myMQX1 RTOS Adapter} Set new interrupt vector (function handler and ISR parameter) */

_int_install_isr(LDD_ivIndex_INT_ENET_Transmit,ETH1_InterruptTxFrame,

DeviceDataPrv);

. . .

return (LDD_TDeviceData*)DeviceDataPrv;

As mentioned earlier, the pointer returned by Init() should be stored somewhere in the OS so that the subsequent calls to the HAL driver can be completed.

Also, notice that in the installation function, the HAL data structure is passed to the ISR installation function of the particular RTOS. When an interrupt occurs, the RTOS is responsible of passing that pointer to the LDD ISR so that it completes its I/O processing:

void ETH1_InterruptRxFrame(void * _isrParameter ) {

/* {myMQX1 RTOS Adapter} ISR parameter is passed as parameter from RTOS interrupt

dispatcher */

ETH1_TDeviceData* DeviceDataPrv = (ETH1_TDeviceData*)_isrParameter;

uint16_t FragCount;

uint16_t Length;

while (ENET_PDD_GetInterruptFlags(ENET_BASE_PTR) & ENET_PDD_RX_FRAME_INT) {

ENET_PDD_ClearInterruptFlags(ENET_BASE_PTR, ENET_PDD_RX_FRAME_INT);

while (ETH1_RemoveRxFrame(DeviceDataPrv, &FragCount, &Length)) {

ETH1_OnFrameReceived(DeviceDataPrv->UserDataPtr, FragCount, Length);

}

}

return;

}

When the pointer is received, an LDD driver casts its own I/O data structure and performs the I/O.

Also, from code snipped above, it can be observed that one event is triggered when a frame is received: ETH1_OnFrameReceived(). In this call, the original RTOS I/O data structure is returned. This connects the LDD driver with the rest of the OS using the adaptation layer.