Rewrote MS/TP to minimize memory usage. Compiles, but untested.
This commit is contained in:
@@ -20,7 +20,6 @@ CSRC = main.c \
|
||||
../../npdu.c \
|
||||
../../bacint.c \
|
||||
../../bacaddr.c \
|
||||
../../mstp.c \
|
||||
../../crc.c
|
||||
|
||||
DEMOSRC = h_rp.c \
|
||||
|
||||
+1090
-231
File diff suppressed because it is too large
Load Diff
@@ -117,7 +117,7 @@ int main(void)
|
||||
task_milliseconds();
|
||||
/* other tasks */
|
||||
/* BACnet handling */
|
||||
pdu_len = datalink_receive(&src, &PDUBuffer[0], MAX_MPDU, 0);
|
||||
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
|
||||
if (pdu_len) {
|
||||
//npdu_handler(&src, &PDUBuffer[0], pdu_len);
|
||||
}
|
||||
|
||||
@@ -35,10 +35,23 @@
|
||||
|
||||
/* This file has been customized for use with ATMEGA168 */
|
||||
#include "hardware.h"
|
||||
#include "timer.h"
|
||||
|
||||
/* baud rate */
|
||||
static uint32_t RS485_Baud = 38400;
|
||||
|
||||
/* The minimum time after the end of the stop bit of the final octet of a */
|
||||
/* received frame before a node may enable its EIA-485 driver: 40 bit times. */
|
||||
/* At 9600 baud, 40 bit times would be about 4.166 milliseconds */
|
||||
/* At 19200 baud, 40 bit times would be about 2.083 milliseconds */
|
||||
/* At 38400 baud, 40 bit times would be about 1.041 milliseconds */
|
||||
/* At 57600 baud, 40 bit times would be about 0.694 milliseconds */
|
||||
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
|
||||
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
|
||||
/* 40 bits is 4 octets including a start and stop bit with each octet */
|
||||
#define Tturnaround (40UL)
|
||||
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/RS485_Baud; */
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||
* receive mode.
|
||||
@@ -61,15 +74,13 @@ void RS485_Initialize(void)
|
||||
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
|
||||
/* Clear Power Reduction USART0 */
|
||||
BIT_CLEAR(PRR,PRUSART0);
|
||||
/* Use port PD2 for RTS - enable and disable of Transceiver Tx/Rx */
|
||||
/* Set port bit as Output */
|
||||
BIT_SET(DDRD,DDD2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void RS485_Cleanup(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
@@ -83,7 +94,7 @@ uint32_t RS485_Get_Baud_Rate(void)
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: none
|
||||
* RETURN: true if valid baud rate
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
@@ -113,23 +124,50 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
|
||||
return valid;
|
||||
}
|
||||
|
||||
/* Transmits a Frame on the wire */
|
||||
void RS485_Send_Frame(
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
|
||||
uint16_t nbytes) /* number of bytes of data (up to 501) */
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Turnaround_Delay(void)
|
||||
{
|
||||
uint8_t turnaround_time;
|
||||
uint16_t turnaround_time;
|
||||
|
||||
/* delay after reception before trasmitting - per MS/TP spec */
|
||||
/* wait a minimum 40 bit times since reception */
|
||||
/* at least 1 ms for errors: rounding, clock tick */
|
||||
turnaround_time = 1 + ((Tturnaround*1000UL)/RS485_Baud);
|
||||
while (Timer_Silence() < turnaround_time) {
|
||||
/* do nothing - wait for timer to increment */
|
||||
};
|
||||
}
|
||||
|
||||
/* delay after reception - per MS/TP spec */
|
||||
if (mstp_port) {
|
||||
/* wait a minimum 40 bit times since reception */
|
||||
/* at least 1 ms for errors: rounding, clock tick */
|
||||
turnaround_time = 1 + ((Tturnaround*1000UL)/RS485_Baud);
|
||||
while (mstp_port->SilenceTimer() < turnaround_time) {
|
||||
/* do nothing - wait for timer to increment */
|
||||
};
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Enable or disable the transmitter
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Transmitter_Enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
BIT_SET(PORTD,PD2);
|
||||
} else {
|
||||
BIT_CLEAR(PORTD,PD2);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Send some data and wait until it is sent
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint8_t nbytes) /* number of bytes of data */
|
||||
{
|
||||
while (nbytes) {
|
||||
while (!BIT_CHECK(UCSR0A,UDRE0)) {
|
||||
/* do nothing - wait until Tx buffer is empty */
|
||||
@@ -142,34 +180,53 @@ void RS485_Send_Frame(
|
||||
/* do nothing - wait until the entire frame in the
|
||||
Transmit Shift Register has been shifted out */
|
||||
}
|
||||
/* per MSTP spec */
|
||||
if (mstp_port) {
|
||||
mstp_port->SilenceTimerReset();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* called by timer, interrupt(?) or other thread */
|
||||
void RS485_Check_UART_Data(struct mstp_port_struct_t *mstp_port)
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if a framing or overrun error is present
|
||||
* RETURN: true if error
|
||||
* ALGORITHM: none
|
||||
* NOTES: Clears any error flags.
|
||||
*****************************************************************************/
|
||||
bool RS485_ReceiveError(void)
|
||||
{
|
||||
if (mstp_port->ReceiveError == true) {
|
||||
/* wait for state machine to clear this */
|
||||
}
|
||||
/* wait for state machine to read from the DataRegister */
|
||||
else if (mstp_port->DataAvailable == false) {
|
||||
/* check for error */
|
||||
if (BIT_CHECK(UCSR0A,FE0)) {
|
||||
mstp_port->ReceiveError = true;
|
||||
}
|
||||
bool uart_error = false;
|
||||
uint8_t dummy_data;
|
||||
|
||||
if (BIT_CHECK(UCSR0A,DOR0)) {
|
||||
mstp_port->ReceiveError = true;
|
||||
}
|
||||
/* check for data */
|
||||
if (BIT_CHECK(UCSR0A,RXC0)) {
|
||||
mstp_port->DataRegister = UDR0;
|
||||
mstp_port->DataAvailable = true;
|
||||
/* check for framing error */
|
||||
if (BIT_CHECK(UCSR0A,FE0)) {
|
||||
uart_error = true;
|
||||
}
|
||||
/* check for overrun error */
|
||||
if (BIT_CHECK(UCSR0A,DOR0)) {
|
||||
uart_error = true;
|
||||
}
|
||||
/* flush the receive buffer */
|
||||
if (uart_error) {
|
||||
while (BIT_CHECK(UCSR0A,RXC0)) {
|
||||
dummy_data = UDR0;
|
||||
}
|
||||
}
|
||||
|
||||
return uart_error;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if data is available
|
||||
* RETURN: true if data is available, with the data in the parameter set
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_DataAvailable(uint8_t *data)
|
||||
{
|
||||
bool uart_data = false;
|
||||
|
||||
/* check for data */
|
||||
if (BIT_CHECK(UCSR0A,RXC0)) {
|
||||
*data = UDR0;
|
||||
uart_data = true;
|
||||
}
|
||||
|
||||
return uart_data;
|
||||
}
|
||||
|
||||
@@ -1,33 +1,42 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2004 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307
|
||||
USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef RS485_H
|
||||
#define RS485_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mstp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -35,14 +44,17 @@ extern "C" {
|
||||
|
||||
void RS485_Initialize(void);
|
||||
|
||||
void RS485_Send_Frame(
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
|
||||
uint16_t nbytes); /* number of bytes of data (up to 501) */
|
||||
void RS485_Transmitter_Enable(bool enable);
|
||||
|
||||
uint8_t RS485_Check_UART_Data(
|
||||
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
|
||||
/* NOTE: Only able to send up to 255 bytes at a time */
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint8_t nbytes); /* number of bytes of data */
|
||||
|
||||
bool RS485_ReceiveError(void);
|
||||
bool RS485_DataAvailable(uint8_t *data);
|
||||
|
||||
void RS485_Turnaround_Delay(void);
|
||||
uint32_t RS485_Get_Baud_Rate(void);
|
||||
bool RS485_Set_Baud_Rate(uint32_t baud);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user