Problems with porting Arduino Zero core

Hi all, I'm currently working on porting the Arduino Zero core to a board I designed for a client, and I'm having some issues. First the relevant hardware differences, then what's going wrong.

It uses a SAMD21J18, because the board needs the extra pins. Instead of a low speed oscillator as a main clock source, it uses a 16 MHz oscillator. It also lacks the EDBG, because the application has no room for it. I think that's the only stuff that matters for my question -- it has a bunch of other hardware added for the client's application, but I don't think it's necessarily relevant to my problem.

I confirmed that my clock setup is correct because I can run the Blink sketch and it shows the proper timing. However...

When I load code (such as Blink), it appears to run after the bootloader exits. However, my computer (Windows 8.1 64 bit) does not recognize the board as a USB device. If I reset it (or unplug and replug it), I have about a toss-up of one of two wrong results (and very occasionally correct behavior, just for extra frustration value):

  1. The code apparently runs normally, but Windows does not recognize the USB device. It reports the VID/PID as 0x0000/0x0002. This occurs whether or not I try to use USB serial from within the program.

  2. The code does not run, and the board re-enumerates as a USB device 2-3 times, finally enumerating as the bootloader (confirmed by VID/PID 0x2341/0x004d, as opposed to 0x804d).

I'm completely stumped -- any clues for the clueless?

Do you have PIN5 tied to ground? In the old bootloader, there is a check : if pin 5 is low at boot, you stay in the bootlaoder. In the last version of the bootloader that is on github, it's desactivated though.

Also, I don't know if the J variant of the SAMD21 is compatible whithout any change with the core.

When you run the blink example, is it the one that start right after you burn the bootloader, or have you been able to upload it via USB once?

The timing and use of clocks in bootloader and application are different, so maybe the 16MHz crystal is still an issue. Have you done any change to the code so that the device use a 16MHz clock as ref?

First, thank you for responding. This is really helpful.

I will double check on pin5... if that's floating, that could well be that issue, and it's easy enough to fix. I'll trye that first. Do I need to change that in the bootloader only or is there something in the core as well?

I've uploaded blink.ino via USB -- as I said, I've had it work correctly once or twice, but nothing consistent. Usually, when the code runs my laptop refuses to correctly enumerate it. I suspect there are issues with my laptop as well, and I am currently working on standing up a dedicated dev machine to rule that in or out. Frustratingly, I even got the SerialCallResponse.ino example apparently working once or twice, but again it's not repeatable.

I modified the startup code to work with a 16 MHz clock... if that was still wrong, it wouldn't run at all and it wouldn't have the correct period for the blink. The board doesn't have a 32 kHz crystal, so if I hadn't modified that it would not run at all.

Removing the bootloader pin #define seems to have fixed the problem! On to find out what else is wrong. :slight_smile:

Wow -- spoke too soon. My board enumerated correctly just after loading code... but I was not able to trip the bootloader nor was I able to get it enumerate again. It is, however, entirely consistent now. Do you have any more suggestions for things I can look at?

Which version of the samd core do you use?

Maybe the USB stack is still configured to use the 32KHz crystal?
Try this bootloader : Bootloader rework by aethaniel · Pull Request #47 · arduino/ArduinoCore-samd · GitHub
Iit works on my custom board, and it claims to improve USB stability.

I was able to get the j running with unmodified zero core files and bootloader. However, I used the same 32kHz xtal configuration that the zero uses.

So, Aloyse's suggestion to look after that detail is probably a good one.

Royce :
Have you been able to use the additional pins of th samd21J without modifying the variant.cpp?

I haven't tried the additional pins via the standard libraries yet, I've only gotten as far as getting the bootloader down and an IDE example program (which uses pins that the g also has) via the bootloader.

As I read the source for digitalWrite, I'll have to update variant.cpp to declare the extra pins to use them with the standard library functions. I don't think digitalWrite will even try to do anything without a declaration in variant.cpp.

Let us know whenever you're able to use the whole samd21j pin :slight_smile:

Maybe I'm being naive about it, but I can't find any mention of the 32 kHz crystal in the standard bootloader -- it looks like it uses the internal 8 MHz RC oscillator while in bootloader mode. AIUI, touching the USB serial port with a 1200 bps connection is supposed to cause it to reset and come back in bootloader mode. Could there be something with the different memory size that's causing that trick to fail?

