Revision 184

trunk/bootloader/rs485_sw.c (revision 184)
1
/**
2
 * @file rs485_sw.c
3
 * @brief RS485 implementation using UART hardware module and no interrupts
4
 *
5
 * This uses the AVR's UART hardware module but does polling rather than
6
 * interrupts to handle transmission and receiving. It assumes the use
7
 * of an external UART<->RS485 converter with the RXEN and TXEN pins tied
8
 * together.
9
 *
10
 * @author Kevin Woo <kwoo@2ndt.com>
11
 **/
12

  
13
/**
14
 * @brief Initializes the uart
15
 * @param baud The baudrate. Use the definitions in rs485_sw.h
16
 */
17
void rs485_init(uint16_t baud) {
18
	// Set baud rate
19
	UBRRH = (uint8_t)(baud>>8);
20
	UBRRL = (uint8_t)baud;
21
	
22
	// Enable RX/TX
23
	UCSRB = _BV(RXEN) | _BV(TXEN);
24
 
25
	// Enable the TXEN pin as output
26
	DDRD |= TX_EN;
27
    rs485_toggle_transmit(RS485_TX_OFF);
28
}
29

  
30
/**
31
 * @brief Non-blocking receive
32
 * 
33
 * Receives a byte from the UART if one exists. If none exist the function
34
 * will return an error code immediately. If there is a byte to receive,
35
 * it will be placed in a passed in pointer and return.
36
 *
37
 * @pre The RS485 TXEN line is not enabled
38
 * @param output_byte Byte to store the received message
39
 * @return 0 on success, negative if there is nothing to receive
40
 */
41
int8_t rs485_get_byte(uint8_t *output_byte) {
42
    if (UCSRA & _BV(RXC)) {
43
        *output_byte = UDR;
44
        return 0;
45
    } else {
46
        return -1;
47
    }
48
}
49

  
50
/**
51
 * @brief Blocking send
52
 *
53
 * Sends the byte in data onto the network. The function will block until
54
 * the transmit is complete so that the transmit enable line can be toggled
55
 * safely. It will wait until any current transmission completes before sending
56
 * and will wait until it completes before returning. The RS485 TX enable line
57
 * is automatically toggled by the function and should not be done so
58
 * outside the function.
59
 *
60
 * @param data The byte to send
61
 */
62
void rs485_send_byte(uint8_t data) {
63
	//Waits until current transmit is done
64
    while (!(UCSRA & _BV(UDRE)));
65

  
66
    // Enable writes and send
67
	rs485_toggle_transmit(RS485_TX_ON);
68
    UDR = data;
69

  
70
    // Waits until the transmit is done
71
    while(!(UCSRA & _BV(TXC)));
72
    rs485_toggle_transmit(RS485_TX_OFF);
73
    UCSRA |= _BV(TXC);
74

  
75
	return;
76
}
77

  
78
/**
79
 * @brief Toggles the RS485 TXEN line
80
 *
81
 * This function should not be used outside of this file
82
 *
83
 * @param state Whether to turn the pin on or off
84
 */
85
void rs485_toggle_transmit(uint8_t state) {
86
	if (state == RS485_TX_ON) {
87
		PORTD |= TX_EN;
88
	} else {
89
		PORTD &= ~TX_EN;
90
	}
91
}
trunk/bootloader/uart.h (revision 184)
16 16
 * Copyright 2009 Kevin Woo <kwoo@2ndt.com>
17 17
 *
18 18
 ********/
19
/** @file uart.h
19
/** @file rs485_sw.h
20 20
 *
21
 *	@brief Initializes UART functions using the UART hardware module
21
 *	@brief Implements rs485 using the uart hardware module.
22 22
 *
23
 *	See rs485_sw.c for more information
24
 *
23 25
 *	@author Kevin Woo (kwoo)
24 26
 */
25 27

  
26
#ifndef UART_H
27
#define UART_H
28
#ifndef _RS485_SW_H
29
#define _RS485_SW_H
28 30

  
29 31
#include <avr/io.h>
30 32
#include <avr/interrupt.h>
31 33
#include <stdint.h>
32
/** **/
33
#define UART_TX_OFF 0
34
#define UART_TX_ON 1
35 34

  
36
/** @brief RX Pin for the UART **/
35
#define RS485_TX_OFF 0
36
#define RS485_TX_ON 1
37

  
38
/** @brief RX Pin for the RS485 */
37 39
#define RX		_BV(PORTD0)
40
/** @brief TX Pin for the RS485 */
38 41
#define TX		_BV(PORTD1)
42
/** @brief TX Enable Pin for the RS485 */
39 43
#define TX_EN	_BV(PORTD5)
40 44

  
41
/** @brief The most recently received byte **/
42
extern uint8_t received_byte;
43
/** @brief If the value in received_byte has been read or not **/
44
extern uint8_t byte_ready;
45

  
46
/** @brief Initializes the UART registers and sets it to the buad rate 
47
 *         which msut be the value that is defined in the datasheet 
48
 *         for any particular speed (ie: 51 -> 9600bps)
49
 **/
