Tuesday, April 6, 2010

Embedded Device Drivers in FunkOS – Example

The following is an example of how to use the FunkOS UART driver on an ATMega328p, as requested in the comments of the previous post.  Using the newly-added UART driver for from FunkOS R3 as an example, this example demonstrates both  how to configure and initialize a device, as well as how to use it in a multithreaded environment.

#include "types.h"
#include "kernelcfg.h"
#include "driver.h"
#include "drvUART.h"
// Define the sizes of the UART TX and RX FIFOs 
#define UART_TX_SIZE        (64)
#define UART_RX_SIZE        (64)
// Define the UART TX and RX FIFOs
static UCHAR aucRxData[UART_RX_SIZE];
static UCHAR aucTxData[UART_TX_SIZE];
// Configure the UART's default driver state
static UART_DRIVER_STRUCT stUART = 
{
    {
        //--[Driver info]--------------------------------------------------------
    "UART0",             //*szName;                
    DRIVER_UNINIT,        //eState;                
    DRIVER_TYPE_UART,    //eType;                
    //--[Driver functions]---------------------------------------------------
    UART_Init,            //pfConstructor;
    UART_Start,            //pfDriverStart;
    UART_Stop,            //pfDriverStop;    
    UART_Control,        //pfControl;    
    UART_Read,            //pfDriverRead;    
    UART_Write,            //pfDriverWrite;
    // Do not initialize mutex
    },
    
    UART_TX_SIZE,    //ucTxSize;                        //!< Size of the TX Buffer
    0,                //UCHAR ucTxHead;                //!< Head index
    0,                //UCHAR ucTxTail;                //!< Tail index 
    
    UART_RX_SIZE,    //UCHAR ucRxSize;                //!< Size of the RX Buffer
    0,                //UCHAR ucRxHead;                //!< Head index
    0,                //UCHAR ucRxTail;                //!< Tail index
    
    0,                //BOOL bRxOverflow;                //!< Receive buffer overflow
    
    aucRxData,        //UCHAR *pucRxBuffer;            //!< Receive buffer pointer
    aucTxData,        //UCHAR *pucTxBuffer;            //!< Transmit buffer pointer
    
    57600            //!< Baud rate
};
static TASK_STRUCT stMyTask;
static UCHAR aucMyStack[128];
static TASK_STRUCT stIdleTask;
static UCHAR aucIdleStack[128];
void MyTask(void *this_);
void IdleTask(void *this_);
int main(void)
{
    Task_Init();                    // Initialize the kernel (must be first)
    Driver_Init(&stUART);            // Initialize the UART driver
    
    Task_CreateTask(    &stMyTask,    // Create the active task
                        "Task1",
                        aucMyStack,
                        128,
                        1,
                        MyTask);
    Task_CreateTask(    &stIdleTask, // Create the idle task
                        "Idle",
                        aucIdleStack,
                        128,
                        0,
                        IdleTask);
    // Add the active and idle threads to the scheduler
    Task_Add(&stMyTask);
    Task_Add(&stIdleTask);
    Task_Start(&stMyTask);
    Task_Start(&stIdleTask);
    // Start the kernel (program continues @ threads)
    Task_StartTasks();
}
//-------------------------------
// Active thread function
//-------------------------------
void MyTask(void *this_)
{
    USHORT usWritten;
    UCHAR aucData[16];
    int i;
    // Start the thread by starting the driver
    Driver_Start(&stUART);        
    {
        // Set the baudrate using the baudrate command
        ULONG ulData = 57600;
        Driver_Control(&stUART, CMD_SET_BAUDRATE, &ulData);
    }
    // Set the data to keep spamming to the UART (ABCDEFGHIJKL..)
    for (i = 0; i < 16; i++)
    {
        aucData[i] = 'A' + i;
    }
    aucData[15] = 0;
    // Keep writing the same string to the UART over and over again
    while(1)
    {
        usWritten = Driver_Write(&stUART, aucData, 16);    
        Task_Sleep(200);
    }
}
//-------------------------------
// Idle thread function
//-------------------------------
void IdleTask(void *this_)
{
    volatile int i = 0;
    while(1)
    {
        i++;
    }
}