-->
Page 1 of 1

SPI on ESP8266. I have been given code that fails to compile

PostPosted: Mon Jul 29, 2019 5:27 am
by Seamus Waldron
Hi there,

I have been given some code that I know has worked for the coder working on a test project for me (who I am not in a position to ask for additional help).

The project is to have an ESP8266 running as an SPI Slave. The test code doesn't do anything pre-se except prove that communication can happen between the Slave and the master.

I believe the coder must have used existing code that he found as I have found a single reference to it elsewhere, but not with the issue I am having.

The problem I have is that when I compile the code, I get the following error:

'SERCOM1' was not declared in this scope

I sure this is something *really obvious*, but I'm not a C coder and so I'm struggling.

The full sketch is:

Code: Select all
#include <SPI.h>

const int slaveAPin = 10; //SERCOM1 10; // SERCOM4 16;
static int sendCounter = 0;
static int cmd = 0;

void setup() {

  Serial.begin(9600);

  pinMode(slaveAPin, INPUT_PULLUP);

  attachInterrupt(10, SERCOM1_Handler, FALLING);
  spiSlave_init();
  SERCOM1->SPI.DATA.reg = 0x12;
}


void loop() {
  //waste some time in a loop
  int var = 0;
  while(var < 200){
  var++;
  }

}


void SERCOM1_Handler()
{
  Serial.println("In SPI Interrupt Handler");
  uint8_t data = 0;
  uint8_t junk = 0;
  data =(uint8_t)SERCOM1->SPI.DATA.reg;
  SERCOM1->SPI.DATA.reg = 0x12;
 
  uint8_t interrupts = SERCOM1->SPI.INTFLAG.reg; //Read SPI interrupt register
  Serial.print("Interrupts: "); Serial.println(interrupts);

  // If error interrupt then clear down and ignore
  if(interrupts & (1<<7))
  {
    Serial.println("Error Interrupt");
    SERCOM1->SPI.INTFLAG.bit.ERROR = 1;
    return;
  }
 
  if(interrupts & (1<<3))
  {
    Serial.println("SPI SSL Interupt");
    SERCOM1->SPI.INTFLAG.bit.SSL = 1; //clear slave select interrupt
  }
  if(interrupts & (1<<2))
  {
    Serial.println("SPI Data Receive Complete Interrupt");
    Serial.print("B4 RXC flag cleared:"); Serial.println(SERCOM1->SPI.INTFLAG.bit.RXC);
   
    // Reading the DATA should clear the flag
    while( SERCOM1->SPI.INTFLAG.bit.RXC != 0)
    {
        //data = SERCOM1->SPI.DATA.bit.DATA; //eat up
        junk = SERCOM1->SPI.DATA.reg; //Read data register
    }

    Serial.print("After RXC flag cleared:"); Serial.println(SERCOM1->SPI.INTFLAG.bit.RXC);
    // Below should have no affect according to docs
    //SERCOM1->SPI.INTFLAG.bit.RXC = 1; //clear receive complete interrupt
  }
 
  if(interrupts & (1<<1))
  {
    Serial.println("SPI Data Transmit Complete Interrupt. SSH");
    SERCOM1->SPI.INTFLAG.bit.TXC = 1; //clear receive complete interrupt
  }
 
  if(interrupts & (1<<0))
  {
    Serial.println("SPI Data Register Empty Interrupt. Ready for new data to transmit");
    SERCOM1->SPI.DATA.reg = 0x12;
  }
 
  Serial.print("DATA: "); Serial.println(data);
  //Serial.print("CTRLA: "); Serial.println(SERCOM1->SPI.CTRLA.reg); 
}

