Author Topic: SPI for SAMD10 not working  (Read 2151 times)

0 Members and 1 Guest are viewing this topic.

Offline n4alpacaTopic starter

  • Newbie
  • Posts: 9
  • Country: us
SPI for SAMD10 not working
« on: January 07, 2018, 01:19:50 am »
Hello, I've been playing around with a broken out micro controller (SAMD10) for some time and lately I've been struggling with SPI. Everything seems to be set alright, but I'm not getting any output (I check physical pins 9 and 10 of the SOIC package) on PA22 or PA23. I've included the code in question and pictures of the registers for each step. It seems as though SPI is functioning, but I'm not seeing any output.

Main
Code: [Select]
int main(void) {

  sys_init();

  struct PIN doSPI = gpio_create_pin(PMUXC,MUX_ENABLE,PORTA,22,OUT,PULLUP,PULL_DISABLE,IN_DISABLE);
  struct PIN sckSPI = gpio_create_pin(PMUXD,MUX_ENABLE,PORTA,23,OUT,PULLUP,PULL_DISABLE,IN_DISABLE);
  struct PIN diSPI = gpio_create_pin(PMUXC,MUX_ENABLE,PORTA,25,IN,PULLUP,PULL_DISABLE,IN_ENABLE);

  init_SPI(BAUD9600,0x0u,0x3u,LSB,0x0u,MASTER,FALSE,200,200);
  do {
    //uart_puts("C");
    spi_putc('C');

  } while (1);

  return 0;
}
SPI initialization
Code: [Select]
void init_SPI(BAUD baud,uint8_t dopo,uint8_t dipo,TX_ORDER ord, uint8_t format, MASTER_SEL masterSel, BOOLEAN addrMode, uint8_t addr, uint8_t addrMask){

  __enable_irq();

  NVIC_EnableIRQ(  DMAC_IRQn  );
  NVIC_EnableIRQ(  EVSYS_IRQn  );
 
  uint32_t br = (uint64_t)65536 * (F_CPU - 16 * baud) / F_CPU;

  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM1;  // enable power
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM1_GCLK_ID_CORE) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0x1ul);

 if(masterSel == 0){
  masterSel = 0x2u;
 }
 else{
  masterSel = 0x3; // default as master
 }
 if(format == 2){
  format = 0x2u; // SPI frame with address (first byte of message is checked)
 }
 else{
  0x0u; // default to SPI frame without address
 }
 if(dopo > 3 || dopo < 0){
  dopo = 0x0u;
  dipo = 0x3u;
 }
 if(dipo > 3 || dipo < 0){
  dopo = 0x0u;
  dipo = 0x3u;
 }
  if(addrMode > 2 || addrMode < 0){
  //0 is addr in addrmask, 1 is addr and addrmask, 2 is a range between addr and addrmask
  addrMode = 0x0u;
 }

  SERCOM1->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(masterSel) | SERCOM_SPI_CTRLA_CPOL | (SERCOM_SPI_CTRLA_DORD & ord) | SERCOM_SPI_CTRLA_DIPO(dopo) | SERCOM_SPI_CTRLA_DIPO(dipo) | SERCOM_SPI_CTRLA_FORM(format);
 

  SERCOM1->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_RXEN | SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_AMODE(addrMode);

  SERCOM1->SPI.ADDR.reg = 0x0u;

  SERCOM1->SPI.ADDR.reg |= SERCOM_SPI_ADDR_ADDR(addr);
  SERCOM1->SPI.ADDR.reg |= SERCOM_SPI_ADDR_ADDRMASK(addrMask);

  SERCOM1->SPI.BAUD.reg = (uint8_t)br+1;

  SERCOM1->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;

 /* SERCOM 1
  Pad[x] Pin   Mux
  Pad[0] PA_22 C
  Pad[0] PA_30 C
  Pad[1] PA_23 C
  Pad[1] PA_31 C
  Pad[2] PA_08 C
  Pad[2] PA_16 C
  Pad[2] PA_30 D
  Pad[2] PA_24 C
  Pad[3] PA_09 C
  Pad[3] PA_17 C
  Pad[3] PA_31 D
  Pad[3] PA_25 C
  */

  /*  Data In Pinout
  DIPO[x] Pad
  0x0     Pad[0]
  0x1     Pad[1]
  0x2     Pad[2]
  0x3     Pad[3]
  */

  /*  Data Out Pinout
  DOPO[x] Data Out SCK      slave_ss
  0x0     Pad[0]   Pad[1]   Pad[2]
  0x1     Pad[1]   Pad[3]   Pad[1]
  0x2     Pad[2]   Pad[1]   Pad[2]
  0x3     Pad[3]   Pad[3]   Pad[1]
  */

}

//-----------------------------------------------------------------------------
void spi_putc(char c)
{
while (!(SERCOM1->SPI.INTFLAG.reg & SERCOM_SPI_INTFLAG_DRE))
;
SERCOM1->SPI.DATA.reg = (uint16_t)c;
}

int spi_getc()
{
if (SERCOM1->SPI.INTFLAG.reg & SERCOM_SPI_INTFLAG_RXC) {
return SERCOM1->SPI.DATA.reg;
}
return -1;
}

