SAMD21 SERCOM hang problem

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using SERCOM0 and SERCOM3 in an application

The initialisation runs correctly on SERCOM0, but hangs when enabling the USART for SERCOM3

At entry to the following code the registers SERCOM->CTRLA and BAUD are identical for both SERCOMs

The code is:

 SERCOM3->USART.CTRLB.bit.RXEN = 0x01;
  while (SERCOM3->USART.SYNCBUSY.bit.CTRLB)
    ;
  SERCOM3->USART.CTRLA.bit.ENABLE = 1u;   /* Enable the receiver */
  while (SERCOM3->USART.SYNCBUSY.bit.CTRLB)
    ;

On setting CTRLA.ENABLE the SERCOM3->SYNCBUSY bits ENABLE and CTRLA bits get set, so the next statement loops for ever. They are not set on SERCOM0. 

The same code on SERCOM1 hangs as well

On page 411 of the SAMD21 datasheet it reads "Writing '1' to CTRLB.RXEN when the USART is disabled will set CTRLB.RXEN immediately. When the
USART is enabled, CTRLB.RXEN will be cleared, and SYNCBUSY.CTRLB will be set and remain set
until the receiver is enabled. When the receiver is enabled, CTRLB.RXEN will read back as '1'."

I tried setting CTRLB.RXEN after the enable, it resulted in a hard fault...

Thanks for any good ideas, I've been messing about with this problem for a few hours

Jerry

 

 

This topic has a solution.
Last Edited: Tue. Oct 31, 2017 - 09:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From code fragment no one is able to give you an advice. Provide complete SERCOM configuration sequence (+OSC, PM, GCLK...)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Before I read jkonicek's comment (for which I thank you) I fixed the problem, and have a very red face

A peripheral needs a clock, and I'd forgotten to set the core clock GCLK_SERCOMn_CORE, see section 26.5.3 of the datasheet. RTFM!

This doesn't explain why SERCOM0 worked right from the start

Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please mark the solution: http://www.avrfreaks.net/comment...

 

jerryr wrote:
This doesn't explain why SERCOM0 worked right from the start

just a lucky set of defaults?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
just a lucky set of defaults?

Not lucky, the SERCOM0 had already got its CORE clock in the function which sets up all the clocks in the program initialisation

The solution to the original problem is to configure a CORE clock for each SERCOM

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

set TX and RX pins:   

    static inline void pin_set_peripheral_function(uint32_t pinmux)
    {
        uint8_t port = (uint8_t)((pinmux >> 16)/32);
        PORT->Group[port].PINCFG[((pinmux >> 16) - (port*32))].bit.PMUXEN = 1;
        PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg &= ~(0xF << (4 * ((pinmux >>
        16) & 0x01u)));
        PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg |= (uint8_t)((pinmux &
        0x0000FFFF) << (4 * ((pinmux >> 16) & 0x01u)));
    }

gclk and pm configuration:

PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0;//APBCMASK
        GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN | GCLK_CLKCTRL_ID_SERCOM0_CORE;// Enable GCLK0 for SERCOM0
        while (GCLK->STATUS.bit.SYNCBUSY==true){}

sercom configuration:

SERCOM0->CTRLA.bit.ENABLE=0;
    while (SERCOM0->SYNCBUSY.bit.ENABLE==1);
    
    
    //USART mode with external or internal clock must be selected
    SERCOM0->CTRLA.bit.MODE=0x01;//0x1: USART with internal clock.
    
    //Communication mode (asynchronous or synchronous) must be selected
    SERCOM0->CTRLA.bit.CMODE=0x00;//0: asynchronous communication.
    
    //This bit indicates the relationship between data output change and data input sampling in synchronous mode.
    SERCOM0->CTRLA.bit.CPOL=0x01;//Rising XCK edge
    
    //SERCOM pad to use for the transmiter must be selected
    SERCOM0->CTRLA.bit.TXPO=0x01;//SERCOM PAD[2] is used for data transmit
    
    //SERCOM pad to use for the receiver must be selected
    SERCOM0->CTRLA.bit.RXPO=0x00;//SERCOM PAD[0] is used for data reception
    
    //Character size must be selected by writing to the Character Size bit group
    SERCOM0->CTRLB.bit.CHSIZE=0x00; //Character Size 0x00: 8 bits
    
    //MSB- or LSB-first data transmission must be selected
    SERCOM0->CTRLA.bit.DORD=0x01;//1: LSB is transmitted first
    
    //Number of stop bits must be selected
    SERCOM0->CTRLB.bit.SBMODE=0x00;//0: One stop bit
    
    //When using an internal clock, the Baud register (BAUD) must be written to generate the desired baud rate
    SERCOM0->BAUD.reg=_baudrate(_baud,48000000);
    
    //The transmitter and receiver can be enabled
    SERCOM0->CTRLB.bit.RXEN=1;//The receiver is enabled or will be enabled when the USART is enabled
    SERCOM0->CTRLB.bit.TXEN=1;//The transmitter is enabled or will be enabled when the USART is enabled
    
    //enable interrupts
    SERCOM0->INTENSET.bit.RXC=1;//enable Receive Complete interrupt flag
    
    NVIC_EnableIRQ(SERCOM0_IRQn);//enable in the NVIC interrupt enable register

 

baudrate:

uint16_t _baudrate(float fbaud, float fref)
{
    float S=16;//Number of samples per bit. Can be 16, 8, or 3
    return uint16_t(float(65536)*(1-S*fbaud/fref));
}