Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • dice
2 results

atsamd51

  • Clone with SSH
  • Clone with HTTPS
  • Yonder D51

    The ATSAMD51 is an ARM Cortex-M4F microcontroller manufactured by Microchip (Atmel).

    As of Oct 13 2019, -> CBA ❤️ D51 <-

    Circuits using the D51

    feather m4 pic Adafruit Feather M4

    module pic squidworks module

    Bare(ish) Metal Toolchains

    OpenOCD

    Bootloader Based Toolchains

    Since Adafruit has adopted the SAMD51, it is well supported by the open source community, and we can borrow their development tools. For instructions on how to burn your board with a bootloader, see the bootloader directory.

    Once you've got a bootloader on your board, you have a lot of options for programming it.

    Platformio

    To write code and load it, Jake uses PlatformIO, which is an open source 'IOT' (embedded) programming tool written as a package for either atom code-editor, or vscode. See their doc for setting up a new project for the D51 / Feather M4.

    Arduino IDE

    We're not going to beat Adafruit's documentation on setting up the Arduino IDE, so just take a gander over here. It's their bootloader, after all. An example sketch lives in the blink-arduino directory.

    Real Registers in an Arduino World

    One of the troubles with Arduino is that people forget that it is just a big C++ library. This means that everything under the sun (that compiles) is legal here. That means that we can use Arduino as a crutch, but write really nice Special Function Register code inside of the same executable. Great!

    Indeed, in the PlatformIO environment, we even have wonderful autocomplete handles on the D51's core register map. For some examples of this kind of manipulation, check out the hunks in the ponyo project.

    D51 Errata and Dev Notes

    Adafruit and PA17

    This is not mentioned in the ada doc, but beware PA17 - ada uses this (afaik) to debug their USB implementation... you can pull it hi / lo as much as you want, but when a USB connection is made ada will reclaim the pin and output some kind of tick on it. Unclear to me. Unfortunately for yrs truly the D51 modules I've built have the RS485 termination enable pin on this line.

    I believe it's possible to find your way through the ada / arduino build core and rm the output, I've done it once before, but have since lost my notes on where it is.

    Interrupt Clear / Set

    2021 08 07

    We can ostensibly set and clear interrupts in the D51 with code like:

    SERCOM1->USART.INTENCLR.bit.DRE = 1;

    FWIW there's the additional step of actually enabling them through the NVIC (nested vector interrupt controller), which we do once during a setup, like:

    NVIC_EnableIRQ(SERCOM1_2_IRQn); // rx interrupts 
    NVIC_EnableIRQ(SERCOM1_1_IRQn); // transmit complete interrupt 
    NVIC_EnableIRQ(SERCOM1_0_IRQn); // data register empty interrupts 

    And then use the INTENCLR / INTENSET registers to turn them on / off during operation. In any case, I've found the .bit interface to be a little less reliable (for whatever reason) than a more direct register access like below:

    SERCOM1->USART.INTENCLR.reg = SERCOM_USART_INTENCLR_DRE;

    So - watch for that. Use the second line if in doubt.

    Interrupt Lines / Handlers / Which is Which

    It's not exactly clear from the datasheet which interrupt handler is which action. For example to get an RXC interrupt on the SER1 UART, we have:

    // enabling the thing from NVIC 
    NVIC_EnableIRQ(SERCOM1_2_IRQn); // rx interrupts 
    
    // turning it on in the peripheral
    SERCOM1->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC;
    
    // handling it 
    void SERCOM1_2_Handler(void){
    
    }

    So how are we meant to discover which is which? Well, we can find this line wherever samd51j19a.h is located in your build system:

    SERCOM1_2_IRQn = 52, /**< 52 SAMD51J19A Serial Communication Interface 1 (SERCOM1): SERCOM1_2 */

    Showing that this is interrupt line '52' - which is what gets passed to the NVIC when the interrupt needs to fire (AFAIK), then on the datasheet section 10.2 we get a list of the Interrupt Line Mapping which shows that this line 52 is mapped to SERCOM1_2 interrupt: well, how do we know that SER1_2 is the RXC interrupt? It's actually not clear, but I have found that the register map / interrupt flags i.e. in the D51 datasheet 34.8.8 has the DRE in bit position 0 (it's interrupt SERx_0), TXC in position 1 (it's SERx_1) and RXC in position 2 (SERx_2) etc.

    Notice also that multiple interrupts can be mapped to the same handler, i.e. back in DS 10.2 we have SER1_3, SER1_4, SER1_5, and SER1_7 all on line 53 - FWIW I can't tell you if they each have different handlers, but I suspect they would all come through something like:

    void SERCOM1_3_Handler(void){}

    And then we can check flags SERCOM1->USART.INTFLAG.reg to figure which of these was actually set when the thing was called.

    GLHF.