Getting around an openocd bug

I’ve been back working with the SAMD20 microcontroller family again for an RS485 network project. While writing code for the device I noticed that it would crash quite often. Further investigations revealed that sections of the code were not being written to flash memory. This device has a 64 byte flash page size and it will only accept writes of 64 byte blocks. If you try to write a smaller amount the write is ignored. This causes a problem when you want to write a flash image that is not an integer multiple of 64 bytes in size – the last few bytes will not be written out. The version of openocd I’m using came from here . I reported the issue but while I’m waiting for a response I’ve managed to workaround the problem by adding some padding to the flash image in the linker file as shown here.

    flash : org = 0x00000000, len = 128k
    ram : org = 0x20000000, len = 16k
	. = ORIGIN(flash);
        .text : {
		  *(.vectors); /* The interrupt vectors */

        } >flash
	. = ORIGIN(ram);
        .data : {
	  . = ALIGN(4);
        } >ram AT>flash
	.bss : {	  
	    . = ALIGN(4);
	} > ram
	BSS_END = .;
	.padding : {
		  /* This is a 64 byte block of 0xff's to ensure that the last */
		  /* page of the program is written to the MCU */
		  /* The openocd SAMD driver does not seem to flush the last partial */
		  /* page out properly */

	} >flash

This linker script is for the SAMD20E17 MCU. The value chose for the padding data is important as the erased state of flash is logic ‘1’. By using 0xffffffff as a padding value (which may or may not be written to the flash) read-back verification will report a success.

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 "../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)

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    
    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)
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
        printString("Hello SamD!\r\n");
        i = SERCOM0_INTFLAG;
        PAOUTTGL = BIT0; // Toggle Port A bit 0
        delay(10000);   // Wait