Trying to Understand Serial/SerialUSB Interactions

I would like to use the "Native" port as the primary "console" port for my application, leaving the "Programming" port disconnected, except when FLASHing new firmware. However, I'm finding the Native port does not even enumerate on the PC unless and until the Programming port is connected, and the SerialMonitor or other terminal application is opened on it.

Another odd thing - the COM port assigned to the Native port keeps changing. In the last hour, it's come up as COM8, COM9 and COM10 at various times.

What's going on here? Is there some trick I'm missing to make this work?

Regards, Ray L.

Something is wrong. The native port doesn't depend on the programming port. Maybe there's something wrong with the power coming from that port of your computer, the power wires in that particular USB cable or the power-switching logic on your Due.

The native port does depend on software running on the Due. If your sketch locks up then it also locks up the native port. That's why there's an "erase" button on the Due.

It may come up as a different port if you plug it into a different socket on your PC.

Morgan,

I considered power might be a problem, but once the Native port is working, I can disconnect the Programming port, and the Native port continues to work, which tells me power is fine. I'm going to write a test program to see if I can figure out what it IS doing when only the Native port is connected.

As for the COM port numbers, I'm running Win8, which normally retains the same port number for a given device, regardless of which USB port it is connected to. I do sometimes see a device "Bossac Communications Port" appear as well. That one seems to appear when I try to program using the Programming port while the Native port is also connected to the PC.

Regards, Ray L.

RayLivingston: Morgan,

I considered power might be a problem, but once the Native port is working, I can disconnect the Programming port, and the Native port continues to work, which tells me power is fine. I'm going to write a test program to see if I can figure out what it IS doing when only the Native port is connected.

As for the COM port numbers, I'm running Win8, which normally retains the same port number for a given device, regardless of which USB port it is connected to. I do sometimes see a device "Bossac Communications Port" appear as well. That one seems to appear when I try to program using the Programming port while the Native port is also connected to the PC.

Regards, Ray L.

I basically never use the programming port on the Due. Using the native port works perfectly fine for me. So, I'd still guess that something odd is happening with your PC or the Due itself.

As for port numbers - WIndows sucks. Even Windows 10 will give you different port numbers for different ports and it's annoying. It might be a bit better than Windows 7 where it is not uncommon for people to be up to COM40 or something. On my Win10 install I think most all my stuff registers at COM12 or less. This is as opposed to sane operating systems like Linux where devices are generally enumerated based on when you plugged them in, first come, first serve.

Also, the native port will register as two different com ports. One is the actual native port and the other is the BOSSA/SAM-BA port. You will see one or the other. If you erase the board it comes back up as BOSSA. If a firmware flash goes bad it might also come up as BOSSA or SAM-BA. Once the firmware is properly flashed it will be a different com port.

OK, this turned out to be a screw-up on my part. Silly me, I assumed the SerialUSB port would be derived from HardwareSerial, but it's not. I was testing for that, which caused the SerialUSB.begin to be skipped. That is now resolved.

Thanks!

Regards, Ray L.

Next question:

Is there a "clean" way to force the equivalent of a reset on the Due? It is not necessary to actually reset the hardware (though that would be nice), but it is necessary to re-start the firmware as though a hardware reset had been performed. I need to be able to do this under firmware control via a command received from the Native port, to more-or-less emulate the DTR functionality on the Programming port.

Regards, Ray L.

You know you can call setup() from inside loop() don't you? It's just another function.

Of course that doesn't reset some of the Arduino framework, but it's up to you to decide how deep of a reset you need.

MorganS: You know you can call setup() from inside loop() don't you? It's just another function.

Of course that doesn't reset some of the Arduino framework, but it's up to you to decide how deep of a reset you need.

Yes, of course. But that is far from the equivalent of the reset, as initialized variables will not be reset to their initial values, etc. What I really want it to re-start from crt0. One way to do it I am considering is to use the watchdog to force a hardware reset.

Regards, Ray L.

Yeah, you could use the watchdog. But, remember, you can only set the interval one time so you'll have to set it on start up and keep kicking it until you want to reset then stop resetting the watchdog timer and it will do a processor reset.

Or, use banzai(); You might need to include "Reset.h" to get the function but it is specially designed to cause a system reset.

