From 1b364d6df1636b880d80b2003d68e996ab79f203 Mon Sep 17 00:00:00 2001 From: skarg Date: Wed, 15 Aug 2007 00:12:19 +0000 Subject: [PATCH] Adding MS/TP demo for ATmega168. Not finished yet. --- bacnet-stack/ports/atmega168/Makefile | 83 ++++++++++++ bacnet-stack/ports/atmega168/avr035.h | 18 +++ bacnet-stack/ports/atmega168/bacnet.aps | 1 + bacnet-stack/ports/atmega168/hardware.h | 40 ++++++ bacnet-stack/ports/atmega168/main.c | 85 +++++++++++++ bacnet-stack/ports/atmega168/rs485.c | 160 ++++++++++++++++++++++++ bacnet-stack/ports/atmega168/rs485.h | 52 ++++++++ bacnet-stack/ports/atmega168/timer.c | 60 +++++++++ bacnet-stack/ports/atmega168/timer.h | 32 +++++ 9 files changed, 531 insertions(+) create mode 100644 bacnet-stack/ports/atmega168/Makefile create mode 100644 bacnet-stack/ports/atmega168/avr035.h create mode 100644 bacnet-stack/ports/atmega168/bacnet.aps create mode 100644 bacnet-stack/ports/atmega168/hardware.h create mode 100644 bacnet-stack/ports/atmega168/main.c create mode 100644 bacnet-stack/ports/atmega168/rs485.c create mode 100644 bacnet-stack/ports/atmega168/rs485.h create mode 100644 bacnet-stack/ports/atmega168/timer.c create mode 100644 bacnet-stack/ports/atmega168/timer.h diff --git a/bacnet-stack/ports/atmega168/Makefile b/bacnet-stack/ports/atmega168/Makefile new file mode 100644 index 00000000..e87f13a7 --- /dev/null +++ b/bacnet-stack/ports/atmega168/Makefile @@ -0,0 +1,83 @@ +############################################################################### +# Makefile for the project bacnet +############################################################################### + +## General Flags +PROJECT = bacnet +MCU = atmega168 +TARGET = bacnet.elf +CC = avr-gcc.exe + +## Options common to compile, link and assembly rules +COMMON = -mmcu=$(MCU) + +## Compile options common for all C compilation units. +CFLAGS = $(COMMON) +CFLAGS += -Wall -gdwarf-2 -O0 +CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d + +## Assembly specific flags +ASMFLAGS = $(COMMON) +ASMFLAGS += $(CFLAGS) +ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2 + +## Linker flags +LDFLAGS = $(COMMON) +LDFLAGS += + + +## Intel Hex file production flags +HEX_FLASH_FLAGS = -R .eeprom + +HEX_EEPROM_FLAGS = -j .eeprom +HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load" +HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings + + +## Include Directories +INCLUDES = -I"C:\code\bacnet-stack\ports\atmega168\..\.." + +## Objects that must be built in order to link +OBJECTS = main.o rs485.o timer.o + +## Objects explicitly added by the user +LINKONLYOBJECTS = + +## Build +all: $(TARGET) bacnet.hex bacnet.eep size + +## Compile +main.o: ../main.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +rs485.o: ../rs485.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +timer.o: ../timer.c + $(CC) $(INCLUDES) $(CFLAGS) -c $< + +##Link +$(TARGET): $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET) + +%.hex: $(TARGET) + avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@ + +%.eep: $(TARGET) + -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0 + +%.lss: $(TARGET) + avr-objdump -h -S $< > $@ + +size: ${TARGET} + @echo + @avr-size -C --mcu=${MCU} ${TARGET} + +## Clean target +.PHONY: clean +clean: + -rm -rf $(OBJECTS) bacnet.elf dep/* bacnet.hex bacnet.eep + +## Other dependencies +-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*) + diff --git a/bacnet-stack/ports/atmega168/avr035.h b/bacnet-stack/ports/atmega168/avr035.h new file mode 100644 index 00000000..0dd766ab --- /dev/null +++ b/bacnet-stack/ports/atmega168/avr035.h @@ -0,0 +1,18 @@ +#ifndef AVR035_H +#define AVR035_H + +/* from AVR035: Efficient C Coding for AVR */ + +/* a=register, b=bit number to act upon */ +#define BIT_SET(a,b) ((a) |= (1<<(b))) +#define BIT_CLEAR(a,b) ((a) &= ~(1<<(b))) +#define BIT_FLIP(a,b) ((a) ^= (1<<(b))) +#define BIT_CHECK(a,b) ((a) & (1<<(b))) + +/* x=target variable, y=mask */ +#define BITMASK_SET(x,y) ((x) |= (y)) +#define BITMASK_CLEAR(x,y) ((x) &= (~(y))) +#define BITMASK_FLIP(x,y) ((x) ^= (y)) +#define BITMASK_CHECK(x,y) ((x) & (y)) + +#endif diff --git a/bacnet-stack/ports/atmega168/bacnet.aps b/bacnet-stack/ports/atmega168/bacnet.aps new file mode 100644 index 00000000..4486921e --- /dev/null +++ b/bacnet-stack/ports/atmega168/bacnet.aps @@ -0,0 +1 @@ +13-Aug-2007 15:08:2714-Aug-2007 17:09:10013-Aug-2007 15:08:2744, 13, 0, 528AVR GCC241bacnet13-Aug-2007 15:11:0713-Aug-2007 15:11:07241013-Aug-2007 15:11:0744, 13, 0, 528AVR GCCdefault\bacnet.elfC:\code\bacnet-stack\ports\atmega168\falseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31AVR SimulatorAVR SimulatorATmega168.xmlAuto000main.crs485.ctimer.cavr035.hhardware.hrs485.hiocompat.htimer.hdefaultNOatmega168100bacnet.elfdefault\0..\..\-Wall -gdwarf-2 -DF_CPU=7372800UL -O0 -fsigned-chardefault1C:\WinAVR-20070525\bin\avr-gcc.exeC:\WinAVR-20070525\utils\bin\make.exe00000C:\WinAVR-20070525\avr\include\avr\eeprom.h100001C:\WinAVR-20070525\avr\include\avr\iomx8.h100002C:\WinAVR-20070525\examples\stdiodemo\uart.h100003C:\WinAVR-20070525\examples\stdiodemo\uart.c100004main.c100005timer.c259748 696 908 72020 45566 211 1235 650690 21428 696 588 7200 0268 696 428 7200 0444 272 1300 69850 14290 118 1092 52052 2 diff --git a/bacnet-stack/ports/atmega168/hardware.h b/bacnet-stack/ports/atmega168/hardware.h new file mode 100644 index 00000000..c4411c57 --- /dev/null +++ b/bacnet-stack/ports/atmega168/hardware.h @@ -0,0 +1,40 @@ +/************************************************************************** +* +* Copyright (C) 2007 Steve Karg +* +* 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. +* +*********************************************************************/ +#ifndef HARDWARE_H +#define HARDWARE_H + +#include +#include +#include "avr035.h" + +#if !defined(__AVR_ATmega168__) +#error Firmware is configured for ATmega168 only. +#endif + +/* The processor clock frequency */ +#define FREQ_CPU (7372800) + + +#endif diff --git a/bacnet-stack/ports/atmega168/main.c b/bacnet-stack/ports/atmega168/main.c new file mode 100644 index 00000000..29f8c54b --- /dev/null +++ b/bacnet-stack/ports/atmega168/main.c @@ -0,0 +1,85 @@ +/************************************************************************** +* +* Copyright (C) 2007 Steve Karg +* +* 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. +* +*********************************************************************/ + +#include +#include +#include "hardware.h" +#include "timer.h" +#include "rs485.h" + +/* For porting to IAR, see: + http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/ + +static uint16_t Transmit_Timer = 0; +#define MAX_FRAME 5 +static uint8_t Transmit_Frame[MAX_FRAME] = {0xAA, 0x55, 0x01, 0x45, 0xAB }; + +void init(void) +{ + + /* Initialize I/O ports */ + /* For Port DDRx (Data Direction) Input=1, Output=1 */ + /* For Port PORTx (Bit Value) TriState=0, High=1 */ + + DDRB = 0; + PORTB = 0; + DDRC = 0; + PORTC = 0; + DDRD = 0; + PORTD = 0; + + /* Configure the watchdog timer */ + + /* Configure USART */ + RS485_Set_Baud_Rate(38400); + RS485_Initialize(); + + /* Configure Timer0 for millisecond timer */ + timer_initialize(); +} + +void task_milliseconds(void) +{ + while (Timer_Milliseconds) { + Timer_Milliseconds--; + /* add other millisecond timer tasks here */ + Transmit_Timer++; + } +} + +int main(void) +{ + init(); + for (;;) { + task_milliseconds(); + /* other tasks */ + if (Transmit_Timer > 1000) { + Transmit_Timer = 0; + RS485_Send_Frame(NULL,Transmit_Frame, MAX_FRAME); + } + } + + return 0; +} diff --git a/bacnet-stack/ports/atmega168/rs485.c b/bacnet-stack/ports/atmega168/rs485.c new file mode 100644 index 00000000..4721717b --- /dev/null +++ b/bacnet-stack/ports/atmega168/rs485.c @@ -0,0 +1,160 @@ +/************************************************************************** +* +* Copyright (C) 2007 Steve Karg +* +* 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. +* +*********************************************************************/ + +/* The module handles sending data out the RS-485 port */ +/* and handles receiving data from the RS-485 port. */ +/* Customize this file for your specific hardware */ +#include +#include +#include +#include +#include +#include "mstp.h" + +/* This file has been customized for use with ATMEGA168 */ +#include "hardware.h" + +/* baud rate */ +static uint32_t RS485_Baud = 38400; + +/**************************************************************************** +* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in +* receive mode. +* RETURN: none +* ALGORITHM: none +* NOTES: none +*****************************************************************************/ +void RS485_Initialize(void) +{ + /* enable Transmit and Receive */ + UCSR0B = _BV(TXEN0) | _BV(RXEN0); + + /* Set frame format: 8data, 2stop bit */ + UCSR0C = _BV(USBS0) | _BV(UCSZ00); + + return; +} + +void RS485_Cleanup(void) +{ + +} + +/**************************************************************************** +* DESCRIPTION: Returns the baud rate that we are currently running at +* RETURN: none +* ALGORITHM: none +* NOTES: none +*****************************************************************************/ +uint32_t RS485_Get_Baud_Rate(void) +{ + return RS485_Baud; +} + +/**************************************************************************** +* DESCRIPTION: Sets the baud rate for the chip USART +* RETURN: none +* ALGORITHM: none +* NOTES: none +*****************************************************************************/ +bool RS485_Set_Baud_Rate(uint32_t baud) +{ + bool valid = true; + + switch (baud) { + case 9600: + case 19200: + case 38400: + case 57600: + case 76800: + case 115200: + RS485_Baud = baud; + /* 2x speed mode */ + BIT_SET(UCSR0A,U2X0); + /* configure baud rate */ + UBRR0 = (FREQ_CPU / (8UL * RS485_Baud)) - 1; + /* FIXME: store the baud rate */ + break; + default: + valid = false; + break; + } + + 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) */ +{ + uint8_t turnaround_time; + + /* delay after reception - per MS/TP spec */ + if (mstp_port) { + /* wait about 40 bit times since reception */ + turnaround_time = (40UL*1000UL)/RS485_Baud; + if (!turnaround_time) { + turnaround_time = 1; + } + while (mstp_port->SilenceTimer < turnaround_time) { + /* do nothing - wait for timer to increment */ + }; + } + while (nbytes) { + while (!BIT_CHECK(UCSR0A,UDRE0)) { + /* do nothing - wait until Tx buffer is empty */ + } + UDR0 = *buffer; + buffer++; + nbytes--; + /* per MSTP spec */ + if (mstp_port) { + mstp_port->SilenceTimer = 0; + } + } + while (!BIT_CHECK(UCSR0A,UDRE0)) { + /* do nothing - wait until Tx buffer is empty */ + } + + return; +} + +/* called by timer, interrupt(?) or other thread */ +void RS485_Check_UART_Data(struct mstp_port_struct_t *mstp_port) +{ + 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 data */ + if (!BIT_CHECK(UCSR0A,RXC0)) { + mstp_port->DataRegister = UDR0; + mstp_port->DataAvailable = true; + } + } +} diff --git a/bacnet-stack/ports/atmega168/rs485.h b/bacnet-stack/ports/atmega168/rs485.h new file mode 100644 index 00000000..acdde4a7 --- /dev/null +++ b/bacnet-stack/ports/atmega168/rs485.h @@ -0,0 +1,52 @@ +/************************************************************************** +* +* Copyright (C) 2007 Steve Karg +* +* 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. +* +*********************************************************************/ + +#ifndef RS485_H +#define RS485_H + +#include +#include "mstp.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + 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) */ + + uint8_t RS485_Check_UART_Data( + volatile struct mstp_port_struct_t *mstp_port); /* port specific data */ + + uint32_t RS485_Get_Baud_Rate(void); + bool RS485_Set_Baud_Rate(uint32_t baud); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif diff --git a/bacnet-stack/ports/atmega168/timer.c b/bacnet-stack/ports/atmega168/timer.c new file mode 100644 index 00000000..63469c54 --- /dev/null +++ b/bacnet-stack/ports/atmega168/timer.c @@ -0,0 +1,60 @@ +/************************************************************************** +* +* Copyright (C) 2007 Steve Karg +* +* 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. +* +*********************************************************************/ + +#include "hardware.h" + +/* Prescaling: 1, 8, 64, 256, 1024 */ +#define TIMER_1_PRESCALER 1 +/* Count: Timer counts up to 0xFFFF and then signals overflow */ +#define TIMER_1_TICKS (FREQ_CPU/TIMER_1_PRESCALER/1000) +#define TIMER_1_COUNT (0xFFFF-TIMER_1_TICKS) +/* Global variable millisecond timer - used by main.c for timers task */ +volatile uint8_t Timer_Milliseconds = 0; + +/* Configure the Timer */ +void timer_initialize(void) +{ + /* Normal Operation */ + TCCR1A = 0; + /* CS10 = clkI/O/1 (No prescaling) */ + TCCR1B = _BV(CS10); + /* Clear any TOV1 Flag set when the timer overflowed */ + BIT_CLEAR(TIFR1,TOV1); + /* Initial value */ + TCNT1 = TIMER_1_COUNT; + /* Enable the overflow interrupt */ + BIT_SET(TIMSK1,TOIE1); +} + + +/* Timer Overflowed! Increment the time. */ +ISR(TIMER1_OVF_vect) +{ + /* Set the counter for the next interrupt */ + TCNT1 = TIMER_1_COUNT; + /* Overflow Flag is automatically cleared */ + if (Timer_Milliseconds < 0xFF) + Timer_Milliseconds++; +} diff --git a/bacnet-stack/ports/atmega168/timer.h b/bacnet-stack/ports/atmega168/timer.h new file mode 100644 index 00000000..f49493a2 --- /dev/null +++ b/bacnet-stack/ports/atmega168/timer.h @@ -0,0 +1,32 @@ +/************************************************************************** +* +* Copyright (C) 2007 Steve Karg +* +* 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. +* +*********************************************************************/ +#ifndef TIMER_H +#define TIMER_H + +extern volatile uint8_t Timer_Milliseconds; + +void timer_initialize(void); + +#endif