From aa8df95f7d144f512842127482eccec6c7d9c3c8 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sun, 15 Dec 2019 09:38:01 -0500 Subject: [PATCH] Add "avr/" includes folder Also, add a "real world" example in AVRA tests, a blink program on a ATtiny45. Some instructions are commented out because they aren't implemented yet, but not many. The output of the program has been verified against AVRA's own output. --- avr/README.md | 16 ++++++++ avr/avr.h | 17 +++++++++ apps/zasm/avr.txt => avr/ops.txt | 0 avr/tn25.h | 10 +++++ avr/tn254585.h | 74 ++++++++++++++++++++++++++++++++++++ avr/tn45.h | 9 +++++ avr/tn85.h | 9 +++++ tools/tests/avra/blink_tn45.asm | 43 +++++++++++++++++++++ tools/tests/avra/blink_tn45.expected | 1 + tools/tests/avra/runtests.sh | 5 ++- tools/zasm.sh | 13 +++++-- 11 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 avr/README.md create mode 100644 avr/avr.h rename apps/zasm/avr.txt => avr/ops.txt (100%) create mode 100644 avr/tn25.h create mode 100644 avr/tn254585.h create mode 100644 avr/tn45.h create mode 100644 avr/tn85.h create mode 100644 tools/tests/avra/blink_tn45.asm create mode 100644 tools/tests/avra/blink_tn45.expected diff --git a/avr/README.md b/avr/README.md new file mode 100644 index 0000000..6f58dc6 --- /dev/null +++ b/avr/README.md @@ -0,0 +1,16 @@ +# AVR include files + +This folder contains header files that can be included in AVR assembly code. + +These definitions are organized in a manner that is very similar to other +modern AVR assemblers, but most bits definitions (`PINB4`, `WGM01`, etc.) are +absent. This is because there's a lot of them, each symbol takes memory during +assembly and machines doing the assembling might be tight in memory. AVR code +post collapse will have to take the habit of using numerical masks accompanied +by comments describing associated symbols. + +To avoid repeats, those includes are organized in 3 levels. First, there's the +`avr.h` file containing definitions common to all AVR models. Then, there's the +"family" file containing definitions common to a "family" (for example, the +ATtiny 25/45/85). Those definitions are the beefiests. Then, there's the exact +model file, which will typically contain RAM and Flash boundaries. diff --git a/avr/avr.h b/avr/avr.h new file mode 100644 index 0000000..c90a804 --- /dev/null +++ b/avr/avr.h @@ -0,0 +1,17 @@ +; *** CPU registers aliases *** + +.equ XH 27 +.equ XL 26 +.equ YH 29 +.equ YL 28 +.equ ZH 31 +.equ ZL 30 + +.equ SREG_C 0 ; Carry Flag +.equ SREG_Z 1 ; Zero Flag +.equ SREG_N 2 ; Negative Flag +.equ SREG_V 3 ; Two's Complement Overflow Flag +.equ SREG_S 4 ; Sign Bit +.equ SREG_H 5 ; Half Carry Flag +.equ SREG_T 6 ; Bit Copy Storage +.equ SREG_I 7 ; Global Interrupt Enable diff --git a/apps/zasm/avr.txt b/avr/ops.txt similarity index 100% rename from apps/zasm/avr.txt rename to avr/ops.txt diff --git a/avr/tn25.h b/avr/tn25.h new file mode 100644 index 0000000..4af6b93 --- /dev/null +++ b/avr/tn25.h @@ -0,0 +1,10 @@ +.equ FLASHEND 0x03ff ; Note: Word address +.equ IOEND 0x003f +.equ SRAM_START 0x0060 +.equ SRAM_SIZE 128 +.equ RAMEND 0x00df +.equ XRAMEND 0x0000 +.equ E2END 0x007f +.equ EEPROMEND 0x007f +.equ EEADRBITS 7 + diff --git a/avr/tn254585.h b/avr/tn254585.h new file mode 100644 index 0000000..8f6c462 --- /dev/null +++ b/avr/tn254585.h @@ -0,0 +1,74 @@ +; *** Registers *** + +.equ SREG 0x3f +.equ SPH 0x3e +.equ SPL 0x3d +.equ GIMSK 0x3b +.equ GIFR 0x3a +.equ TIMSK 0x39 +.equ TIFR 0x38 +.equ SPMCSR 0x37 +.equ MCUCR 0x35 +.equ MCUSR 0x34 +.equ TCCR0B 0x33 +.equ TCNT0 0x32 +.equ OSCCAL 0x31 +.equ TCCR1 0x30 +.equ TCNT1 0x2f +.equ OCR1A 0x2e +.equ OCR1C 0x2d +.equ GTCCR 0x2c +.equ OCR1B 0x2b +.equ TCCR0A 0x2a +.equ OCR0A 0x29 +.equ OCR0B 0x28 +.equ PLLCSR 0x27 +.equ CLKPR 0x26 +.equ DT1A 0x25 +.equ DT1B 0x24 +.equ DTPS 0x23 +.equ DWDR 0x22 +.equ WDTCR 0x21 +.equ PRR 0x20 +.equ EEARH 0x1f +.equ EEARL 0x1e +.equ EEDR 0x1d +.equ EECR 0x1c +.equ PORTB 0x18 +.equ DDRB 0x17 +.equ PINB 0x16 +.equ PCMSK 0x15 +.equ DIDR0 0x14 +.equ GPIOR2 0x13 +.equ GPIOR1 0x12 +.equ GPIOR0 0x11 +.equ USIBR 0x10 +.equ USIDR 0x0f +.equ USISR 0x0e +.equ USICR 0x0d +.equ ACSR 0x08 +.equ ADMUX 0x07 +.equ ADCSRA 0x06 +.equ ADCH 0x05 +.equ ADCL 0x04 +.equ ADCSRB 0x03 + + +; *** Interrupt vectors *** + +.equ INT0addr 0x0001 ; External Interrupt 0 +.equ PCI0addr 0x0002 ; Pin change Interrupt Request 0 +.equ OC1Aaddr 0x0003 ; Timer/Counter1 Compare Match 1A +.equ OVF1addr 0x0004 ; Timer/Counter1 Overflow +.equ OVF0addr 0x0005 ; Timer/Counter0 Overflow +.equ ERDYaddr 0x0006 ; EEPROM Ready +.equ ACIaddr 0x0007 ; Analog comparator +.equ ADCCaddr 0x0008 ; ADC Conversion ready +.equ OC1Baddr 0x0009 ; Timer/Counter1 Compare Match B +.equ OC0Aaddr 0x000a ; Timer/Counter0 Compare Match A +.equ OC0Baddr 0x000b ; Timer/Counter0 Compare Match B +.equ WDTaddr 0x000c ; Watchdog Time-out +.equ USI_STARTaddr 0x000d ; USI START +.equ USI_OVFaddr 0x000e ; USI Overflow + +.equ INT_VECTORS_SIZE 15 ; size in words diff --git a/avr/tn45.h b/avr/tn45.h new file mode 100644 index 0000000..5868719 --- /dev/null +++ b/avr/tn45.h @@ -0,0 +1,9 @@ +.equ FLASHEND 0x07ff ; Note: Word address +.equ IOEND 0x003f +.equ SRAM_START 0x0060 +.equ SRAM_SIZE 256 +.equ RAMEND 0x015f +.equ XRAMEND 0x0000 +.equ E2END 0x00ff +.equ EEPROMEND 0x00ff +.equ EEADRBITS 8 diff --git a/avr/tn85.h b/avr/tn85.h new file mode 100644 index 0000000..bd052ce --- /dev/null +++ b/avr/tn85.h @@ -0,0 +1,9 @@ +.equ FLASHEND 0x0fff ; Note: Word address +.equ IOEND 0x003f +.equ SRAM_START 0x0060 +.equ SRAM_SIZE 512 +.equ RAMEND 0x025f +.equ XRAMEND 0x0000 +.equ E2END 0x01ff +.equ EEPROMEND 0x01ff +.equ EEADRBITS 9 diff --git a/tools/tests/avra/blink_tn45.asm b/tools/tests/avra/blink_tn45.asm new file mode 100644 index 0000000..09a9344 --- /dev/null +++ b/tools/tests/avra/blink_tn45.asm @@ -0,0 +1,43 @@ +; TODO: implement instructions that are commented out +; REGISTER USAGE +; +; R1: overflow counter +; R16: tmp stuff + +.inc "avr.h" +.inc "tn254585.h" +.inc "tn45.h" + +main: + ldi r16, RAMEND&0xff + out SPL, r16 + ldi r16, RAMEND}8 + out SPH, r16 + + ;sbi DDRB, 0 + ;cbi PORTB, 0 + + ; To have a blinking delay that's visible, we have to prescale a lot. + ; The maximum prescaler is 1024, which makes our TCNT0 increase + ; 976 times per second, which means that it overflows 4 times per + ; second. + in r16, TCCR0B + ori r16, 0x05 ; CS00 + CS02 = 1024 prescaler + out TCCR0B, r16 + + ;clr r1 + +loop: + in r16, TIFR ; TIFR0 + sbrc r16, 1 ; is TOV0 flag clear? + rcall toggle + rjmp loop + +toggle: + ldi r16, 0b00000010 ; TOV0 + out TIFR, R16 + inc r1 + ;cbi PORTB, 0 + sbrs r1, 1 ; if LED is on + ;sbi PORTB, 0 + ret diff --git a/tools/tests/avra/blink_tn45.expected b/tools/tests/avra/blink_tn45.expected new file mode 100644 index 0000000..f245628 --- /dev/null +++ b/tools/tests/avra/blink_tn45.expected @@ -0,0 +1 @@ +å ¿à¿·`¿·ýÐüÏà¿”þ• \ No newline at end of file diff --git a/tools/tests/avra/runtests.sh b/tools/tests/avra/runtests.sh index 99b8ffa..03ca0a6 100755 --- a/tools/tests/avra/runtests.sh +++ b/tools/tests/avra/runtests.sh @@ -1,11 +1,12 @@ #!/bin/sh -e -AVRA=../../emul/zasm/avra +ZASM=../../zasm.sh +AVRINC=../../../avr cmpas() { FN=$1 EXPECTED=$(xxd ${FN%.*}.expected) - ACTUAL=$(cat ${FN} | $AVRA | xxd) + ACTUAL=$(cat ${FN} | "${ZASM}" -a "${AVRINC}" | xxd) if [ "$ACTUAL" = "$EXPECTED" ]; then echo ok else diff --git a/tools/zasm.sh b/tools/zasm.sh index c1bea60..f3d274a 100755 --- a/tools/zasm.sh +++ b/tools/zasm.sh @@ -6,15 +6,22 @@ # binary. For example, "zasm.sh -o 4f < foo.asm" assembles foo.asm as if it # started with the line ".org 0x4f00". +# The -a flag makes us switch to the AVR assembler + # readlink -f doesn't work with macOS's implementation # so, if we can't get readlink -f to work, try python with a realpath implementation ABS_PATH=$(readlink -f "$0" || python -c "import os; print(os.path.realpath('$0'))") +DIR=$(dirname "${ABS_PATH}") +ZASMBIN="${DIR}/emul/zasm/zasm" -usage() { echo "Usage: $0 [-o ] ..." 1>&2; exit 1; } +usage() { echo "Usage: $0 [-a] [-o ] ..." 1>&2; exit 1; } org='00' -while getopts ":o:" opt; do +while getopts ":ao:" opt; do case "${opt}" in + a) + ZASMBIN="${DIR}/emul/zasm/avra" + ;; o) org=${OPTARG} ;; @@ -26,8 +33,6 @@ done shift $((OPTIND-1)) # wrapper around ./emul/zasm/zasm that prepares includes CFS prior to call -DIR=$(dirname "${ABS_PATH}") -ZASMBIN="${DIR}/emul/zasm/zasm" CFSPACK="${DIR}/cfspack/cfspack" INCCFS=$(mktemp)