50
void init_uart(uint16_t baud);
51
/** @brief Gets latest byte and returns it in output_byte. If the byte 
52
 *         was already read, returns -1 otherwise it returns 0 
53
 **/
45
void uart_init(uint16_t baud);
54 46
int8_t uart_get_byte(uint8_t *output_byte);
55
/** @brief Sends a character array of size size. If we are currently 
56
 *         transmitting it will block until the the current transmit 
57
 *         is done. 
58
 **/
59 47
void uart_send_byte(uint8_t data);
60
void uart_toggle_transmit(uint8_t state);
48
static void uart_toggle_transmit(uint8_t state);
61 49
#endif
trunk/bootloader/bootloader.c (revision 184)
2 2
#include <avr/boot.h>
3 3
#include <avr/wdt.h>
4 4
#include <tooltron.h>
5
#include "uart.h"
5
#include "rs485_sw.h"
6 6

  
7 7
#define ADDR    18
8 8

  
......
23 23
    int16_t sword;
24 24
} rjump_t;
25 25

  
26
void init_uart(uint16_t baud) {
27
	// Set baud rate
28
	UBRRH = (uint8_t)(baud>>8);
29
	UBRRL = (uint8_t)baud;
30
	
31
	// Enable RX/TX
32
	UCSRB = _BV(RXEN) | _BV(TXEN);
33
 
34
	// Enable the TXEN pin as output
35
	DDRD |= TX_EN;
36
    uart_toggle_transmit(UART_TX_OFF);
37
}
38 26

  
39
int8_t uart_get_byte(uint8_t *output_byte) {
40
    if (UCSRA & _BV(RXC)) {
41
        *output_byte = UDR;
42
        return 0;
43
    } else {
44
        return -1;
45
    }
46
}
47

  
48
void uart_send_byte(uint8_t data) {
49
	//Waits until current transmit is done
50
    while (!(UCSRA & _BV(UDRE)));
51

  
52
    // Enable writes and send
53
	uart_toggle_transmit(UART_TX_ON);
54
    UDR = data;
55

  
56
    // Waits until the transmit is done
57
    while(!(UCSRA & _BV(TXC)));
58
    uart_toggle_transmit(UART_TX_OFF);
59
    UCSRA |= _BV(TXC);
60

  
61
	return;
62
}
63

  
64
void uart_toggle_transmit(uint8_t state) {
65
	if (state == UART_TX_ON) {
66
		PORTD |= TX_EN;
67
	} else {
68
		PORTD &= ~TX_EN;
69
	}
70
}
71

  
72 27
char parse_packet(uint8_t *mbuf) {
73 28
  uint8_t r;        // Byte from the network
74 29
  uint8_t crc;      // Running checksum of the packet
......
88 43

  
89 44
  while (1) {
90 45
    // Wait for the next byte
91
    while ((uart_get_byte(&r)) < 0) {
46
    while ((rs485_get_byte(&r)) < 0) {
92 47
        if (count >= MAX_TIMEOUT) {
93 48
            return TT_BAD;
94 49
        } else {
......
167 122
}
168 123

  
169 124
void send_packet(uint8_t cmd) {
170
    uart_send_byte(DELIM);
171
    uart_send_byte(ADDR);
172
    uart_send_byte(SERVER);
173
    uart_send_byte(cmd);
174
    uart_send_byte(ACK_CRC ^ cmd);
125
    rs485_send_byte(DELIM);
126
    rs485_send_byte(ADDR);
127
    rs485_send_byte(SERVER);
128
    rs485_send_byte(cmd);
129
    rs485_send_byte(ACK_CRC ^ cmd);
175 130
}
176 131

  
177 132
// SPM_PAGESIZE is set to 32 bytes
......
210 165
  WDTCSR = 0;
211 166

  
212 167

  
213
  init_uart(51); //MAGIC NUMBER??
168
  rs485_init(51); //MAGIC NUMBER??
214 169

  
215 170
  //set LED pin as output
216 171
  LED_DDR |= 0x07;

Also available in: Unified diff