Example #1
0
File: spi.c Project: deepfryed/RIOT
int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
{
    /* get exclusive access to the device */
    mutex_lock(&locks[bus]);
    /* power on the device */
    poweron(bus);

    /* configure bus clock, in synchronous mode its calculated from
     * BAUD.reg = (f_ref / (2 * f_bus) - 1)
     * with f_ref := CLOCK_CORECLOCK as defined by the board */
    dev(bus)->BAUD.reg = (uint8_t)(((uint32_t)CLOCK_CORECLOCK) / (2 * clk) - 1);

    /* configure device to be master and set mode and pads,
     *
     * NOTE: we could configure the pads already during spi_init, but for
     * efficiency reason we do that here, so we can do all in one single write
     * to the CTRLA register */
    dev(bus)->CTRLA.reg = (SERCOM_SPI_CTRLA_MODE(0x3) |     /* 0x3 -> master */
                           SERCOM_SPI_CTRLA_DOPO(spi_config[bus].mosi_pad) |
                           SERCOM_SPI_CTRLA_DIPO(spi_config[bus].miso_pad) |
                           (mode <<  SERCOM_SPI_CTRLA_CPOL_Pos));
    /* also no synchronization needed here, as CTRLA is write-synchronized */

    /* finally enable the device */
    dev(bus)->CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
    while (dev(bus)->SYNCBUSY.reg & SERCOM_SPI_SYNCBUSY_ENABLE) {}

    return SPI_OK;
}
Example #2
0
/*	=========================
 *	===== Sercom SPI
 *	=========================
*/
void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder)
{
    resetSPI();
    initClockNVIC();

    //Setting the CTRLA register
    sercom->SPI.CTRLA.reg =	SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
                            SERCOM_SPI_CTRLA_DOPO(mosi) |
                            SERCOM_SPI_CTRLA_DIPO(miso) |
                            dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;

    //Setting the CTRLB register
    sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(charSize) |
                            SERCOM_SPI_CTRLB_RXEN;	//Active the SPI receiver.


}
Example #3
0
/*************************************************************************//**
*****************************************************************************/
void halPhyInit(void)
{
  // Configure IO pins
  HAL_GPIO_PHY_SLP_TR_out();
  HAL_GPIO_PHY_SLP_TR_clr();
  HAL_GPIO_PHY_RST_out();
  HAL_GPIO_PHY_IRQ_in();
  HAL_GPIO_PHY_IRQ_pmuxen();
  HAL_GPIO_PHY_CS_out();
  HAL_GPIO_PHY_MISO_in();
  HAL_GPIO_PHY_MISO_pmuxen();
  HAL_GPIO_PHY_MOSI_out();
  HAL_GPIO_PHY_MOSI_pmuxen();
  HAL_GPIO_PHY_SCK_out();
  HAL_GPIO_PHY_SCK_pmuxen();

  // Configure SPI
  PORT->Group[HAL_GPIO_PORTA].PMUX[9].bit.PMUXE = 2/*C*/; // MOSI
  PORT->Group[HAL_GPIO_PORTA].PMUX[9].bit.PMUXO = 2/*C*/; // SCK
  PORT->Group[HAL_GPIO_PORTA].PMUX[8].bit.PMUXE = 2/*C*/; // MISO

  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM1;

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM1_GCLK_ID_CORE) |
      GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);

  SERCOM1->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_RXEN;
  halPhySpiSync();

#if F_CPU <= 16000000
  SERCOM1->SPI.BAUD.reg = 0;
#elif F_CPU <= 32000000
  SERCOM1->SPI.BAUD.reg = 1;
#elif F_CPU <= 48000000
  SERCOM1->SPI.BAUD.reg = 2;
#else
  #error Unsupported frequency