I forked from the 1.6.1 samd core. I plan to merge mainline changes in at some point, but I'm trying to get the fundamentals working first... and that means solving my USB issues. I'll give aethaniel's new bootloader a spin and see if that improves the situation. Unfortunately, I changed the name of the bootloader directory to correspond to my board's name, so git had some issues with merging that will take a bit of time to fiddle out. Yay, go me... :confused:

Due to the nature of the board, I monkeyed with the variant.cpp while I was waiting for the PCB to come back from assembly. It has rather more stuff on it than most variants... I used all of the pins on the J. I know digitalWrite has no way to touch pins that are not listed in variant.cpp.

AloyseTech:
Let us know whenever you’re able to use the whole samd21j pin :slight_smile:

I got as far as digitalWrite with light modifications to variant.cpp. Going further would appear to require changes to a core file: WVariant.h. I found a lot of SAMD specific stuff in there, some even for the J. I guess they are sort of inbetween moving from WVariant.h in core to the this new variant.cpp scheme. So the Arduino-land hardware description appears to be currently split between the files.

Anyway below is my J doing its thing. A couple pins didn’t seem to respond, but I haven’t had the time to chase after it. Again, I used the 32kHz xtal, in just the way the Zero does. I don’t know why the rocketgeek’s 16Mhz xtal is not working, but I suspect it doesn’t have anything to do with J vs. G. I’d bet a G configured with the 16Mhz xtal would have overcome the exact same hurdle.

Video: https://youtu.be/HE9Wrq-Gvrc (Note my pins were layed out in port order, rather than Arduino pin order. So they don’t go on and off in a nice line as the sketch would suggest.)

The Sketch:

static const int pin_count = 58;

void setup() {
  // put your setup code here, to run once:
  for(int i = 0; i < pin_count; ++i)
  {
    pinMode(i, OUTPUT);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  static uint32_t state = LOW;

  if (state == LOW) state = HIGH;
  else state = LOW;

  for(int i = 0; i < pin_count; ++i)
  {
    digitalWrite(i, state);
    delay(100);
  }
}

The addition to variant.cpp:

//Extra J pins
  { PORTB,  4, PIO_DIGITAL, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, 
  { PORTB,  5, PIO_DIGITAL, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, 
  { PORTB,  6, PIO_DIGITAL, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, 
  { PORTB,  7, PIO_DIGITAL, PIN_ATTR_ANALOG, 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 }, 
  { PORTB,  15, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, 
  
  { PORTB,  16, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, 
  { PORTB,  17, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, 
  
  { PORTB,  30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, 
  { PORTB,  31, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, 
  { PORTB,  0, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, 
  { PORTB,  1, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },

Hi Royce, thanks for your work. :slight_smile:
Have you taken a look to the Autonomo board?

It uses a samd21j and this files : github link

It seems to have a custom variant.cpp and WVariant.cpp that includes all the digital and analog pins.

rocketgeek : Have taken a look in the USB files if there is any reference to some clock settings?

Back from vacation.

I merged the latest USB code into my fork and, after a bit of clock fiddling, managed to get it to work... once.

Here's the sequence of events:

  • Load revamped bootloader with my debugger
  • Reset to force my computer to enumerate the device, which it did, showing up as a serial port
  • Load the Blink sketch
  • Verify Blink sketch works correctly and device enumerates as a serial port (both good)
  • Attempt to reload Blink sketch
  • This failed; my computer no longer enumerates it as a serial port, and now Blink does not run
  • Reloaded bootloader with debugger
  • Device fails to enumerate

Any suggestions?

Looks like the reason it wasn't working after reloading the bootloader was because I accidentally broke the build process. With that fixed, I'm back to somewhere near my origin point. IOW, I can load and use the bootloader for one-off writing to the board, but the serial port doesn't seem to come up, ever. Thoughts?

Hi rocketgeek,

It sounds to me that the bootloader's working OK, but the native USB isn't.

Are you clocking the SAMD21's USB module at 48MHz? The SAMD21's data sheet (page 745) states:

The USB module requires a GCLK_USB of 48 MHz ± 0.25% clock for low speed and full speed operation.

I believe that the Zero uses generic clock 0 (GCLK0) running at 48MHz to clock the USB module.