summaryrefslogtreecommitdiffstats
path: root/sw/programmer/avr
diff options
context:
space:
mode:
authorleleraffa97@hotmail.it <leleraffa97@hotmail.it>2017-08-23 21:18:02 +0200
committerleleraffa97@hotmail.it <leleraffa97@hotmail.it>2017-08-23 21:18:02 +0200
commit3f92d0e29700fc2da45354a4cf3e3afe5c5245c2 (patch)
treecb6def68635ff2b4e4ab30c7e8fdbdf3e730bc05 /sw/programmer/avr
parentFilesystem struct order (diff)
parentnew programmer interface for linux (diff)
downloadz80uPC-3f92d0e29700fc2da45354a4cf3e3afe5c5245c2.tar.gz
z80uPC-3f92d0e29700fc2da45354a4cf3e3afe5c5245c2.zip
Merge remote-tracking branch 'origin/naopross' into atlas
Diffstat (limited to '')
-rw-r--r--sw/programmer/avr/main.c119
-rw-r--r--sw/programmer/avr/makefile31
-rw-r--r--sw/programmer/avr/usart.c107
-rw-r--r--sw/programmer/avr/usart.h96
4 files changed, 353 insertions, 0 deletions
diff --git a/sw/programmer/avr/main.c b/sw/programmer/avr/main.c
new file mode 100644
index 0000000..9cdc35d
--- /dev/null
+++ b/sw/programmer/avr/main.c
@@ -0,0 +1,119 @@
+#include "usart.h"
+
+#include <stdio.h>
+#include <util/delay.h>
+
+#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
+
+struct file_blk
+{
+ uint16_t addr;
+ uint16_t size;
+};
+
+void eeprom_write(uint16_t addr, uint8_t byte);
+void eeprom_tick();
+
+int main(void)
+{
+ uint8_t *buffer, i;
+ size_t read;
+ char str[64];
+
+ struct file_blk *blk = malloc(sizeof(struct file_blk));
+
+ DDRB = 0x7F;
+ DDRC = 0x83;
+ DDRD = 0xFC;
+
+ /* get configuration */
+ usart_init(1200);
+ usart_print("programmer Ready\n<waiting for binary>\n\r");
+
+ while (usart_read((uint8_t *) blk, sizeof(struct file_blk))) {
+ buffer = malloc(blk->size);
+ read = usart_read(buffer, blk->size);
+
+#ifdef DEBUG
+ sprintf(str, "info : reading block from addr %d of size %d\n\r",
+ blk->addr, blk->size);
+ usart_print(str);
+
+ if (read != blk->size) {
+ sprintf(str, "error: expected %d but read %d\n\r",
+ blk->size, read);
+ usart_print(str);
+ }
+#endif
+
+ for (i = 0; i < read; i++) {
+ eeprom_write(blk->addr +i, buffer[i]);
+ }
+
+ free(buffer);
+ }
+
+ free(blk);
+ 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..ba2a709
--- /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 -DDEBUG
+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 <stdint.h>
+#include <stdlib.h>
+
+#include <avr/io.h>
+
+#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