void at86rf231_gpio_spi_interrupts_init(void) { /* set up GPIO pins */ /* SCLK and MOSI*/ GPIOA->CRL &= ~(0xf << (5 * 4)); GPIOA->CRL |= (0xb << (5 * 4)); GPIOA->CRL &= ~(0xf << (7 * 4)); GPIOA->CRL |= (0xb << (7 * 4)); /* MISO */ gpio_init_in(SPI_0_MISO_GPIO, GPIO_NOPULL); /* SPI init */ spi_init_master(SPI_0, SPI_CONF_FIRST_RISING, SPI_SPEED_5MHZ); spi_poweron(SPI_0); /* IRQ0 */ gpio_init_in(SPI_0_IRQ0_GPIO, GPIO_NOPULL); gpio_init_int(SPI_0_IRQ0_GPIO, GPIO_NOPULL, GPIO_RISING, (gpio_cb_t)at86rf231_rx_irq, NULL); /* Connect EXTI4 Line to PC4 pin */ at86rf231_enable_interrupts(); /* CS */ gpio_init_out(SPI_0_CS_GPIO, GPIO_NOPULL); /* SLEEP */ gpio_init_out(SPI_0_SLEEP_GPIO, GPIO_NOPULL); /* RESET */ gpio_init_out(SPI_0_RESET_GPIO, GPIO_NOPULL); }
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) { LPC_SSPx_Type *spi; /* power on the SPI device */ spi_poweron(dev); /* configure SCK, MISO and MOSI pin */ spi_conf_pins(dev); switch(dev) { #if SPI_0_EN case SPI_0: spi = LPC_SSP0; break; #endif #if SPI_1_EN case SPI_1: spi = LPC_SSP1; break; #endif default: return -1; } /* Master mode, SPI disabled */ spi->CR1 = 0; /* Base clock frequency : 12MHz */ spi->CPSR = 4; /* configure bus clock speed */ switch (speed) { case SPI_SPEED_100KHZ: spi->CR0 |= (119 << 8); break; case SPI_SPEED_400KHZ: spi->CR0 |= (29 << 8); break; case SPI_SPEED_1MHZ: spi->CR0 |= (11 << 8); break; case SPI_SPEED_5MHZ: spi->CR0 |= (2 << 8); /* Actual : 4MHz */ break; case SPI_SPEED_10MHZ: spi->CR0 |= (0 << 8); /* Actual : 12MHz */ break; } /* Set mode and 8-bit transfer */ spi->CR0 |= 0x07 | (conf << 6); /* Enable SPI */ spi->CR1 |= (1 << 1); /* Wait while the BUSY flag is set */ while(spi->SR & (1 << 4)) {} /* Clear the RX FIFO */ while(spi->SR & (1 << 2)) { spi->DR; } return 0; }
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) { SPI_TypeDef *spi; /* power on the SPI device */ spi_poweron(dev); switch (dev) { #if SPI_0_EN case SPI_0: spi = SPI_0_DEV; SPI_0_PORT_CLKEN(); break; #endif #if SPI_1_EN case SPI_1: spi = SPI_1_DEV; SPI_1_PORT_CLKEN(); break; #endif default: return -1; } /* configure SCK, MISO and MOSI pin */ spi_conf_pins(dev); /* reset SPI configuration registers */ spi->CR1 = 0; spi->CR2 = 0; spi->I2SCFGR = 0; /* this makes sure SPI mode is selected */ /* configure bus clock speed */ switch (speed) { case SPI_SPEED_100KHZ: spi->CR1 |= (7 << 3); /* actual clock: 125KHz (lowest possible) */ break; case SPI_SPEED_400KHZ: spi->CR1 |= (5 << 3); /* actual clock: 500KHz */ break; case SPI_SPEED_1MHZ: spi->CR1 |= (4 << 3); /* actual clock: 1MHz */ break; case SPI_SPEED_5MHZ: spi->CR1 |= (2 << 3); /* actual clock: 4MHz */ break; case SPI_SPEED_10MHZ: spi->CR1 |= (1 << 3); /* actual clock 8MHz */ } /* select clock polarity and clock phase */ spi->CR1 |= conf; /* select master mode */ spi->CR1 |= SPI_CR1_MSTR; /* the NSS (chip select) is managed purely by software */ spi->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI; /* enable the SPI device */ spi->CR1 |= SPI_CR1_SPE; return 0; }
int ws2812_init(ws2812_t *dev, spi_t spi){ dev->spi = spi; log; /* Init SPI */ spi_poweron(dev->spi); log; spi_acquire(dev->spi); log; int status = spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, SPI_SPEED_4MHZ); log; spi_release(dev->spi); log; return status; }
SOL_API struct sol_spi * sol_spi_open(unsigned int bus, const struct sol_spi_config *config) { struct sol_spi *spi; SOL_LOG_INTERNAL_INIT_ONCE; if (unlikely(config->api_version != SOL_SPI_CONFIG_API_VERSION)) { SOL_WRN("Couldn't open SPI that has unsupported version '%u', " "expected version is '%u'", config->api_version, SOL_SPI_CONFIG_API_VERSION); return NULL; } SOL_EXP_CHECK(config->bits_per_word != 8, NULL); spi = malloc(sizeof(struct sol_spi)); SOL_NULL_CHECK(spi, NULL); spi_poweron(bus); spi_acquire(bus); spi_conf_pins(bus); if (spi_init_master(bus, config->mode, uint32_to_spi_speed_enum(config->frequency)) != 0) { SOL_WRN("%u,%u: Unable to setup SPI", bus, config->chip_select); spi_release(bus); free(spi); return NULL; } spi_release(spi->bus); spi->bus = bus; spi->cs_pin = config->chip_select; spi->transfer.timeout = NULL; gpio_init(spi->cs_pin, GPIO_DIR_OUT, GPIO_NOPULL); gpio_set(spi->cs_pin); return spi; }
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; }
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; }
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; }
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) { uint8_t speed_divider; Spi *spi_port; spi_poweron(dev); switch (speed) { case SPI_SPEED_400KHZ: speed_divider = 210; break; case SPI_SPEED_1MHZ: speed_divider = 84; break; case SPI_SPEED_5MHZ: speed_divider = 17; break; case SPI_SPEED_10MHZ: /* this might be too fast */ speed_divider = 8; break; default: return -1; } switch (dev) { #if SPI_0_EN case SPI_0: spi_port = SPI_0_DEV; break; #endif /* SPI_0_EN */ default: return -2; } /* Configure SCK, MISO and MOSI pin */ spi_conf_pins(dev); /***************** SPI-Init *****************/ /* Chip Select Register */ spi_port->SPI_CSR[0] = 0; /* This is index 0 since we don't use internal CS-Signals */ switch (conf) { case SPI_CONF_FIRST_RISING: spi_port->SPI_CSR[0] &= ~SPI_CSR_CPOL; spi_port->SPI_CSR[0] |= SPI_CSR_NCPHA; break; case SPI_CONF_SECOND_RISING: spi_port->SPI_CSR[0] &= ~SPI_CSR_CPOL; spi_port->SPI_CSR[0] &= ~SPI_CSR_NCPHA; break; case SPI_CONF_FIRST_FALLING: spi_port->SPI_CSR[0] |= SPI_CSR_CPOL; spi_port->SPI_CSR[0] |= SPI_CSR_NCPHA; break; case SPI_CONF_SECOND_FALLING: spi_port->SPI_CSR[0] |= SPI_CSR_CPOL; spi_port->SPI_CSR[0] &= ~ SPI_CSR_NCPHA; break; default: return -2; } spi_port->SPI_CSR[0] |= SPI_CSR_SCBR(speed_divider); spi_port->SPI_CSR[0] |= SPI_CSR_BITS_8_BIT; /* Control Register */ spi_port->SPI_CR |= SPI_CR_SPIEN; /* Mode Register */ spi_port->SPI_MR = 0; spi_port->SPI_MR |= SPI_MR_MSTR; spi_port->SPI_MR |= SPI_MR_MODFDIS; spi_port->SPI_MR &= ~SPI_MR_PS; spi_port->SPI_MR &= ~SPI_MR_PCS(0); return 0; }
int spi_init_slave(spi_t dev, spi_conf_t conf, char(*cb)(char data)) { Spi *spi_port; spi_poweron(dev); switch (dev) { #if SPI_0_EN case SPI_0: spi_port = SPI_0_DEV; NVIC_SetPriority(SPI_0_IRQ, SPI_0_IRQ_PRIO); NVIC_EnableIRQ(SPI_0_IRQ); /* Initialize predefined NSS pin as output so it is "disabled" */ PIOA->PIO_PER |= PIO_PA28A_SPI0_NPCS0; PIOA->PIO_OER |= PIO_PA28A_SPI0_NPCS0; break; #endif /* SPI_0_EN */ default: return -1; } /* Configure SCK, MISO and MOSI pin */ spi_conf_pins(dev); /***************** SPI-Init *****************/ /* Chip Select Register */ spi_port->SPI_CSR[0] = 0; switch (conf) { case SPI_CONF_FIRST_RISING: spi_port->SPI_CSR[0] &= ~SPI_CSR_CPOL; spi_port->SPI_CSR[0] |= SPI_CSR_NCPHA; break; case SPI_CONF_SECOND_RISING: spi_port->SPI_CSR[0] &= ~SPI_CSR_CPOL; spi_port->SPI_CSR[0] &= ~SPI_CSR_NCPHA; break; case SPI_CONF_FIRST_FALLING: spi_port->SPI_CSR[0] |= SPI_CSR_CPOL; spi_port->SPI_CSR[0] |= SPI_CSR_NCPHA; break; case SPI_CONF_SECOND_FALLING: spi_port->SPI_CSR[0] |= SPI_CSR_CPOL; spi_port->SPI_CSR[0] &= ~ SPI_CSR_NCPHA; break; default: return -1; } /* Control Register */ spi_port->SPI_CR |= SPI_CR_SPIEN; /* Mode Register */ spi_port->SPI_MR = 0; spi_port->SPI_MR |= SPI_MR_MODFDIS; /* Enable SPI interrupts */ spi_port->SPI_IER = 0; spi_port->SPI_IDR = ~(0); spi_port->SPI_IER |= 1; spi_port->SPI_IDR &= ~SPI_IDR_RDRF; /* Set callback */ spi_config[dev].cb = cb; return 0; }
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) { if (dev >= SPI_NUMOF) { return -1; } spi_poweron(dev); /* disable the device -> nRF51822 reference 3.0 26.1.1 and 27.1*/ spi[dev]->ENABLE = 0; switch(dev) { #if SPI_0_EN case SPI_0: /* disable TWI Interface */ NRF_TWI0->ENABLE = 0; break; #endif #if SPI_1_EN case SPI_1: /* disable SPI Slave */ NRF_SPIS1->ENABLE = 0; /* disable TWI Interface */ NRF_TWI1->ENABLE = 0; break; #endif default: return -1; } /* configure direction of used pins */ spi_conf_pins(dev); /* configure SPI mode */ switch (conf) { case SPI_CONF_FIRST_RISING: spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveHigh << 2) | (SPI_CONFIG_CPHA_Leading << 1); break; case SPI_CONF_SECOND_RISING: spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveHigh << 2) | (SPI_CONFIG_CPHA_Trailing << 1); break; case SPI_CONF_FIRST_FALLING: spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveLow << 2) | (SPI_CONFIG_CPHA_Leading << 1); break; case SPI_CONF_SECOND_FALLING: spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveLow << 2) | (SPI_CONFIG_CPHA_Trailing << 1); break; } /* select bus speed */ switch (speed) { case SPI_SPEED_100KHZ: /* 125 KHz for this device */ spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_K125; break; case SPI_SPEED_400KHZ: /* 500 KHz for this device */ spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_K500; break; case SPI_SPEED_1MHZ: /* 1 MHz for this device */ spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M1; break; case SPI_SPEED_5MHZ: /* 4 MHz for this device */ spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M4; break; case SPI_SPEED_10MHZ: /* 8 MHz for this device */ spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M8; break; } /* finally enable the device */ spi[dev]->ENABLE = 1; return 0; }
int nrf24l01p_init(nrf24l01p_t *dev, spi_t spi, gpio_t ce, gpio_t cs, gpio_t irq) { int status; char INITIAL_TX_ADDRESS[] = {0xe7, 0xe7, 0xe7, 0xe7, 0xe7,}; char INITIAL_RX_ADDRESS[] = {0xe7, 0xe7, 0xe7, 0xe7, 0xe7,}; dev->spi = spi; dev->ce = ce; dev->cs = cs; dev->irq = irq; dev->listener = KERNEL_PID_UNDEF; /* Init CE pin */ gpio_init(dev->ce, GPIO_DIR_OUT, GPIO_NOPULL); /* Init CS pin */ gpio_init(dev->cs, GPIO_DIR_OUT, GPIO_NOPULL); gpio_set(dev->cs); /* Init IRQ pin */ gpio_init_int(dev->irq, GPIO_PULLUP, GPIO_FALLING, nrf24l01p_rx_cb, dev); /* Init SPI */ spi_poweron(dev->spi); spi_acquire(dev->spi); status = spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, SPI_SPEED_400KHZ); spi_release(dev->spi); if (status < 0) { return status; } xtimer_spin(DELAY_AFTER_FUNC_TICKS); /* Flush TX FIFIO */ status = nrf24l01p_flush_tx_fifo(dev); if (status < 0) { return status; } /* Flush RX FIFIO */ status = nrf24l01p_flush_rx_fifo(dev); if (status < 0) { return status; } /* Setup adress width */ status = nrf24l01p_set_address_width(dev, NRF24L01P_AW_5BYTE); if (status < 0) { return status; } /* Setup payload width */ status = nrf24l01p_set_payload_width(dev, NRF24L01P_PIPE0, NRF24L01P_MAX_DATA_LENGTH); if (status < 0) { return status; } /* Set RF channel */ status = nrf24l01p_set_channel(dev, INITIAL_RF_CHANNEL); if (status < 0) { return status; } /* Set RF power */ status = nrf24l01p_set_power(dev, INITIAL_RX_POWER_0dB); if (status < 0) { return status; } /* Set RF datarate */ status = nrf24l01p_set_datarate(dev, NRF24L01P_DR_250KBS); if (status < 0) { return status; } /* Set TX Address */ status = nrf24l01p_set_tx_address(dev, INITIAL_TX_ADDRESS, INITIAL_ADDRESS_WIDTH); if (status < 0) { return status; } /* Set RX Adress */ status = nrf24l01p_set_rx_address(dev, NRF24L01P_PIPE0, INITIAL_RX_ADDRESS, INITIAL_ADDRESS_WIDTH); if (status < 0) { return status; } /* Reset auto ack for all pipes */ status = nrf24l01p_disable_all_auto_ack(dev); if (status < 0) { return status; } /* Setup Auto ACK and retransmission */ status = nrf24l01p_setup_auto_ack(dev, NRF24L01P_PIPE0, NRF24L01P_RETR_750US, 15); if (status < 0) { return status; } /* Setup CRC */ status = nrf24l01p_enable_crc(dev, NRF24L01P_CRC_2BYTE); if (status < 0) { return status; } /* Reset all interrupt flags */ status = nrf24l01p_reset_all_interrupts(dev); if (status < 0) { return status; } return nrf24l01p_on(dev); }