Serial transmission on the SAMD20

This is a follow up to a previous post about bare-metal programming of the SAMD20 MCU. It has been tricky. There is a very complex clock system in the SAMD20 which is difficult to set up. The UART itself is pretty straight forward however and I’ve added a simple UART transmit example to the github repository.
Shown below is a listing for the UART related and main functions. System clock setup is done in another file (init.c).
Next step: Interrupts.

/* User LED is on PA0 */
/* This example uses SERCOM0 (UART mode) to send data to a host PC
 * 
 */
#include 
#include "../samd20e16.h"
/*
 How to program: run openocd first
 Next, run arm-none-eabi-gdb in another window and execute these commands (adjust directory to suit)
 target remote :3333
 monitor at91samd chip-erase
 monitor reset halt
 monitor load_image /home/frank/Documents/programming/samd/Baremetal/samd20_examples/serial/main.elf 0
 monitor reset 
*/
void delay(uint32_t dly)
{
    while(dly--);
}

void initUART()
{    
    // UART is on:    
    PM_APBCMASK |= BIT2; // turn on SERCOM0
    // Reset SERCOM 0
    SERCOM0_CTRLA = 1; // reset the UART
    while(SERCOM0_STATUS & BIT15); // wait for sync to complete   
    while ( SERCOM0_CTRLA & BIT0 ); // wait for reset to complete
    // Will route the main 48MHz clock to SERCOM0 as the baud rate base clock.
    GCLK_CLKCTRL = 0x0d + BIT14;        
    while(  (GCLK_STATUS & BIT7)); // wait for sync to complete
    SERCOM0_BAUD = 65325; // configure for 9600 bps
    while(SERCOM0_STATUS & BIT15); // wait for sync to complete   
    SERCOM0_CTRLB = BIT17 + BIT16 + BIT9 ; // enable TX, RX, Start-of-frame wakeup, 1 stop bit, 8 bits;
    // 0x00030200 RXEN,TXEN,SFDE,
    while(SERCOM0_STATUS & BIT15); // wait for sync to complete
    SERCOM0_CTRLA = BIT30 + BIT20 + BIT2 + BIT1; // LSB first, UART mode , internal clock, PAD1 = RX, PAD0 = TX, ENABLE    
    // 0x40000006 DORD,ENABLE,MODE001 (USART INTERNAL CLOCK), ENABLE
    while(SERCOM0_STATUS & BIT15); // wait for synchronization between clock domains to complete    
    // The actual special function is selected by writing to the upper 4 bits of PAPMUX5 
    // To select function C, write  '2' to these bits
    PAPMUX4 = 0x22;    
    PAPPINCFG8 |= BIT0; // enable special function multplexing on Pin 11                
    PAPPINCFG9 |= BIT0; // enable special function multplexing on Pin 12
}
void eputc(char c)
{
    SERCOM0_DATA = c;
    while((SERCOM0_INTFLAG & BIT1)==0);// wait for TXC flag
    
}
void printString(char *String)
{
    while (*String)
    {
        eputc(*String++);
    }
}
int main()
{
    int i=0;
    PADIRSET = BIT0; // make Port A bit 0 an output
    // Startup delay to allow escape from a potentially bricked chip: ONLY DELETE WHEN SURE OF PROPER CLOCK OPERATION
    for (i=0;i<10;i++)
    {
        PAOUTTGL = BIT0; // Toggle Port A bit 0
        delay(1000000);   // Wait  
    }    
    initUART(); // get SERCOM0 going
    while(1)
    {
        printString("Hello SamD!\r\n");
        i = SERCOM0_INTFLAG;
        PAOUTTGL = BIT0; // Toggle Port A bit 0
        delay(10000);   // Wait  
        
    }
   
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s