Adapting Arduino SAMD Core for SAMD21J18A

Hey Everyone,

Over the past month, I have designed and built a custom SAMD21J18A microcontroller board for a home automation project I am working on. I designed this board with the SAMD21J18A because I needed a lot of pins to connect sensors, modules, etc.

Throughout the design process, I expected to have zero issues with using the latest version of the Arduino SAMD Core. Unfortunately, that I not the case.

A lot of my sensors/modules use the SPI and I2C libraries. The major problem that I am having is that when I upload code with these libraries (it always uploads just fine), there is NEVER a response in the serial console.

For example, I just uploaded examples from the Arduino SAMD Core SPI and I2C libraries, and I never got any answer in the serial console.

At first, I thought that maybe the serial console was not working, however, if I write some basic code with Serial.print("hello world"); it works just fine.

Also, before I continue, I wanted to mention that I did modify the SAMD21 bootloader as well as the boards.txt and variants files. I am able to upload simple pieces of code such as blink, but not any code with libraries from the arduino samd core such as SPI, I2C...

If I had to guess, I think that there are some incompatibility issues with the SAMD21J18A, and the standard SAMD21G18A. To further test this, I used a spare Arduino MKR board I had with the SPI and I2C libraries and after uploading, the serial monitor successfully printed information.

What do I need to change to fix these incompatibility issues? I have seen existing libraries forked off from the Arduino SAMD Core but they are all extremely outdated.

I'm sure its possible, and would really appreciate any help.

Thanks again!!

Hello,

