SAMD10 USART won't send character  - Page 1
Forum section: electronics / beginners

author: n4alpaca
author_rank: Newbie
timestamp: November 27, 2017, 04:15:30 am
content: Hello, I'm working my way through all of the sections of this micro controller (SAMD10) in an attempt to familiarize myself with them and I've run into a problem where I cannot figure out what I've done wrong. There is no output from the pin and the program builds without any trouble. I have also noticed that the MUX selection for the rx pin fails to set to C and stays as A (picture 1). I have Also noticed that the Error flag is set in the SERCOM0->USART.DATA register (picture 2).Have I failed to initialize something correctly?Here's the progression of my code.Main.cCode:int main(void) {// ENABLEenable_SERCOM0();struct PIN tx = gpio_create_pin(PMUXD,MUX_ENABLE,PORTA,4,OUT,PULLUP,PULL_DISABLE,IN_DISABLE);struct PIN rx = gpio_create_pin(PMUXC,MUX_ENABLE,PORTA,2,IN,PULLUP,PULL_DISABLE,IN_ENABLE);init_USART();//do {uart_putc('c');} while (1);return 0;}Enable SERCOM methodCode:void enable_SERCOM0(){PM->APBCMASK.reg = PM_APBCMASK_SERCOM0; // enable powerGCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM0_GCLK_ID_CORE) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);// write to CLKCTRL}Pin SettingsCode:struct PIN gpio_create_pin( IOMUX m, MUX_EN mEn,IOPORT p, unsigned int pn , PINDIR pd, PULL pl, PULL_EN pEn,INPUT inp){if(pn > 31){pn = pn%32;}struct PIN pin = {.port = p, .mux = m, .muxEn = mEn,.pinNum = pn, .dir = pd, .pull = pl, .pullEn = pEn,.inEn = inp};gpio_init_pin(pin);return pin;}void gpio_init_pin(struct PIN p){//Set as outputPORT->Group[p.port].DIRSET.reg = (p.dir<<p.pinNum);//Set PA10 as inputif(p.dir == IN)PORT->Group[p.port].DIRCLR.reg = (!p.dir<<p.pinNum);//Enable input buffer for PA10PORT->Group[p.port].PINCFG[p.pinNum].reg = (p.inEn<<PORT_PINCFG_INEN_Pos);//Enable pullif(p.pullEn){PORT->Group[p.port].PINCFG[p.pinNum].reg = (p.pullEn<<PORT_PINCFG_PULLEN_Pos);//Set pullup/downPORT->Group[p.port].OUTCLR.reg = (!p.pull<<p.pinNum);PORT->Group[p.port].OUTSET.reg = (p.pull<<p.pinNum);}//Enable sampling on PA10 and the 8 bit subgroupif(!p.dir)PORT->Group[p.port].CTRL.reg = paddr[p.pinNum];if(p.muxEn == MUX_ENABLE){PORT->Group[p.port].PINCFG[p.pinNum].reg = PORT_PINCFG_PMUXEN;// pinmuxing is done based on whether the pin of interest is odd or evenif(p.pinNum%2){PORT->Group[p.port].PMUX[(p.pinNum/2)].reg = PORT_PMUX_PMUXO(p.mux);}else{PORT->Group[p.port].PMUX[(p.pinNum/2)].reg = PORT_PMUX_PMUXE(p.mux);}}}Enabling the USARTCode:void enable_NVIC(){__enable_irq();}void init_USART(){enable_NVIC();NVIC_EnableIRQ( DMAC_IRQn );//enable EVSYS interrupt followed by evsys gen clockNVIC_EnableIRQ( EVSYS_IRQn );enable_SERCOM0();SERCOM0->USART.BAUD.reg = SERCOM_USART_BAUD_BAUD(65536*(1-(8*(9600/8000000))));SERCOM0->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0) | SERCOM_USART_CTRLB_SBMODE; //SBMODE sets two stop bits, otherwise there is oneSERCOM0->USART.CTRLA.reg = SERCOM_USART_CTRLA_ENABLE | SERCOM_USART_CTRLA_MODE_USART_INT_CLK | SERCOM_USART_CTRLA_MODE(0x1) |SERCOM_USART_CTRLA_SAMPR(0x2u) | SERCOM_USART_CTRLA_TXPO(0x1u) | SERCOM_USART_CTRLA_RXPO(0x0) | SERCOM_USART_CTRLA_FORM(0x1u);/*SAMPR[2:0]Description0x0 16x over-sampling using arithmetic baud rate generation.0x1 16x over-sampling using fractional baud rate generation.0x2 8x over-sampling using arithmetic baud rate generation.0x3 8x over-sampling using fractional baud rate generation.0x4 3x over-sampling using arithmetic baud rate generation.TXPO XCK Pin Location (currently using 0x1)TxD Pin RTS CTS0x0 SERCOM PAD SERCOM PAD N/A N/A0x1 SERCOM PAD SERCOM PAD N/A N/A0x2 SERCOM PAD N/A SERCOM PAD SERCOM PADRXPO[1:0] (currently using 0x0)Name Description0x0 PAD SERCOM PAD is used for data reception0x1 PAD SERCOM PAD is used for data reception0x2 PAD SERCOM PAD is used for data reception0x3 PAD SERCOM PAD is used for data receptionFORM[3:0]Description0x0 USART frame0x1 USART frame with parity0x2-0x3 Reserved0x4 Auto-baud -- break detection and auto-baud.0x5 Auto-baud -- break detection and auto-baud with parityCPOLTxD Change RxD Sample0x0 Rising XCK edge Falling XCK edge0x1 Falling XCK edge Rising XCK edge*/}picture 1:picture 2:

author: ataradov
author_rank: Super Contributor
timestamp: November 27, 2017, 05:50:32 am
content: This is really messy code, so it is hard to say what's wrong exactly, but I'll point out a few strange things that are probably not related to the problem:1. "PM->APBCMASK.reg = PM_APBCMASK_SERCOM0;" should be "PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0;", otherwise you disable all other peripherals on that bridge.2. SERCOM_USART_CTRLA_MODE_USART_INT_CLK and SERCOM_USART_CTRLA_MODE(0x1) are redundant.3. Your code for setting PMUX ("PORT->Group[p.port].PMUX[(p.pinNum/2)].reg = PORT_PMUX_PMUXO(p.mux);" and the other part) has to preserve already existing setting, otherwise calls for sequential pins will undo the settings for the previous one. Instead of ".reg" use ".bit.PMUXO" and ".bit.PMUXE" and let the compiler figure it out.Also - good compact code for reference:https://github.com/ataradov/mcu-starter-projects/tree/master/samd10