Porting Arduino Zero to another samd21g variant.

Hi Everyone,

I want to port Arduino Zero from samd21g18 to samd21g17 (or g16), which has the same pin count, just less Flash and RAM. How can this be done? Anyone know of a tutorial?

I've created my own variant of the Zero for g18 before by modifying the Makefile for the bootloader, boards.txt, and variant.h (as discussed here). However, I suspect those modifications are not sufficient when switching to the g17 because there are a number of references specifically to the x18 variant (ie. samd21g18 or samd21x18) throughout the ArduinoCore-samd, including in:

  • boards.txt,
  • Makefile (for the bootloader),
  • samd21_sam_bas.cproj,
  • pulse_asm.S,
  • WVariant.h,
  • SAMD21_USBDevice,
  • USBCore, SPI.h,
  • arduino_zero.cfg,
  • variant.gdb.

So, at first glance, it appears to be more involved. If anyone has done this before and can advise, I'd greatly appreciate your insight.

One of the most important file when dealing with variant with different memory size is the linker script. It's here that you say how much RAM and of much FLASH your device has. And it will be used to compile and map your programm correctly.

If you changed correctly the board.txt file to match you board variant it should work correctly. Other files (puls_asm, WVariant, USBCore etc..) should work whithout modification.

I don't have a list of step by step instructions on how to make the necessary changes, but I did take notes are I was figuring out how to get all of this to work for the Tau:

Must edit:

C:\Users\Shawn\AppData\Local\Arduino15\packages\tau\hardware\samd\1.6.5\boards.txt
To have correct processor flag.

Makefile for project also contains this reference:

Rabid Prototypes Tau (PID == 0x004D)

CFLAGS_EXTRA?=-D__SAMD21E17A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x4D -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23

Left the PID and VID alone so it identifies as a Zero. Changed the processor flag.

Changed device selection in Atmel Studio to SAMD21E17A as well.

BootloaderSam21x18.ld has the following lines:

/* Linker script to configure memory regions.

  • Need modifying for a specific board.
  • FLASH.ORIGIN: starting address of flash
  • FLASH.LENGTH: length of flash
  • RAM.ORIGIN: starting address of RAM bank 0
  • RAM.LENGTH: length of RAM bank 0
    /
    MEMORY
    {
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x2000 /
    First 8KB used by bootloader /
    RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000-0x0004 /
    4 bytes used by bootloader to keep data between resets */
    }

Does this need to be altered?

0x00008000 = 32K. That is the length of the ram?
Minus the 4 bytes used by the bootloader = length of usable ram?

So I guess I should change that to 4000 for the SAMD21E17A since it only has 16K of ram.

I changed the filename to SAM21x17 then realized it is probably referenced somewhere.
Turns out Makefile references it:

$(ELF): Makefile $(BUILD_PATH) $(OBJECTS)
@echo ----------------------------------------------------------
@echo Creating ELF binary
"$(CC)" -L. -L$(BUILD_PATH) $(LDFLAGS) -Os -Wl,--gc-sections -save-temps -Tbootloader_samd21x17.ld -Wl,-Map,"$(BUILD_PATH)/$(NAME).map" -o "$(BUILD_PATH)/$(ELF)" -Wl,--start-group $(OBJECTS) -lm -Wl,--end-group
"$(NM)" "$(BUILD_PATH)/$(ELF)" >"$(BUILD_PATH)/$(NAME)_symbols.txt"
"$(SIZE)" --format=sysv -t -x $(BUILD_PATH)/$(ELF)

<sam.h> not found!

Found this on the web:

sam.h is not included.

go to: properties -> toolchain -> ARM/GNU C Compiler -> Directories and add
include path:

C:\Program Files\Atmel\Atmel Toolchain\ARM
GCC\Native\4.8.1443\CMSIS_Atmel\Device\ATMEL

C:\Users\Shawn\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\Device\ATMEL

I have no idea how to make this a friendly path that would work regardless of the user that installed it, but that’s where sam.h is.

But I notice there is a checkbox for “include device support header path”. What is that?

Well, I think maybe that means to include the paths I specify in the box.
And when I pasted the address above into the dialog that came up and left “relative path” checked it spit this out in the path dialog:

../../../../../../../arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL

And when I click that “relative path” is now checked, so I guess if I’d entered that in the first place I would have had to check that box.

And I guess that’s 7 directories up from where my project is? But that can’t be Tau, so it must be Tau/Release? I see a make file in there. So I guess maybe that’s it.

I also had to include this directory:
C:\Users\Shawn\AppData\Local\Arduino15\packages\arduino\tools\CMSIS\4.0.0-atmel\CMSIS\Include

Could not successfully build release after adding those directories due to missing USB VID PID defines. These are in the makefile provided... but it seems release generates a new makefile and it doesn’t have these? And the provided makefile does, and has those directories defined in it for the includes?

All I know is a debug build compiles, release does not.

But debug also only generates an .ELF file, no BIN which is needed for Arduino to burn bootloader. Why?

I think I see the problem. Release build config didn’t have “use external makefle” checked under build?

I’m not sure what I wrote that for, but it turns out that if I click “build samd21” and not “build project” then it creates .HEX and .BIN files in addition to the .ELF

In:
C:\Users\Shawn\AppData\Local\Arduino15\packages\rabid prototypes\hardware\samd\1.6.5\variants\tau\linker_scripts\gcc

Have to modify two linker scripts for compilation.

MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}

