From 83426edcdcc60f1f38427a9201868595a17bd6e8 Mon Sep 17 00:00:00 2001 From: Travis McLane Date: Tue, 24 Mar 2020 16:24:47 -0500 Subject: [PATCH] avr: add Arduino Mega 2560 --- src/machine/board_arduino_mega2560.go | 104 ++++++++++++++++++ src/machine/machine_atmega.go | 46 -------- src/machine/machine_atmega1284p.go | 15 ++- src/machine/machine_atmega2560.go | 148 ++++++++++++++++++++++++++ src/machine/machine_atmega328p.go | 50 ++++++++- targets/arduino-mega2560.json | 8 ++ targets/atmega2560.json | 18 ++++ 7 files changed, 341 insertions(+), 48 deletions(-) create mode 100644 src/machine/board_arduino_mega2560.go create mode 100644 src/machine/machine_atmega2560.go create mode 100644 targets/arduino-mega2560.json create mode 100644 targets/atmega2560.json diff --git a/src/machine/board_arduino_mega2560.go b/src/machine/board_arduino_mega2560.go new file mode 100644 index 00000000..94da3b37 --- /dev/null +++ b/src/machine/board_arduino_mega2560.go @@ -0,0 +1,104 @@ +// +build arduino_mega2560 + +package machine + +// Return the current CPU frequency in hertz. +func CPUFrequency() uint32 { + return 16000000 +} + +const ( + AREF Pin = NoPin + LED Pin = PB7 + + A0 Pin = PF0 + A1 Pin = PF1 + A2 Pin = PF2 + A3 Pin = PF3 + A4 Pin = PF4 + A5 Pin = PF5 + A6 Pin = PF6 + A7 Pin = PF7 + A8 Pin = PK0 + A9 Pin = PK1 + A10 Pin = PK2 + A11 Pin = PK3 + A12 Pin = PK4 + A13 Pin = PK5 + A14 Pin = PK6 + A15 Pin = PK7 + + // Analog Input + ADC0 Pin = PF0 + ADC1 Pin = PF1 + ADC2 Pin = PF2 + ADC3 Pin = PF3 + ADC4 Pin = PF4 + ADC5 Pin = PF5 + ADC6 Pin = PF6 + ADC7 Pin = PF7 + ADC8 Pin = PK0 + ADC9 Pin = PK1 + ADC10 Pin = PK2 + ADC11 Pin = PK3 + ADC12 Pin = PK4 + ADC13 Pin = PK5 + ADC14 Pin = PK6 + ADC15 Pin = PK7 + + // Digital pins + D0 Pin = PE0 + D1 Pin = PE1 + D2 Pin = PE6 + D3 Pin = PE5 + D4 Pin = PG5 + D5 Pin = PE3 + D6 Pin = PH3 + D7 Pin = PH4 + D8 Pin = PH5 + D9 Pin = PH6 + D10 Pin = PB4 + D11 Pin = PB5 + D12 Pin = PB6 + D13 Pin = PB7 + D14 Pin = PJ1 + D15 Pin = PJ0 + D16 Pin = PH1 + D17 Pin = PH0 + D18 Pin = PD3 + D19 Pin = PD2 + D20 Pin = PD1 + D21 Pin = PD0 + D22 Pin = PA0 + D23 Pin = PA1 + D24 Pin = PA2 + D25 Pin = PA3 + D26 Pin = PA4 + D27 Pin = PA5 + D28 Pin = PA6 + D29 Pin = PA7 + D30 Pin = PC7 + D31 Pin = PC6 + D32 Pin = PC5 + D33 Pin = PC4 + D34 Pin = PC3 + D35 Pin = PC2 + D36 Pin = PC1 + D37 Pin = PC0 + D38 Pin = PD7 + D39 Pin = PG2 + D40 Pin = PG1 + D41 Pin = PG0 + D42 Pin = PL7 + D43 Pin = PL6 + D44 Pin = PL5 + D45 Pin = PL4 + D46 Pin = PL3 + D47 Pin = PL2 + D48 Pin = PL1 + D49 Pin = PL0 + D50 Pin = PB3 + D51 Pin = PB2 + D52 Pin = PB1 + D53 Pin = PB0 +) diff --git a/src/machine/machine_atmega.go b/src/machine/machine_atmega.go index 34014347..cac2ce6e 100644 --- a/src/machine/machine_atmega.go +++ b/src/machine/machine_atmega.go @@ -5,54 +5,8 @@ package machine import ( "device/avr" "runtime/interrupt" - "runtime/volatile" ) -// Configure sets the pin to input or output. -func (p Pin) Configure(config PinConfig) { - if config.Mode == PinOutput { // set output bit - if p < 8 { - avr.DDRD.SetBits(1 << uint8(p)) - } else if p < 14 { - avr.DDRB.SetBits(1 << uint8(p-8)) - } else { - avr.DDRC.SetBits(1 << uint8(p-14)) - } - } else { // configure input: clear output bit - if p < 8 { - avr.DDRD.ClearBits(1 << uint8(p)) - } else if p < 14 { - avr.DDRB.ClearBits(1 << uint8(p-8)) - } else { - avr.DDRC.ClearBits(1 << uint8(p-14)) - } - } -} - -// Get returns the current value of a GPIO pin. -func (p Pin) Get() bool { - if p < 8 { - val := avr.PIND.Get() & (1 << uint8(p)) - return (val > 0) - } else if p < 14 { - val := avr.PINB.Get() & (1 << uint8(p-8)) - return (val > 0) - } else { - val := avr.PINC.Get() & (1 << uint8(p-14)) - return (val > 0) - } -} - -func (p Pin) getPortMask() (*volatile.Register8, uint8) { - if p < 8 { - return avr.PORTD, 1 << uint8(p) - } else if p < 14 { - return avr.PORTB, 1 << uint8(p-8) - } else { - return avr.PORTC, 1 << uint8(p-14) - } -} - // InitPWM initializes the registers needed for PWM. func InitPWM() { // use waveform generation diff --git a/src/machine/machine_atmega1284p.go b/src/machine/machine_atmega1284p.go index d94db284..bc25f674 100644 --- a/src/machine/machine_atmega1284p.go +++ b/src/machine/machine_atmega1284p.go @@ -2,7 +2,10 @@ package machine -import "device/avr" +import ( + "device/avr" + "runtime/volatile" +) const irq_USART0_RX = avr.IRQ_USART0_RX @@ -10,3 +13,13 @@ const irq_USART0_RX = avr.IRQ_USART0_RX func CPUFrequency() uint32 { return 20000000 } + +func (p Pin) getPortMask() (*volatile.Register8, uint8) { + if p < 8 { + return avr.PORTD, 1 << uint8(p) + } else if p < 14 { + return avr.PORTB, 1 << uint8(p-8) + } else { + return avr.PORTC, 1 << uint8(p-14) + } +} diff --git a/src/machine/machine_atmega2560.go b/src/machine/machine_atmega2560.go new file mode 100644 index 00000000..e4c3f010 --- /dev/null +++ b/src/machine/machine_atmega2560.go @@ -0,0 +1,148 @@ +// +build avr,atmega2560 + +package machine + +import ( + "device/avr" + "runtime/volatile" +) + +const irq_USART0_RX = avr.IRQ_USART0_RX + +const ( + portA Pin = iota * 8 + portB + portC + portD + portE + portF + portG + portH + portJ + portK + portL +) + +const ( + PA0 = portA + 0 + PA1 = portA + 1 + PA2 = portA + 2 + PA3 = portA + 3 + PA4 = portA + 4 + PA5 = portA + 5 + PA6 = portA + 6 + PA7 = portA + 7 + PB0 = portB + 0 + PB1 = portB + 1 + PB2 = portB + 2 + PB3 = portB + 3 + PB4 = portB + 4 + PB5 = portB + 5 + PB6 = portB + 6 + PB7 = portB + 7 + PC0 = portC + 0 + PC1 = portC + 1 + PC2 = portC + 2 + PC3 = portC + 3 + PC4 = portC + 4 + PC5 = portC + 5 + PC6 = portC + 6 + PC7 = portC + 7 + PD0 = portD + 0 + PD1 = portD + 1 + PD2 = portD + 2 + PD3 = portD + 3 + PD7 = portD + 7 + PE0 = portE + 0 + PE1 = portE + 1 + PE3 = portE + 2 + PE5 = portE + 5 + PE6 = portE + 6 + PF0 = portF + 0 + PF1 = portF + 1 + PF2 = portF + 2 + PF3 = portF + 3 + PF4 = portF + 4 + PF5 = portF + 5 + PF6 = portF + 6 + PF7 = portF + 7 + PG0 = portG + 0 + PG1 = portG + 1 + PG2 = portG + 2 + PG5 = portG + 5 + PH0 = portH + 0 + PH1 = portH + 1 + PH3 = portH + 3 + PH4 = portH + 4 + PH5 = portH + 5 + PH6 = portH + 6 + PJ0 = portJ + 0 + PJ1 = portJ + 1 + PK0 = portK + 0 + PK1 = portK + 1 + PK2 = portK + 2 + PK3 = portK + 3 + PK4 = portH + 4 + PK5 = portH + 5 + PK6 = portH + 6 + PK7 = portH + 7 + PL0 = portL + 0 + PL1 = portL + 1 + PL2 = portL + 2 + PL3 = portL + 3 + PL4 = portL + 4 + PL5 = portL + 5 + PL6 = portL + 6 + PL7 = portE + 7 +) + +// Configure sets the pin to input or output. +func (p Pin) Configure(config PinConfig) { + register, _, mask := p.getRegisterPortMask() + if config.Mode == PinOutput { // set output bit + register.SetBits(mask) + } else { // configure input: clear output bit + register.ClearBits(mask) + } +} + +// Get returns the current value of a GPIO pin. +func (p Pin) Get() bool { + _, port, mask := p.getRegisterPortMask() + return (port.Get() & mask) > 0 +} + +func (p Pin) getPortMask() (*volatile.Register8, uint8) { + _, port, mask := p.getRegisterPortMask() + return port, mask +} + +// getRegisterPortMask returns the register, port, and mask for the pin +func (p Pin) getRegisterPortMask() (*volatile.Register8, *volatile.Register8, uint8) { + switch { + case p >= PA0 && p <= PA7: + return avr.DDRA, avr.PORTA, 1 << uint8(p-portA) + case p >= PB0 && p <= PB7: + return avr.DDRB, avr.PORTB, 1 << uint8(p-portB) + case p >= PC0 && p <= PC7: + return avr.DDRC, avr.PORTC, 1 << uint8(p-portC) + case p >= PD0 && p <= PD7: + return avr.DDRD, avr.PORTD, 1 << uint8(p-portD) + case p >= PE0 && p <= PE6: + return avr.DDRE, avr.PORTE, 1 << uint8(p-portE) + case p >= PF0 && p <= PF7: + return avr.DDRF, avr.PORTF, 1 << uint8(p-portF) + case p >= PG0 && p <= PG5: + return avr.DDRG, avr.PORTG, 1 << uint8(p-portG) + case p >= PH0 && p <= PH6: + return avr.DDRH, avr.PORTH, 1 << uint8(p-portH) + case p >= PJ0 && p <= PJ1: + return avr.DDRJ, avr.PORTJ, 1 << uint8(p-portJ) + case p >= PK0 && p <= PK7: + return avr.DDRK, avr.PORTK, 1 << uint8(p-portK) + case p >= PL0 && p <= PL7: + return avr.DDRL, avr.PORTL, 1 << uint8(p-portL) + default: + return avr.DDRB, avr.PORTA, 255 + } +} diff --git a/src/machine/machine_atmega328p.go b/src/machine/machine_atmega328p.go index 91252d6d..60c36a37 100644 --- a/src/machine/machine_atmega328p.go +++ b/src/machine/machine_atmega328p.go @@ -2,6 +2,54 @@ package machine -import "device/avr" +import ( + "device/avr" + "runtime/volatile" +) const irq_USART0_RX = avr.IRQ_USART_RX + +// Configure sets the pin to input or output. +func (p Pin) Configure(config PinConfig) { + if config.Mode == PinOutput { // set output bit + if p < 8 { + avr.DDRD.SetBits(1 << uint8(p)) + } else if p < 14 { + avr.DDRB.SetBits(1 << uint8(p-8)) + } else { + avr.DDRC.SetBits(1 << uint8(p-14)) + } + } else { // configure input: clear output bit + if p < 8 { + avr.DDRD.ClearBits(1 << uint8(p)) + } else if p < 14 { + avr.DDRB.ClearBits(1 << uint8(p-8)) + } else { + avr.DDRC.ClearBits(1 << uint8(p-14)) + } + } +} + +// Get returns the current value of a GPIO pin. +func (p Pin) Get() bool { + if p < 8 { + val := avr.PIND.Get() & (1 << uint8(p)) + return (val > 0) + } else if p < 14 { + val := avr.PINB.Get() & (1 << uint8(p-8)) + return (val > 0) + } else { + val := avr.PINC.Get() & (1 << uint8(p-14)) + return (val > 0) + } +} + +func (p Pin) getPortMask() (*volatile.Register8, uint8) { + if p < 8 { + return avr.PORTD, 1 << uint8(p) + } else if p < 14 { + return avr.PORTB, 1 << uint8(p-8) + } else { + return avr.PORTC, 1 << uint8(p-14) + } +} diff --git a/targets/arduino-mega2560.json b/targets/arduino-mega2560.json new file mode 100644 index 00000000..792ede40 --- /dev/null +++ b/targets/arduino-mega2560.json @@ -0,0 +1,8 @@ +{ + "inherits": ["atmega2560"], + "build-tags": ["arduino_mega2560"], + "ldflags": [ + "-Wl,--defsym=_bootloader_size=8192" + ], + "flash-command":"avrdude -c wiring -b 115200 -p atmega2560 -P {port} -U flash:w:{hex} -v -D" +} diff --git a/targets/atmega2560.json b/targets/atmega2560.json new file mode 100644 index 00000000..420e803a --- /dev/null +++ b/targets/atmega2560.json @@ -0,0 +1,18 @@ +{ + "inherits": ["avr"], + "llvm-target": "avr-atmel-none", + "cpu": "atmega2560", + "build-tags": ["atmega2560", "atmega"], + "cflags": [ + "-mmcu=atmega2560" + ], + "ldflags": [ + "-mmcu=avr6", + "-Wl,--defsym=_stack_size=512" + ], + "linkerscript": "src/device/avr/atmega2560.ld", + "extra-files": [ + "targets/avr.S", + "src/device/avr/atmega2560.s" + ] +}