Permalink
Browse files

Merge branch 'feature/swuart'

  • Loading branch information...
blastur committed Sep 3, 2011
2 parents c08b103 + e89f498 commit ae772976a49aaa036fe14542118b6892e8d7990a
Showing with 284 additions and 50 deletions.
  1. +29 −16 Makefile
  2. +42 −9 README
  3. +14 −0 config.h
  4. +43 −0 hwuart.c
  5. +2 −24 magboot.c
  6. +1 −1 magboot.py
  7. +127 −0 swuart.c
  8. +26 −0 uart.h
View
@@ -24,34 +24,47 @@ PROGTYPE=stk500v2
PROGPORT=/dev/avrusb0
AVRDUDE=avrdude -p $(MCU) -c $(PROGTYPE) -P $(PROGPORT)
-PROG=magboot
-IHEX=magboot.ihex
-SRCS=magboot.c
-OBJS=$(SRCS:%.c=%.o)
+HWUART=magboot_hw
+SWUART=magboot_sw
+HWUART_IHEX=magboot_hw.ihex
+SWUART_IHEX=magboot_sw.ihex
+
+COMMON_OBJS=magboot.o
+HWUART_OBJS=hwuart.o
+SWUART_OBJS=swuart.o
#OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls
OPTIMIZE = -Os
-CFLAGS += -g -Wall $(OPTIMIZE) -mmcu=$(MCU) -DF_CPU=$(CPU_FREQ)
+CFLAGS += -g -Wall $(OPTIMIZE) -mmcu=$(MCU) -include config.h -DBAUD_RATE=19200
LDFLAGS += -Wl,--section-start=.text=$(BOOTADDR)
-CFLAGS += -DBAUD_RATE=115200
-CFLAGS += -DJUMP_ADDR=0x00
-
-# Target specifics: ATmega328p @ external 16 MHz
+# Target definition
MCU=atmega328p
-CPU_FREQ=16000000L
HFUSE=0xdc
BOOTADDR=0x7c00
-$(PROG): $(OBJS)
+.PHONY: all
+all: $(HWUART_IHEX) $(SWUART_IHEX)
+
+$(HWUART): $(COMMON_OBJS) $(HWUART_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
-$(IHEX): $(PROG)
+$(SWUART): $(COMMON_OBJS) $(SWUART_OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
+
+$(HWUART_IHEX): $(HWUART)
+ $(OBJCOPY) -j .text -j .data -S -O ihex $^ $@
+
+$(SWUART_IHEX): $(SWUART)
$(OBJCOPY) -j .text -j .data -S -O ihex $^ $@
-.PHONY: flash
-flash: $(IHEX)
- $(AVRDUDE) -e -U flash:w:$(IHEX)
+.PHONY: flash_sw
+flash_sw: $(SWUART_IHEX)
+ $(AVRDUDE) -e -U flash:w:$^
+
+.PHONY: flash_hw
+flash_hw: $(HWUART_IHEX)
+ $(AVRDUDE) -e -U flash:w:$^
.PHONY: fusedump
fusedump:
@@ -67,4 +80,4 @@ flashdump:
.PHONY: clean
clean:
- rm -f $(OBJS) $(PROG) $(IHEX)
+ rm -f $(COMMON_OBJS) $(HWUART) $(HWUART_IHEX) $(HWUART_OBJS) $(SWUART) $(SWUART_IHEX) $(SWUART_OBJS)
View
51 README
@@ -12,34 +12,41 @@ Features
* Basic device identification to prevent flashing unknown or unsupported devices
* Fits in a 1 kb boot section (binary size is approx. 650 bytes)
* Supports loading raw binaries only (ihex is NOT supported at the moment)
+* Supports native AVR serialport or software serialport on two arbitrary pins
Installation
================================================================================
To install magboot you need an ISP programmer.
-1) Edit Makefile and the "Target specifics"-section:
+1) Edit Makefile and the "Target definition"-section:
- MCU Set to either atmega328p or atmega168p depending on target.
+ MCU Set to either 'atmega328p' or 'atmega168p' depending on target.
- CPU_FREQ Match your clock settings (LFUSE and oscillator etc)
-
- HFUSE Should be OK on both targets. If you have special requirements,
+ HFUSE Sets AVR Hi-Fuse. Normally you will not have to change this
+ value for either 328p or 168p. If you have special requirements,
http://www.engbedded.com/fusecalc is a good AVR fuse calculator.
BOOTADDR This is flash size minus boot section size, expressed in bytes.
For example, 32 kb - 1 kb = 31 kb = 31 * 1024 = 0x7c00
Set to 0x7c00 for Atmega328p and 0x3c00 for Atmega168p.
-2) Program the device:
+2) Edit the target configuration in config.h:
+
+ FCPU Target clock frequency
+
+Unless you plan to use the software serialport implementation (SWUART), you do
+not have to change any of the CONFIG_SWUART_* directives.
+
+3) Build and program the device:
- make fuseprog
- make flash
+ make magboot_hw
+ make flash_hw
The Makefile assumes your ISP programmer is of type stk500v2 and located at file
/dev/avrusb0. If this is not true, append the PROGTYPE and PROGPORT parameters
with appropriate values. Example:
- make PROGPORT=/dev/ttyUSB0 PROGTYPE=jtagmkII flash
+ make PROGPORT=/dev/ttyUSB0 PROGTYPE=jtagmkII flash_hw
For a list of valid PROGTYPE values, please refer to the Avrdude manual:
@@ -99,3 +106,29 @@ was successfull!
Optionally, the device may be reset using -r. This will cause the device to
reboot and bypass the bootloader.
+
+Software serial port support (ADVANCED)
+================================================================================
+Magboot normally operates over the built-in serialport of the AVR using the
+predefined TX and RX pins. This covers most needs and is the recommended mode of
+operation unless your serial port is connected to another pair of pins.
+
+In this case, you may use the software serialport mode of operation. It allows
+you to configure two arbitrary pins to use for TX and RX. This is useful if the
+native serialport is unavailable, perhaps because of other peripheral serial
+devices.
+
+The serialport mode is a compile-time option. You may build the SoftWare UART
+(SWUART) version of Magboot by issuing Make-target "magboot_sw":
+
+ make magboot_sw
+
+Prior to building the SWUART version, pin-configuration must be setup in
+config.h. Please note that all the configuration steps listed in the
+Installation section above also applies for the SWUART build (F_CPU etc.).
+
+Finally, flash Magboot SWUART onto target:
+
+ make [PROGPORT=/dev/ttyUSB0 PROGTYPE=myprogrammer] flash_sw
+
+For usage information, please refer to the Usage section above.
View
@@ -0,0 +1,14 @@
+/* Target configuration */
+#define F_CPU (16000000L)
+#define JUMP_ADDR (0x00)
+
+/* SWUART pin-configuration */
+#define CONFIG_SWUART_RX_BIT (PB3)
+#define CONFIG_SWUART_RX_PORT (PORTB)
+#define CONFIG_SWUART_RX_PIN (PINB)
+#define CONFIG_SWUART_RX_DIR (DDRB)
+
+#define CONFIG_SWUART_TX_BIT (PB4)
+#define CONFIG_SWUART_TX_PORT (PORTB)
+#define CONFIG_SWUART_TX_DIR (DDRB)
+
View
@@ -0,0 +1,43 @@
+/* Copyright (C) 2010-2011 Magnus Olsson
+ *
+ * This file is part of magboot
+ * Windnode 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Windnode 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 magboot. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdint.h>
+#include <avr/io.h>
+
+void uart_putc(uint8_t ch)
+{
+ loop_until_bit_is_set(UCSR0A, UDRE0);
+ UDR0 = ch;
+}
+
+uint8_t uart_getc(void)
+{
+ uint8_t ch;
+
+ loop_until_bit_is_set(UCSR0A, RXC0);
+ ch = UDR0;
+
+ return ch;
+}
+
+void uart_init()
+{
+ UCSR0A = _BV(U2X0);
+ UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+ UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+ UBRR0L = (uint8_t)((F_CPU + BAUD_RATE * 4L)/(BAUD_RATE * 8L) - 1);
+}
+
View
@@ -25,6 +25,8 @@
#include <avr/interrupt.h>
#include <avr/sfr_defs.h>
+#include "uart.h"
+
#define LED_DIR DDRB
#define LED_PORT PORTB
#define LED_BIT PB5
@@ -34,30 +36,6 @@
typedef void (*jump_t)(void);
-static void uart_putc(char ch)
-{
- loop_until_bit_is_set(UCSR0A, UDRE0);
- UDR0 = ch;
-}
-
-static uint8_t uart_getc(void)
-{
- uint8_t ch;
-
- loop_until_bit_is_set(UCSR0A, RXC0);
- ch = UDR0;
-
- return ch;
-}
-
-static void uart_init()
-{
- UCSR0A = _BV(U2X0);
- UCSR0B = _BV(RXEN0) | _BV(TXEN0);
- UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
- UBRR0L = (uint8_t)((F_CPU + BAUD_RATE * 4L)/(BAUD_RATE * 8L) - 1);
-}
-
static bool cmd_load_addr(uint16_t *addr)
{
/* 16-bit addr, little-endian */
View
@@ -143,7 +143,7 @@ def cmd_wait():
print "Unsupported device '" + sys.argv[2] + "'"
sys.exit(3)
- ser = serial.Serial(port=sys.argv[1], baudrate=115200, timeout=1)
+ ser = serial.Serial(port=sys.argv[1], baudrate=19200, timeout=1)
try:
opts, args = getopt.getopt(sys.argv[3:], 'a:w:ijrz')
View
127 swuart.c
@@ -0,0 +1,127 @@
+/* Copyright (C) 2010-2011 Magnus Olsson
+ *
+ * This file is part of magboot
+ * Windnode 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Windnode 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 magboot. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+
+#include "uart.h"
+
+#define STARTBIT (0)
+#define STOPBIT (1)
+
+/* Calculate baudtime using timer pre-scaler 64 */
+#define BAUDTIME ((F_CPU)/(BAUD_RATE*64l))
+
+#if (BAUDTIME > 255)
+#error Baudrate is too low!
+#endif
+
+#if (BAUDTIME < 1)
+#error Baudrate is too high!
+#endif
+
+static void __bit_delay(void)
+{
+ TCCR0B |= _BV(CS01) | _BV(CS00); /* Timer pre-scaler 64 */
+ while (TCNT0 < BAUDTIME) { /* NOP */ }
+ TCCR0B &= ~(_BV(CS01) | _BV(CS00));
+}
+
+static void bit_delay(void)
+{
+ TCNT0 = 0;
+ __bit_delay();
+}
+
+static void half_bit_delay(void)
+{
+ TCNT0 = BAUDTIME/2;
+ __bit_delay();
+}
+
+static uint8_t rx_pin(void)
+{
+ return (CONFIG_SWUART_RX_PIN & _BV(CONFIG_SWUART_RX_BIT)) != 0;
+}
+
+static void tx_pin(uint8_t hi)
+{
+ if (hi)
+ CONFIG_SWUART_TX_PORT |= _BV(CONFIG_SWUART_TX_BIT);
+ else
+ CONFIG_SWUART_TX_PORT &= ~(_BV(CONFIG_SWUART_TX_BIT));
+}
+
+/* uart_putc() -- blocking 8N1 transmit */
+void uart_putc(uint8_t ch)
+{
+ uint8_t bit;
+
+ tx_pin(STARTBIT);
+ bit_delay();
+ for (bit = 0; bit < 8; bit++) {
+ tx_pin(ch & 0x1);
+ ch = ch >> 1;
+ bit_delay();
+ }
+ tx_pin(STOPBIT);
+ bit_delay();
+}
+
+static int __getc(void)
+{
+ uint8_t bit;
+ uint8_t ch;
+
+ half_bit_delay();
+ if (rx_pin() != STARTBIT)
+ return -1; /* Glitch */
+ bit_delay();
+ for (bit = 0; bit < 8; bit++) {
+ ch = ch >> 1;
+ if (rx_pin())
+ ch |= 1 << 7;
+ bit_delay();
+ }
+
+ if (rx_pin() != STOPBIT)
+ return -2; /* Frame error */
+
+ return (int) ch;
+}
+
+/* uart_getc() -- blocking 8N1 receive */
+uint8_t uart_getc(void)
+{
+ while (1) {
+ int ch;
+ while (rx_pin() != STARTBIT) { /* NOP */ }
+
+ ch = __getc();
+ if (ch >= 0)
+ return (uint8_t) ch;
+ }
+}
+
+void uart_init()
+{
+ CONFIG_SWUART_RX_DIR &= ~(_BV(CONFIG_SWUART_RX_BIT));
+ CONFIG_SWUART_RX_PORT |= _BV(CONFIG_SWUART_RX_BIT);
+ CONFIG_SWUART_TX_DIR |= _BV(CONFIG_SWUART_TX_BIT);
+ tx_pin(STOPBIT);
+}
+
Oops, something went wrong.

0 comments on commit ae77297

Please sign in to comment.