I had previously seen that post before, and my boards.txt file does have the correct chip name. (I have tried adding my board/variants to my existing arduino samd core folder and creating a new one, both don't change anything)

Besides the chip, the other main component on my board is a Ublox WiFi/BLE module, in order to upload sensor data to the cloud.

I have been trying to get this library to work, however like before, whenever I try to upload an example program like CheckFirmware, there is never a response in the serial console. (for WiFiNina firmware check, it does actually print "WiFiNINA firmware check"), but nothing else.

I then tried to change the chip name back to "SAMD21G18A" in boards.txt, because I have a standard SAMD21G18A board, but when I upload code, the port automatically disappears after the upload finishes.
(On the SAMD21G18A board without the wifi module, the serial console does work and prints "no module connection" or something...) For some reason, the samd core/code/libraries do not like the fact that I am using a SAMD21J18A

When planning this project, I thought that the Arduino SAMD core would be compatible with this chip because it is identical to the SAMD21G18A, just with a few more pins.... I guess not...

Do you have an idea of what could be the problem or something to try?

Thank you

I would imagine that someone has had this issue in the past.. If not, hopefully we can figure this out to help anyone in the future.

Do you have a schematic of your custom board? I have written some custom C library specifically for the SAMD21 and I might be able to help you re-purpose existing libraries to work with your board.

Note: the libraries I have are written purely in C but can be adapted to the Arduino IDE

the USB port is created by the core code in your sketch. if the sketch doesn't work the port disappears. on Arduino SAMD boards a double reset activates the bootloader to upload a working sketch.

see this thread about a custom board for WiFiNINA Arduino Forum

Hey, thanks for the replies.

I think I may have got sidetracked in my last post. The main problem I am facing is that I am not getting any output from the Serial Monitor when I upload certain libraries such as WiFi NINA for a SAMD21J18A.

In order to get the WiFi/BLE working, I need to be able to see the Serial Monitor outputs. For some odd reason, WiFiNINA does not like the SAMD21J18A. I also have the ECC608 crypto chip, because I based my massive board off the MRK WiFi1010, just with the bigger chip and lots of more pins outputted. Not only did I get no Serial Monitor outputs for WiFi NINA, but also the crypto library.

Once, I am able to fix this odd serial monitor issue, I will then be able to get the WiFi working and write the code for my sensors to upload data.

Here is a an image of my schematic connections to the Ublox NINA W102. Besides these connections, everything is exactly same as on the MKR WiFi 1010, expect the bigger chip (SAMD21J18A).

Thank you everyone for your help!

This is not a serial monitor issue because you clearly can output something when loaded with a basic sketch

At first, I thought that maybe the serial console was not working, however, if I write some basic code with Serial.print("hello world"); it works just fine.

In the SAMD21 CPU, there are clocks to consider, the routing of clock sources to clock generators and generic clocks, etc. If somehow the Arduino core routes these clocks in a particular way that is not compatible with the J18A you have, then the peripherals won't come up and you won't be able to do anything about it unless you modify the clock routing in a manner that is compatible with your board. Do you have a 32kHz crystal connected? I'm guessing the MKR uses this to feed the 48MHz generator, and if you don't have it in your custom board, it will surely fail as it will default to 2MHz I believe

Hello, thanks again for responding.

I do have an external crystal. It is the same one from the MKR WiFI 1010 schematic. (link: https://www.digikey.com/product-detail/en/abracon-llc/ABS07-32.768KHZ-T/535-9542-1-ND/1237009)

I do believe it is working because the computer does recognize the board. In previous SAMD21 boards I have made, I have had problems with the crystal. But when this happens, the board never shows up unless it is running crystal-less in the bootloader.

Thanks again.

do you have a variant.h for your board and did you set the SPI1 pins for WiFiNINA and the modified IO0 and RESET pins? are the pins you connected as SPI to NINA valid pins for some sercom?

Yeah, I think so...

Here is from variant.cpp

{ PORTA, 4, PIO_SERCOM_ALT, (PIN_ATTR_NONE ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
{ PORTA, 5, PIO_SERCOM_ALT, (PIN_ATTR_NONE ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
{ PORTA, 6, PIO_DIGITAL, (PIN_ATTR_NONE ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
{ PORTA, 7, PIO_SERCOM_ALT, (PIN_ATTR_NONE ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },

{ PORTB, 12, PIO_DIGITAL, (PIN_ATTR_DIGITAL ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
{ PORTB, 13, PIO_DIGITAL, (PIN_ATTR_DIGITAL ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
{ PORTB, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL ), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },

I also have this:

// NINA - SPI boot
pinMode(NINA_GPIO0, OUTPUT);
digitalWrite(NINA_GPIO0, HIGH);

// disable NINA
pinMode(NINA_RESETN, OUTPUT);
digitalWrite(NINA_RESETN, LOW);

From variant.h I have this:

#define NINA_GPIO0 (40u)
#define NINA_RESETN (41u)
#define NINA_ACK (42u)

and

// SPI1
#define PIN_SPI1_MISO (37u)
#define PIN_SPI1_MOSI (36u)
#define PIN_SPI1_SCK (39u)
#define PIN_SPI1_SS (38u)
#define PERIPH_SPI1 sercom0
#define PAD_SPI1_TX SPI_PAD_0_SCK_3
#define PAD_SPI1_RX SERCOM_RX_PAD_1
static const uint8_t SS1 = PIN_SPI1_SS;
static const uint8_t MOSI1 = PIN_SPI1_MOSI;
static const uint8_t MISO1 = PIN_SPI1_MISO;
static const uint8_t SCK1 = PIN_SPI1_SCK;

#define SPIWIFI_SS PIN_SPI1_SS
#define SPIWIFI_ACK NINA_ACK
#define SPIWIFI_RESET NINA_RESETN

and

#define Serial SerialUSB

// Alias Serial1 to SerialNina (useful in libraries)
#define SerialNina Serial1

#define SPIWIFI SPI1

Finally, in the boards.txt, I set the board ID to be "SAMD_NANO_33_IOT" because I believe that because similar to my schematic, the Nano 33 IOT is not inverted on the reset connection.

Even with all of this, I still don't get any response from the WiFi Nina sketches. None of them tell me if the module is connected or not...

Also, I attached the schematic for the module connections a few posts above.

I just tried to read some basic data from a few environmental sensors that I hooked up to my board and got zero response from the Serial Monitor.

I still feel like something is wrong with the core files... When I then upload the same exact code using the same core/variants/boards.txt files on my custom SAMD21G18A, I at least get a response even though nothing is connected.

Also, I went through the Arduino SAMD Core looking for files that had something about the SAMD21G18A in them. I turns out that I found 7 files with the default microcontroller mentioned. Most of them were in the USB sub folder. Could that be important? Or should the Arduino SAMD Core already work with the SAMD21J18A?

What should I try?

Thanks!

I just tested the following code on my SAMD21 (using a debugger). It will activate the I2C master on SERCOM0 on PA8/PA9 (the one connected to your ECC608). This will start GENCLK7, use the built-in 8MHz oscillator, and feed that clock to SERCOM0

	// CLOCK GENERATOR 7, use internal OSC8M, no pre-scaling
	REG_GCLK_GENCTRL = GCLK_GENCTRL_ID(0x7);
	REG_GCLK_GENDIV  = GCLK_GENDIV_DIV(1) | GCLK_GENDIV_ID(0x7);
	REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC8M | GCLK_GENCTRL_ID(0x7);
	while(REG_GCLK_STATUS & GCLK_STATUS_SYNCBUSY);
	
	// use clock generator 7 for SERCOM0
	REG_GCLK_CLKCTRL = GCLK_CLKCTRL_ID_SERCOM0_CORE;
	while(REG_GCLK_CLKCTRL & 1<<14);
	REG_GCLK_CLKCTRL = GCLK_CLKCTRL_GEN_GCLK7 | GCLK_CLKCTRL_ID_SERCOM0_CORE;
	REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK7 | GCLK_CLKCTRL_ID_SERCOM0_CORE;
	
	
	// select alternate functions on multiplex pins (SERCOM0)
	PORT->Group[0].PMUX[4].reg = PORT_PMUX_PMUXO_C | PORT_PMUX_PMUXE_C;

	// SDA pin PA08
	PORT->Group[0].PINCFG[8].reg = PORT_PINCFG_PMUXEN;

	// SCL pin PA09
	PORT->Group[0].PINCFG[9].reg = PORT_PINCFG_PMUXEN;
	
	// enable power manager for sercom0
	REG_PM_APBCMASK |= PM_APBCMASK_SERCOM0;

	// reset sercom0 registers
	REG_SERCOM0_I2CM_CTRLA = SERCOM_I2CM_CTRLA_SWRST;
	while(REG_SERCOM0_I2CM_SYNCBUSY & (SERCOM_I2CM_SYNCBUSY_SWRST));

	// configure I2C master mode
	REG_SERCOM0_I2CM_CTRLA = SERCOM_I2CM_CTRLA_MODE_I2C_MASTER | SERCOM_I2CM_CTRLA_INACTOUT(0x3);

	// set I2C baud rate 370 KHz
	REG_SERCOM0_I2CM_BAUD = SERCOM_I2CM_BAUD_BAUD(5);

	// enable sercom0 I2C master
	REG_SERCOM0_I2CM_CTRLA |= SERCOM_I2CM_CTRLA_ENABLE;
	while(REG_SERCOM0_I2CM_SYNCBUSY & (SERCOM_I2CM_SYNCBUSY_ENABLE));

	// force master into IDLE state
	REG_SERCOM0_I2CM_STATUS = SERCOM_I2CM_STATUS_BUSSTATE(0x1);
	while(REG_SERCOM0_I2CM_SYNCBUSY & (SERCOM_I2CM_SYNCBUSY_SYSOP));

You can then modify this code below to send/receive basic data to any of your I2C device connected to those pins mentioned above. Just replaced anything that referenced to SERCOM3 to SERCOM0 and change the MASTER_READ and MASTER_WRITE addresses to match your I2C slave

void bme280_i2cReads(uint8_t address, uint8_t len, uint8_t * data)
{
	// master write operation (to send register address)
	REG_SERCOM3_I2CM_ADDR = BME280_MASTER_WRITE;
	while((REG_SERCOM3_I2CM_INTFLAG & (SERCOM_I2CM_INTFLAG_MB)) == 0);

	// check for bus error
	if(REG_SERCOM3_I2CM_STATUS & ((SERCOM_I2CM_STATUS_ARBLOST) | (SERCOM_I2CM_STATUS_BUSERR)))
	{
		// clear bus error and go to IDLE
		REG_SERCOM3_I2CM_STATUS = (SERCOM_I2CM_STATUS_ARBLOST) | (SERCOM_I2CM_STATUS_BUSERR) | (SERCOM_I2CM_STATUS_BUSSTATE(0x1));
		while(REG_SERCOM3_I2CM_SYNCBUSY & (SERCOM_I2CM_SYNCBUSY_SYSOP));

		return;
	}
	else
	{
		// register address to read from
		REG_SERCOM3_I2CM_DATA = address;
		while((REG_SERCOM3_I2CM_INTFLAG & (SERCOM_I2CM_INTFLAG_MB)) == 0);

		// master read operation, repeated START condition
		REG_SERCOM3_I2CM_ADDR = BME280_MASTER_READ;
		while((REG_SERCOM3_I2CM_INTFLAG & (SERCOM_I2CM_INTFLAG_SB)) == 0);

		// retrieve data until finish
		for(uint8_t count=0; count<(len-1); count++)
		{
			while((REG_SERCOM3_I2CM_INTFLAG & (SERCOM_I2CM_INTFLAG_SB)) == 0);
			data[count] = REG_SERCOM3_I2CM_DATA;
			REG_SERCOM3_I2CM_CTRLB = SERCOM_I2CM_CTRLB_CMD(0x2);
			while(REG_SERCOM3_I2CM_SYNCBUSY & (SERCOM_I2CM_SYNCBUSY_SYSOP));
		}

		// read last byte and NACK- STOP
		while((REG_SERCOM3_I2CM_INTFLAG & (SERCOM_I2CM_INTFLAG_SB)) == 0);
		data[len-1] = REG_SERCOM3_I2CM_DATA;
		REG_SERCOM3_I2CM_CTRLB = SERCOM_I2CM_CTRLB_ACKACT | SERCOM_I2CM_CTRLB_CMD(0x3);
		while(REG_SERCOM3_I2CM_SYNCBUSY & (SERCOM_I2CM_SYNCBUSY_SYSOP));
	}

	return;
}

If I get time tomorrow, I'll hook up some real I2C slave on PA8/PA9 to simulate your setting and see if I can talk to it with the above code.

Wow, that's really cool, however, is it completely necessary?

My board works great minus the difficulties with Arduino SAMD Libraries/Files...

All my digital/analog pins work, and I am able to program it, the one issue is the serial communication or something.

I have more information now, hopefully this will allow you to better understand my problem and hopefully be able to spot a red flag.

Previously, I said how I never get a response from programs in the Serial Monitor from the Arduino WiFiNINA library and the Arduino ECC608 crypto library. However, just today I tried using the Arduino BLE library, and I actually got a response from the serial monitor.

WiFiNINA uses SPI, ECC608 Crypto uses I2C, and BLE uses UART. Therefore, could there be some incompatibility issue with the Arduino SAMD Core SPI and I2C libraries with the SAMD21J18A?

I am no expert and may totally be wrong. But I don't have the correct to explain why the UART Arduino SAMD Core libraries work while the SPI and I2C Arduino SAMD Core libraries never show a response in the Serial Monitor.

Does anyone know what could be causing my problem? If you have any questions, please ask.

Thank you so much!!!

The Arduino SAMD Core Library folder can be found here: ArduinoCore-samd/libraries at master · arduino/ArduinoCore-samd · GitHub

Here is another update:

So, I just downgraded the firmware for the NINA module to 1.2.2 and then upgraded to 1.3.0

Then when I uploaded CheckFirmwareVersion, I actually got a response. It didn't say the firmware version, just that it saw no module connected. In order to see if this was more than just UART, I uploaded Scan Networks, and got the same no module connected response. But most importantly, I actually got a response which I previously didn't get.

However, I still don't get any response from the Arduino ECCX08 Library. Whenever, I upload a sketch from that library and then open the serial console after is uploads, the serial monitor is just blank.

I will keep trying things to keep everyone updated. The worst thing about this problem is that is seems to be intermittent. Hopefully, the more information that I provided will help give everyone a better understanding.

Let me know if you have any questions.

Thanks.

Another Update: I just unplugged the board and then plugged it back in, and now I am getting no response from the serial monitor again with the WiFiNINA library .. :frowning:

This makes no sense to me....

WiFiNina uses SPI and a pin for ACK and a pin connected to io 0 of NINA for 'heartbeat' signal. (so 6 digital pins)

Hello,

A few posts above I printed my setup for the WiFi NINA pins. I do have 4 wire SPI + 3 gpio pins.

Is that what you mean?

Thanks

Also, shouldn't it still print whether if it sees no module connected?

And the issue is the same with the crypto chip. There is never a serial console print out.

Just to double check, PA8 and PA9 are on the correct pins

SAMD21GXX has them on 13/14
SAMD21JXX has them on 17/18