#endif

  SERCOM1->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
      SERCOM_SPI_CTRLA_DIPO(0) | SERCOM_SPI_CTRLA_DOPO;
  halPhySpiSync();
}
Example #4
0
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
{
    SercomSpi* spi_dev = spi[dev].dev;

    uint8_t   dopo = 0;
    uint8_t   dipo = 0;
    uint8_t   cpha = 0;
    uint8_t   cpol = 0;
    uint32_t  f_baud = 0;

    switch(speed)
    {
        case SPI_SPEED_100KHZ:
            f_baud = 100000;
            break;
        case SPI_SPEED_400KHZ:
            f_baud = 400000;
            break;
        case SPI_SPEED_1MHZ:
            f_baud = 1000000;
            break;
        case SPI_SPEED_5MHZ:
            return -1;
        case SPI_SPEED_10MHZ:
            return -1;
    }

    switch(conf)
    {
        case SPI_CONF_FIRST_RISING: /**< first data bit is transacted on the first rising SCK edge */
            cpha = 0;
            cpol = 0;
            break;
        case SPI_CONF_SECOND_RISING:/**< first data bit is transacted on the second rising SCK edge */
            cpha = 1;
            cpol = 0;
            break;
        case SPI_CONF_FIRST_FALLING:/**< first data bit is transacted on the first falling SCK edge */
            cpha = 0;
            cpol = 1;
            break;
        case SPI_CONF_SECOND_FALLING:/**< first data bit is transacted on the second falling SCK edge */
            cpha = 1;
            cpol = 1;
            break;
    }

    /* Enable sercom4 in power manager */
    MCLK->APBCMASK.reg |= spi[dev].mclk;

    /* Setup clock */
    GCLK->PCHCTRL[ spi[dev].gclk_id ].reg =
        GCLK_PCHCTRL_CHEN |
        GCLK_PCHCTRL_GEN_GCLK0;

    while (!(GCLK->PCHCTRL[spi[dev].gclk_id].reg & GCLK_PCHCTRL_CHEN));

    /* SCLK+MOSI = output */
    gpio_init(spi[dev].sclk.pin, GPIO_DIR_OUT, GPIO_NOPULL);
    gpio_init(spi[dev].mosi.pin, GPIO_DIR_OUT, GPIO_NOPULL);
    /* MISO = input */
    gpio_init(spi[dev].miso.pin, GPIO_DIR_IN, GPIO_PULLUP);

    /*
     * Set alternate funcion (PMUX) for our ports.
     */
    gpio_init_mux(spi[dev].sclk.pin, spi[dev].sclk.pmux);
    gpio_init_mux(spi[dev].miso.pin, spi[dev].miso.pmux);
    gpio_init_mux(spi[dev].mosi.pin, spi[dev].mosi.pmux);

    /* pin pad mapping */
    dipo = spi[dev].dipo;
    dopo = spi[dev].dopo;

    /* Disable spi to write config */
    spi_dev->CTRLA.bit.ENABLE = 0;
    while (spi_dev->SYNCBUSY.reg);

    /* setup baud */
    spi_dev->BAUD.bit.BAUD = (uint8_t) (((uint32_t) GCLK_REF) / (2 * f_baud) - 1); /* Syncronous mode*/

    spi_dev->CTRLA.reg |= SERCOM_SPI_CTRLA_MODE(0x3) /* 0x2 = slave 0x3 = master */
                          |  (SERCOM_SPI_CTRLA_DOPO(dopo))
                          |  (SERCOM_SPI_CTRLA_DIPO(dipo))
                          |  (cpha << SERCOM_SPI_CTRLA_CPHA_Pos)
                          |  (cpol << SERCOM_SPI_CTRLA_CPOL_Pos);

    while (spi_dev->SYNCBUSY.reg);
    spi_dev->CTRLB.reg = (SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN);
    while(spi_dev->SYNCBUSY.reg);
    spi_poweron(dev);
    return 0;
}
Example #5
0
File: spi.c Project: Cr0s/RIOT
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
{
    SercomSpi* spi_dev = 0;
    uint8_t   dopo = 0;
    uint8_t   dipo = 0;
    uint8_t   cpha = 0;
    uint8_t   cpol = 0;
    uint32_t   f_baud = 0;
    switch(speed)
    {
    case SPI_SPEED_100KHZ:
        f_baud = 100000;
        break;
    case SPI_SPEED_400KHZ:
        f_baud = 400000;
        break;
    case SPI_SPEED_1MHZ:
        f_baud = 1000000;
        break;
    case SPI_SPEED_5MHZ:
#if CLOCK_CORECLOCK >= 5000000
        f_baud = 5000000;
        break;
#else
        return -1;
#endif
    case SPI_SPEED_10MHZ:
#if CLOCK_CORECLOCK >= 10000000
        f_baud = 10000000;
        break;
#else
        return -1;
#endif
    }
    switch(conf)
    {
    case SPI_CONF_FIRST_RISING: /**< first data bit is transacted on the first rising SCK edge */
        cpha = 0;
        cpol = 0;
        break;
    case SPI_CONF_SECOND_RISING:/**< first data bit is transacted on the second rising SCK edge */
        cpha = 1;
        cpol = 0;
        break;
    case SPI_CONF_FIRST_FALLING:/**< first data bit is transacted on the first falling SCK edge */
        cpha = 0;
        cpol = 1;
        break;
    case SPI_CONF_SECOND_FALLING:/**< first data bit is transacted on the second falling SCK edge */
        cpha = 1;
        cpol = 1;
        break;
    }
    switch(dev)
    {
#ifdef SPI_0_EN
    case SPI_0:
        spi_dev = &SPI_0_DEV;

        /* Enable sercom4 in power manager */
        PM->APBCMASK.reg |= PM_APBCMASK_SERCOM4;
        GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN
                                        | GCLK_CLKCTRL_GEN_GCLK0
                                        | (SERCOM4_GCLK_ID_CORE << GCLK_CLKCTRL_ID_Pos)));

        /* Setup clock */
        while (GCLK->STATUS.bit.SYNCBUSY) {}
        /* Mux enable*/
        SPI_0_SCLK_DEV.PINCFG[ SPI_0_SCLK_PIN ].bit.PMUXEN = 1;
        SPI_0_MISO_DEV.PINCFG[ SPI_0_MISO_PIN ].bit.PMUXEN = 1;
        SPI_0_MOSI_DEV.PINCFG[ SPI_0_MOSI_PIN ].bit.PMUXEN = 1;

        /*Set mux function to spi. seperate registers, for even or odd pins */
        SPI_0_SCLK_DEV.PMUX[ SPI_0_SCLK_PIN / 2].bit.PMUXE = 5;
        SPI_0_MISO_DEV.PMUX[ SPI_0_MISO_PIN / 2].bit.PMUXO = 5;
        SPI_0_MOSI_DEV.PMUX[ SPI_0_MOSI_PIN / 2].bit.PMUXE = 5;

        /* SCLK+MOSI */
        SPI_0_SCLK_DEV.DIRSET.reg = 1 << SPI_0_SCLK_PIN;
        SPI_0_MOSI_DEV.DIRSET.reg = 1 << SPI_0_MOSI_PIN;

        /* MISO = input */
        /* configure as input */
        SPI_0_MISO_DEV.DIRCLR.reg = 1 << SPI_0_MISO_PIN;
        SPI_0_MISO_DEV.PINCFG[ SPI_0_MISO_PIN ].bit.INEN = true;

        SPI_0_MISO_DEV.OUTCLR.reg = 1 << SPI_0_MISO_PIN;
        SPI_0_MISO_DEV.PINCFG[ SPI_0_MISO_PIN ].bit.PULLEN = true;

        dopo = SPI_0_DOPO;
        dipo  = SPI_0_DIPO;
        break;
