From fdf387ed1d8f91631ffa21261b9cb4ca31c2e26e Mon Sep 17 00:00:00 2001 From: skarg Date: Sat, 10 Mar 2012 20:18:14 +0000 Subject: [PATCH] Changed MS/TP receive to read more bytes from UART queue if they are available during each cycle. This fixes high baud rate issues on slower processors if the main loop cycle time is not fast enough. --- bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c | 34 +++++---- bacnet-stack/ports/bdk-atxx4-mstp/rs485.c | 85 +++++++++++++++++++++- 2 files changed, 102 insertions(+), 17 deletions(-) diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c b/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c index b9aac6c9..722eb563 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/dlmstp.c @@ -370,7 +370,8 @@ static void MSTP_Send_Frame( { /* number of bytes of data (up to 501) */ uint8_t crc8 = 0xFF; /* used to calculate the crc value */ uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */ - uint8_t buffer[8]; /* stores the header and data crc */ + uint8_t buffer[8]; /* stores the header and header crc */ + uint8_t buffer_crc[2]; /* stores the data crc */ uint16_t i = 0; /* used to calculate CRC for data */ /* create the MS/TP header */ @@ -387,20 +388,24 @@ static void MSTP_Send_Frame( buffer[6] = LO_BYTE(data_len); crc8 = CRC_Calc_Header(buffer[6], crc8); buffer[7] = ~crc8; - rs485_turnaround_delay(); - rs485_rts_enable(true); - rs485_bytes_send(buffer, 8); - /* send any data */ if (data_len) { /* calculate CRC for any data */ for (i = 0; i < data_len; i++) { crc16 = CRC_Calc_Data(data[i], crc16); } crc16 = ~crc16; - buffer[0] = (crc16 & 0x00FF); - buffer[1] = ((crc16 & 0xFF00) >> 8); + buffer_crc[0] = (crc16 & 0x00FF); + buffer_crc[1] = ((crc16 & 0xFF00) >> 8); + } + /* on a slower processor, we don't want to calculate + the CRC after we send the header because there + will be a gap */ + rs485_turnaround_delay(); + rs485_rts_enable(true); + rs485_bytes_send(buffer, 8); + if (data_len) { rs485_bytes_send(data, data_len); - rs485_bytes_send(buffer, 2); + rs485_bytes_send(buffer_crc, 2); } rs485_rts_enable(false); } @@ -1211,11 +1216,15 @@ uint16_t dlmstp_receive( InputBuffer = pdu; InputBufferSize = max_pdu; } - /* only do receive state machine while we don't have a frame */ - if ((MSTP_Flag.ReceivedValidFrame == false) && + while ((MSTP_Flag.ReceivedValidFrame == false) && (MSTP_Flag.ReceivedValidFrameNotForUs == false) && (MSTP_Flag.ReceivedInvalidFrame == false)) { + /* only do receive state machine while we don't have a frame */ MSTP_Receive_Frame_FSM(); + /* process another byte, if available */ + if (!rs485_byte_available(NULL)) { + break; + } } if (MSTP_Flag.ReceivedValidFrameNotForUs) { MSTP_Flag.ReceivedValidFrameNotForUs = false; @@ -1246,11 +1255,6 @@ void dlmstp_set_mac_address( /* Master Nodes can only have address 0-127 */ if (mac_address <= 127) { This_Station = mac_address; - /* FIXME: implement your data storage */ - /* I2C_Write_Byte( - EEPROM_DEVICE_ADDRESS, - mac_address, - EEPROM_MSTP_MAC_ADDR); */ if (mac_address > Nmax_master) dlmstp_set_max_master(127); } diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/rs485.c b/bacnet-stack/ports/bdk-atxx4-mstp/rs485.c index d1c68b97..34a67d2c 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/rs485.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/rs485.c @@ -53,18 +53,33 @@ static FIFO_BUFFER Receive_Buffer; static struct etimer Silence_Timer; +/**************************************************************************** +* DESCRIPTION: Determines the amount of silence time elapsed +* RETURN: true if the amount of silence time has elapsed +* NOTES: none +*****************************************************************************/ bool rs485_silence_time_elapsed( uint16_t milliseconds) { return timer_elapsed_milliseconds_short(&Silence_Timer, milliseconds); } +/**************************************************************************** +* DESCRIPTION: Resets the silence timer +* RETURN: nothing +* NOTES: none +*****************************************************************************/ void rs485_silence_time_reset( void) { timer_elapsed_start(&Silence_Timer); } +/**************************************************************************** +* DESCRIPTION: Configures the RTS output +* RETURN: nothing +* NOTES: none +*****************************************************************************/ static void rs485_rts_init( void) { @@ -72,7 +87,11 @@ static void rs485_rts_init( BIT_SET(DDRD, DDD4); } -/* enable the transmit-enable line on the RS-485 transceiver */ +/**************************************************************************** +* DESCRIPTION: enable the transmit-enable line on the RS-485 transceiver +* RETURN: nothing +* NOTES: none +*****************************************************************************/ void rs485_rts_enable( bool enable) { @@ -83,12 +102,22 @@ void rs485_rts_enable( } } +/**************************************************************************** +* DESCRIPTION: enable the UART receiver and interrupt +* RETURN: nothing +* NOTES: none +*****************************************************************************/ static void rs485_receiver_enable( void) { UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0); } +/**************************************************************************** +* DESCRIPTION: delay for 40 bit times +* RETURN: nothing +* NOTES: none +*****************************************************************************/ void rs485_turnaround_delay( void) { @@ -114,6 +143,11 @@ void rs485_turnaround_delay( BIT_SET(UCSR0A, TXC0); } +/**************************************************************************** +* DESCRIPTION: Interrupt service routine for UART Receiver +* RETURN: nothing +* NOTES: none +*****************************************************************************/ ISR(USART0_RX_vect) { uint8_t data_byte; @@ -128,6 +162,11 @@ ISR(USART0_RX_vect) } } +/**************************************************************************** +* DESCRIPTION: Checks for data on the receive UART, and handles errors +* RETURN: none +* NOTES: none +*****************************************************************************/ bool rs485_byte_available( uint8_t * data_register) { @@ -135,19 +174,31 @@ bool rs485_byte_available( if (!FIFO_Empty(&Receive_Buffer)) { led_on_interval(LED_4, 1); - *data_register = FIFO_Get(&Receive_Buffer); + if (data_register) { + *data_register = FIFO_Get(&Receive_Buffer); + } data_available = true; } return data_available; } +/**************************************************************************** +* DESCRIPTION: returns an error indication if errors are enabled +* RETURN: nothing +* NOTES: none +*****************************************************************************/ bool rs485_receive_error( void) { return false; } +/**************************************************************************** +* DESCRIPTION: Transmits a frame using the UART +* RETURN: none +* NOTES: none +*****************************************************************************/ void rs485_bytes_send( uint8_t * buffer, /* data to send */ uint16_t nbytes) @@ -181,12 +232,22 @@ void rs485_bytes_send( return; } +/**************************************************************************** +* DESCRIPTION: Returns the baud rate that we are currently running at +* RETURN: baud rate in bps +* NOTES: none +*****************************************************************************/ uint32_t rs485_baud_rate( void) { return Baud_Rate; } +/**************************************************************************** +* DESCRIPTION: configure the UART baud rate +* RETURN: nothing +* NOTES: none +*****************************************************************************/ static void rs485_baud_rate_configure( void) { @@ -196,6 +257,11 @@ static void rs485_baud_rate_configure( UBRR0 = (F_CPU / (8UL * Baud_Rate)) - 1; } +/**************************************************************************** +* DESCRIPTION: set the UART baud rate to a standard value +* RETURN: true if the baud rate is valid +* NOTES: none +*****************************************************************************/ bool rs485_baud_rate_set( uint32_t baud) { @@ -223,6 +289,11 @@ bool rs485_baud_rate_set( return valid; } +/**************************************************************************** +* DESCRIPTION: initialize the hardware UART +* RETURN: nothing +* NOTES: none +*****************************************************************************/ static void rs485_usart_init( void) { @@ -243,6 +314,11 @@ static void rs485_usart_init( BIT_CLEAR(PRR, PRUSART0); } +/**************************************************************************** +* DESCRIPTION: read any non-volatile data +* RETURN: nothing +* NOTES: none +*****************************************************************************/ static void rs485_init_nvdata( void) { @@ -278,6 +354,11 @@ static void rs485_init_nvdata( rs485_baud_rate_configure(); } +/**************************************************************************** +* DESCRIPTION: initialize the module +* RETURN: nothing +* NOTES: none +*****************************************************************************/ void rs485_init( void) {