Uploading code to the Uno R4 without any ide

Hey there. I was wondering how I could upload my arm-none-eabi compiled code to to the RA4M1. I am on Linux and I tried using the rfp-cli but it couldn’t even read from it. I have also jumped the D40 pin (through software) so that usb-c is directly connected to the M4 but it still did not work. I wouldn’t even mind going through the ESP to flash the main MCU I’d just need to know what tools I would need and how to set it up the right way.

Why do I want to do it without an IDE? I would like to do it from scratch. Looking into the docs trying to understand them and switching the GPIO pins modes and input through the memory mapped regions. Making a driver and all that cool stuff.

If searched quite a lot but I couldn’t find anything useful tbh.

I don’t have any fancy flashers/programmers thus it would be really useful if the solutions would work via serial usb-c.

Have you tried arduino-cli? It's all I use.

I tried it on my windows machine and it worked (compiling and uploading the compiled sketch) but it’s not exactly what I was searching for. I was trying to do it the „avrdude“ way if this makes any sense. The arduino-cli is nice but maybe a tat too much and not really the thing I am looking for. Thank you anyways for the advice appreciate it ^^

Hi @eyyy7. Arduino IDE uses the bossac uploader tool to upload the compiled sketch binary to the UNO R4 WiFi board.

You can see the exact command it runs by doing this:

  1. Start Arduino IDE.
    You can also perform the equivalent procedure using Arduino CLI if you prefer.
  2. Select File > Preferences... (or Arduino IDE > Settings... for macOS users) from the Arduino IDE menus.
    The "Preferences" dialog will open.
  3. Check the box next to Show verbose output during: ☐ upload.
  4. Click the "OK" button.
  5. Select File > New Sketch from the Arduino IDE menus.
  6. Connect your UNO R4 WiFi board to your computer with a USB cable.
  7. Select the board and port from the menu on the Arduino IDE toolbar.
  8. Select Sketch > Upload from the Arduino IDE menus.
  9. Wait for the upload to finish.

Now examine the contents of the black "Output" panel at the bottom of the Arduino IDE window. You will see the bossac command there.

For example:

Performing 1200-bps touch reset on serial port COM42
"C:\Users\per\AppData\Local\Arduino15\packages\arduino\tools\bossac\1.9.1-arduino5/bossac" -d --port=COM42 -U -e -w "C:\Users\per\AppData\Local\Temp\arduino\sketches\1176A74767CED11DBE7AD3DCE64EABA5/sketch_feb6a.ino.bin" -R
Set binary mode

[...]

If you copy and paste that same command to the command line terminal, you will find that it fails with a No device found error:

$ "C:\Users\per\AppData\Local\Arduino15\packages\arduino\tools\bossac\1.9.1-arduino5/bossac" -d --port=COM42 -U -e -w "C:\Users\per\AppData\Local\Temp\arduino\sketches\1176A74767CED11DBE7AD3DCE64EABA5/sketch_feb6a.ino.bin" -R
Set binary mode
Send auto-baud
Set binary mode
No device found on COM42

The reason for this different result is explained by this part of the IDE's upload output you can see in the example I provided above:

Performing 1200-bps touch reset on serial port COM42

The UNO R4 WiFi board must be put into a special mode where it can accept the upload. Arduino IDE and Arduino CLI accomplish this by momentarily configuring a serial port connection to the board at 1200 baud. This arbitrary uncommon baud rate is recognized as a special signal by the firmware on the bridge module of the UNO R4 WiFi board to put the board into the upload mode.

So one approach would be for you to configure your upload system to emulate that "1200-bps touch" behavior before running the bossac command. However, you might find it more simple to juste put the board into the upload mode manually before each upload. You can do that by pressing and releasing the button on the board marked "RESET" twice quickly. You will now see the "L" LED start pulsing. The board will remain in this state until an upload has been performed or the board was reset or power cycled.

That's really interesting thank you for the tip. Just a little question what is the standard baud rate of the uno r4 9600 or 115200 bps and how long does the touch have to be? I couldn't find anything in the docs I am kinda curious where I can find this information.

I'm not sure what you mean by "standard".

9600 is the default setting in the Arduino IDE Serial Monitor, so if you are sharing an Arduino sketch with the community and want to make it as beginner-friendly as possible then that is the best baud rate to use since that makes it most likely to work for a beginner (who probably won't read the instructions even if you clearly document the need to set a specific baud rate in Serial Monitor).

We explicitly configure the baud rate in our sketches via the Serial.begin function.

The subject of baud rate of the serial port is actually a bit complex for the UNO R4 WiFi. This board has a switch that determines whether the USB socket on the board is electrically connected to the "bridge" module, or directly to the primary RA4M1 microcontroller. The HID code of the board's core causes the switch to be set to connect it to the RA4M1 when the sketch uses HID capabilities (e.g., "Keyboard" or "Mouse" library). In this mode, baud rate is actually irrelevant since the board is communicating directly with the computer via USB. It is only when the switch is in the default mode where the USB socket is connected to the ESP32 microcontroller of the "bridge" module that the baud rate configuration has any effect on the board's communication over the serial port.

The IDE closes the port again immediately after opening it;

https://github.com/arduino/arduino-cli/blob/v0.35.2/arduino/serialutils/serialutils.go#L31-L62

// TouchSerialPortAt1200bps open and close the serial port at 1200 bps. This
// is used on many Arduino boards as a signal to put the board in "bootloader"
// mode.
func TouchSerialPortAt1200bps(port string) error {
	// Open port
	p, err := serial.Open(port, &serial.Mode{BaudRate: 1200})
	if err != nil {
		return errors.WithMessage(err, tr("opening port at 1200bps"))
	}

	if runtime.GOOS != "windows" {
		// This is not required on Windows
		// TODO: Investigate if it can be removed for other OS too

		// Set DTR to false
		if err = p.SetDTR(false); err != nil {
			p.Close()
			return errors.WithMessage(err, tr("setting DTR to OFF"))
		}
	}

	// Close serial port
	p.Close()

	// Scanning for available ports seems to open the port or
	// otherwise assert DTR, which would cancel the WDT reset if
	// it happens within 250 ms. So we wait until the reset should
	// have already occurred before going on.
	time.Sleep(500 * time.Millisecond)

	return nil
}

However, you can see it does wait 500 ms after closing the port.

In addition, under certain conditions the touch will cause the port to disappear and the reappear again (sometimes with a different address). The operating system takes a little while to recognize the new port so there is also a mechanism that allows the upload operation to wait after performing a "touch" until a new port appears, then use that new port for the upload. There is some information about that as it relates to the UNO R4 WiFi here:

I got it working. I put it all on my github: es_r4. This allows you to skip the entire ArduinoIDE and do it all in plain old C/C++ and CMake. Contributors are welcomed ^ ^. It also has clangd support