#endif
#ifdef SPI_1_EN
    case SPI_1:
        spi_dev = &SPI_1_DEV;

        /* Enable sercom5 in power manager */
        PM->APBCMASK.reg |= PM_APBCMASK_SERCOM5;
        /* Setup clock */            /* configure GCLK0 to feed sercom5 */;
        GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN
                                        | GCLK_CLKCTRL_GEN_GCLK0
                                        | (SERCOM5_GCLK_ID_CORE << GCLK_CLKCTRL_ID_Pos)));

        /* Mux enable*/
        SPI_1_SCLK_DEV.PINCFG[ SPI_1_SCLK_PIN ].bit.PMUXEN = 1;
        SPI_1_MISO_DEV.PINCFG[ SPI_1_MISO_PIN ].bit.PMUXEN = 1;
        SPI_1_MOSI_DEV.PINCFG[ SPI_1_MOSI_PIN ].bit.PMUXEN = 1;
        /*Set mux function to spi. seperate registers, for even or odd pins */
        SPI_1_SCLK_DEV.PMUX[ SPI_1_SCLK_PIN / 2].bit.PMUXO = 3;
        SPI_1_MISO_DEV.PMUX[ SPI_1_MISO_PIN / 2].bit.PMUXE = 3;
        SPI_1_MOSI_DEV.PMUX[ SPI_1_MOSI_PIN / 2].bit.PMUXE = 3;
        /* SCLK+MOSI */
        SPI_1_SCLK_DEV.DIRSET.reg = 1 << SPI_1_SCLK_PIN;
        SPI_1_MOSI_DEV.DIRSET.reg = 1 << SPI_1_MOSI_PIN;

        /* MISO = input */
        /* configure as input */
        SPI_1_MISO_DEV.DIRCLR.reg = 1 << SPI_1_MISO_PIN;
        SPI_1_MISO_DEV.PINCFG[ SPI_1_MISO_PIN ].bit.INEN = true;

        SPI_1_MISO_DEV.OUTCLR.reg = 1 << SPI_1_MISO_PIN;
        SPI_1_MISO_DEV.PINCFG[SPI_1_MISO_PIN].bit.PULLEN = true;

        dopo = SPI_1_DOPO;
        dipo  = SPI_1_DIPO;
        break;
