Below is a sample code that will appear in the next SourceBoost release. It shows how Novo can handle serial port. Please use it as a reference.
Don't forget to add
-swcs to linker command line
Regards,
Pavel
CODE
/********************************************************************
BoostC/BoostC++ sample code for
Microchip "PICDEM HPC Explorer Board"
Part Number: DM183022
Asynchronous UART and Novo RTOS
This code uses Novo RTOS and shows how to use interrupts
to receive and transmit serial data and how to safely share
this data with tasks.
Two tasks are implemented:
- one task runs every second and updates
port D connected to 8 LEDs
- another task waits for data from UART, than transforms
it and sends back
Receive buffer uses counting semaphore to indicate data
availability so that tasks waiting for data will yield
if data is not available.
BoostC/BoostC++ compilers are available from www.sourceboost.com
Author(s) Pavel Baranov
Copyright(C) 2009 Pavel Baranov
This code can be used free of charge in both commercial and
non-commercial projects as long as this copyright notice and
this entire statement is left unchanged. This software is provided
"as is", without warranty of any kind.
********************************************************************/
//System headers
#include <system.h>
#include <novocfg_pic18t3e5ts1.h>
#include <novo.h>
//Target PIC18F8722 configuration word
#pragma DATA _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVREN_OFF_4L & _XINST_OFF_4L
#pragma DATA _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H
#pragma DATA _CONFIG2L, _PWRT_OFF_2L & _BOREN_OFF_2L
#pragma DATA _CONFIG1H, _FCMEN_OFF_1H & _OSC_HS_1H
//Set clock frequency
#pragma CLOCK_FREQ 10000000
//Novo tasks
#define hTask0 0
#define hTask1 1
//Novo semaphores
#define hRxSem 0
//LED counter
static unsigned char led = 0;
//UART Tx and Rx data
#define TX_BUFFER_SIZE 8
#define RX_BUFFER_SIZE 16
static unsigned char TxBuffer[TX_BUFFER_SIZE], txHead, txTail;
static unsigned char RxBuffer[RX_BUFFER_SIZE], rxHead, rxTail;
//Port settings
#define USE_PORT_0
#if defined USE_PORT_0
#define TX_IRQ_FLAG pir1.TX1IF
#define RX_IRQ_FLAG pir1.RC1IF
#define TX_IRQ_ENABLE pie1.TX1IE
#define RX_IRQ_ENABLE pie1.RC1IE
#define TX_IRQ_PRIO ipr1.TXIP
#define RX_IRQ_PRIO ipr1.RCIP
#define TX_ENABLE txsta.TXEN
#define RX_ENABLE rcsta.CREN
#define UART_TX_END txsta.TRMT
#define UART_ENABLE rcsta.SPEN
#define UART_EVERFLOW_ERR rcsta.OERR
#define UART_FRAME_ERR rcsta.FERR
#define UART_BRG_HIGH_SPEED txsta.BRGH
#define UART_BRG spbrg
#define UART_TX_REG txreg1
#define UART_RX_REG rcreg1
#elif defined USE_PORT_1
#define TX_IRQ_FLAG pir3.TX2IF
#define RX_IRQ_FLAG pir3.RC2IF
#define TX_IRQ_ENABLE pie3.TX2IE
#define RX_IRQ_ENABLE pie3.RC2IE
#define TX_IRQ_PRIO ipr3.TXIP
#define RX_IRQ_PRIO ipr3.RCIP
#define TX_ENABLE txsta2.TXEN
#define RX_ENABLE rcsta2.CREN
#define UART_TX_END txsta2.TRMT
#define UART_ENABLE rcsta2.SPEN
#define UART_EVERFLOW_ERR rcsta2.OERR
#define UART_FRAME_ERR rcsta2.FERR
#define UART_BRG_HIGH_SPEED txsta2.BRGH
#define UART_BRG spbrg2
#define UART_TX_REG txreg2
#define UART_RX_REG rcreg2
#else
#error "Error: unsupported port selected"
#endif
//////////////////////////////////////////////
// High priority interrupt handles
// handles system time
//////////////////////////////////////////////
void interrupt( void )
{
//Handle timer0 interrupt
if( intcon.T0IF )
{
// update system time every 1s
static unsigned char nDivider = 0;
if( 39 == ++nDivider )
{
nDivider = 0;
SysTimerUpdate();
}
clear_bit( intcon, T0IF ); //clear timer 0 interrupt bit
}
}
//////////////////////////////////////////////
// Low priority interrupt handles
// handles UART send and receive
//////////////////////////////////////////////
void interrupt_low( void )
{
//Handle UART transmit
if( TX_IRQ_FLAG )
{
//Check if there is data in transmit buffer
if( txHead != txTail )
{
UART_TX_REG = TxBuffer[txTail++];
if( TX_BUFFER_SIZE == txTail )
txTail = 0;
}
else
{
//Nothing to send, disable Tx irq
//but only after the last bit from
//prev transmission is out
while( !UART_TX_END );
TX_ENABLE = 0;
}
}
//Handle UART receive
if( RX_IRQ_FLAG )
{
//Test for errors first
if( UART_EVERFLOW_ERR ) //overflow error
{
//read and discard incoming byte
unsigned char discard = UART_RX_REG;
}
else if( UART_FRAME_ERR ) //frame error
{
//restart Rx to clear this error
RX_ENABLE = 0;
RX_ENABLE = 1;
}
else
{
//Check if there is free space in receive buffer
BYTE cnt = SysReadSemaphore( hRxSem );
if( cnt < RX_BUFFER_SIZE )
{
//Write incoming byte into the buffer and increment Rx semaphore
RxBuffer[rxHead++] = UART_RX_REG;
if( RX_BUFFER_SIZE == rxHead )
rxHead = 0;
SysSignalSemaphoreIsr( hRxSem );
}
else
{
//Buffer overflow, the incoming byte will be lost
unsigned char discard = UART_RX_REG;
}
}
}
}
//////////////////////////////////////////////
//Receive one byte from serial port
//////////////////////////////////////////////
unsigned char Rx( void )
{
//Wait for serial data to come
Sys_WaitSemaphore( hRxSem, EVENT_NO_TIMEOUT );
//Read one byte from rx queue
SysCriticalSectionBegin();
unsigned char data = RxBuffer[rxTail++];
if( RX_BUFFER_SIZE == rxTail )
rxTail = 0;
SysCriticalSectionEnd();
return data;
}
//////////////////////////////////////////////
//Send one byte into serial port
//////////////////////////////////////////////
void Tx( unsigned char data )
{
//Put data into the rx queue
SysCriticalSectionBegin();
TxBuffer[txHead++] = data;
if( TX_BUFFER_SIZE == txHead )
txHead = 0;
TX_ENABLE = 1; //enable Tx
SysCriticalSectionEnd();
}
//////////////////////////////////////////////
//Send a string into serial port
//////////////////////////////////////////////
void Tx( char * text )
{
while( *text )
Tx( *text++ );
}
//////////////////////////////////////////////
// Task that processes UART data
//////////////////////////////////////////////
void Task0()
{
//Send out hello string (string should fit into the tx buffer)
Tx( "Ready..." );
//This tack will receive data, transform it and send back
while( 1 )
{
//Wait for serial data to come. This is a blocking
//call that will yield if no data is available
unsigned char data = Rx();
//If this is lover case character convert it to capital
if( data >= 'a' && data <= 'z' )
data -= 'a' - 'A';
//Send data back
Tx( data );
}
}
//////////////////////////////////////////////
// Task that every second flashes a LED
//////////////////////////////////////////////
void Task1()
{
//Update LEDs connected to port D every second
while( 1 )
{
latd = ++led;
Sys_Sleep( 1 );
}
}
//////////////////////////////////////////////
// Program entry point
//////////////////////////////////////////////
void main( void )
{
//Disable watchdog
wdtcon.SWDTEN = 0;
//Configure port A
trisa = 0x00;
//Configure port B
trisb = 0x00;
//Configure port C
trisc = 0x00;
//Configure port D
trisd = 0x00;
//Initialize port A
porta = 0x00;
//Initialize port B
portb = 0x00;
//Initialize port C
portc = 0x00;
//Initialize port D
portd = 0x00;
//Set Timer0 mode
set_bit( t0con, TMR0ON ); //enable timer0
clear_bit( t0con, T0CS ); //configure timer0 as a timer
//Set Timer0 resolution
set_bit( t0con, T08BIT ); //set timer0 8 bit wide
//Set prescaler assignment
clear_bit( t0con, PSA ); //prescaler is assigned
//Set prescaler rate
set_bit( t0con, T0PS2 ); //prescaler rate 1:256
set_bit( t0con, T0PS1 );
set_bit( t0con, T0PS0 );
//Set timer0 source edge selection
set_bit( t0con, T0SE ); //increment on high-to-low transition on RA4/T0CKI pin
//Configure serial port
RX_IRQ_PRIO = TX_IRQ_PRIO = 0; //use low priority interrupt
UART_BRG_HIGH_SPEED = 1; //high speed
UART_BRG = 64; //9600kbps/10Mhz
RX_IRQ_ENABLE = 1; //enable Rx irq
TX_IRQ_ENABLE = 1; //enable Tx irq
RX_ENABLE = 1; //enable continuous receive
UART_ENABLE = 1; //enable serial port
//Configure UART pins
#if defined USE_PORT_0
trisc.7 = 1;
trisc.6 = 0;
#elif defined USE_PORT_1
trisg.2 = 1;
trisg.1 = 0;
#endif
//Configure interrupts
rcon.IPEN = 1; //enable priority level interrupts
intcon.TMR0IE = 1; //enable timer 0 interrupt
intcon.GIEH = intcon.GIEL = 1; //Enable hign and low priority interruptr
//Initialize Novo RTOS
SysInit();
//Create Novo tasks
SysCreateTask( hTask0, 2, Task0 );
SysCreateTask( hTask1, 2, Task1 );
//Start Novo tasks
SysStartTask( hTask0 );
SysStartTask( hTask1 );
//Endless loop
while( 1 ) Sys_Yield();
}
// End of code