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