#endif
    default:
        return -1;
    }
    spi_dev->CTRLA.bit.ENABLE = 0;  /* Disable spi to write confs */
    while (spi_dev->SYNCBUSY.reg) {}
    spi_dev->CTRLA.reg |= SERCOM_SPI_CTRLA_MODE_SPI_MASTER;
    while (spi_dev->SYNCBUSY.reg) {}

    spi_dev->BAUD.bit.BAUD = (uint8_t) (((uint32_t)CLOCK_CORECLOCK) / (2 * f_baud) - 1); /* Syncronous mode*/


    spi_dev->CTRLA.reg |= (SERCOM_SPI_CTRLA_DOPO(dopo))
                          |  (SERCOM_SPI_CTRLA_DIPO(dipo))
                          |  (cpha << SERCOM_SPI_CTRLA_CPHA_Pos)
                          |  (cpol << SERCOM_SPI_CTRLA_CPOL_Pos);

    while (spi_dev->SYNCBUSY.reg) {}
    spi_dev->CTRLB.reg = (SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN);
    while(spi_dev->SYNCBUSY.reg) {}
    spi_poweron(dev);
    return 0;
}
Example #6
0
File: spi.c Project: Troels51/RIOT
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
{
    SercomSpi* spi_dev = 0;
    uint8_t   dopo = 0;
    uint8_t   dipo = 0;
    uint8_t   cpha = 0;
    uint8_t   cpol = 0;
    uint32_t   f_baud = 0;
    /* Speed < ½ f_ref, current f_ref = 8`000`000 
    *  baud = f_ref/(2 f_baud) - 1 
    */
    switch(speed)
    {
        case SPI_SPEED_100KHZ:       /**< drive the SPI bus with 100KHz */
            f_baud = 100000;
            break;
        case SPI_SPEED_400KHZ:           /**< drive the SPI bus with 400KHz */
            f_baud = 400000;
            break;
        case SPI_SPEED_1MHZ:             /**< drive the SPI bus with 1MHz */
            f_baud = 1000000;
            break;
        case SPI_SPEED_5MHZ:             /**< drive the SPI bus with 5MHz */
            return -1;
        case SPI_SPEED_10MHZ:             /**< drive the SPI bus with 10MHz */
            return -1;
    }
    switch(conf)
    {
        case SPI_CONF_FIRST_RISING: /**< first data bit is transacted on the first rising SCK edge */
            cpha = 0;
            cpol = 0;
            break;
        case SPI_CONF_SECOND_RISING:/**< first data bit is transacted on the second rising SCK edge */
            cpha = 1;
            cpol = 0;
            break;
        case SPI_CONF_FIRST_FALLING:/**< first data bit is transacted on the first falling SCK edge */
            cpha = 0;
            cpol = 1;
            break;
        case SPI_CONF_SECOND_FALLING:/**< first data bit is transacted on the second falling SCK edge */
            cpha = 1;
            cpol = 1;
            break;
    }
    switch(dev)
    {
#ifdef SPI_0_EN
        case SPI_0:
            spi_dev = &SPI_0_DEV;  
            
            /* Enable sercom4 in power manager */
            PM->APBCMASK.reg |= PM_APBCMASK_SERCOM4;
            GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | (SERCOM4_GCLK_ID_CORE << GCLK_CLKCTRL_ID_Pos)));

            /* Setup clock */            
            while (GCLK->STATUS.bit.SYNCBUSY);
            pmux_set(SPI_0_SCLK_PIN, F);
            pmux_set(SPI_0_MISO_PIN, F);
            pmux_set(SPI_0_MOSI_PIN, F);

            // uint32_t pinmask = (((1UL << (SPI_0_SCLK_PIN % 32)) | (1UL << (SPI_0_MISO_PIN % 32)))  >> 16);
            // /* PMUX */
            // SPI_0_PORT0.WRCONFIG.reg |= 
            //                  PORT_WRCONFIG_HWSEL
            //                 | PORT_WRCONFIG_WRPMUX
            //                 | (0x5 << PORT_WRCONFIG_PMUX_Pos)
            //                 | PORT_WRCONFIG_PMUXEN
            //                 | (pinmask << PORT_WRCONFIG_PINMASK_Pos);

            // pinmask = (1UL << (SPI_0_MOSI_PIN % 32)) >> 16;
            // SPI_0_PORT1.WRCONFIG.reg |= 
            //                  PORT_WRCONFIG_HWSEL
            //                 | PORT_WRCONFIG_WRPMUX
            //                 | (0x5 << PORT_WRCONFIG_PMUX_Pos)
            //                 | PORT_WRCONFIG_PMUXEN
            //                 | (pinmask << PORT_WRCONFIG_PINMASK_Pos);
            //SCLK+MOSI
            SPI_0_SCLK_DEV.DIRSET.reg = (1 << (SPI_0_SCLK_PIN % 32));
            SPI_0_MOSI_DEV.DIRSET.reg = (1 << (SPI_0_MOSI_PIN % 32));

            //MISO = input
            /* configure as input */
            SPI_0_MISO_DEV.DIRCLR.reg = (1<<(SPI_0_MISO_PIN % 32));
            SPI_0_MISO_DEV.PINCFG[SPI_0_MISO_PIN % 32].bit.INEN = true;

            SPI_0_MISO_DEV.OUTCLR.reg = (1 << (SPI_0_MISO_PIN % 32));
            SPI_0_MISO_DEV.PINCFG[SPI_0_MISO_PIN % 32].bit.PULLEN = true;

            dopo = SPI_0_DOPO;
            dipo  = SPI_0_DIPO;
            break;