Edit: Seems you can't directly use banzai from a sketch but you can copy the whole function into your sketch and it at least compiles:

__attribute__ ((long_call, section (".ramfunc")))
void banzai() {
    // Disable all interrupts
    __disable_irq();

    // Set bootflag to run SAM-BA bootloader at restart
    const int EEFC_FCMD_CGPB = 0x0C;
    const int EEFC_KEY = 0x5A;
    while ((EFC0->EEFC_FSR & EEFC_FSR_FRDY) == 0);
    EFC0->EEFC_FCR =
        EEFC_FCR_FCMD(EEFC_FCMD_CGPB) |
        EEFC_FCR_FARG(1) |
        EEFC_FCR_FKEY(EEFC_KEY);
    while ((EFC0->EEFC_FSR & EEFC_FSR_FRDY) == 0);

    // From here flash memory is no more available.

    // BANZAIIIIIII!!!
    const int RSTC_KEY = 0xA5;
    RSTC->RSTC_CR =
        RSTC_CR_KEY(RSTC_KEY) |
        RSTC_CR_PROCRST |
        RSTC_CR_PERRST;

    while (true);
}

Collin80: Yeah, you could use the watchdog. But, remember, you can only set the interval one time so you'll have to set it on start up and keep kicking it until you want to reset then stop resetting the watchdog timer and it will do a processor reset.

Or, use banzai(); You might need to include "Reset.h" to get the function but it is specially designed to cause a system reset.

Edit: Seems you can't directly use banzai from a sketch but you can copy the whole function into your sketch and it at least compiles:

__attribute__ ((long_call, section (".ramfunc")))
void banzai() {
    // Disable all interrupts
    __disable_irq();
// Set bootflag to run SAM-BA bootloader at restart
const int EEFC_FCMD_CGPB = 0x0C;
const int EEFC_KEY = 0x5A;
while ((EFC0->EEFC_FSR & EEFC_FSR_FRDY) == 0);
EFC0->EEFC_FCR =
    EEFC_FCR_FCMD(EEFC_FCMD_CGPB) |
    EEFC_FCR_FARG(1) |
    EEFC_FCR_FKEY(EEFC_KEY);
while ((EFC0->EEFC_FSR & EEFC_FSR_FRDY) == 0);

// From here flash memory is no more available.

// BANZAIIIIIII!!!
const int RSTC_KEY = 0xA5;
RSTC->RSTC_CR =
    RSTC_CR_KEY(RSTC_KEY) |
    RSTC_CR_PROCRST |
    RSTC_CR_PERRST;

while (true);

}

It compiles, but it doesn't seem to work.... When executed, it goes out to lunch and never comes back.

Regards, Ray L.

I'll have to spend some time with the datasheet to understand exactly what banzai is doing, but it appears to be disabling, if not clearing, FLASH. If I comment out the first block of code, which writes the EEFC registers, and just leave the code that writes the RSTC registers, it appears to do what I need.

Regards, Ray L.

It's very hard to make sense of the 8 billion options in the SAM chip, but it appears the first block of code in banzai() is configuring the FLASH controller to execute from the embedded boot ROM after a reset, which is why banzai() does not do what I need. By commenting out that code, the writes to the Reset controller force a hardware reset, but execution beings from FLASH, rather than the boot ROM, so the effect is my program is re-started exactly as if the reset button had been pressed, which is exactly what I needed. banzai() is apparently there to support some Atmel functionality, but is not used by the Arduino startup code.

Regards, Ray L.

The banzai function is used to create a way to upload a new sketch properly. To upload a new sketch you set the port speed to 1200 then back and this causes the reset to happen and banzai to be called. I didn't think about it setting the boot flag but I suppose that makes sense. Yes, the second part just causes a hardware reset which is what you wanted.

Banzai could have ben called HARAKIRI().

It erases the first page of your application address ( most of the time @ 0x2000 ) and then call a reset. NVIC_SystemReset();

New sketch upload is then mandatory .... bootloader checks is flash adress 0x2000 content is 0xFFFF ( no sketch loaded ).

The easiest reset is the one from ARM trough CMSIS commands.

I use it in my code... if it happens that the "bootloading pin" is asserted, it will stay in bootloader mode NVIC_SystemReset();