From 2cdf64ab9073e951e43ffd2e212e8af3048c683d Mon Sep 17 00:00:00 2001 From: skarg Date: Sat, 18 Aug 2007 00:03:11 +0000 Subject: [PATCH] Testing the Atmel ARM7 port with an actual UART attached. Fixed several problems, but still not responding. --- bacnet-stack/ports/at91sam7s/.gdbinit | 8 +- bacnet-stack/ports/at91sam7s/dlmstp.c | 10 +- bacnet-stack/ports/at91sam7s/h_rp.c | 69 ++++++------- bacnet-stack/ports/at91sam7s/h_wp.c | 142 +++++++++++++------------- bacnet-stack/ports/at91sam7s/main.c | 105 ++++++++++++++----- bacnet-stack/ports/at91sam7s/makefile | 11 +- bacnet-stack/ports/at91sam7s/rs485.c | 25 +++-- bacnet-stack/ports/at91sam7s/timer.c | 10 +- 8 files changed, 225 insertions(+), 155 deletions(-) diff --git a/bacnet-stack/ports/at91sam7s/.gdbinit b/bacnet-stack/ports/at91sam7s/.gdbinit index ab5006bf..6b6f0d8d 100644 --- a/bacnet-stack/ports/at91sam7s/.gdbinit +++ b/bacnet-stack/ports/at91sam7s/.gdbinit @@ -6,11 +6,11 @@ monitor speed auto monitor long 0xffffff60 0x00320100 monitor long 0xfffffd44 0xa0008000 monitor long 0xfffffc20 0xa0000601 -#monitor sleep 100 +monitor sleep 100 monitor long 0xfffffc2c 0x00480a0e -#monitor sleep 200 +monitor sleep 200 monitor long 0xfffffc30 0x7 -#monitor sleep 100 +monitor sleep 100 monitor long 0xfffffd08 0xa5000401 -#monitor sleep 100 +monitor sleep 100 diff --git a/bacnet-stack/ports/at91sam7s/dlmstp.c b/bacnet-stack/ports/at91sam7s/dlmstp.c index c3f586e1..999af867 100644 --- a/bacnet-stack/ports/at91sam7s/dlmstp.c +++ b/bacnet-stack/ports/at91sam7s/dlmstp.c @@ -48,9 +48,9 @@ static uint8_t RxBuffer[MAX_MPDU]; #define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;} -void dlmstp_millisecond_timer(void) +volatile uint16_t *dlmstp_millisecond_timer_address(void) { - INCREMENT_AND_LIMIT_UINT16(MSTP_Port.SilenceTimer); + return &(MSTP_Port.SilenceTimer); } void dlmstp_copy_bacnet_address(BACNET_ADDRESS * dest, BACNET_ADDRESS * src) @@ -116,6 +116,7 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */ } dlmstp_copy_bacnet_address(&Transmit_Packet.address, dest); bytes_sent = sizeof(Transmit_Packet); + Transmit_Packet.ready = true; } return bytes_sent; @@ -123,12 +124,9 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */ static void dlmstp_task(void) { - volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; /* only do receive state machine while we don't have a frame */ if ((MSTP_Port.ReceivedValidFrame == false) && (MSTP_Port.ReceivedInvalidFrame == false)) { - /* LED OFF */ - pPIO->PIO_SODR = LED2; do { RS485_Check_UART_Data(&MSTP_Port); MSTP_Receive_Frame_FSM(&MSTP_Port); @@ -137,8 +135,6 @@ static void dlmstp_task(void) break; } while (MSTP_Port.DataAvailable); } else { - /* LED ON */ - pPIO->PIO_CODR = LED2; } /* only do master state machine while rx is idle */ if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE) { diff --git a/bacnet-stack/ports/at91sam7s/h_rp.c b/bacnet-stack/ports/at91sam7s/h_rp.c index eb3c1080..8f4f3f50 100644 --- a/bacnet-stack/ports/at91sam7s/h_rp.c +++ b/bacnet-stack/ports/at91sam7s/h_rp.c @@ -134,58 +134,57 @@ void handler_read_property(uint8_t * service_request, BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; BACNET_ADDRESS my_address; - len = rp_decode_service_request(service_request, service_len, &data); /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); - if (len < 0) { - /* bad decoding - send an abort */ - len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, ABORT_REASON_OTHER, true); - } else if (service_data->segmented_message) { + if (service_data->segmented_message) { /* we don't support segmentation - send an abort */ len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); - } else { - /* most cases will be error */ - error = true; - len = Encode_Property_APDU( - &Temp_Buf[0], - data.object_type, - data.object_instance, - data.object_property, - data.array_index, - &error_class, &error_code); - if (len >= 0) { - /* encode the APDU portion of the packet */ - data.application_data = &Temp_Buf[0]; - data.application_data_len = len; - /* FIXME: probably need a length limitation sent with encode */ - len = - rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, &data); - error = false; - } + goto RP_ABORT; + } + len = rp_decode_service_request(service_request, service_len, &data); + if (len < 0) { + /* bad decoding - send an abort */ + len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, ABORT_REASON_OTHER, true); + goto RP_ABORT; + } + /* most cases will be error */ + error = true; + len = Encode_Property_APDU( + &Temp_Buf[0], + data.object_type, + data.object_instance, + data.object_property, + data.array_index, + &error_class, &error_code); + if (len >= 0) { + /* encode the APDU portion of the packet */ + data.application_data = &Temp_Buf[0]; + data.application_data_len = len; + /* FIXME: probably need a length limitation sent with encode */ + len = + rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, &data); + error = false; } if (error) { - switch (len) { + if (len == -2) { /* BACnet APDU too small to fit data, so proper response is Abort */ - case -2: len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); - break; - case -1: - default: - len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code); - break; + goto RP_ABORT; } + len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code); } +RP_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); diff --git a/bacnet-stack/ports/at91sam7s/h_wp.c b/bacnet-stack/ports/at91sam7s/h_wp.c index 59e9ecfc..c10fca80 100644 --- a/bacnet-stack/ports/at91sam7s/h_wp.c +++ b/bacnet-stack/ports/at91sam7s/h_wp.c @@ -58,85 +58,89 @@ void handler_write_property(uint8_t * service_request, int bytes_sent = 0; BACNET_ADDRESS my_address; - /* decode the service request only */ - len = wp_decode_service_request(service_request, - service_len, &wp_data); /* encode the NPDU portion of the packet */ datalink_get_my_address(&my_address); npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address, &npdu_data); + if (service_data->segmented_message) { + len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); + goto WP_ABORT; + } + /* decode the service request only */ + len = wp_decode_service_request(service_request, + service_len, &wp_data); /* bad decoding or something we didn't understand - send an abort */ if (len <= 0) { len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true); - } else if (service_data->segmented_message) { - len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); - } else { - switch (wp_data.object_type) { - case OBJECT_DEVICE: - if (Device_Write_Property(&wp_data, &error_class, &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); - } - break; - case OBJECT_ANALOG_INPUT: - case OBJECT_BINARY_INPUT: - error_class = ERROR_CLASS_PROPERTY; - error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, - error_class, error_code); - break; - case OBJECT_BINARY_VALUE: - if (Binary_Value_Write_Property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); - } - break; - case OBJECT_ANALOG_VALUE: - if (Analog_Value_Write_Property(&wp_data, &error_class, - &error_code)) { - len = - encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY); - } else { - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, - SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, - error_code); - } - break; - default: - len = - bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, - error_class, error_code); - break; - } + goto WP_ABORT; } + /* handle the object type */ + switch (wp_data.object_type) { + case OBJECT_DEVICE: + if (Device_Write_Property(&wp_data, &error_class, &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); + } + break; + case OBJECT_ANALOG_INPUT: + case OBJECT_BINARY_INPUT: + error_class = ERROR_CLASS_PROPERTY; + error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, + error_class, error_code); + break; + case OBJECT_BINARY_VALUE: + if (Binary_Value_Write_Property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); + } + break; + case OBJECT_ANALOG_VALUE: + if (Analog_Value_Write_Property(&wp_data, &error_class, + &error_code)) { + len = + encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY); + } else { + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, + SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, + error_code); + } + break; + default: + len = + bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY, + error_class, error_code); + break; + } +WP_ABORT: pdu_len += len; bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); diff --git a/bacnet-stack/ports/at91sam7s/main.c b/bacnet-stack/ports/at91sam7s/main.c index d7edfaf6..121a5908 100644 --- a/bacnet-stack/ports/at91sam7s/main.c +++ b/bacnet-stack/ports/at91sam7s/main.c @@ -23,12 +23,15 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * *********************************************************************/ +/* hardware specific */ #include "AT91SAM7S256.h" #include "board.h" -#include "math.h" -#include "stdlib.h" -#include "string.h" -#include "stdbool.h" +#include "timer.h" +/* standard libraries */ +#include +#include +#include +#include /* BACnet */ #include "rs485.h" #include "datalink.h" @@ -37,6 +40,10 @@ #include "dcc.h" #include "iam.h" #include "handlers.h" +#include "device.h" +#include "dcc.h" +#include "iam.h" +#include "txbuf.h" // ******************************************************* // FIXME: use header files? External References @@ -45,9 +52,6 @@ extern void LowLevelInit(void); extern unsigned enableIRQ(void); extern unsigned enableFIQ(void); -extern void TimerInit(void); -extern volatile unsigned long Timer_Milliseconds; - // ******************************************************* // FIXME: use header files? Global Variables // ******************************************************* @@ -58,8 +62,9 @@ static unsigned long LED_Timer_1 = 0; static unsigned long LED_Timer_2 = 0; static unsigned long LED_Timer_3 = 0; static unsigned long LED_Timer_4 = 1000; +static unsigned long DCC_Timer = 1000; -void millisecond_timer(void) +static void millisecond_timer(void) { while (Timer_Milliseconds) { Timer_Milliseconds--; @@ -75,21 +80,15 @@ void millisecond_timer(void) if (LED_Timer_4) { LED_Timer_4--; } - dlmstp_millisecond_timer(); + if (DCC_Timer) { + DCC_Timer--; + } } + /* note: MS/TP silence timer is updated in ISR */ } -int main (void) { - unsigned long IdleCount = 0; // idle loop blink counter - bool LED3_Off_Enabled = true; - uint16_t pdu_len = 0; - BACNET_ADDRESS src; /* source address */ - uint8_t pdu[MAX_MPDU]; /* PDU data */ - - // Initialize the Atmel AT91SAM7S256 - // (watchdog, PLL clock, default interrupts, etc.) - LowLevelInit(); - TimerInit(); +static void init(void) +{ /* Initialize the Parallel I/O Controller A Peripheral Clock */ volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<AIC_IECR = (1<PIO_ODSR & LED1) == LED1) && (LED1_Off_Enabled)) + { + LED1_Off_Enabled = false; + /* wait */ + LED_Timer_1 = 20; + } + if (!LED_Timer_1) { + /* turn off */ + pPIO->PIO_SODR = LED1; + LED1_Off_Enabled = true; + } + /* USART Rx turns the LED on, we turn it off */ + if (((pPIO->PIO_ODSR & LED2) == LED2) && (LED2_Off_Enabled)) + { + LED2_Off_Enabled = false; + /* wait */ + LED_Timer_2 = 20; + } + if (!LED_Timer_2) { + /* turn off */ + pPIO->PIO_SODR = LED2; + LED2_Off_Enabled = true; + } + /* switch or NPDU turns on the LED, we turn it off */ if (((pPIO->PIO_ODSR & LED3) == LED3) && (LED3_Off_Enabled)) { LED3_Off_Enabled = false; /* wait */ - LED_Timer_3 = 250; + LED_Timer_3 = 500; } if (!LED_Timer_3) { /* turn LED3 (DS3) off */ pPIO->PIO_SODR = LED3; LED3_Off_Enabled = true; } + /* Blink LED every second */ if (!LED_Timer_4) { if ((pPIO->PIO_ODSR & LED4) == LED4) { - // turn LED2 (DS2) on + /* turn on */ pPIO->PIO_CODR = LED4; } else { - // turn LED2 (DS2) off + /* turn off */ pPIO->PIO_SODR = LED4; } /* wait */ diff --git a/bacnet-stack/ports/at91sam7s/makefile b/bacnet-stack/ports/at91sam7s/makefile index 36a03320..9a9f9415 100644 --- a/bacnet-stack/ports/at91sam7s/makefile +++ b/bacnet-stack/ports/at91sam7s/makefile @@ -11,7 +11,12 @@ AR=arm-elf-ar LDSCRIPT=at91sam7s256.ld -BACNET_FLAGS = -DBACDL_MSTP=1 -DPRINT_ENABLED=0 -DBIG_ENDIAN=0 -DMAX_APDU=480 -DDLMSTP_TEST +BACNET_FLAGS = -DBACDL_MSTP +BACNET_FLAGS += -DPRINT_ENABLED=0 +BACNET_FLAGS += -DBIG_ENDIAN=0 +BACNET_FLAGS += -DMAX_APDU=480 +#BACNET_FLAGS += -DDLMSTP_TEST + INCLUDES = -I. -I../.. -I../../demo/handler -I../../demo/object #OPTIMIZATION = -O0 OPTIMIZATION = -Os @@ -67,8 +72,8 @@ CORESRC = ../../npdu.c \ ../../iam.c \ ../../version.c -#CSRC = $(PORTSRC) $(DEMOSRC) $(CORESRC) -CSRC = $(PORTSRC) +CSRC = $(PORTSRC) $(DEMOSRC) +#CSRC = $(PORTSRC) AOBJ = $(ASRC:.s=.o) COBJ = $(CSRC:.c=.o) diff --git a/bacnet-stack/ports/at91sam7s/rs485.c b/bacnet-stack/ports/at91sam7s/rs485.c index a6698414..9574621f 100644 --- a/bacnet-stack/ports/at91sam7s/rs485.c +++ b/bacnet-stack/ports/at91sam7s/rs485.c @@ -33,6 +33,7 @@ #include #include #include "mstp.h" +#include "timer.h" /* This file has been customized for use with UART0 on the AT91SAM7S-EK */ @@ -63,10 +64,16 @@ void RS485_Set_Interface(char *ifname) *****************************************************************************/ void RS485_Initialize(void) { - // enable the USART0 peripheral clock + /* Enable the USART0 clock in the Power Management Controller */ volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<AIC_IDCR = (1<AIC_ICCR = (1<US_CR = AT91C_US_RXEN | /* Receiver Enable */ AT91C_US_TXEN; /* Transmitter Enable */ - + return; } @@ -149,10 +156,6 @@ void RS485_Send_Frame( { uint8_t turnaround_time; - /* toggle LED on send */ - volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; - /* LED ON */ - pPIO->PIO_CODR = LED1; /* delay after reception - per MS/TP spec */ if (mstp_port) { /* wait about 40 bit times since reception */ @@ -164,6 +167,10 @@ void RS485_Send_Frame( /* do nothing - wait for timer to increment */ }; } + /* toggle LED on send */ + volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; + /* LED ON */ + pPIO->PIO_CODR = LED1; while (nbytes) { while (!(RS485_Interface->US_CSR & AT91C_US_TXRDY)) { /* do nothing - wait until Tx buffer is empty */ @@ -179,8 +186,6 @@ void RS485_Send_Frame( while (!(RS485_Interface->US_CSR & AT91C_US_TXRDY)) { /* do nothing - wait until Tx buffer is empty */ } - /* LED OFF */ - pPIO->PIO_SODR = LED1; return; } @@ -188,6 +193,8 @@ void RS485_Send_Frame( /* called by timer, interrupt(?) or other thread */ void RS485_Check_UART_Data(struct mstp_port_struct_t *mstp_port) { + volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; + if (mstp_port->ReceiveError == true) { /* wait for state machine to clear this */ } @@ -197,6 +204,8 @@ void RS485_Check_UART_Data(struct mstp_port_struct_t *mstp_port) if ( RS485_Interface->US_CSR & AT91C_US_RXRDY) { mstp_port->DataRegister = RS485_Interface->US_RHR; mstp_port->DataAvailable = true; + /* LED ON */ + pPIO->PIO_CODR = LED2; } } } diff --git a/bacnet-stack/ports/at91sam7s/timer.c b/bacnet-stack/ports/at91sam7s/timer.c index 012f2384..2ee203d6 100644 --- a/bacnet-stack/ports/at91sam7s/timer.c +++ b/bacnet-stack/ports/at91sam7s/timer.c @@ -40,11 +40,14 @@ /********************************************************** Header files **********************************************************/ +#include #include "AT91SAM7S256.h" #include "board.h" +#include "dlmstp.h" // global variable counts interrupts -volatile unsigned long Timer_Milliseconds = 0; +volatile unsigned long Timer_Milliseconds; +volatile uint16_t *pTimer_MSTP_Silence; void Timer0_Setup(int milliseconds) { // TC Block Control Register TC_BCR (read/write) @@ -302,6 +305,8 @@ void Timer0IrqHandler (void) { dummy = pTC->TC_SR; // increment the tick count Timer_Milliseconds++; + if ((*pTimer_MSTP_Silence) < 0xFFFF) + (*pTimer_MSTP_Silence)++; } // ***************************************************************************** @@ -314,8 +319,9 @@ void Timer0IrqHandler (void) { // modified the peripheral clock init // ***************************************************************************** void TimerInit(void) { + pTimer_MSTP_Silence = dlmstp_millisecond_timer_address(); // enable the Timer0 peripheral clock - volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; + volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<