From d0801b36b47d8f3da610597160fde92059fd7e62 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Mon, 7 Aug 2017 19:27:05 +0200 Subject: implementation for avr programmer the programmer will receive the binary in blocks of defined size by a program under sw/programmer/linux (moved from sw/linux). --- sw/programmer/avr/fileinfo.h | 13 ++++++ sw/programmer/avr/main.c | 109 +++++++++++++++++++++++++++++++++++++++++++ sw/programmer/avr/makefile | 31 ++++++++++++ sw/programmer/avr/usart.c | 107 ++++++++++++++++++++++++++++++++++++++++++ sw/programmer/avr/usart.h | 96 +++++++++++++++++++++++++++++++++++++ 5 files changed, 356 insertions(+) create mode 100644 sw/programmer/avr/fileinfo.h create mode 100644 sw/programmer/avr/main.c create mode 100644 sw/programmer/avr/makefile create mode 100644 sw/programmer/avr/usart.c create mode 100644 sw/programmer/avr/usart.h (limited to 'sw/programmer/avr') diff --git a/sw/programmer/avr/fileinfo.h b/sw/programmer/avr/fileinfo.h new file mode 100644 index 0000000..6c831ed --- /dev/null +++ b/sw/programmer/avr/fileinfo.h @@ -0,0 +1,13 @@ +#ifndef __FILEINFO_H__ +#define __FILEINFO_H__ + +#include + +struct file_info +{ + size_t size; + size_t blklen; + uint16_t start_addr; +}; + +#endif diff --git a/sw/programmer/avr/main.c b/sw/programmer/avr/main.c new file mode 100644 index 0000000..90d05fa --- /dev/null +++ b/sw/programmer/avr/main.c @@ -0,0 +1,109 @@ +#include "fileinfo.h" +#include "usart.h" +#include + +#define EEPROM_TICK_MS 10 + +#define ADDRCR PORTB +#define EEPROMCR PORTC +#define EEPROMDR PORTD + +#define ADDR_BIT 0 +#define ADDR_EL 3 +#define ADDR_EH 4 +#define ADDR_DL 5 +#define ADDR_DH 6 + +#define EEPROM_WR 0 +#define EEPROM_RD 1 +#define EEPROM_CLK 2 + + +void eeprom_write(uint16_t addr, uint8_t byte); +void eeprom_tick(); + +int main(void) +{ + uint8_t *buffer, i; + uint16_t addr; + size_t read; + + struct file_info *finfo = malloc(sizeof(struct file_info)); + + DDRB = 0x7F; + DDRC = 0x83; + DDRD = 0xFC; + + /* get configuration */ + usart_init(1200); + + usart_print("EEPROM Programmer\n\r"); + + do { + usart_print("Waiting for configuration\n\r"); + read = usart_read((uint8_t *) finfo, sizeof(struct file_info)); + } while (read != sizeof(struct file_info)); + + usart_print("Programmer Ready\n\n\r"); + + buffer = malloc(finfo->blklen); + addr = finfo->start_addr; + + /* read file */ + while ((read = usart_read(buffer, finfo->blklen))) { + for (i = 0; i < read; i++) { + eeprom_write(addr + i, *(buffer++)); + } + + addr += finfo->blklen; + } + + return 0; +} + + +void eeprom_write(uint16_t addr, uint8_t byte) +{ + int bit; + + /* set address */ + for (bit = 0; bit < 8; bit++) { + // clear bit + ADDRCR &= ~0x07; + // select the bit + ADDRCR |= bit; + + // write bit for lower byte + if (addr & _BV(bit)) + ADDRCR |= _BV(ADDR_DL); + else + ADDRCR &= ~_BV(ADDR_DL); + + // write bit for higher byte + if ((addr>>8) & _BV(bit)) + ADDRCR |= _BV(ADDR_DH); + else + ADDRCR &= ~_BV(ADDR_DH); + } + + /* set data */ + EEPROMDR = byte; + EEPROMCR &= ~(_BV(ADDR_EH) | _BV(ADDR_EL)); + + /* write eeprom */ + EEPROMCR &= ~_BV(EEPROM_WR); + eeprom_tick(); + + EEPROMCR |= _BV(EEPROM_WR); + EEPROMCR |= _BV(ADDR_EH) | _BV(ADDR_EL); +} + +/* pulse the clock line for the eeprom */ +void eeprom_tick() +{ + EEPROMCR |= _BV(EEPROM_CLK); + _delay_ms(EEPROM_TICK_MS); + EEPROMCR &= ~_BV(EEPROM_CLK); + _delay_ms(EEPROM_TICK_MS); +} + diff --git a/sw/programmer/avr/makefile b/sw/programmer/avr/makefile new file mode 100644 index 0000000..95fb5fe --- /dev/null +++ b/sw/programmer/avr/makefile @@ -0,0 +1,31 @@ +### +# Project settings +# +TARGET := programmer +SOURCES := $(wildcard *.c) + +### +# Compiler settings +# +CC := avr-gcc +PORT := /dev/ttyUSB0 +MCU := atmega328p + +CFLAGS := -g -Wall -mcall-prologues -mmcu=$(MCU) -Os -I . \ + -DF_CPU=1000000UL +LDFLAGS := -Wl,-gc-sections -Wl,-relax + +.PHONY: all clean program +all: $(TARGET).hex + +clean: + rm -f *.o *.hex *.obj *.bin + +$(TARGET).hex: $(TARGET).bin + avr-objcopy -R .eeprom -O ihex $(TARGET).bin $@ + +$(TARGET).bin: $(SOURCES) + $(CC) $(CFLAGS) $(SOURCES) -o $@ $(LDFLAGS) + +program: $(TARGET).hex + avrdude -p $(MCU) -c usbasp -P usb -U flash:w:$(TARGET).hex diff --git a/sw/programmer/avr/usart.c b/sw/programmer/avr/usart.c new file mode 100644 index 0000000..8c2eb38 --- /dev/null +++ b/sw/programmer/avr/usart.c @@ -0,0 +1,107 @@ +#include "usart.h" + +static uint16_t usart_baudrate; +static uint16_t usart_baud_prescale; + +void usart_init(uint16_t baudrate) +{ + // enable RX and TX + UCSR0B |= _BV(RXEN0) | _BV(TXEN0); + + // set 8 bit size char + UCSR0C |= _BV(UCSZ01) | _BV(UCSZ00); + + // set baudrate + usart_baudrate = baudrate; + usart_baud_prescale = (F_CPU / (usart_baudrate * 16)) -1; + + UBRR0L = usart_baud_prescale; + UBRR0H = usart_baud_prescale >> 8; +} + +void usart_send_byte(uint8_t data) +{ + while (!(UCSR0A & _BV(UDRE0))); + UDR0 = data; +} + +void usart_send(uint8_t *data, size_t len) +{ + uint8_t *p = data; + + while (len--) { + usart_send_byte(*(p++)); + } +} + +void usart_print(char *str) +{ + char *p = str; + size_t len = 0; + + while (*p++ != '\0') { + len++; + } + + usart_send((uint8_t *) str, len); +} + +int usart_read_byte(uint8_t *byte) +{ + uint16_t timeout = USART_TIMEOUT; + + do { + if (UCSR0A & _BV(RXC0)) { + *byte = UDR0; + return 0; + } + } while (timeout--); + + return -1; +} + +uint8_t usart_read_byte_nt(void) +{ + while ((UCSR0A & _BV(RXC0)) == 0); + return UDR0; +} + + +size_t usart_read(uint8_t *buffer, size_t len) +{ + size_t read = 0; + uint8_t *p = buffer; + + while (len--) { + if (usart_read_byte(p) == 0) { + p++; + read++; + } + } + + return read; +} + +int usart_read_line(uint8_t *buffer, size_t len) +{ + uint8_t ch; + uint8_t *p = buffer; + size_t read = 0; + + while (len--) { + if (usart_read_byte(&ch) != 0) + continue; + else + read++; + + if (ch == '\n') + break; + else + *(p++) = ch; + } + + if (ch != '\n') + return -1; + + return 0; +} diff --git a/sw/programmer/avr/usart.h b/sw/programmer/avr/usart.h new file mode 100644 index 0000000..1bb6607 --- /dev/null +++ b/sw/programmer/avr/usart.h @@ -0,0 +1,96 @@ +#ifndef __USART_H__ +#define __USART_H__ +/*** + * USART REGISTERS {{{ + * + * UCSR: control and status regisers, composed from 3 registers: + * +------------------------------------------------------------------------+ + * | UCSRA :| RXC | TXC | UDRE | FE | DOR | PE | U2X | MPCM | + * +------------------------------------------------------------------------+ + * UCSRA is a status register (read only) + * Relevant bits: + * - RXC : set to 1 if data is present on the receive buffer + * - TXC : set to 1 when data is transferred to the transfer register + * - UDRE: set to 1 when trasmit buffer is empty (data sent) + * +------------------------------------------------------------------------+ + * | UCSRB :| RXCIE | TXCIE | UDRIE | RXEN | TXEN | UCSZ2 | RXB8 | TXB8 | + * +------------------------------------------------------------------------+ + * UCSRB is used to setup hardware configuration + * Relevant bits: + * - RXCIE: RX complete interrupt enabled when set to 1 + * - TXCIE: TX complete interrupt enabled when set to 1 + * - UDRIE: data register empty interrupt enabled when set to 1 + * - RXEN : uart receiver enabled when set to 1 + * - TXEN : uart transmitter enabled when set to 1 + * +------------------------------------------------------------------------+ + * | UCSRC :| URSEL | UMSEL | UPM1 | UPM0 | USBS | UCSZ1 | UCSZ0 | UCPOL | + * +------------------------------------------------------------------------+ + * UCSRB is used to setup protocol configuration + * Relevant bits: + * - URSEL: register select (location is shared with UBRRH and UCSRC) + * - UMSEL: mode select + * 1 -> synchronous + * 0 -> asynchronous + * - UMP1 + UPM0: set parity + * 00 -> no parity + * 01 -> reserved + * 10 -> even + * 11 -> odd + * - UCSZ2 + UCSZ1 + UCSZ0: set data frame (char size) + * 000 -> 5 bit + * 001 -> 6 bit + * 010 -> 7 bit + * 011 -> 8 bit + * 100 to 110 -> reserved + * 111 -> 9 bit + * + * UBRR: baudrate register + * +------------------------------------------------------------------------+ + * | UBRRH :| URSEL | | | | UBRR11| UBRR10| UBRR9 | UBRR8 | + * +------------------------------------------------------------------------+ + * | UBRRL :| UBRR7 | UBRR6 | UBRR5 | UBRR4 | UBRR3 | UBRR2 | UBRR1 | UBRR0 | + * +------------------------------------------------------------------------+ + * UBRR is composed of 2 8 bit registers to store a 12 bit baudrate value. + * The value to be stored in this register is calculated with the following + * formula (approximate to integer): + * UBRR = ( XTAL_frequency ) / ( 16 * BAUDRATE ) -1 + * + * in C code corresponds to: + * #define USART_BAUDRATE 9600 + * #define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) + * + * Relevant bits: + * - URSEL: register select (location is share with UCSRC) + * + * UDR : data register + * This register is shared between RX and TX + * + * }}} + */ + +#include +#include + +#include + +#define USART_TIMEOUT 5000 + +// struct usart_conf +// { +// uint16_t baudrate; +// }; + +void usart_init(uint16_t baudrate); +// void usart_init_conf(struct usart_conf *conf); + +void usart_send_byte(uint8_t data); +void usart_send(uint8_t *data, size_t len); + +void usart_print(char *str); + +int usart_read_byte(uint8_t *byte); +uint8_t usart_read_byte_nt(void); +size_t usart_read(uint8_t *buffer, size_t len); +int uart_read_line(uint8_t *buffer, size_t len); + +#endif -- cgit v1.2.1 From c7925cbb73f319a390507b33e4df44f106822683 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Wed, 23 Aug 2017 16:43:56 +0200 Subject: new programmer interface for linux there is a new program with GUI (gtk3) to send data to its avr conterpart. it needs to be tested, since there may be a few bugs in it; building a GUI was a terrible idea. --- sw/programmer/avr/fileinfo.h | 13 ------------- sw/programmer/avr/main.c | 42 ++++++++++++++++++++++++++---------------- sw/programmer/avr/makefile | 2 +- 3 files changed, 27 insertions(+), 30 deletions(-) delete mode 100644 sw/programmer/avr/fileinfo.h (limited to 'sw/programmer/avr') diff --git a/sw/programmer/avr/fileinfo.h b/sw/programmer/avr/fileinfo.h deleted file mode 100644 index 6c831ed..0000000 --- a/sw/programmer/avr/fileinfo.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __FILEINFO_H__ -#define __FILEINFO_H__ - -#include - -struct file_info -{ - size_t size; - size_t blklen; - uint16_t start_addr; -}; - -#endif diff --git a/sw/programmer/avr/main.c b/sw/programmer/avr/main.c index 90d05fa..9cdc35d 100644 --- a/sw/programmer/avr/main.c +++ b/sw/programmer/avr/main.c @@ -1,5 +1,6 @@ -#include "fileinfo.h" #include "usart.h" + +#include #include #define EEPROM_TICK_MS 10 @@ -18,6 +19,11 @@ #define EEPROM_RD 1 #define EEPROM_CLK 2 +struct file_blk +{ + uint16_t addr; + uint16_t size; +}; void eeprom_write(uint16_t addr, uint8_t byte); void eeprom_tick(); @@ -25,10 +31,10 @@ void eeprom_tick(); int main(void) { uint8_t *buffer, i; - uint16_t addr; size_t read; + char str[64]; - struct file_info *finfo = malloc(sizeof(struct file_info)); + struct file_blk *blk = malloc(sizeof(struct file_blk)); DDRB = 0x7F; DDRC = 0x83; @@ -36,28 +42,32 @@ int main(void) /* get configuration */ usart_init(1200); + usart_print("programmer Ready\n\n\r"); - usart_print("EEPROM Programmer\n\r"); - - do { - usart_print("Waiting for configuration\n\r"); - read = usart_read((uint8_t *) finfo, sizeof(struct file_info)); - } while (read != sizeof(struct file_info)); + while (usart_read((uint8_t *) blk, sizeof(struct file_blk))) { + buffer = malloc(blk->size); + read = usart_read(buffer, blk->size); - usart_print("Programmer Ready\n\n\r"); +#ifdef DEBUG + sprintf(str, "info : reading block from addr %d of size %d\n\r", + blk->addr, blk->size); + usart_print(str); - buffer = malloc(finfo->blklen); - addr = finfo->start_addr; + if (read != blk->size) { + sprintf(str, "error: expected %d but read %d\n\r", + blk->size, read); + usart_print(str); + } +#endif - /* read file */ - while ((read = usart_read(buffer, finfo->blklen))) { for (i = 0; i < read; i++) { - eeprom_write(addr + i, *(buffer++)); + eeprom_write(blk->addr +i, buffer[i]); } - addr += finfo->blklen; + free(buffer); } + free(blk); return 0; } diff --git a/sw/programmer/avr/makefile b/sw/programmer/avr/makefile index 95fb5fe..ba2a709 100644 --- a/sw/programmer/avr/makefile +++ b/sw/programmer/avr/makefile @@ -12,7 +12,7 @@ PORT := /dev/ttyUSB0 MCU := atmega328p CFLAGS := -g -Wall -mcall-prologues -mmcu=$(MCU) -Os -I . \ - -DF_CPU=1000000UL + -DF_CPU=1000000UL -DDEBUG LDFLAGS := -Wl,-gc-sections -Wl,-relax .PHONY: all clean program -- cgit v1.2.1