#endif
#ifdef SPI_1_EN
        case SPI_1:
            spi_dev = &SPI_1_DEV;

            /* Enable sercom5 in power manager */
            PM->APBCMASK.reg |= PM_APBCMASK_SERCOM5;
            /* Setup clock */            /* configure GCLK0 to feed sercom5 */;
            GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | (SERCOM5_GCLK_ID_CORE << GCLK_CLKCTRL_ID_Pos)));
            while (GCLK->STATUS.reg);

            pmux_set(SPI_1_SCLK_PIN, D);
            pmux_set(SPI_1_MISO_PIN, D);
            pmux_set(SPI_1_MOSI_PIN, D);
            //SCLK+MOSI
            SPI_1_SCLK_DEV.DIRSET.reg = (1 << (SPI_1_SCLK_PIN % 32));
            SPI_1_MOSI_DEV.DIRSET.reg = (1 << (SPI_1_MOSI_PIN % 32));

            //MISO = input
            /* configure as input */
            SPI_1_MISO_DEV.DIRCLR.reg = (1<<(SPI_1_MISO_PIN % 32));
            SPI_1_MISO_DEV.PINCFG[SPI_1_MISO_PIN % 32].bit.INEN = true;

            SPI_1_MISO_DEV.OUTCLR.reg = (1 << (SPI_1_MISO_PIN % 32));
            SPI_1_MISO_DEV.PINCFG[SPI_1_MISO_PIN % 32].bit.PULLEN = true;

            dopo = SPI_1_DOPO;
            dipo  = SPI_1_DIPO;
            break;
#endif
    }
    spi_dev->CTRLA.bit.ENABLE = 0;  // Disable spi to write confs
    while (spi_dev->SYNCBUSY.reg);
    spi_dev->CTRLA.reg |= SERCOM_SPI_CTRLA_MODE_SPI_MASTER;
    while (spi_dev->SYNCBUSY.reg);
    
    spi_dev->BAUD.bit.BAUD = (uint8_t) (((uint32_t) SPI_0_F_REF) / (2 * f_baud) - 1); // Synchronous mode
    spi_dev->CTRLA.reg |= (SERCOM_SPI_CTRLA_DOPO(dopo))
                       |  (SERCOM_SPI_CTRLA_DIPO(dipo))
                       |  (cpha << SERCOM_SPI_CTRLA_CPHA_Pos)
                       |  (cpol << SERCOM_SPI_CTRLA_CPOL_Pos);

    while (spi_dev->SYNCBUSY.reg);
    spi_dev->CTRLB.reg = (SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN);
    while(spi_dev->SYNCBUSY.reg);
    spi_poweron(dev);
    return 0;
}