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
}
}