void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { int i; for (i = 0; i < SPI_COUNT; ++i) { spi_info_t *p_spi_info = &m_spi_info[i]; if (!p_spi_info->initialized) { NVIC_SetVector(spi_hanlder_desc[i].IRQn, spi_hanlder_desc[i].vector); p_spi_info->sck_pin = (uint8_t)sclk; p_spi_info->mosi_pin = (mosi != NC) ? (uint8_t)mosi : NRF_DRV_SPI_PIN_NOT_USED; p_spi_info->miso_pin = (miso != NC) ? (uint8_t)miso : NRF_DRV_SPI_PIN_NOT_USED; p_spi_info->ss_pin = (ssel != NC) ? (uint8_t)ssel : NRF_DRV_SPI_PIN_NOT_USED; p_spi_info->spi_mode = (uint8_t)NRF_DRV_SPI_MODE_0; p_spi_info->frequency = NRF_DRV_SPI_FREQ_1M; // By default each SPI instance is initialized to work as a master. // Should the slave mode be used, the instance will be reconfigured // appropriately in 'spi_format'. nrf_drv_spi_config_t config; prepare_master_config(&config, p_spi_info); nrf_drv_spi_t const *p_spi = &m_instances[i].master; ret_code_t ret_code = nrf_drv_spi_init(p_spi, &config, m_master_event_handlers[i]); if (ret_code == NRF_SUCCESS) { p_spi_info->initialized = true; p_spi_info->master = true; p_spi_info->flag.busy = false; #if DEVICE_SPI_ASYNCH p_spi_info->handler = 0; #endif SPI_IDX(obj) = i; return; } } } // No available peripheral error("No available SPI peripheral\r\n"); }
void spi_frequency(spi_t *obj, int hz) { spi_info_t *p_spi_info = SPI_INFO(obj); nrf_drv_spi_frequency_t new_frequency = freq_translate(hz); if (p_spi_info->master) { if (p_spi_info->frequency != new_frequency) { p_spi_info->frequency = new_frequency; nrf_drv_spi_config_t config; prepare_master_config(&config, p_spi_info); nrf_drv_spi_t const *p_spi = MASTER_INST(obj); nrf_drv_spi_uninit(p_spi); (void)nrf_drv_spi_init(p_spi, &config, m_master_event_handlers[SPI_IDX(obj)]); } } // There is no need to set anything in slaves when it comes to frequency, // since slaves just synchronize with the clock provided by a master. }
void spi_format(spi_t *obj, int bits, int mode, int slave) { if (bits != 8) { error("Only 8-bits SPI is supported\r\n"); } if (mode > 3) { error("SPI format error\r\n"); } spi_info_t *p_spi_info = SPI_INFO(obj); if (slave) { nrf_drv_spis_mode_t spi_modes[4] = { NRF_DRV_SPIS_MODE_0, NRF_DRV_SPIS_MODE_1, NRF_DRV_SPIS_MODE_2, NRF_DRV_SPIS_MODE_3, }; nrf_drv_spis_mode_t new_mode = spi_modes[mode]; // If the peripheral is currently working as a master, the SDK driver // it uses needs to be switched from SPI to SPIS. if (p_spi_info->master) { nrf_drv_spi_uninit(MASTER_INST(obj)); } // I the SPI mode has to be changed, the SDK's SPIS driver needs to be // re-initialized (there is no other way to change its configuration). else if (p_spi_info->spi_mode != (uint8_t)new_mode) { nrf_drv_spis_uninit(SLAVE_INST(obj)); } else { return; } p_spi_info->spi_mode = (uint8_t)new_mode; p_spi_info->master = false; p_spi_info->flag.readable = false; // Initialize SDK's SPIS driver with the new configuration. nrf_drv_spis_config_t config; prepare_slave_config(&config, p_spi_info); (void)nrf_drv_spis_init(SLAVE_INST(obj), &config, m_slave_event_handlers[SPI_IDX(obj)]); // Prepare the slave for transfer. p_spi_info->tx_buf = NRF_DRV_SPIS_DEFAULT_ORC; nrf_drv_spis_buffers_set(SLAVE_INST(obj), (uint8_t const *)&p_spi_info->tx_buf, 1, (uint8_t *)&p_spi_info->rx_buf, 1); } else // master { nrf_drv_spi_mode_t spi_modes[4] = { NRF_DRV_SPI_MODE_0, NRF_DRV_SPI_MODE_1, NRF_DRV_SPI_MODE_2, NRF_DRV_SPI_MODE_3, }; nrf_drv_spi_mode_t new_mode = spi_modes[mode]; // If the peripheral is currently working as a slave, the SDK driver // it uses needs to be switched from SPIS to SPI. if (!p_spi_info->master) { nrf_drv_spis_uninit(SLAVE_INST(obj)); } // I the SPI mode has to be changed, the SDK's SPI driver needs to be // re-initialized (there is no other way to change its configuration). else if (p_spi_info->spi_mode != (uint8_t)new_mode) { nrf_drv_spi_uninit(MASTER_INST(obj)); } else { return; } p_spi_info->spi_mode = (uint8_t)new_mode; p_spi_info->master = true; p_spi_info->flag.busy = false; // Initialize SDK's SPI driver with the new configuration. nrf_drv_spi_config_t config; prepare_master_config(&config, p_spi_info); (void)nrf_drv_spi_init(MASTER_INST(obj), &config, m_master_event_handlers[SPI_IDX(obj)]); } }
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { int i; // This block is only a workaround that allows to create SPI object several // times, what would be otherwise impossible in the current implementation // of mbed driver that does not call spi_free() from SPI destructor. // Once this mbed's imperfection is corrected, this block should be removed. for (i = 0; i < SPI_COUNT; ++i) { spi_info_t *p_spi_info = &m_spi_info[i]; if (p_spi_info->initialized && p_spi_info->mosi_pin == (uint8_t)mosi && p_spi_info->miso_pin == (uint8_t)miso && p_spi_info->sck_pin == (uint8_t)sclk && p_spi_info->ss_pin == (uint8_t)ssel) { // Reuse the already allocated SPI instance (instead of allocating // a new one), if it appears to be initialized with exactly the same // pin assignments. SPI_IDX(obj) = i; return; } } for (i = 0; i < SPI_COUNT; ++i) { spi_info_t *p_spi_info = &m_spi_info[i]; if (!p_spi_info->initialized) { p_spi_info->sck_pin = (uint8_t)sclk; p_spi_info->mosi_pin = (mosi != NC) ? (uint8_t)mosi : NRF_DRV_SPI_PIN_NOT_USED; p_spi_info->miso_pin = (miso != NC) ? (uint8_t)miso : NRF_DRV_SPI_PIN_NOT_USED; p_spi_info->ss_pin = (ssel != NC) ? (uint8_t)ssel : NRF_DRV_SPI_PIN_NOT_USED; p_spi_info->spi_mode = (uint8_t)NRF_DRV_SPI_MODE_0; p_spi_info->frequency = NRF_DRV_SPI_FREQ_1M; NVIC_SetVector(spi_handler_desc[i].IRQn, spi_handler_desc[i].vector); // By default each SPI instance is initialized to work as a master. // Should the slave mode be used, the instance will be reconfigured // appropriately in 'spi_format'. nrf_drv_spi_config_t config; prepare_master_config(&config, p_spi_info); nrf_drv_spi_t const *p_spi = &m_instances[i].master; ret_code_t ret_code = nrf_drv_spi_init(p_spi, &config, m_master_event_handlers[i]); if (ret_code == NRF_SUCCESS) { p_spi_info->initialized = true; p_spi_info->master = true; p_spi_info->flag.busy = false; #if DEVICE_SPI_ASYNCH p_spi_info->handler = 0; #endif SPI_IDX(obj) = i; return; } } } // No available peripheral error("No available SPI peripheral\r\n"); }