Nano Every Page: Difference between revisions
(44 intermediate revisions by the same user not shown) | |||
Line 212: | Line 212: | ||
I did not like the use of PORTC, PORTD etc as this suggested shortcuts and would obfuscate the code. But reading more I found that the code struggled to meet the timings to disable the AT28C256 protections which is why it took me so long to get this going. Many thanks to TommyPROM which was my last port of call. https://tomnisbet.github.io/TommyPROM/28C256-notes/<br> | I did not like the use of PORTC, PORTD etc as this suggested shortcuts and would obfuscate the code. But reading more I found that the code struggled to meet the timings to disable the AT28C256 protections which is why it took me so long to get this going. Many thanks to TommyPROM which was my last port of call. https://tomnisbet.github.io/TommyPROM/28C256-notes/<br> | ||
[[File:AT28C256.jpg]]<br> | [[File:AT28C256.jpg]]<br> | ||
=Nano Every= | =Arduino Nano= | ||
I also had trouble setting up the Nano, the every previous. Need to stop the brtty service running for it to connect | |||
<syntaxhighlight lang="bashs"> | |||
systemctl stop brltty-udev.service | |||
sudo systemctl mask brltty-udev.service | |||
systemctl stop brltty.service | |||
systemctl disable brltty.service | |||
</syntaxhighlight> | |||
=Arduino and with Nano Every= | |||
I could not install the Arduino software using apt and with snap the directories were somewhere else. For me on Ubuntu 23.04 I instead downloaded, and extracted it. Make sure you make a directory to extract to. Then when you run the IDE you will be able to select Nano Every and there will be the 1.8.8 directory. Without 1.8.8 you will not be able to upload with VS Code. Here is my arduino.json setting. | |||
<syntaxhighlight lang="json"> | |||
{ | |||
"port": "/dev/ttyACM1", | |||
"board": "arduino:megaavr:nona4809", | |||
"sketch": "blinkNative.ino", | |||
"programmer": "medbg", | |||
"configuration": "mode=on" | |||
} | |||
</syntaxhighlight> | |||
=Blink and VS Code with Nano Every= | |||
Really do not like the Arduino IDE so was really happy VS Code not supports it with the Microsoft Extension. Just look at the colours and the status bar, board, usb port.<br> | Really do not like the Arduino IDE so was really happy VS Code not supports it with the Microsoft Extension. Just look at the colours and the status bar, board, usb port.<br> | ||
[[File:Ardunino VSCOD.jpg]]<br><br> | [[File:Ardunino VSCOD.jpg]]<br><br> | ||
Line 770: | Line 790: | ||
] | ] | ||
} | } | ||
</syntaxhighlight> | |||
=Rust on Nano Every= | |||
Next up is trying to get Rust to run on the nano every which has a atmega4809. This was a weekend journey and probably could be done faster in the person driving had better skills. I document it here so people can may find this page and learn from the problems I have experienced. | |||
==Create Cargo Project== | |||
First off let create a new project | |||
<syntaxhighlight lange="bash"> | |||
cargo new project_me | |||
</syntaxhighlight> | |||
==Add HAL (hardware abstraction layer) to project== | |||
Add the embedded-hal to project by going to the Cargo.toml and adding embedded-hal as a dependency. It is a generic layer and you will need a chip specific one as well. | |||
<syntaxhighlight lang="toml"> | |||
[dependencies] | |||
embedded-hal = "0.1.2" | |||
</syntaxhighlight> | |||
Using cargo build resulted in the following error | |||
<syntaxhighlight lang="bash"> | |||
error[E0554]: `#![feature]` may not be used on the stable release channel | |||
</syntaxhighlight> | |||
This is because we cannot use the stable toolchain which is the default. To list the toolchains available you can use. | |||
<syntaxhighlight lang="bash"> | |||
rustup toolchain list | |||
</syntaxhighlight> | |||
In my case, because I have already installed other toolchains, the output was | |||
<syntaxhighlight lang="bash"> | |||
stable-x86_64-unknown-linux-gnu (default) | |||
nightly-x86_64-unknown-linux-gnu | |||
snowgoons | |||
</syntaxhighlight> | |||
To install the nightly toolchain use the rustup command. | |||
<syntaxhighlight lang="bash"> | |||
rustup install nightly | |||
</syntaxhighlight> | |||
We are going to override the default but it if we wanted to set the default we can with this | |||
<syntaxhighlight lang="bash"> | |||
rustup default stable-x86_64-unknown-linux-gnu | |||
</syntaxhighlight> | |||
Now we can run the cargo build and it completes successfully. We can set the toolchain to use in the an override file in the root directory rust-toolchain.toml. You find this in the overrides section of the [https://rust-lang.github.io/rustup/overrides.html rustup book]. An example is shown below. | |||
<syntaxhighlight lang="toml"> | |||
[toolchain] | |||
#The name of the toolchain to use. We are using snowgoons as this is | |||
channel = "nightly-x86_64-unknown-linux-gnu" | |||
components = ["rust-src"] | |||
</syntaxhighlight> | |||
==Adding Chip Specific HAL== | |||
In the videos by [https://www.youtube.com/playlist?list=PLP_X41VhYn5X6Wwjnm0bRwI3n2pdaszxU Vers Binarii] it mentions finding the hal for an STM32F103C8T6 and guides you to [https://lib.rs lib.rs] to get the board specific hal. Unfortunately this does not exist for the ATMega4809. So from there I made my way back to [https://snowgoons.ro/posts/2020-11-11-compiling-rust-for-arduino-nano-every-part-one snowgoons] where I first started. He suggested, at least to me, instead of stm32f1xx-hal I should use ruduino for my ATMega4809 (nano every). This gave the error | |||
<syntaxhighlight lang="bash"> | |||
error: cannot find macro `llvm_asm` in this scope | |||
</syntaxhighlight> | |||
Googling led me to running the rustup update command | |||
<syntaxhighlight lang="bash"> | |||
rustup update | |||
</syntaxhighlight> | |||
Was not hopeful as I assume that I am already at the latest. After the version shown was (rustc 1.71.0-nightly). So I reran the build and... | |||
<syntaxhighlight lang="bash"> | |||
error[E0635]: unknown feature `llvm_asm` | |||
</syntaxhighlight> | |||
Looking at this, and not that familiar with rust, I think they have renamed llvm_asm to asm and this appears avr_delay presumably used by ruduino. This went into the too hard basket and I went looking for a different hal. Next up is avr-oxide. Putting in the latest version at the time 0.4.0 ( nothing is version 1.0.0 :grinning: ). So running the build gives new and more fun problems. | |||
<syntaxhighlight lang="bash"> | |||
| | |||
22 | compile_error!("A clockspeed feature (\"16MHz\", \"20MHz\") must be enabled for this crate"); | |||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |||
</syntaxhighlight> | |||
I remember when watching Vers you can enable and disable features. Lets see what we need. We know that the nano every is 20MHz. So lets put that in and the chip which it also spat out on the error | |||
<syntaxhighlight lang="toml"> | |||
[dependencies.avr-oxide] | |||
version = "0.4.1" | |||
features = ["20MHz","atmega4809"] | |||
</syntaxhighlight> | |||
No joy just more errors. But we have learned a fair bit about the rust build system | |||
<syntaxhighlight lang="bash"> | |||
error: ~const can only be applied to `#[const_trait]` traits | |||
--> /home/iwiseman/.cargo/registry/src/index.crates.io-6f17d22bba15001f/avr-oxide-0.4.1/src/oserror.rs:194:22 | |||
</syntaxhighlight> | |||
Next up I found [https://github.com/Rahix/avr-hal avr-hal]. This mentions nano but not nano every. Lets give it a go. | |||
<syntaxhighlight lang="bash"> | |||
git clone https://github.com/Rahix/avr-hal avr-hal | |||
cd examples/arduino-nano/ | |||
cargo build | |||
... | |||
Compiling avr-device v0.5.1 | |||
Compiling nb v0.1.3 | |||
Compiling embedded-hal v0.2.7 | |||
Compiling atmega-hal v0.1.0 (/home/iwiseman/dev/projects/at4809/avr-hal/mcu/atmega-hal) | |||
Compiling arduino-hal v0.1.0 (/home/iwiseman/dev/projects/at4809/avr-hal/arduino-hal) | |||
Compiling arduino-nano-examples v0.0.0 (/home/iwiseman/dev/projects/at4809/avr-hal/examples/arduino-nano) | |||
WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without. | |||
WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without. | |||
Finished dev [optimized + debuginfo] target(s) in 22.28s | |||
</syntaxhighlight> | |||
==Built but not running== | |||
To run the we do the following | |||
<syntaxhighlight lang="bash"> | |||
cargo run --bin nano-blink | |||
WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without. | |||
Finished dev [optimized + debuginfo] target(s) in 0.03s | |||
Running `ravedude nano -cb 57600 /home/iwiseman/dev/projects/at4809/avr-hal/target/avr-atmega328p/debug/nano-blink.elf` | |||
Board Arduino Nano | |||
Error: no matching serial port found, use -P or set RAVEDUDE_PORT in your environment | |||
</syntaxhighlight> | |||
So we know how to solve this one, it is looking for the device my nano is on /dev/ttyACMO. | |||
<syntaxhighlight lang="bash"> | |||
export RAVEDUDE_PORT=/dev/ttyACMO | |||
</syntaxhighlight> | |||
So lets give it a whirl | |||
<syntaxhighlight lang="bash"> | |||
WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without. | |||
Finished dev [optimized + debuginfo] target(s) in 0.03s | |||
Running `ravedude nano -cb 57600 /home/iwiseman/dev/projects/at4809/avr-hal/target/avr-atmega328p/debug/nano-blink.elf` | |||
Board Arduino Nano | |||
Programming /home/iwiseman/dev/projects/at4809/avr-hal/target/avr-atmega328p/debug/nano-blink.elf => /dev/ttyACM0 | |||
avrdude: stk500_recv(): programmer is not responding | |||
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00 | |||
avrdude: stk500_recv(): programmer is not responding | |||
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x00 | |||
avrdude: stk500_recv(): programmer is not responding | |||
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x00 | |||
</syntaxhighlight> | |||
I found that avr-hal is running something called ravedude which appears to be a wrapper for avrdude which is what I noticed the native blink example runs when using vscode and the arduino plugin uses. We are using the same software and we know it works so what is the problem. So lets see which version of avrdude it is using. | |||
<syntaxhighlight lang="bash"> | |||
which avrdude | |||
/usr/bin/avrdude | |||
avrdude -v | |||
avrdude: Version 6.3-20171130 | |||
</syntaxhighlight> | |||
Lets see what arduino is using. In my case this was going to home directory and look for a likely hidden folder. | |||
<syntaxhighlight lang="bash"> | |||
ls -la |grep ".ard" | |||
drwxr-xr-x 6 iwiseman iwiseman 4096 May 13 17:25 .arduino15 | |||
drwxrwxr-x 7 iwiseman iwiseman 4096 May 13 17:25 .arduinoIDE | |||
</syntaxhighlight> | |||
Looking in .arduino15 showed a version of avrdude exists and was 6.3-20171130 so this clearly was not the issue. Getting there I promise. So I looked at he parameters being used with avrdude by making a fake script replacing avrdude | |||
<syntaxhighlight lang="bash"> | |||
#!/bin/bash | |||
echo $@ >/tmp/fred.txt | |||
</syntaxhighlight> | |||
Looking an the output we have. So I change the avr-hal/examples/arduino-nano/.cargo/config.toml to have these | |||
<syntaxhighlight lang="bash"> | |||
-C/home/iwiseman/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -V -patmega4809 -cjtag2updi -P/dev/ttyACM0 -b115200 -e -D -Uflash:w:/tmp/arduino/sketches/6F5689DFFC2E237B65FDBBAD8847D814/blinkNative.ino.hex:i -Ufuse2:w:0x01:m -Ufuse5:w:0xC9:m -Ufuse8:w:0x00:m {upload.extra_files} | |||
</syntaxhighlight> | |||
So here is the config.toml. Note I need to change the command to use an elf rather than the hex file. I went to [https://quickref.me/toml.html TOML cheat sheet] for the multiline command | |||
<syntaxhighlight lang="toml"> | |||
[build] | |||
target = "../../avr-specs/avr-atmega328p.json" | |||
[target.'cfg(target_arch = "avr")'] | |||
#runner = "ravedude nano -cb 57600" | |||
runner = """/home/iwiseman/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude \ | |||
-C /home/iwiseman/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf \ | |||
-v \ | |||
-V \ | |||
-patmega4809 \ | |||
-cjtag2updi \ | |||
-P/dev/ttyACM0 \ | |||
-b115200 \ | |||
-e \ | |||
-D \ | |||
-Uflash:w:./target/avr-atmega328p/debug/nano-blink.elf | |||
-Ufuse2:w:0x01:m \ | |||
-Ufuse5:w:0xC9:m \ | |||
-Ufuse8:w:0x00:m""" | |||
[unstable] | |||
build-std = ["core"] | |||
</syntaxhighlight> | |||
This gave the following output and was the final issue to solve. | |||
<syntaxhighlight lang="bash"> | |||
avrdude: jtagmkII_getsync(): sign-on command: status -1 | |||
avrdude: jtagmkII_getsync(): sign-on command: status -1 | |||
avrdude: jtagmkII_getsync(): sign-on command: status -1 | |||
avrdude: jtagmkII_getsync(): sign-on command: status -1 | |||
</syntaxhighlight> | |||
I googled avrdude: jtagmkII_getsync() and found [https://forum.arduino.cc/t/cant-upload-sketches-to-nano-every-jtagmkii-getsync-sign-on-command-status-1/1058014/13 this]. It appears you need to set the baud rate at 1200 bps briefly before attempting to upload. I am a idiot and know nothing so back to google on how to do this. Googling "avrdude 1200 rust" I find I am back to snowgoons and indeed there is a script showing how to do this. Here it is. '''Had to change stty -f to stty -F'''' probably a windows thing and I am on linux | |||
<syntaxhighlight lang="bash"> | |||
#!/bin/bash | |||
# Gimme the name of a file to load | |||
ELFFILE=${1} | |||
# We need to use the `avrdude` that comes with the Arduino IDE, it seems | |||
# to have some custom changes not in the version we installed from Brew, that | |||
# work with the UPDI-over-USB bootloader on the Arduino Nano Every | |||
AVRDUDE=~/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude | |||
AVRCONF=~/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf | |||
# Chip option fuses | |||
FUSE_OSCCFG=0x82 # 20 MHz | |||
FUSE_SYSCFG0=0xC9 # No CRC, Reset is Reset, don't erase EEPROM | |||
FUSE_BOOTEND=0x00 # Whole Flash is boot | |||
# Device specific flags | |||
PART=atmega4809 | |||
PROGRAMMER=jtag2updi | |||
BAUDRATE=115200 | |||
# Where to find it | |||
PORT=$(find /dev/cu.usbmodem* | head -n 1) | |||
# We reset the Arduino (and put it into UPDI mode) by opening & closing the | |||
# serial port at 1200baud (this is some kind of 'backdoor' reset process | |||
# built into the USB software that runs on the Nano Every's coprocessor | |||
# for handling USB-to-UPDI. | |||
stty -F "${PORT}" 1200 | |||
# Wait for the port to be available again | |||
while [ 1 ]; do | |||
sleep 0.5 | |||
[ -c "${PORT}" ] && break | |||
done | |||
# NOW, finally, we can actually upload our code | |||
${AVRDUDE} \ | |||
-C ${AVRCONF} \ | |||
-v -p${PART} \ | |||
-c${PROGRAMMER} \ | |||
-P${PORT} -b${BAUDRATE} \ | |||
-e -D \ | |||
-Uflash:w:${ELFFILE}:e \ | |||
-Ufuse2:w:${FUSE_OSCCFG}:m -Ufuse5:w:${FUSE_SYSCFG0}:m -Ufuse8:w:${FUSE_BOOTEND}:m | |||
</syntaxhighlight> | |||
==Working at Last== | |||
So putting it all together | |||
<syntaxhighlight lang="bash"> | |||
cargo install cargo-generate | |||
cargo generate --git https://github.com/Rahix/avr-hal-template.git | |||
</syntaxhighlight> | |||
Go into your project and here is the blink code | |||
<syntaxhighlight lang="rs"> | |||
#![no_std] | |||
#![no_main] | |||
use panic_halt as _; | |||
#[arduino_hal::entry] | |||
fn main() -> ! { | |||
let dp = arduino_hal::Peripherals::take().unwrap(); | |||
let pins = arduino_hal::pins!(dp); | |||
let mut led = pins.d13.into_output(); | |||
loop { | |||
led.set_high(); | |||
arduino_hal::delay_ms(500); | |||
led.set_low(); | |||
arduino_hal::delay_ms(500); | |||
} | |||
} | |||
</syntaxhighlight> | |||
Build and upload | |||
<syntaxhighlight lang="bash"> | |||
cargo build | |||
arduino-nano-every-upload.sh ./target/avr-atmega328p/debug/blink-me.elf | |||
</syntaxhighlight> | |||
[[File:Atmega4809 rust.gif]] | |||
==First PR For years== | |||
So looked at how to streamline this and amended Rahix code to support the arduino approach. | |||
<syntaxhighlight lang="bash"> | |||
git clone https://github.com/bibble235/avr-hal | |||
export RAVEDUDE_PORT=/dev/ttyACM0 | |||
export RAVEDUDE_AVRDUDE_ROOT=/home/iwiseman/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 | |||
cd examples/nano-every | |||
cargo run | |||
</syntaxhighlight> | </syntaxhighlight> |
Latest revision as of 21:13, 24 December 2024
Introduction
I while ago I started my interest in the 6502 where it all began to me. This led me to Ben Eater and building an 8-bit computer. Which led me to building a EEPROM programmer and a Nano was required to build it. I had a bit of work to do and my interest seemed to be waning a little. Partly because of the time to get it to work and and because I just felt demotivated. So I solved my motivation by returning to rust and saw that it is possible to run it on a Nano Every. Let the games begin.
Ben's EEPROM
The Board
Here is the EEPROM. I think I made it look quite pretty with the colours. Funny how that seemed important at the time.
The Circuit
I ended up using the circuit from Ben's page. The nano D5 connected to the AT28C256
The Code
And of course the code.
#define SHIFT_DATA 2
#define SHIFT_CLK 3
#define SHIFT_LATCH 4
#define WRITE_EN 13
// 32 byte test pattern to verify the EEPROM device. The pattern includes a walking one
// and a walking zero, which may help to detect pins that are tied together or swapped.
// byte data[] = {
// 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
// 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
// 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe,
// 0x00, 0xff, 0x55, 0xaa, '0', '1', '2', '3'
// };
byte data[] = {
'A', 'B', 'B', 'D', 'E', 'F', 'G', 'H',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'
};
void enableWrite() { digitalWrite(WRITE_EN, LOW);}
void disableWrite() { digitalWrite(WRITE_EN, HIGH);}
// Read a byte from the data bus. The caller must set the bus to input_mode
// before calling this or no useful data will be returned.
byte readDataBus() {
return (PINB << 3) | (PIND >> 5);
}
// Read a byte from the EEPROM at the specified address.
byte readEEPROM(int address) {
setDataBusMode(INPUT);
setAddress(address, /*outputEnable*/ true);
return readDataBus();
}
// Write a byte to the EEPROM at the specified address.
void writeEEPROM(int address, byte data) {
setAddress(address, /*outputEnable*/ false);
setDataBusMode(OUTPUT);
writeDataBus(data);
enableWrite();
// delayMicroseconds(1);
disableWrite();
delay(10);
}
// Read the first 256 byte block of the EEPROM and dump it to the serial monitor.
void printContents(int size) {
for (int base = 0; (base < size); base += 16) {
byte data[16];
for (int offset = 0; offset <= 15; offset += 1) {
data[offset] = readEEPROM(base + offset);
}
char buf[80];
sprintf(buf, "%04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
base, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
Serial.println(buf);
}
}
// Output the address bits and outputEnable signal using shift registers.
void setAddress(int addr, bool outputEnable) {
// Set the highest bit as the output enable bit (active low)
if (outputEnable) {
addr &= ~0x8000;
} else {
addr |= 0x8000;
}
byte dataMask = 0x04;
byte clkMask = 0x08;
byte latchMask = 0x10;
// Make sure the clock is low to start.
PORTD &= ~clkMask;
// Shift 16 bits in, starting with the MSB.
for (uint16_t ix = 0; (ix < 16); ix++)
{
// Set the data bit
if (addr & 0x8000)
{
PORTD |= dataMask;
}
else
{
PORTD &= ~dataMask;
}
// Toggle the clock high then low
PORTD |= clkMask;
// delayMicroseconds(3);
PORTD &= ~clkMask;
addr <<= 1;
}
// Latch the shift register contents into the output register.
PORTD &= ~latchMask;
// delayMicroseconds(1);
PORTD |= latchMask;
// delayMicroseconds(1);
PORTD &= ~latchMask;
}
// Write a byte to the data bus. The caller must set the bus to output_mode
// before calling this or no data will be written.
void writeDataBus(byte data) {
PORTB = (PORTB & 0xe0) | (data >> 3);
PORTD = (PORTD & 0x1f) | (data << 5);
}
// Set an address and data value and toggle the write control. This is used
// to write control sequences, like the software write protect. This is not a
// complete byte write function because it does not set the chip enable or the
// mode of the data bus.
void setByte(byte value, word address) {
setAddress(address, false);
writeDataBus(value);
// delayMicroseconds(1);
enableWrite();
// delayMicroseconds(1);
disableWrite();
}
// Set the I/O state of the data bus.
// The 8 bits data bus are is on pins D5..D12.
void setDataBusMode(uint8_t mode) {
// On the Uno and Nano, D5..D12 maps to the upper 3 bits of port D and the
// lower 5 bits of port B.
if (mode == OUTPUT) {
DDRB |= 0x1f;
DDRD |= 0xe0;
} else {
DDRB &= 0xe0;
DDRD &= 0x1f;
}
}
void disableSoftwareWriteProtect() {
disableWrite();
setDataBusMode(OUTPUT);
setByte(0xaa, 0x5555);
setByte(0x55, 0x2aaa);
setByte(0x80, 0x5555);
setByte(0xaa, 0x5555);
setByte(0x55, 0x2aaa);
setByte(0x20, 0x5555);
setDataBusMode(INPUT);
delay(10);
}
void setup() {
// put your setup code here, to run once:
pinMode(SHIFT_DATA, OUTPUT);
pinMode(SHIFT_CLK, OUTPUT);
pinMode(SHIFT_LATCH, OUTPUT);
disableWrite();
pinMode(WRITE_EN, OUTPUT);
Serial.begin(115200);
Serial.print("\nDisabling EEPROM Software Data Protection(SDP)...");
disableSoftwareWriteProtect();
Serial.println(" done\n");
// Read and print out the contents of the EERPROM
Serial.println("Reading EEPROM");
printContents(32);
// Program a test pattern and fill the remainder of the first block with 0xff
Serial.print("Programming EEPROM...");
for (word address = 0; (address < sizeof(data)); address++) {
writeEEPROM(address, data[address]);
}
// for (word address = sizeof(data); (address < 256); address++) {
// writeEEPROM(address, 0xfe);
// }
Serial.println(" done\n");
// Read and print out the contents of the EERPROM
Serial.println("Reading EEPROM");
printContents(32);
}
void loop()
{
// put your main code here, to run repeatedly:
}
Disabling Software Protection (SDP)
I did not like the use of PORTC, PORTD etc as this suggested shortcuts and would obfuscate the code. But reading more I found that the code struggled to meet the timings to disable the AT28C256 protections which is why it took me so long to get this going. Many thanks to TommyPROM which was my last port of call. https://tomnisbet.github.io/TommyPROM/28C256-notes/
Arduino Nano
I also had trouble setting up the Nano, the every previous. Need to stop the brtty service running for it to connect
systemctl stop brltty-udev.service
sudo systemctl mask brltty-udev.service
systemctl stop brltty.service
systemctl disable brltty.service
Arduino and with Nano Every
I could not install the Arduino software using apt and with snap the directories were somewhere else. For me on Ubuntu 23.04 I instead downloaded, and extracted it. Make sure you make a directory to extract to. Then when you run the IDE you will be able to select Nano Every and there will be the 1.8.8 directory. Without 1.8.8 you will not be able to upload with VS Code. Here is my arduino.json setting.
{
"port": "/dev/ttyACM1",
"board": "arduino:megaavr:nona4809",
"sketch": "blinkNative.ino",
"programmer": "medbg",
"configuration": "mode=on"
}
Blink and VS Code with Nano Every
Really do not like the Arduino IDE so was really happy VS Code not supports it with the Microsoft Extension. Just look at the colours and the status bar, board, usb port.
Had to add the udev rules in /etc/udev/rules.d/99-arduino-nano.rules
# Arduino nano SUBSYSTEM=="tty", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0058", PROGRAM="/usr/bin/arduino-udev-name -w 2 %k", SYMLINK+="%c", GROUP="plugdev"
These were generated by the plugin but here for reference. (Loving the nona) in arduino.json
{
"port": "/dev/ttyACM0",
"configuration": "mode=on",
"board": "arduino:megaavr:nona4809",
"sketch": "blinkNative.ino"
}
and c_cpp_properties.json
{
"version": 4,
"configurations": [
{
"name": "Arduino",
"compilerPath": "/home/iwiseman/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/bin/avr-g++",
"compilerArgs": [
"-w",
"-std=gnu++11",
"-fpermissive",
"-fno-exceptions",
"-ffunction-sections",
"-fdata-sections",
"-fno-threadsafe-statics",
"-Wno-error=narrowing"
],
"intelliSenseMode": "gcc-x64",
"includePath": [
"/home/iwiseman/.arduino15/packages/arduino/hardware/megaavr/1.8.8/cores/arduino/api/deprecated",
"/home/iwiseman/.arduino15/packages/arduino/hardware/megaavr/1.8.8/cores/arduino",
"/home/iwiseman/.arduino15/packages/arduino/hardware/megaavr/1.8.8/variants/nona4809",
"/home/iwiseman/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/lib/gcc/avr/7.3.0/include",
"/home/iwiseman/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/lib/gcc/avr/7.3.0/include-fixed",
"/home/iwiseman/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/avr/include"
],
"forcedInclude": [
"/home/iwiseman/.arduino15/packages/arduino/hardware/megaavr/1.8.8/cores/arduino/Arduino.h"
],
"cStandard": "c11",
"cppStandard": "c++11",
"defines": [
"F_CPU=16000000L",
"ARDUINO=10607",
"ARDUINO_AVR_NANO_EVERY",
"ARDUINO_ARCH_MEGAAVR",
"AVR_NANO_4809_328MODE",
"MILLIS_USE_TIMERB3",
"NO_EXTERNAL_I2C_PULLUP",
"__DBL_MIN_EXP__=(-125)",
"__HQ_FBIT__=15",
"__cpp_attributes=200809",
"__UINT_LEAST16_MAX__=0xffffU",
"__ATOMIC_ACQUIRE=2",
"__SFRACT_IBIT__=0",
"__FLT_MIN__=1.17549435e-38F",
"__GCC_IEC_559_COMPLEX=0",
"__BUILTIN_AVR_SLEEP=1",
"__BUILTIN_AVR_COUNTLSULLK=1",
"__cpp_aggregate_nsdmi=201304",
"__BUILTIN_AVR_COUNTLSULLR=1",
"__UFRACT_MAX__=0XFFFFP-16UR",
"__UINT_LEAST8_TYPE__=unsigned char",
"__DQ_FBIT__=63",
"__INTMAX_C(c)=c ## LL",
"__ULFRACT_FBIT__=32",
"__SACCUM_EPSILON__=0x1P-7HK",
"__CHAR_BIT__=8",
"__USQ_IBIT__=0",
"__UINT8_MAX__=0xff",
"__ACCUM_FBIT__=15",
"__WINT_MAX__=0x7fff",
"__FLT32_MIN_EXP__=(-125)",
"__cpp_static_assert=200410",
"__USFRACT_FBIT__=8",
"__ORDER_LITTLE_ENDIAN__=1234",
"__SIZE_MAX__=0xffffU",
"__WCHAR_MAX__=0x7fff",
"__LACCUM_IBIT__=32",
"__DBL_DENORM_MIN__=double(1.40129846e-45L)",
"__GCC_ATOMIC_CHAR_LOCK_FREE=1",
"__GCC_IEC_559=0",
"__FLT_EVAL_METHOD__=0",
"__BUILTIN_AVR_LLKBITS=1",
"__cpp_binary_literals=201304",
"__LLACCUM_MAX__=0X7FFFFFFFFFFFFFFFP-47LLK",
"__GCC_ATOMIC_CHAR32_T_LOCK_FREE=1",
"__BUILTIN_AVR_HKBITS=1",
"__BUILTIN_AVR_BITSLLK=1",
"__FRACT_FBIT__=15",
"__BUILTIN_AVR_BITSLLR=1",
"__cpp_variadic_templates=200704",
"__UINT_FAST64_MAX__=0xffffffffffffffffULL",
"__SIG_ATOMIC_TYPE__=char",
"__BUILTIN_AVR_UHKBITS=1",
"__UACCUM_FBIT__=16",
"__DBL_MIN_10_EXP__=(-37)",
"__FINITE_MATH_ONLY__=0",
"__cpp_variable_templates=201304",
"__LFRACT_IBIT__=0",
"__GNUC_PATCHLEVEL__=0",
"__FLT32_HAS_DENORM__=1",
"__LFRACT_MAX__=0X7FFFFFFFP-31LR",
"__UINT_FAST8_MAX__=0xff",
"__has_include(STR)=__has_include__(STR)",
"__DEC64_MAX_EXP__=385",
"__INT8_C(c)=c",
"__INT_LEAST8_WIDTH__=8",
"__UINT_LEAST64_MAX__=0xffffffffffffffffULL",
"__SA_FBIT__=15",
"__SHRT_MAX__=0x7fff",
"__LDBL_MAX__=3.40282347e+38L",
"__FRACT_MAX__=0X7FFFP-15R",
"__UFRACT_FBIT__=16",
"__UFRACT_MIN__=0.0UR",
"__UINT_LEAST8_MAX__=0xff",
"__GCC_ATOMIC_BOOL_LOCK_FREE=1",
"__UINTMAX_TYPE__=long long unsigned int",
"__LLFRACT_EPSILON__=0x1P-63LLR",
"__BUILTIN_AVR_DELAY_CYCLES=1",
"__DEC32_EPSILON__=1E-6DF",
"__FLT_EVAL_METHOD_TS_18661_3__=0",
"__UINT32_MAX__=0xffffffffUL",
"__GXX_EXPERIMENTAL_CXX0X__=1",
"__ULFRACT_MAX__=0XFFFFFFFFP-32ULR",
"__TA_IBIT__=16",
"__LDBL_MAX_EXP__=128",
"__WINT_MIN__=(-__WINT_MAX__ - 1)",
"__INT_LEAST16_WIDTH__=16",
"__ULLFRACT_MIN__=0.0ULLR",
"__SCHAR_MAX__=0x7f",
"__WCHAR_MIN__=(-__WCHAR_MAX__ - 1)",
"__INT64_C(c)=c ## LL",
"__DBL_DIG__=6",
"__GCC_ATOMIC_POINTER_LOCK_FREE=1",
"__AVR_HAVE_SPH__=1",
"__LLACCUM_MIN__=(-0X1P15LLK-0X1P15LLK)",
"__BUILTIN_AVR_KBITS=1",
"__BUILTIN_AVR_ABSK=1",
"__BUILTIN_AVR_ABSR=1",
"__SIZEOF_INT__=2",
"__SIZEOF_POINTER__=2",
"__GCC_ATOMIC_CHAR16_T_LOCK_FREE=1",
"__USACCUM_IBIT__=8",
"__USER_LABEL_PREFIX__",
"__STDC_HOSTED__=1",
"__LDBL_HAS_INFINITY__=1",
"__LFRACT_MIN__=(-0.5LR-0.5LR)",
"__HA_IBIT__=8",
"__FLT32_DIG__=6",
"__TQ_IBIT__=0",
"__FLT_EPSILON__=1.19209290e-7F",
"__GXX_WEAK__=1",
"__SHRT_WIDTH__=16",
"__USFRACT_IBIT__=0",
"__LDBL_MIN__=1.17549435e-38L",
"__FRACT_MIN__=(-0.5R-0.5R)",
"__AVR_SFR_OFFSET__=0x20",
"__DEC32_MAX__=9.999999E96DF",
"__cpp_threadsafe_static_init=200806",
"__DA_IBIT__=32",
"__INT32_MAX__=0x7fffffffL",
"__UQQ_FBIT__=8",
"__INT_WIDTH__=16",
"__SIZEOF_LONG__=4",
"__UACCUM_MAX__=0XFFFFFFFFP-16UK",
"__UINT16_C(c)=c ## U",
"__PTRDIFF_WIDTH__=16",
"__DECIMAL_DIG__=9",
"__LFRACT_EPSILON__=0x1P-31LR",
"__AVR_2_BYTE_PC__=1",
"__ULFRACT_MIN__=0.0ULR",
"__INTMAX_WIDTH__=64",
"__has_include_next(STR)=__has_include_next__(STR)",
"__BUILTIN_AVR_ULLRBITS=1",
"__LDBL_HAS_QUIET_NAN__=1",
"__ULACCUM_IBIT__=32",
"__UACCUM_EPSILON__=0x1P-16UK",
"__BUILTIN_AVR_SEI=1",
"__GNUC__=7",
"__ULLACCUM_MAX__=0XFFFFFFFFFFFFFFFFP-48ULLK",
"__cpp_delegating_constructors=200604",
"__HQ_IBIT__=0",
"__BUILTIN_AVR_SWAP=1",
"__FLT_HAS_DENORM__=1",
"__SIZEOF_LONG_DOUBLE__=4",
"__BIGGEST_ALIGNMENT__=1",
"__STDC_UTF_16__=1",
"__UINT24_MAX__=16777215UL",
"__BUILTIN_AVR_NOP=1",
"__GNUC_STDC_INLINE__=1",
"__DQ_IBIT__=0",
"__FLT32_HAS_INFINITY__=1",
"__DBL_MAX__=double(3.40282347e+38L)",
"__ULFRACT_IBIT__=0",
"__cpp_raw_strings=200710",
"__INT_FAST32_MAX__=0x7fffffffL",
"__DBL_HAS_INFINITY__=1",
"__INT64_MAX__=0x7fffffffffffffffLL",
"__ACCUM_IBIT__=16",
"__DEC32_MIN_EXP__=(-94)",
"__BUILTIN_AVR_UKBITS=1",
"__INTPTR_WIDTH__=16",
"__BUILTIN_AVR_FMULSU=1",
"__LACCUM_MAX__=0X7FFFFFFFFFFFFFFFP-31LK",
"__INT_FAST16_TYPE__=int",
"__LDBL_HAS_DENORM__=1",
"__BUILTIN_AVR_BITSK=1",
"__BUILTIN_AVR_BITSR=1",
"__cplusplus=201402L",
"__cpp_ref_qualifiers=200710",
"__DEC128_MAX__=9.999999999999999999999999999999999E6144DL",
"__INT_LEAST32_MAX__=0x7fffffffL",
"__USING_SJLJ_EXCEPTIONS__=1",
"__DEC32_MIN__=1E-95DF",
"__ACCUM_MAX__=0X7FFFFFFFP-15K",
"__DEPRECATED=1",
"__cpp_rvalue_references=200610",
"__DBL_MAX_EXP__=128",
"__USACCUM_EPSILON__=0x1P-8UHK",
"__WCHAR_WIDTH__=16",
"__FLT32_MAX__=3.40282347e+38F32",
"__DEC128_EPSILON__=1E-33DL",
"__SFRACT_MAX__=0X7FP-7HR",
"__FRACT_IBIT__=0",
"__PTRDIFF_MAX__=0x7fff",
"__UACCUM_MIN__=0.0UK",
"__UACCUM_IBIT__=16",
"__BUILTIN_AVR_NOPS=1",
"__BUILTIN_AVR_WDR=1",
"__FLT32_HAS_QUIET_NAN__=1",
"__GNUG__=7",
"__LONG_LONG_MAX__=0x7fffffffffffffffLL",
"__SIZEOF_SIZE_T__=2",
"__ULACCUM_MAX__=0XFFFFFFFFFFFFFFFFP-32ULK",
"__cpp_rvalue_reference=200610",
"__cpp_nsdmi=200809",
"__SIZEOF_WINT_T__=2",
"__LONG_LONG_WIDTH__=64",
"__cpp_initializer_lists=200806",
"__FLT32_MAX_EXP__=128",
"__SA_IBIT__=16",
"__ULLACCUM_MIN__=0.0ULLK",
"__BUILTIN_AVR_ROUNDUHK=1",
"__BUILTIN_AVR_ROUNDUHR=1",
"__cpp_hex_float=201603",
"__GXX_ABI_VERSION=1011",
"__INT24_MAX__=8388607L",
"__UTA_FBIT__=48",
"__FLT_MIN_EXP__=(-125)",
"__USFRACT_MAX__=0XFFP-8UHR",
"__UFRACT_IBIT__=0",
"__BUILTIN_AVR_ROUNDFX=1",
"__BUILTIN_AVR_ROUNDULK=1",
"__BUILTIN_AVR_ROUNDULR=1",
"__cpp_lambdas=200907",
"__BUILTIN_AVR_COUNTLSLLK=1",
"__BUILTIN_AVR_COUNTLSLLR=1",
"__BUILTIN_AVR_ROUNDHK=1",
"__INT_FAST64_TYPE__=long long int",
"__BUILTIN_AVR_ROUNDHR=1",
"__DBL_MIN__=double(1.17549435e-38L)",
"__BUILTIN_AVR_COUNTLSK=1",
"__BUILTIN_AVR_ROUNDLK=1",
"__BUILTIN_AVR_COUNTLSR=1",
"__BUILTIN_AVR_ROUNDLR=1",
"__LACCUM_MIN__=(-0X1P31LK-0X1P31LK)",
"__ULLACCUM_FBIT__=48",
"__BUILTIN_AVR_LKBITS=1",
"__ULLFRACT_EPSILON__=0x1P-64ULLR",
"__DEC128_MIN__=1E-6143DL",
"__REGISTER_PREFIX__",
"__UINT16_MAX__=0xffffU",
"__DBL_HAS_DENORM__=1",
"__BUILTIN_AVR_ULKBITS=1",
"__ACCUM_MIN__=(-0X1P15K-0X1P15K)",
"__AVR_ARCH__=2",
"__SQ_IBIT__=0",
"__FLT32_MIN__=1.17549435e-38F32",
"__UINT8_TYPE__=unsigned char",
"__BUILTIN_AVR_ROUNDUK=1",
"__BUILTIN_AVR_ROUNDUR=1",
"__UHA_FBIT__=8",
"__NO_INLINE__=1",
"__SFRACT_MIN__=(-0.5HR-0.5HR)",
"__UTQ_FBIT__=128",
"__FLT_MANT_DIG__=24",
"__LDBL_DECIMAL_DIG__=9",
"__VERSION__=\"7.3.0\"",
"__UINT64_C(c)=c ## ULL",
"__ULLFRACT_FBIT__=64",
"__cpp_unicode_characters=200704",
"__FRACT_EPSILON__=0x1P-15R",
"__ULACCUM_MIN__=0.0ULK",
"__UDA_FBIT__=32",
"__cpp_decltype_auto=201304",
"__LLACCUM_EPSILON__=0x1P-47LLK",
"__GCC_ATOMIC_INT_LOCK_FREE=1",
"__FLT32_MANT_DIG__=24",
"__BUILTIN_AVR_BITSUHK=1",
"__BUILTIN_AVR_BITSUHR=1",
"__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__",
"__USFRACT_MIN__=0.0UHR",
"__BUILTIN_AVR_BITSULK=1",
"__ULLACCUM_IBIT__=16",
"__BUILTIN_AVR_BITSULR=1",
"__UQQ_IBIT__=0",
"__BUILTIN_AVR_LLRBITS=1",
"__SCHAR_WIDTH__=8",
"__BUILTIN_AVR_BITSULLK=1",
"__BUILTIN_AVR_BITSULLR=1",
"__INT32_C(c)=c ## L",
"__DEC64_EPSILON__=1E-15DD",
"__ORDER_PDP_ENDIAN__=3412",
"__DEC128_MIN_EXP__=(-6142)",
"__UHQ_FBIT__=16",
"__LLACCUM_FBIT__=47",
"__FLT32_MAX_10_EXP__=38",
"__BUILTIN_AVR_ROUNDULLK=1",
"__BUILTIN_AVR_ROUNDULLR=1",
"__INT_FAST32_TYPE__=long int",
"__BUILTIN_AVR_HRBITS=1",
"__UINT_LEAST16_TYPE__=unsigned int",
"__BUILTIN_AVR_UHRBITS=1",
"__INT16_MAX__=0x7fff",
"__SIZE_TYPE__=unsigned int",
"__UINT64_MAX__=0xffffffffffffffffULL",
"__UDQ_FBIT__=64",
"__INT8_TYPE__=signed char",
"__cpp_digit_separators=201309",
"__ELF__=1",
"__ULFRACT_EPSILON__=0x1P-32ULR",
"__LLFRACT_FBIT__=63",
"__FLT_RADIX__=2",
"__INT_LEAST16_TYPE__=int",
"__BUILTIN_AVR_ABSFX=1",
"__LDBL_EPSILON__=1.19209290e-7L",
"__UINTMAX_C(c)=c ## ULL",
"__INT24_MIN__=(-__INT24_MAX__-1)",
"__SACCUM_MAX__=0X7FFFP-7HK",
"__BUILTIN_AVR_ABSHR=1",
"__SIG_ATOMIC_MAX__=0x7f",
"__GCC_ATOMIC_WCHAR_T_LOCK_FREE=1",
"__cpp_sized_deallocation=201309",
"__SIZEOF_PTRDIFF_T__=2",
"__AVR=1",
"__BUILTIN_AVR_ABSLK=1",
"__BUILTIN_AVR_ABSLR=1",
"__LACCUM_EPSILON__=0x1P-31LK",
"__DEC32_SUBNORMAL_MIN__=0.000001E-95DF",
"__INT_FAST16_MAX__=0x7fff",
"__UINT_FAST32_MAX__=0xffffffffUL",
"__UINT_LEAST64_TYPE__=long long unsigned int",
"__USACCUM_MAX__=0XFFFFP-8UHK",
"__SFRACT_EPSILON__=0x1P-7HR",
"__FLT_HAS_QUIET_NAN__=1",
"__FLT_MAX_10_EXP__=38",
"__LONG_MAX__=0x7fffffffL",
"__DEC128_SUBNORMAL_MIN__=0.000000000000000000000000000000001E-6143DL",
"__FLT_HAS_INFINITY__=1",
"__cpp_unicode_literals=200710",
"__USA_FBIT__=16",
"__UINT_FAST16_TYPE__=unsigned int",
"__DEC64_MAX__=9.999999999999999E384DD",
"__INT_FAST32_WIDTH__=32",
"__BUILTIN_AVR_RBITS=1",
"__CHAR16_TYPE__=unsigned int",
"__PRAGMA_REDEFINE_EXTNAME=1",
"__SIZE_WIDTH__=16",
"__INT_LEAST16_MAX__=0x7fff",
"__DEC64_MANT_DIG__=16",
"__UINT_LEAST32_MAX__=0xffffffffUL",
"__SACCUM_FBIT__=7",
"__FLT32_DENORM_MIN__=1.40129846e-45F32",
"__GCC_ATOMIC_LONG_LOCK_FREE=1",
"__SIG_ATOMIC_WIDTH__=8",
"__INT_LEAST64_TYPE__=long long int",
"__INT16_TYPE__=int",
"__INT_LEAST8_TYPE__=signed char",
"__SQ_FBIT__=31",
"__DEC32_MAX_EXP__=97",
"__INT_FAST8_MAX__=0x7f",
"__INTPTR_MAX__=0x7fff",
"__QQ_FBIT__=7",
"__cpp_range_based_for=200907",
"__UTA_IBIT__=16",
"__AVR_ERRATA_SKIP__=1",
"__FLT32_MIN_10_EXP__=(-37)",
"__LDBL_MANT_DIG__=24",
"__SFRACT_FBIT__=7",
"__SACCUM_MIN__=(-0X1P7HK-0X1P7HK)",
"__DBL_HAS_QUIET_NAN__=1",
"__SIG_ATOMIC_MIN__=(-__SIG_ATOMIC_MAX__ - 1)",
"AVR=1",
"__BUILTIN_AVR_FMULS=1",
"__cpp_return_type_deduction=201304",
"__INTPTR_TYPE__=int",
"__UINT16_TYPE__=unsigned int",
"__WCHAR_TYPE__=int",
"__SIZEOF_FLOAT__=4",
"__AVR__=1",
"__BUILTIN_AVR_INSERT_BITS=1",
"__USQ_FBIT__=32",
"__UINTPTR_MAX__=0xffffU",
"__INT_FAST64_WIDTH__=64",
"__DEC64_MIN_EXP__=(-382)",
"__cpp_decltype=200707",
"__FLT32_DECIMAL_DIG__=9",
"__INT_FAST64_MAX__=0x7fffffffffffffffLL",
"__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1",
"__FLT_DIG__=6",
"__UINT_FAST64_TYPE__=long long unsigned int",
"__BUILTIN_AVR_BITSHK=1",
"__BUILTIN_AVR_BITSHR=1",
"__INT_MAX__=0x7fff",
"__LACCUM_FBIT__=31",
"__USACCUM_MIN__=0.0UHK",
"__UHA_IBIT__=8",
"__INT64_TYPE__=long long int",
"__BUILTIN_AVR_BITSLK=1",
"__BUILTIN_AVR_BITSLR=1",
"__FLT_MAX_EXP__=128",
"__UTQ_IBIT__=0",
"__DBL_MANT_DIG__=24",
"__cpp_inheriting_constructors=201511",
"__BUILTIN_AVR_ULLKBITS=1",
"__INT_LEAST64_MAX__=0x7fffffffffffffffLL",
"__DEC64_MIN__=1E-383DD",
"__WINT_TYPE__=int",
"__UINT_LEAST32_TYPE__=long unsigned int",
"__SIZEOF_SHORT__=2",
"__ULLFRACT_IBIT__=0",
"__LDBL_MIN_EXP__=(-125)",
"__UDA_IBIT__=32",
"__WINT_WIDTH__=16",
"__INT_LEAST8_MAX__=0x7f",
"__LFRACT_FBIT__=31",
"__LDBL_MAX_10_EXP__=38",
"__ATOMIC_RELAXED=0",
"__DBL_EPSILON__=double(1.19209290e-7L)",
"__BUILTIN_AVR_BITSUK=1",
"__BUILTIN_AVR_BITSUR=1",
"__UINT8_C(c)=c",
"__INT_LEAST32_TYPE__=long int",
"__BUILTIN_AVR_URBITS=1",
"__SIZEOF_WCHAR_T__=2",
"__LLFRACT_MAX__=0X7FFFFFFFFFFFFFFFP-63LLR",
"__TQ_FBIT__=127",
"__INT_FAST8_TYPE__=signed char",
"__ULLACCUM_EPSILON__=0x1P-48ULLK",
"__BUILTIN_AVR_ROUNDK=1",
"__BUILTIN_AVR_ROUNDR=1",
"__UHQ_IBIT__=0",
"__LLACCUM_IBIT__=16",
"__FLT32_EPSILON__=1.19209290e-7F32",
"__DBL_DECIMAL_DIG__=9",
"__STDC_UTF_32__=1",
"__INT_FAST8_WIDTH__=8",
"__DEC_EVAL_METHOD__=2",
"__TA_FBIT__=47",
"__UDQ_IBIT__=0",
"__ORDER_BIG_ENDIAN__=4321",
"__cpp_runtime_arrays=198712",
"__WITH_AVRLIBC__=1",
"__UINT64_TYPE__=long long unsigned int",
"__ACCUM_EPSILON__=0x1P-15K",
"__UINT32_C(c)=c ## UL",
"__BUILTIN_AVR_COUNTLSUHK=1",
"__INTMAX_MAX__=0x7fffffffffffffffLL",
"__cpp_alias_templates=200704",
"__BUILTIN_AVR_COUNTLSUHR=1",
"__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__",
"__FLT_DENORM_MIN__=1.40129846e-45F",
"__LLFRACT_IBIT__=0",
"__INT8_MAX__=0x7f",
"__LONG_WIDTH__=32",
"__UINT_FAST32_TYPE__=long unsigned int",
"__CHAR32_TYPE__=long unsigned int",
"__BUILTIN_AVR_COUNTLSULK=1",
"__BUILTIN_AVR_COUNTLSULR=1",
"__FLT_MAX__=3.40282347e+38F",
"__cpp_constexpr=201304",
"__USACCUM_FBIT__=8",
"__BUILTIN_AVR_COUNTLSFX=1",
"__INT32_TYPE__=long int",
"__SIZEOF_DOUBLE__=4",
"__FLT_MIN_10_EXP__=(-37)",
"__UFRACT_EPSILON__=0x1P-16UR",
"__INT_LEAST32_WIDTH__=32",
"__BUILTIN_AVR_COUNTLSHK=1",
"__BUILTIN_AVR_COUNTLSHR=1",
"__INTMAX_TYPE__=long long int",
"__BUILTIN_AVR_ABSLLK=1",
"__BUILTIN_AVR_ABSLLR=1",
"__DEC128_MAX_EXP__=6145",
"__AVR_HAVE_16BIT_SP__=1",
"__ATOMIC_CONSUME=1",
"__GNUC_MINOR__=3",
"__INT_FAST16_WIDTH__=16",
"__UINTMAX_MAX__=0xffffffffffffffffULL",
"__DEC32_MANT_DIG__=7",
"__HA_FBIT__=7",
"__BUILTIN_AVR_COUNTLSLK=1",
"__BUILTIN_AVR_COUNTLSLR=1",
"__BUILTIN_AVR_CLI=1",
"__DBL_MAX_10_EXP__=38",
"__LDBL_DENORM_MIN__=1.40129846e-45L",
"__INT16_C(c)=c",
"__cpp_generic_lambdas=201304",
"__STDC__=1",
"__PTRDIFF_TYPE__=int",
"__LLFRACT_MIN__=(-0.5LLR-0.5LLR)",
"__BUILTIN_AVR_LRBITS=1",
"__ATOMIC_SEQ_CST=5",
"__DA_FBIT__=31",
"__UINT32_TYPE__=long unsigned int",
"__BUILTIN_AVR_ROUNDLLK=1",
"__UINTPTR_TYPE__=unsigned int",
"__BUILTIN_AVR_ROUNDLLR=1",
"__USA_IBIT__=16",
"__BUILTIN_AVR_ULRBITS=1",
"__DEC64_SUBNORMAL_MIN__=0.000000000000001E-383DD",
"__DEC128_MANT_DIG__=34",
"__LDBL_MIN_10_EXP__=(-37)",
"__BUILTIN_AVR_COUNTLSUK=1",
"__BUILTIN_AVR_COUNTLSUR=1",
"__SIZEOF_LONG_LONG__=8",
"__ULACCUM_EPSILON__=0x1P-32ULK",
"__cpp_user_defined_literals=200809",
"__SACCUM_IBIT__=8",
"__GCC_ATOMIC_LLONG_LOCK_FREE=1",
"__LDBL_DIG__=6",
"__FLT_DECIMAL_DIG__=9",
"__UINT_FAST16_MAX__=0xffffU",
"__GCC_ATOMIC_SHORT_LOCK_FREE=1",
"__BUILTIN_AVR_ABSHK=1",
"__BUILTIN_AVR_FLASH_SEGMENT=1",
"__INT_LEAST64_WIDTH__=64",
"__ULLFRACT_MAX__=0XFFFFFFFFFFFFFFFFP-64ULLR",
"__UINT_FAST8_TYPE__=unsigned char",
"__USFRACT_EPSILON__=0x1P-8UHR",
"__ULACCUM_FBIT__=32",
"__QQ_IBIT__=0",
"__cpp_init_captures=201304",
"__ATOMIC_ACQ_REL=4",
"__ATOMIC_RELEASE=3",
"__BUILTIN_AVR_FMUL=1",
"USBCON"
]
}
]
}
Rust on Nano Every
Next up is trying to get Rust to run on the nano every which has a atmega4809. This was a weekend journey and probably could be done faster in the person driving had better skills. I document it here so people can may find this page and learn from the problems I have experienced.
Create Cargo Project
First off let create a new project
cargo new project_me
Add HAL (hardware abstraction layer) to project
Add the embedded-hal to project by going to the Cargo.toml and adding embedded-hal as a dependency. It is a generic layer and you will need a chip specific one as well.
[dependencies]
embedded-hal = "0.1.2"
Using cargo build resulted in the following error
error[E0554]: `#![feature]` may not be used on the stable release channel
This is because we cannot use the stable toolchain which is the default. To list the toolchains available you can use.
rustup toolchain list
In my case, because I have already installed other toolchains, the output was
stable-x86_64-unknown-linux-gnu (default)
nightly-x86_64-unknown-linux-gnu
snowgoons
To install the nightly toolchain use the rustup command.
rustup install nightly
We are going to override the default but it if we wanted to set the default we can with this
rustup default stable-x86_64-unknown-linux-gnu
Now we can run the cargo build and it completes successfully. We can set the toolchain to use in the an override file in the root directory rust-toolchain.toml. You find this in the overrides section of the rustup book. An example is shown below.
[toolchain]
#The name of the toolchain to use. We are using snowgoons as this is
channel = "nightly-x86_64-unknown-linux-gnu"
components = ["rust-src"]
Adding Chip Specific HAL
In the videos by Vers Binarii it mentions finding the hal for an STM32F103C8T6 and guides you to lib.rs to get the board specific hal. Unfortunately this does not exist for the ATMega4809. So from there I made my way back to snowgoons where I first started. He suggested, at least to me, instead of stm32f1xx-hal I should use ruduino for my ATMega4809 (nano every). This gave the error
error: cannot find macro `llvm_asm` in this scope
Googling led me to running the rustup update command
rustup update
Was not hopeful as I assume that I am already at the latest. After the version shown was (rustc 1.71.0-nightly). So I reran the build and...
error[E0635]: unknown feature `llvm_asm`
Looking at this, and not that familiar with rust, I think they have renamed llvm_asm to asm and this appears avr_delay presumably used by ruduino. This went into the too hard basket and I went looking for a different hal. Next up is avr-oxide. Putting in the latest version at the time 0.4.0 ( nothing is version 1.0.0 :grinning: ). So running the build gives new and more fun problems.
|
22 | compile_error!("A clockspeed feature (\"16MHz\", \"20MHz\") must be enabled for this crate");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I remember when watching Vers you can enable and disable features. Lets see what we need. We know that the nano every is 20MHz. So lets put that in and the chip which it also spat out on the error
[dependencies.avr-oxide]
version = "0.4.1"
features = ["20MHz","atmega4809"]
No joy just more errors. But we have learned a fair bit about the rust build system
error: ~const can only be applied to `#[const_trait]` traits
--> /home/iwiseman/.cargo/registry/src/index.crates.io-6f17d22bba15001f/avr-oxide-0.4.1/src/oserror.rs:194:22
Next up I found avr-hal. This mentions nano but not nano every. Lets give it a go.
git clone https://github.com/Rahix/avr-hal avr-hal
cd examples/arduino-nano/
cargo build
...
Compiling avr-device v0.5.1
Compiling nb v0.1.3
Compiling embedded-hal v0.2.7
Compiling atmega-hal v0.1.0 (/home/iwiseman/dev/projects/at4809/avr-hal/mcu/atmega-hal)
Compiling arduino-hal v0.1.0 (/home/iwiseman/dev/projects/at4809/avr-hal/arduino-hal)
Compiling arduino-nano-examples v0.0.0 (/home/iwiseman/dev/projects/at4809/avr-hal/examples/arduino-nano)
WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without.
WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without.
Finished dev [optimized + debuginfo] target(s) in 22.28s
Built but not running
To run the we do the following
cargo run --bin nano-blink
WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without.
Finished dev [optimized + debuginfo] target(s) in 0.03s
Running `ravedude nano -cb 57600 /home/iwiseman/dev/projects/at4809/avr-hal/target/avr-atmega328p/debug/nano-blink.elf`
Board Arduino Nano
Error: no matching serial port found, use -P or set RAVEDUDE_PORT in your environment
So we know how to solve this one, it is looking for the device my nano is on /dev/ttyACMO.
export RAVEDUDE_PORT=/dev/ttyACMO
So lets give it a whirl
WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without.
Finished dev [optimized + debuginfo] target(s) in 0.03s
Running `ravedude nano -cb 57600 /home/iwiseman/dev/projects/at4809/avr-hal/target/avr-atmega328p/debug/nano-blink.elf`
Board Arduino Nano
Programming /home/iwiseman/dev/projects/at4809/avr-hal/target/avr-atmega328p/debug/nano-blink.elf => /dev/ttyACM0
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x00
I found that avr-hal is running something called ravedude which appears to be a wrapper for avrdude which is what I noticed the native blink example runs when using vscode and the arduino plugin uses. We are using the same software and we know it works so what is the problem. So lets see which version of avrdude it is using.
which avrdude
/usr/bin/avrdude
avrdude -v
avrdude: Version 6.3-20171130
Lets see what arduino is using. In my case this was going to home directory and look for a likely hidden folder.
ls -la |grep ".ard"
drwxr-xr-x 6 iwiseman iwiseman 4096 May 13 17:25 .arduino15
drwxrwxr-x 7 iwiseman iwiseman 4096 May 13 17:25 .arduinoIDE
Looking in .arduino15 showed a version of avrdude exists and was 6.3-20171130 so this clearly was not the issue. Getting there I promise. So I looked at he parameters being used with avrdude by making a fake script replacing avrdude
#!/bin/bash
echo $@ >/tmp/fred.txt
Looking an the output we have. So I change the avr-hal/examples/arduino-nano/.cargo/config.toml to have these
-C/home/iwiseman/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -V -patmega4809 -cjtag2updi -P/dev/ttyACM0 -b115200 -e -D -Uflash:w:/tmp/arduino/sketches/6F5689DFFC2E237B65FDBBAD8847D814/blinkNative.ino.hex:i -Ufuse2:w:0x01:m -Ufuse5:w:0xC9:m -Ufuse8:w:0x00:m {upload.extra_files}
So here is the config.toml. Note I need to change the command to use an elf rather than the hex file. I went to TOML cheat sheet for the multiline command
[build]
target = "../../avr-specs/avr-atmega328p.json"
[target.'cfg(target_arch = "avr")']
#runner = "ravedude nano -cb 57600"
runner = """/home/iwiseman/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude \
-C /home/iwiseman/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf \
-v \
-V \
-patmega4809 \
-cjtag2updi \
-P/dev/ttyACM0 \
-b115200 \
-e \
-D \
-Uflash:w:./target/avr-atmega328p/debug/nano-blink.elf
-Ufuse2:w:0x01:m \
-Ufuse5:w:0xC9:m \
-Ufuse8:w:0x00:m"""
[unstable]
build-std = ["core"]
This gave the following output and was the final issue to solve.
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
I googled avrdude: jtagmkII_getsync() and found this. It appears you need to set the baud rate at 1200 bps briefly before attempting to upload. I am a idiot and know nothing so back to google on how to do this. Googling "avrdude 1200 rust" I find I am back to snowgoons and indeed there is a script showing how to do this. Here it is. Had to change stty -f to stty -F' probably a windows thing and I am on linux
#!/bin/bash
# Gimme the name of a file to load
ELFFILE=${1}
# We need to use the `avrdude` that comes with the Arduino IDE, it seems
# to have some custom changes not in the version we installed from Brew, that
# work with the UPDI-over-USB bootloader on the Arduino Nano Every
AVRDUDE=~/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude
AVRCONF=~/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf
# Chip option fuses
FUSE_OSCCFG=0x82 # 20 MHz
FUSE_SYSCFG0=0xC9 # No CRC, Reset is Reset, don't erase EEPROM
FUSE_BOOTEND=0x00 # Whole Flash is boot
# Device specific flags
PART=atmega4809
PROGRAMMER=jtag2updi
BAUDRATE=115200
# Where to find it
PORT=$(find /dev/cu.usbmodem* | head -n 1)
# We reset the Arduino (and put it into UPDI mode) by opening & closing the
# serial port at 1200baud (this is some kind of 'backdoor' reset process
# built into the USB software that runs on the Nano Every's coprocessor
# for handling USB-to-UPDI.
stty -F "${PORT}" 1200
# Wait for the port to be available again
while [ 1 ]; do
sleep 0.5
[ -c "${PORT}" ] && break
done
# NOW, finally, we can actually upload our code
${AVRDUDE} \
-C ${AVRCONF} \
-v -p${PART} \
-c${PROGRAMMER} \
-P${PORT} -b${BAUDRATE} \
-e -D \
-Uflash:w:${ELFFILE}:e \
-Ufuse2:w:${FUSE_OSCCFG}:m -Ufuse5:w:${FUSE_SYSCFG0}:m -Ufuse8:w:${FUSE_BOOTEND}:m
Working at Last
So putting it all together
cargo install cargo-generate
cargo generate --git https://github.com/Rahix/avr-hal-template.git
Go into your project and here is the blink code
#![no_std]
#![no_main]
use panic_halt as _;
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let mut led = pins.d13.into_output();
loop {
led.set_high();
arduino_hal::delay_ms(500);
led.set_low();
arduino_hal::delay_ms(500);
}
}
Build and upload
cargo build
arduino-nano-every-upload.sh ./target/avr-atmega328p/debug/blink-me.elf
First PR For years
So looked at how to streamline this and amended Rahix code to support the arduino approach.
git clone https://github.com/bibble235/avr-hal
export RAVEDUDE_PORT=/dev/ttyACM0
export RAVEDUDE_AVRDUDE_ROOT=/home/iwiseman/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17
cd examples/nano-every
cargo run