Here, LENGTH = 0x00008000 must be changed to LENGTH = 0x00004000 because tau has half the ram.

And 0x00040000 for the flash length equals 262,144 and the Tau has half the flash, so that also has to be reduced.

The last piece of a puzzle is that the default BOSSA tool which uploads to the board does not provide support for the SAMD21E17:
BOSSA/src/Devices.h at arduino · shumatech/BOSSA · GitHub

Unless you tick a little box in the IDE that tells it to provide verbose output during UPLOAD (not compile, they are two separate options!) the only error you will see when BOSSA does not recognize the processor is “no device found on COM [whatever]”, which would lead you to believe there is a problem with your board’s hardware instead of a problem with the IDE’s tools.

There is a version of BOSSA here which has been recompiled to include support for all the SAMD, SAMC, and SAML chips:

GitHub - mattairtech/BOSSA: BOSSA is a flash programming utility for Atmel's SAM family of flash-based ARM microcontrollers. The motivation behind BOSSA is to create a simple, easy-to-use, open source utility to replace Atmel's SAM-BA software. BOSSA is an acronym for Basic Open Source SAM-BA Application to reflect that goal.

Actual compiled version can be found hre:
GitHub - mattairtech/ArduinoCore-samd: This is a fork from arduino/ArduinoCore-samd on GitHub. This will be used to maintain Arduino support for SAM D|L|C (M0+ and M4F) boards including the MattairTech Xeno Mini and the MT-D21E (see https://www.mattairtech.com/). It adds support for new devices like the D51, L21, C21, and D11. It also adds new clock sources, like a high speed crystal or internal oscillator.

Scroll down and there are links to compiled versions near the bottom. Alternatively you can use the boards manager to install the mattairtech board files which have a compiled BOSSA in the tools folder for that variant.

Hey guys,
Thanks to both of you for your responses. I will try out your suggestions, starting with AloyseTech, and moving on to scswift's notes as needed.
I'll let you know what works, and hopefully can post a guide on the topic later.

Hi again,

It took a while but I got a bootloader running on a different samd21 chip(samd21g17), and can upload to it from the Arduino IDE. scswift's notes above capture mostly all the steps, except for step 7 in the list below. Before starting, you should already have a created (and hopefully tested) a samd21g18 variant. Here's a guide on doing that: Adding custom (Zero based) boards to the Arduino IDE - Arduino Zero - Arduino Forum

  • In boards.txt, change processor flag. eg: "yourboard.build.extra_flags=-DARDUINO_SAMD_ZERO -D__SAMD21G17A__ {build.usb_flags}"
  • In boards.txt, change "yourboard.build.variant=arduino_zero" to "yourboard.build.variant=yourboard"
  • copy variants/arduino_zero directory to variants/yourboard (match to boardname used in step 2).
  • Inside the variant you made, edit memory of flash_with_bootloader.ld and flash_without_bootloader.ld to match your device (see scswifts notes above for example).
  • In Atmel Studio, open project and change target device to match yours.
  • In Atmel Studio, edit Project > YourProject Properties > Build, and check "Use External Makefile", and point it to your Makefile
  • board_definitions.h - change BOOT_DOUBLE_TAP_ADDRESS (0x20007FFCul) to match your target's (see Mattairtech for example).
  • Makefile - change processor flag. eg: CFLAGS_EXTRA?=-D__SAMD21G17A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x4D -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
  • Makefile - change linker script name to match your linker file. eg. "$(CC)" -L. -L$(BUILD_PATH) $(LDFLAGS) -Os -Wl,--gc-sections -save-temps -Tbootloader_samd21x17.ld
  • Rename bootloaderSam21x18.ld to match your linker file referenced in Makefile. eg. bootloader_samd21x17.ld
  • In same linker file edit Memory to match the particulars of your device (see scswifts notes above for example).
  • Build and upload bootloader to your board
  • Replace bossac.exe (in C:\Users\you\AppData\Local\Arduino15\packages\arduino\tools\bossac\1.6.1-arduino) with MattairTech's Bossac BOSSA fork (see scswift's notes). Backup Arduino's bossac.exe
  • Upload code from Arduino IDE.

That's it! Try it out and let me know if it doesn't work for you.

There's another bit you'll want to change, and I don't know if there's any other places this needs to be done, but in SPI.h there is a preprocessor command that defines the maximum SPI speed:

#if defined(__SAMD21E17A__)
  // Even if not specified on the datasheet, the SAMD21E17A MCU
  // doesn't operate correctly with clock dividers lower than 4.
  // This allows a theoretical maximum SPI clock speed of 12Mhz
  #define SPI_MIN_CLOCK_DIVIDER 4
  // Other SAMD21xxxxx MCU may be affected as well
#else
  #define SPI_MIN_CLOCK_DIVIDER 2
#endif

It normally checks for the SAMD21G18A and you can see here I have altered it for my board the Tau.

Hello everybody,

I developed hardware for the Atmel ATSAML21J18B. It has the same pin count as the Arduino Zero/Atmel ATSAMD21. It should be possible to port the ATSAMD21 to ATSAML21J18B. Can someone port it for me? Of course I can give you hardware and a fee.

Swangoo:
Hello everybody,

I developed hardware for the Atmel ATSAML21J18B. It has the same pin count as the Arduino Zero/Atmel ATSAMD21. It should be possible to port the ATSAMD21 to ATSAML21J18B. Can someone port it for me? Of course I can give you hardware and a fee.

Just curious - did you success ? I just did the same. Not easy task, but possible ! Regards !