/**@brief Function for initializing SPI slave. * * Function configures a SPI slave and sets buffers. * * @retval NRF_SUCCESS Initialization successful. */ uint32_t spi_slave_example_init(void) { uint32_t err_code; spi_slave_config_t spi_slave_config; err_code = spi_slave_evt_handler_register(spi_slave_event_handle); APP_ERROR_CHECK(err_code); spi_slave_config.pin_miso = SPIS_MISO_PIN; spi_slave_config.pin_mosi = SPIS_MOSI_PIN; spi_slave_config.pin_sck = SPIS_SCK_PIN; spi_slave_config.pin_csn = SPIS_CSN_PIN; spi_slave_config.mode = SPI_MODE_0; spi_slave_config.bit_order = SPIM_LSB_FIRST; spi_slave_config.def_tx_character = DEF_CHARACTER; spi_slave_config.orc_tx_character = ORC_CHARACTER; err_code = spi_slave_init(&spi_slave_config); APP_ERROR_CHECK(err_code); //Initialize buffers. spi_slave_buffers_init(m_tx_buf, m_rx_buf, (uint16_t)TX_BUF_SIZE); //Set buffers. err_code = spi_slave_buffers_set(m_tx_buf, m_rx_buf, sizeof(m_tx_buf), sizeof(m_rx_buf)); APP_ERROR_CHECK(err_code); return NRF_SUCCESS; }
// This function is called to put data in the SPI buffer when data is added // to the queue. void spi_slave_notify() { uint32_t err_code; if (!buffer_full) { // Check if we need to repopulate the SPI buffer with the next // thing from the queue uint8_t data_len; uint8_t len; uint8_t response_type; data_len = interrupt_event_queue_get(&response_type, spi_tx_buf+2); if (data_len > 0) { buffer_full = true; len = data_len + 1; // for the response type byte // Create the response SPI buffer. spi_tx_buf[0] = len; spi_tx_buf[1] = response_type; // Send the TX buffer to the SPI module err_code = spi_slave_buffers_set(spi_tx_buf, spi_rx_buf, SPI_BUF_LEN, SPI_BUF_LEN); APP_ERROR_CHECK(err_code); // The interrupt will be send to the CC2538 when the data is loaded } } }
uint32_t spi_slave_example_init(void) { uint32_t err_code; spi_slave_config_t spi_slave_config; // This callback fires after the master has de-asserted chip select err_code = spi_slave_evt_handler_register(spi_slave_event_handle); APP_ERROR_CHECK(err_code); // Setup the pins from the board's .h file spi_slave_config.pin_miso = SPIS_MISO_PIN; spi_slave_config.pin_mosi = SPIS_MOSI_PIN; spi_slave_config.pin_sck = SPIS_SCK_PIN; spi_slave_config.pin_csn = SPIS_CSN_PIN; spi_slave_config.mode = SPI_MODE_0; spi_slave_config.bit_order = SPIM_MSB_FIRST; spi_slave_config.def_tx_character = 0x00; spi_slave_config.orc_tx_character = 0x55; err_code = spi_slave_init(&spi_slave_config); APP_ERROR_CHECK(err_code); // Set buffers so we can receive err_code = spi_slave_buffers_set(spi_tx_buf, spi_rx_buf, SPI_BUF_LEN, SPI_BUF_LEN); APP_ERROR_CHECK(err_code); return NRF_SUCCESS; }
static uint32_t header_get() { uint32_t err_code; err_code = spi_slave_buffers_set((uint8_t *) m_zero_buff, m_header_rx_buffer, SER_PHY_HEADER_SIZE, SER_PHY_HEADER_SIZE); return err_code; }
static void prepare_rx(void) { uint32_t error_code; error_code = spi_slave_buffers_set(&dummy_data, rx_buffer.buffer, 1, SERIAL_DATA_MAX_LEN - 2); APP_ERROR_CHECK(error_code); has_pending_tx = false; }
static uint32_t header_send(uint16_t len) { uint32_t err_code; m_header_tx_buffer[0] = (uint8_t) 0; //this is guard byte (void)uint16_encode(len, &(m_header_tx_buffer[1])); err_code = spi_slave_buffers_set(m_header_tx_buffer, m_header_rx_buffer, SER_PHY_HEADER_SIZE + 1, SER_PHY_HEADER_SIZE + 1); return err_code; }
/* * Do one bulk read/write SPI operations */ uint32_t intermcu_spi_transaction(uint8_t *tx_buffer, uint16_t tx_len) { uint16_t idx; if (tx_len > MAX_BUF_SIZE) { return NRF_ERROR_INVALID_PARAM; } for (idx = 0; idx < tx_len; idx++) { m_tx_buf[idx] = tx_buffer[idx]; } //Set buffers. return spi_slave_buffers_set(m_tx_buf, m_rx_buf, tx_len, tx_len); }
static uint32_t frame_get() { uint32_t err_code; m_current_rx_frame_length = compute_current_frame_length(m_rx_packet_length, m_accumulated_rx_packet_length); if (!m_trash_payload_flag) { err_code = spi_slave_buffers_set((uint8_t *) m_zero_buff, &(m_p_rx_buffer[m_accumulated_rx_packet_length]), m_current_rx_frame_length, m_current_rx_frame_length); } else { err_code = spi_slave_buffers_set((uint8_t *) m_zero_buff, m_rx_frame_buffer, m_current_rx_frame_length, m_current_rx_frame_length); } return err_code; }
/**@brief Function for SPI slave event callback. * * Upon receiving an SPI transaction complete event, LED1 will blink and the buffers will be set. * * @param[in] event SPI slave driver event. */ static void spi_slave_event_handle(spi_slave_evt_t event) { uint32_t err_code; if (event.evt_type == SPI_SLAVE_XFER_DONE) { led_toggle(); //Check if buffer size is the same as amount of received data. APP_ERROR_CHECK_BOOL(event.rx_amount == RX_BUF_SIZE); //Check if received data is valid. bool success = spi_slave_buffer_check(m_rx_buf, event.rx_amount); APP_ERROR_CHECK_BOOL(success); //Set buffers. err_code = spi_slave_buffers_set(m_tx_buf, m_rx_buf, sizeof(m_tx_buf), sizeof(m_rx_buf)); APP_ERROR_CHECK(err_code); } }
/** * @brief Called when master requests send, or we want to notify master */ static void do_transmit(void) { uint8_t* tx_ptr = &dummy_data; uint8_t tx_len = 0; uint32_t error_code; serial_state = SERIAL_STATE_TRANSMIT; /* don't want GPIOTE to interrupt again before after packet is successfully transmitted. */ enable_pin_listener(false); bool ordered_buffer = false; if (!fifo_is_empty(&tx_fifo)) { if (fifo_pop(&tx_fifo, &tx_buffer) == NRF_SUCCESS) { tx_len = tx_buffer.buffer[0] + 2; tx_ptr = (uint8_t*) &tx_buffer; memset(rx_buffer.buffer, 0, SERIAL_DATA_MAX_LEN); error_code = spi_slave_buffers_set(tx_ptr, rx_buffer.buffer, tx_len, sizeof(rx_buffer)); APP_ERROR_CHECK(error_code); ordered_buffer = true; has_pending_tx = true; } } if (!ordered_buffer) { /* don't need to wait for SPIS mutex */ NRF_GPIO->OUTCLR = (1 << PIN_RDYN); } nrf_gpio_pin_set(0); nrf_gpio_pin_clear(0); /* wait for SPI driver to finish buffer set operation */ }
static uint32_t frame_send() { uint32_t err_code; m_current_tx_frame_length = compute_current_frame_length(m_tx_packet_length, m_accumulated_tx_packet_length); if (m_current_tx_frame_length == SER_PHY_SPI_5W_MTU_SIZE) { m_current_tx_frame_length -= 1; //extra space for guard byte must be taken into account for MTU } m_tx_frame_buffer[0] = 0; //guard byte copy_buff(&(m_tx_frame_buffer[1]), &(m_p_tx_buffer[m_accumulated_tx_packet_length]), m_current_tx_frame_length); err_code = spi_slave_buffers_set(m_tx_frame_buffer, m_rx_frame_buffer, m_current_tx_frame_length + 1, m_current_tx_frame_length + 1); return err_code; }
// Callback after a SPI transaction completes (CS goes back high). static void spi_slave_event_handle(spi_slave_evt_t event) { uint32_t err_code; // Check the event type. There are only two events, and only one is useful. if (event.evt_type == SPI_SLAVE_XFER_DONE) { // The first byte is the command byte switch (spi_rx_buf[0]) { case BCP_CMD_READ_IRQ: // This message was only to read data. Success. break; case BCP_CMD_SNIFF_ADVERTISEMENTS: // Instructs us to send all advertisements to the host // bcp_sniff_advertisements(); break; case BCP_CMD_UPDATE_LED_STATE: // The LEDs on the CC2538 changed, update the characteristic main_set_led_state(spi_rx_buf[1]); break; default: break; } { // Check if we need to repopulate the SPI buffer with the next // thing from the queue uint8_t data_len; uint8_t len; uint8_t response_type; data_len = interrupt_event_queue_get(&response_type, spi_tx_buf+2); if (data_len > 0) { len = data_len + 1; // for the response type byte // Create the response SPI buffer. spi_tx_buf[0] = len; spi_tx_buf[1] = response_type; // Send the TX buffer to the SPI module buffer_full = true; err_code = spi_slave_buffers_set(spi_tx_buf, spi_rx_buf, SPI_BUF_LEN, SPI_BUF_LEN); APP_ERROR_CHECK(err_code); } else { // Still need to set the RX buffer as the reception // destination buffer_full = false; memset(spi_tx_buf, 0x0, SPI_BUF_LEN); memset(spi_rx_buf, 0x0, SPI_BUF_LEN); err_code = spi_slave_buffers_set(spi_tx_buf, spi_rx_buf, SPI_BUF_LEN, SPI_BUF_LEN); APP_ERROR_CHECK(err_code); bcp_interupt_host_clear(); } } } else if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE) { nrf_gpio_pin_toggle(24); // If we set the buffers, we must have data we want to send // to the host if (buffer_full) { // Set the interrupt line high bcp_interrupt_host(); } } }