demo/PLATFORM
which hold the application and project files. In addition a subdirectory port
should be created for the port specific files. demo/PLATFORM/Makefile demo/PLATFORM/main.c demo/PLATFORM/port/portserial.c demo/PLATFORM/port/porttimer.c demo/PLATFORM/port/portother.c demo/PLATFORM/port/port.h
demo/BARE
as a starting point. Simply copy the directory and rename it to a name of your choice.port.h
and check the if the examples are already suitable for your platform. You must at least define the macros for enabling ENTER_CRITICAL_SECTION
and disabling EXIT_CRITICAL_SECTION
interrupts.
You should start by implementing the function xMBPortTimersInit( USHORT usTim1Timerout50us )
and vMBPortTimersEnable( )
. Test the function with the following sample code:
xMBPortTimersInit( 20 );
vMBPortTimersEnable( );
for( ;; );
pxMBPortCBTimerExpired
. The ISR should occur approx. 1ms after the call to vMBPortTimersEnable()
. You should also check that vMBPortTimersDisable( )
works as expected. usTim1Timerout50us
which corresponds to an one second timeout. See mbconfig.h
for the value of the timeout defined by MB_ASCII_TIMEOUT_SEC
.xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
and vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
. In addition you need to create two interrupt service routines for you communication devices. It is usually simpler to start with the receive interrupt.
Create an interrupt handler for the receive interrupt, set a breakpoint there and check if xMBPortSerialGetByte( CHAR * pucByte )
correctly returns the character. This can be tested by the following code:
/* Initialize COM device 0 with 38400 baud, 8 data bits and no parity. */ if( xMBPortSerialInit( 0, 38400, 8, MB_PAR_NONE ) == FALSE ) { fprintf(stderr, "error: com init failed"); } else { /* Enable the receiver. */ vMBPortSerialEnable( TRUE, FALSE ); /* Now block. Any character received should cause an interrupt now. */ for( ;; ); }
static void prvvUARTTxReadyISR( void ) { CHAR cByte; ( void )xMBPortSerialGetByte( &cByte ); /* Now cByte should contain the character received. */ }
Next you should check that the transmitter part is actually working as expected. Open a terminal program and simply call xMBPortSerialPutByte( 'a' )
in the transmit buffer empty ISR. If you use the sample code from below exactly 10 characters should be received.
/* Initialize COM device 0 with 38400 baud, 8 data bits and no parity. */ if( xMBPortSerialInit( 0, 38400, 8, MB_PAR_NONE ) == FALSE ) { fprintf(stderr, "error: com init failed"); } else { /* Enable the transmitter. */ vMBPortSerialEnable( FALSE, TRUE ); /* Now block. Any character received should cause an interrupt now. */ for( ;; ); }
static unsigned int uiCnt = 0; void prvvUARTTxReadyISR( void ) { if( uiCnt++ < 10 ) { ( void )xMBPortSerialPutByte( 'a' ); } else { vMBPortSerialEnable( FALSE, FALSE ); } }
If you are sure everything works correctly change the interrupt routines back to the examples shown in portserial.c
for( ;; ) { ( void )eMBPoll( ); }
xMBPortEventPost
to post an event to a queue. Note that this function will be called from an ISR so check your RTOS documentation for that.
xMBPortEventGet
to retrieve an event from that queue. The function eMBPoll
periodically calls it. The function should block until an event has been posted to the queue.
In addition the serial and timer interrupt function must be modified. Whenever the protocol handler callback functions pxMBFrameCBByteReceived
, pxMBFrameCBTransmitterEmpty
and pxMBPortCBTimerExpired
return TRUE
a context switch should be made after exiting the ISR because an event has been posted to the queue. Forgetting to do this will result in slow performance of the protocol stack.