void spiSlave_init()
{
 
  //Configure SERCOM1 SPI PINS
  //PORTA.DIR.reg &= ~PORT_PA16; //Set PA16 as input (MOSI)
  //PORTA.DIR.reg &= ~PORT_PA17; //Set PA17 as input (SCK)
  //PORTA.DIR.reg &= ~PORT_PA18; //Set PA18 as input (SS)
  //PORTA.DIR.reg |= PORT_PA19; //Set PA19 as output (MISO)

  /*
  PORTA.PINCFG[16].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORTA.PMUX[8].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  PORTA.PINCFG[17].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORTA.PMUX[8].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  PORTA.PINCFG[18].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORTA.PMUX[9].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  PORTA.PINCFG[19].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORTA.PMUX[9].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  */
 
  PORT->Group[PORTA].PINCFG[16].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORT->Group[PORTA].PMUX[8].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  PORT->Group[PORTA].PINCFG[17].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORT->Group[PORTA].PMUX[8].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  PORT->Group[PORTA].PINCFG[18].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORT->Group[PORTA].PMUX[9].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  PORT->Group[PORTA].PINCFG[19].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORT->Group[PORTA].PMUX[9].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad
 
  //Disable SPI 1
  SERCOM1->SPI.CTRLA.bit.ENABLE =0;
  while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE);
 
  //Reset SPI 1
  SERCOM1->SPI.CTRLA.bit.SWRST = 1;
  while(SERCOM1->SPI.CTRLA.bit.SWRST || SERCOM1->SPI.SYNCBUSY.bit.SWRST);
 
  //Setting up NVIC
  NVIC_EnableIRQ(SERCOM1_IRQn);
  NVIC_SetPriority(SERCOM1_IRQn,2);
 
  //Setting Generic Clock Controller!!!!
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM1_CORE) | //Generic Clock 0
            GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is the source
            GCLK_CLKCTRL_CLKEN; // Enable Generic Clock Generator
 
  while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); //Wait for synchronisation
 
 
  //Set up SPI Control A Register
  SERCOM1->SPI.CTRLA.bit.DORD = 0; //MSB first
  SERCOM1->SPI.CTRLA.bit.CPOL = 0; //SCK is low when idle, leading edge is rising edge
  SERCOM1->SPI.CTRLA.bit.CPHA = 0; //data sampled on leading sck edge and changed on a trailing sck edge
  SERCOM1->SPI.CTRLA.bit.FORM = 0x0; //Frame format = SPI
  SERCOM1->SPI.CTRLA.bit.DIPO = 0x0; //DATA PAD0 MOSI is used as input (slave mode)
  SERCOM1->SPI.CTRLA.bit.DOPO = 0x2; //DATA PAD3 MISO is used as output
  SERCOM1->SPI.CTRLA.bit.MODE = 0x2; //SPI in Slave mode
  SERCOM1->SPI.CTRLA.bit.IBON = 0x1; //Buffer Overflow notification
  SERCOM1->SPI.CTRLA.bit.RUNSTDBY = 1; //wake on receiver complete
 
  //Set up SPI control B register
  //SERCOM1->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver
  SERCOM1->SPI.CTRLB.bit.SSDE = 0x1; //Slave Selecte Detection Enabled
  SERCOM1->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
  //SERCOM1->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
  //while (SERCOM1->SPI.SYNCBUSY.bit.CTRLB); 
 
  //Set up SPI interrupts
  SERCOM1->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt       
  SERCOM1->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
  SERCOM1->SPI.INTENSET.bit.TXC = 0x1; //Transmit complete interrupt
  SERCOM1->SPI.INTENSET.bit.ERROR = 0x1; //Error interrupt
  SERCOM1->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
  //init SPI CLK 
  //SERCOM1->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
  //Enable SPI
  SERCOM1->SPI.CTRLA.bit.ENABLE = 1;
  while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE);
  SERCOM1->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
  while(SERCOM1->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled

}

Re: SPI on ESP8266. I have been given code that fails to com

PostPosted: Tue Jul 30, 2019 6:48 am
by schufti
switch your esp8266 for an ATmega and the code might work ....

Re: SPI on ESP8266. I have been given code that fails to com

PostPosted: Tue Jul 30, 2019 3:56 pm
by Seamus Waldron
Thank you. You nudged me in the right direction. After further digger, I believe this was coded for the Adafruit Feather M0 basic.