//-----------------------------------------------------------------------------
void spi_puts(const char *s)
{
while (*s)
uart_putc(*s++);
}

Setting GCLK:

Initialize CTRLA:

Initialize CTRLB

CTRLA enabled:

Before Send Data:

After Send Data:



 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: SPI for SAMD10 not working
« Reply #1 on: January 07, 2018, 02:11:38 am »
Do you actually have Clock Generator 1 configured and enabled?
Alex
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: SPI for SAMD10 not working
« Reply #2 on: January 07, 2018, 02:22:31 am »
Do you need to enable SERCOM1?
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: SPI for SAMD10 not working
« Reply #3 on: January 07, 2018, 02:23:26 am »
Do you need to enable SERCOM1?
He does:
Quote
SERCOM1->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
Alex
 

Offline ajb

  • Super Contributor
  • ***
  • Posts: 2601
  • Country: us
Re: SPI for SAMD10 not working
« Reply #4 on: January 07, 2018, 05:08:37 am »
If the DRE flag is changing, that suggests that the SERCOM is getting a clock.  What does the gpio_create_pin function do?  Looks like it creates a struct representing the pin settings, but does it actually apply those settings?  Have you verified that the pin registers are being set correctly?

I don't think this is your main problem right now, but I think your baud rate calculation is wrong.  Datasheet says that SPI mode uses the synchronous baud generator mode.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: SPI for SAMD10 not working
« Reply #5 on: January 07, 2018, 05:11:34 am »
If the DRE flag is changing, that suggests that the SERCOM is getting a clock.
Not necessarily. Depends on what clock domain that bit is in.

Double check that this bit ever gets set back again and the loop is looping.
Alex
 

Offline n4alpacaTopic starter

  • Newbie
  • Posts: 9
  • Country: us
Re: SPI for SAMD10 not working
« Reply #6 on: January 08, 2018, 02:49:56 am »
Hello,
Alex: I used the uart_init method from your samd10 as a reference and I guess I forgot to link the genclk to a source with the GENCTRL register.
I added:
Code: [Select]
  GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_ID(SERCOM1_GCLK_ID_CORE) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(GCLK_CLKCTRL_GEN_GCLK1_Val);
And now I have output on the data out pin, but for some reason not the SCLK pin. I haven't had too much time this weekend to devote to debugging this, but I will be able to spend some time this week.

ajb: Yes, my baud calculation is wrong. The baud calculation is a point of confusion for me. The data sheet specifies that for synchronous mode the calculation should result in an 8-bit number, however my calculation results in a 9-bit number. The equation they give is BAUD = (fref / (2 * fbaud)) where fref is the frequency from the GCLK (8MHz in this case), fbaud is the baud rate as a frequency I think and BAUD is the value to be put into the register which would give the corresponding baud rate.

My fref is 8MHz if as I have disabled the prescaler. The baud I would like is 9600 which equates to 9600Hz. so plugging in the numbers gives 417(rounded). If I'm not mistaken, the solution is to to divide this gclk by 8.
I added:
Code: [Select]
uint32_t br = (uint16_t)((F_CPU/8)/(baud*2)) - 1;
GCLK->GENDIV.reg = GCLK_GENDIV_ID(GCLK_CLKCTRL_GEN_GCLK1_Val) | GCLK_GENDIV_DIV(8);
« Last Edit: January 08, 2018, 02:57:46 am by n4alpaca »
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: SPI for SAMD10 not working
« Reply #7 on: January 08, 2018, 02:54:57 am »
Alex: I used the uart_init method from your samd10 as a reference and I guess I forgot to link the genclk to a source with the GENCTRL register.
You can just specify 0 as the generator in the SERCOM code. EDIT: but not if you need a divider, of course.

And now I have output on the data out pin, but for some reason not the SCLK pin. I haven't had too much time this weekend to devote to debugging this, but I will be able to spend some time this week.
That looks more like PORT configuration problem, and with your port initialization functions, I have no idea what might be wrong.

The data sheet specifies that for synchronous mode the calculation should result in an 8-bit number
To get super low baudrates on SPI you have to divide peripheral clock, as you did.

But it is very strange to have such low frequencies on the synchronous interface. What's your application for this?
Alex
 

Offline n4alpacaTopic starter

  • Newbie
  • Posts: 9
  • Country: us
Re: SPI for SAMD10 not working
« Reply #8 on: January 08, 2018, 03:14:37 am »
I'll be going over the port configuration stuff hopefully on Tuesday. I have no specific application as of yet. I'm just trying to familiarize myself with programming micro-controllers. I'm looking to try to involve myself with some kind of process automation projects soon (I dabble in hydroponics, so that's likely where I'll start).

EDIT: accidentally wrote PMUXD instead of PMUXC, the clock outputs just fine
« Last Edit: January 08, 2018, 04:17:01 am by n4alpaca »
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11248
  • Country: us
    • Personal site
Re: SPI for SAMD10 not working
« Reply #9 on: January 08, 2018, 03:17:41 am »
I have no specific application as of yet. I'm just trying to familiarize myself with programming micro-controllers.
In that case for most real application your BR setting will be 0, 1, or 2. And that's for 48 MHz operation. If you are running at 8 MHz, just stick with BR=0. I doubt there are any SPI devices that can't handle 4 MHz.
Alex
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf