From 63f3f77552a2e19f690733c3ca52ba752768268e Mon Sep 17 00:00:00 2001 From: skarg Date: Fri, 28 Nov 2008 13:37:42 +0000 Subject: [PATCH] Modified the PIC port MS/TP RS-485 handling to use an interrupt safe FIFO library (untested). --- bacnet-stack/include/fifo.h | 5 ++ bacnet-stack/ports/pic18f6720/dlmstp.c | 16 ++-- bacnet-stack/ports/pic18f6720/rs485.c | 111 ++++++++----------------- bacnet-stack/ports/pic18f6720/rs485.h | 17 +--- bacnet-stack/src/fifo.c | 39 +++++++++ 5 files changed, 90 insertions(+), 98 deletions(-) diff --git a/bacnet-stack/include/fifo.h b/bacnet-stack/include/fifo.h index 184c9b1c..2431c101 100755 --- a/bacnet-stack/include/fifo.h +++ b/bacnet-stack/include/fifo.h @@ -70,6 +70,11 @@ bool FIFO_Put( FIFO_BUFFER * b, uint8_t data_byte); +bool FIFO_Add( + FIFO_BUFFER * b, + uint8_t *data_bytes, + unsigned count); + /* note: buffer_len must be a power of two */ void FIFO_Init( FIFO_BUFFER * b, diff --git a/bacnet-stack/ports/pic18f6720/dlmstp.c b/bacnet-stack/ports/pic18f6720/dlmstp.c index f7bdbad4..d9cefce9 100644 --- a/bacnet-stack/ports/pic18f6720/dlmstp.c +++ b/bacnet-stack/ports/pic18f6720/dlmstp.c @@ -79,7 +79,7 @@ void dlmstp_init( MSTP_Init(&MSTP_Port); /* FIXME: implement your data storage */ data = 64; /* I2C_Read_Byte( - EEPROM_DEVICE_ADDRESS, + EEPROM_DEVICE_ADDRESS, EEPROM_MSTP_MAC_ADDR); */ if (data <= 127) MSTP_Port.This_Station = data; @@ -87,7 +87,7 @@ void dlmstp_init( dlmstp_set_my_address(DEFAULT_MAC_ADDRESS); /* FIXME: implement your data storage */ data = 127; /* I2C_Read_Byte( - EEPROM_DEVICE_ADDRESS, + EEPROM_DEVICE_ADDRESS, EEPROM_MSTP_MAX_MASTER_ADDR); */ if ((data <= 127) && (data >= MSTP_Port.This_Station)) MSTP_Port.Nmax_master = data; @@ -96,7 +96,7 @@ void dlmstp_init( /* FIXME: implement your data storage */ data = 1; /* I2C_Read_Byte( - EEPROM_DEVICE_ADDRESS, + EEPROM_DEVICE_ADDRESS, EEPROM_MSTP_MAX_INFO_FRAMES_ADDR); */ if (data >= 1) MSTP_Port.Nmax_info_frames = data; @@ -155,7 +155,7 @@ int dlmstp_send_pdu( void dlmstp_task( void) { - uint8_t bytes_remaining; + bool bytes_remaining; bool received_frame; /* only do receive state machine while we don't have a frame */ @@ -234,7 +234,7 @@ void dlmstp_set_my_address( MSTP_Port.This_Station = mac_address; /* FIXME: implement your data storage */ /* I2C_Write_Byte( - EEPROM_DEVICE_ADDRESS, + EEPROM_DEVICE_ADDRESS, mac_address, EEPROM_MSTP_MAC_ADDR); */ if (mac_address > MSTP_Port.Nmax_master) @@ -263,8 +263,8 @@ void dlmstp_set_max_info_frames( if (max_info_frames >= 1) { MSTP_Port.Nmax_info_frames = max_info_frames; /* FIXME: implement your data storage */ - /* I2C_Write_Byte( - EEPROM_DEVICE_ADDRESS, + /* I2C_Write_Byte( + EEPROM_DEVICE_ADDRESS, (uint8_t)max_info_frames, EEPROM_MSTP_MAX_INFO_FRAMES_ADDR); */ } @@ -291,7 +291,7 @@ void dlmstp_set_max_master( MSTP_Port.Nmax_master = max_master; /* FIXME: implement your data storage */ /* I2C_Write_Byte( - EEPROM_DEVICE_ADDRESS, + EEPROM_DEVICE_ADDRESS, max_master, EEPROM_MSTP_MAX_MASTER_ADDR); */ } diff --git a/bacnet-stack/ports/pic18f6720/rs485.c b/bacnet-stack/ports/pic18f6720/rs485.c index d70c484f..646833d1 100644 --- a/bacnet-stack/ports/pic18f6720/rs485.c +++ b/bacnet-stack/ports/pic18f6720/rs485.c @@ -33,6 +33,7 @@ #include "hardware.h" #include "mstp.h" #include "rs485.h" +#include "fifo.h" /* public port info */ extern volatile struct mstp_port_struct_t MSTP_Port; @@ -40,16 +41,14 @@ extern volatile struct mstp_port_struct_t MSTP_Port; /* the baud rate is adjustable */ uint32_t RS485_Baud_Rate = 38400; -/* the ISR and other use this for status and control */ -COMSTAT RS485_Comstat; - /*#pragma udata MSTPPortData */ -/* the buffer for receiving characters */ -volatile uint8_t RS485_Rx_Buffer[MAX_MPDU]; - -/* UART transmission buffer and index */ -volatile uint8_t RS485_Tx_Buffer[MAX_MPDU]; +/* the buffer for receiving data (size must be a power of 2) */ +volatile uint8_t RS485_Rx_Buffer[128]; +FIFO_BUFFER FIFO_Rx; +/* the buffer for sending data (size must be a power of 2) */ +volatile uint8_t RS485_Tx_Buffer[128]; +FIFO_BUFFER FIFO_Tx; /**************************************************************************** * DESCRIPTION: Transmits a frame using the UART @@ -68,12 +67,8 @@ void RS485_Send_Frame( if (!buffer) return; - /* bounds check */ - if (nbytes >= sizeof(RS485_Tx_Buffer)) - return; - - /* buffer is full. Wait for ISR to transmit. */ - while (RS485_Comstat.Tx_Bytes) { + while (!Empty(&FIFO_Tx)) { + /* buffer is not empty. Wait for ISR to transmit. */ }; /* wait 40 bit times since reception */ @@ -85,18 +80,10 @@ void RS485_Send_Frame( turnaround_time = 1; while (mstp_port->SilenceTimer < turnaround_time) { + /* The line has not been silent long enough, so wait. */ }; - RS485_Comstat.TxHead = 0; - memcpy((void *) &RS485_Tx_Buffer[0], (void *) buffer, nbytes); -#if 0 - for (i = 0; i < nbytes; i++) { - /* put the data into the buffer */ - RS485_Tx_Buffer[i] = *buffer; - buffer++; - } -#endif - RS485_Comstat.Tx_Bytes = nbytes; + FIFO_Add(&FIFO_Tx, buffer, nbytes); /* disable the receiver */ PIE3bits.RC2IE = 0; RCSTA2bits.CREN = 0; @@ -106,7 +93,7 @@ void RS485_Send_Frame( /* enable the transmitter */ TXSTA2bits.TXEN = 1; PIE3bits.TX2IE = 1; - /* per MSTP spec, sort of */ + /* reset the silence timer per MSTP spec, sort of */ mstp_port->SilenceTimer = 0; return; @@ -118,29 +105,16 @@ void RS485_Send_Frame( * ALGORITHM: none * NOTES: none *****************************************************************************/ -uint8_t RS485_Check_UART_Data( +bool RS485_Check_UART_Data( volatile struct mstp_port_struct_t * mstp_port) { /* check for data */ - if (RS485_Comstat.Rx_Bytes) { - mstp_port->DataRegister = RS485_Rx_Buffer[RS485_Comstat.RxTail]; - if (RS485_Comstat.RxTail >= (sizeof(RS485_Rx_Buffer) - 1)) - RS485_Comstat.RxTail = 0; - else - RS485_Comstat.RxTail++; - /* FIXME: disable interrupts around Rx_Bytes */ - RS485_Comstat.Rx_Bytes--; - /* errors? let the state machine know */ - if (RS485_Comstat.Rx_Bufferoverrun) { - RS485_Comstat.Rx_Bufferoverrun = FALSE; - mstp_port->ReceiveError = TRUE; - } - /* We read a good byte */ - else - mstp_port->DataAvailable = TRUE; + if (!FIFO_Empty(&FIFO_Rx)) { + mstp_port->DataRegister = FIFO_Get(&FIFO_Rx); + mstp_port->DataAvailable = TRUE; } - return RS485_Comstat.Rx_Bytes; + return (!FIFO_Empty(&FIFO_Rx)); } /* ************************************************************************* @@ -155,25 +129,17 @@ uint8_t RS485_Check_UART_Data( void RS485_Interrupt_Rx( void) { - char dummy; + uint8_t data_byte; if ((RCSTA2bits.FERR) || (RCSTA2bits.OERR)) { /* Clear the error */ RCSTA2bits.CREN = 0; RCSTA2bits.CREN = 1; - RS485_Comstat.Rx_Bufferoverrun = TRUE; - dummy = RCREG2; - } else if (RS485_Comstat.Rx_Bytes < sizeof(RS485_Rx_Buffer)) { - RS485_Rx_Buffer[RS485_Comstat.RxHead] = RCREG2; - if (RS485_Comstat.RxHead >= (sizeof(RS485_Rx_Buffer) - 1)) - RS485_Comstat.RxHead = 0; - else - RS485_Comstat.RxHead++; - RS485_Comstat.Rx_Bytes++; + /* FIXME: flag the MS/TP state machine on buffer overrun */ + data_byte = RCREG2; } else { - RS485_Comstat.Rx_Bufferoverrun = TRUE; - dummy = RCREG2; - (void) dummy; + data_byte = RCREG2; + FIFO_Put(&FIFO_Rx, data_byte); } } @@ -189,13 +155,8 @@ void RS485_Interrupt_Rx( void RS485_Interrupt_Tx( void) { - if (RS485_Comstat.Tx_Bytes) { - /* Get the data byte */ - TXREG2 = RS485_Tx_Buffer[RS485_Comstat.TxHead]; - /* point to the next byte */ - RS485_Comstat.TxHead++; - /* reduce the buffer size */ - RS485_Comstat.Tx_Bytes--; + if (!FIFO_Empty(&FIFO_Tx)) { + TXREG2 = FIFO_Get(&FIFO_Tx); } else { /* wait for the USART to be empty */ while (!TXSTA2bits.TRMT); @@ -204,8 +165,7 @@ void RS485_Interrupt_Tx( /* enable the receiver */ RS485_TX_ENABLE = 0; RS485_RX_DISABLE = 0; - /* FIXME: might not be necessary - */ + /* enable the this interrupt */ PIE3bits.RC2IE = 1; RCSTA2bits.CREN = 1; } @@ -251,7 +211,7 @@ bool RS485_Set_Baud_Rate( if (valid) { /* FIXME: store the baud rate */ /* I2C_Write_Block( - EEPROM_DEVICE_ADDRESS, + EEPROM_DEVICE_ADDRESS, (char *)&RS485_Baud_Rate, sizeof(RS485_Baud_Rate), EEPROM_MSTP_BAUD_RATE_ADDR); */ @@ -355,6 +315,12 @@ void RS485_Disable_Port( PIE3 &= 0xCF; /* Disable both interrupts */ } +/**************************************************************************** +* DESCRIPTION: Reinitializes the port +* RETURN: none +* ALGORITHM: none +* NOTES: none +*****************************************************************************/ void RS485_Reinit( void) { @@ -371,17 +337,12 @@ void RS485_Initialize( void) { /* Init the Rs485 buffers */ - RS485_Comstat.RxHead = 0; - RS485_Comstat.RxTail = 0; - RS485_Comstat.Rx_Bytes = 0; - RS485_Comstat.Rx_Bufferoverrun = FALSE; - RS485_Comstat.TxHead = 0; - RS485_Comstat.TxTail = 0; - RS485_Comstat.Tx_Bytes = 0; + FIFO_Init(&FIFO_Rx, RS485_Rx_Buffer, sizeof(RS485_Rx_Buffer)); + FIFO_Init(&FIFO_Tx, RS485_Tx_Buffer, sizeof(RS485_Tx_Buffer)); - /* FIXME: read the data from storage */ + /* FIXME: read the stored baud rate */ /* I2C_Read_Block( - EEPROM_DEVICE_ADDRESS, + EEPROM_DEVICE_ADDRESS, (char *)&RS485_Baud_Rate, sizeof(RS485_Baud_Rate), EEPROM_MSTP_BAUD_RATE_ADDR); */ diff --git a/bacnet-stack/ports/pic18f6720/rs485.h b/bacnet-stack/ports/pic18f6720/rs485.h index f5444233..f0827deb 100644 --- a/bacnet-stack/ports/pic18f6720/rs485.h +++ b/bacnet-stack/ports/pic18f6720/rs485.h @@ -39,20 +39,6 @@ #include #include "mstp.h" -typedef struct { - uint8_t RxHead; - uint8_t RxTail; - uint8_t Rx_Bytes; - uint8_t TxHead; - uint8_t TxTail; - uint8_t Tx_Bytes; - uint8_t Rx_Bufferoverrun:1; - uint8_t Tx_Bufferoverrun:1; -} COMSTAT; - -extern COMSTAT RS485_Comstat; -extern volatile uint8_t RS485_Rx_Buffer[MAX_MPDU]; -extern volatile uint8_t RS485_Tx_Buffer[MAX_MPDU]; extern uint32_t RS485_Baud_Rate; @@ -73,7 +59,8 @@ extern "C" { uint8_t * buffer, /* frame to send (up to 501 bytes of data) */ uint16_t nbytes); /* number of bytes of data (up to 501) */ - uint8_t RS485_Check_UART_Data( + /* returns true if there is more data waiting */ + bool RS485_Check_UART_Data( volatile struct mstp_port_struct_t *mstp_port); /* port specific data */ void RS485_Interrupt_Rx( diff --git a/bacnet-stack/src/fifo.c b/bacnet-stack/src/fifo.c index 0c124127..3e3e216b 100755 --- a/bacnet-stack/src/fifo.c +++ b/bacnet-stack/src/fifo.c @@ -65,6 +65,19 @@ static bool FIFO_Full ( return (b ? (FIFO_Count(b) == b->buffer_len) : true); } +/**************************************************************************** +* DESCRIPTION: Tests to see if space is available +* RETURN: true if the number of bytes is available +* ALGORITHM: none +* NOTES: none +*****************************************************************************/ +static bool FIFO_Available ( + FIFO_BUFFER const *b, + unsigned count) +{ + return (b ? (count < (b->buffer_len - FIFO_Count(b))) : false); +} + /**************************************************************************** * DESCRIPTION: Returns the empty/full status of the ring buffer * RETURN: true if the ring buffer is empty, false if it is not. @@ -135,6 +148,32 @@ bool FIFO_Put( return status; } +/**************************************************************************** +* DESCRIPTION: Adds one or more elements of data to the FIFO +* RETURN: true if space available and added, false if not added +* ALGORITHM: none +* NOTES: none +*****************************************************************************/ +bool FIFO_Add( + FIFO_BUFFER * b, + uint8_t *data_bytes, + unsigned count) +{ + bool status = false; /* return value */ + + /* limit the ring to prevent overwriting */ + if (FIFO_Available (b, count)) { + while (count) { + b->buffer[b->head % b->buffer_len] = data_byte; + b->head++; + count--; + } + status = true; + } + + return status; +} + /**************************************************************************** * DESCRIPTION: Configures the ring buffer * RETURN: none