int main(void) { //! [main_setup] //! [system_init] system_init(); //! [system_init] //! [run_config] configure_spi_master(); //! [run_config] //! [main_setup] //! [main_use_case] //! [inf_loop] while (true) { /* Infinite loop */ if(!port_pin_get_input_level(BUTTON_0_PIN)) { //! [select_slave] spi_select_slave(&spi_master_instance, &slave, true); //! [select_slave] //! [write] spi_write_buffer_wait(&spi_master_instance, buffer, BUF_LENGTH); //! [write] //! [deselect_slave] spi_select_slave(&spi_master_instance, &slave, false); //! [deselect_slave] //! [light_up] port_pin_set_output_level(LED_0_PIN, LED0_ACTIVE); //! [light_up] } } //! [inf_loop] //! [main_use_case] }
/** * \brief Write a register value. * * \param reg the register address to modify. * \param wrdata the new register value. */ void ksz8851_reg_write(uint16_t reg, uint16_t wrdata) { uint8_t inbuf[4]; uint8_t outbuf[4]; uint16_t cmd = 0; spi_select_slave(&ksz8851snl_master, &ksz8851snl_slave, true); /* Move register address to cmd bits 9-2, make 32-bit address. */ cmd = (reg << 2) & REG_ADDR_MASK; /* Last 2 bits still under "don't care bits" handled with byte enable. */ /* Select byte enable for command. */ if (reg & 2) { /* Odd word address writes bytes 2 and 3 */ cmd |= (0xc << 10); } else { /* Even word address write bytes 0 and 1 */ cmd |= (0x3 << 10); } /* Add command write code. */ cmd |= CMD_WRITE; outbuf[0] = cmd >> 8; outbuf[1] = cmd & 0xff; outbuf[2] = wrdata & 0xff; outbuf[3] = wrdata >> 8; /* Perform SPI transfer. */ spi_transceive_buffer_wait(&ksz8851snl_master, outbuf, inbuf, 4); spi_select_slave(&ksz8851snl_master, &ksz8851snl_slave, false); }
/*! * @brief Receives data from BMM050 on SPI * * @param[in] dev_addr Device I2C slave address (not used) * * @param[in] reg_addr Address of destination register * * @param[out] reg_data Pointer to data buffer to be received * * @param[in] length Length of the data to be received * * @retval 0 BMG160_SUCCESS * @retval -1 BMG160_ERROR * */ int8_t bmg_spi_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *rx_data, uint8_t length) { enum status_code bmg_read_stat = STATUS_NO_CHANGE; /* This variable is used to avoid infinite loops. */ uint16_t loop_count; uint16_t dummy = 0; reg_addr = reg_addr | 0x80; spi_select_slave(&spi_master_instance, &bmg160_spi_slave, true); loop_count = 0; do { bmg_read_stat = spi_write_buffer_wait(&spi_master_instance, ®_addr, 1); loop_count++; }while(bmg_read_stat != STATUS_OK && loop_count < 100); loop_count = 0; do { bmg_read_stat = spi_read_buffer_wait(&spi_master_instance, rx_data, length, dummy); loop_count++; }while(bmg_read_stat != STATUS_OK && loop_count < 100); spi_select_slave(&spi_master_instance, &bmg160_spi_slave, false); if (bmg_read_stat != STATUS_OK) { return -1; } return 0; }
/** * \internal * \brief Test sending and receiving 9-bit data by polling. * * This test sends (writes) one 9-bit data to the slave and * receives (reads) the data back and compares. * * Writing and reading are carried out by polling. * * \param test Current test case. */ static void run_transfer_9bit_test(const struct test_case *test) { uint16_t txd_data = 0x155; uint16_t rxd_data = 0; /* Skip test if initialization failed */ test_assert_true(test, spi_init_success, "Skipping test due to failed initialization"); /* Send data to slave */ spi_select_slave(&master, &slave_inst, true); while (!spi_is_ready_to_write(&master)) { } spi_write(&master, txd_data); while (!spi_is_write_complete(&master)) { } /* Dummy read SPI master data register */ while (!spi_is_ready_to_read(&master)) { } spi_read(&master, &rxd_data); /* Read SPI slave data register */ while (!spi_is_ready_to_read(&slave)) { } spi_read(&slave, &rxd_data); spi_select_slave(&master, &slave_inst, false); /* Output test result */ test_assert_true(test, rxd_data == txd_data, "Failed transmitting/receiving byte. TX='%d', RX='%d'", txd_data, rxd_data); }
/** * \brief Writes a command to the display controller * * This functions pull pin D/C# low before writing to the controller. Different * data write function is called based on the selected interface. * * \param command the command to write */ void ssd1306_write_command(uint8_t command) { spi_select_slave(&ssd1306_master, &ssd1306_slave, true); port_pin_set_output_level(SSD1306_DC_PIN, false); spi_write_buffer_wait(&ssd1306_master, &command, 1); spi_select_slave(&ssd1306_master, &ssd1306_slave, false); }
/** * \internal * \brief Test: Send & receive data using transceive functions. * * This test sends (writes) an array of data to the slave and * receives (reads) the buffer back using transceive functions * and compares. * * \param test Current test case. */ static void run_transceive_buffer_test(const struct test_case *test) { enum status_code status = STATUS_ERR_IO; /* Skip test if initialization failed */ test_assert_true(test, spi_init_success, "Skipping test due to failed initialization"); /* Start the test */ spi_transceive_buffer_job(&slave, slave_tx_buf, slave_rx_buf, BUFFER_LENGTH); spi_select_slave(&master, &slave_inst, true); status = spi_transceive_buffer_wait(&master, tx_buf, rx_buf, BUFFER_LENGTH); spi_select_slave(&master, &slave_inst, false); test_assert_true(test, status == STATUS_OK, "Transceive buffer failed"); /* Compare received data with transmitted data */ if (status == STATUS_OK) { for (uint16_t i = 0; i < BUFFER_LENGTH; i++) { test_assert_true(test, tx_buf[i] == slave_rx_buf[i], "During TX: Bytes differ at buffer index %d : %d != %d", i, tx_buf[i], slave_rx_buf[i]); test_assert_true(test, slave_tx_buf[i] == rx_buf[i], "During RX: Bytes differ at buffer index %d : %d != %d", i, slave_tx_buf[i], rx_buf[i]); } } }
int main(void) { //! [main_setup] //! [system_init] system_init(); //! [system_init] //! [run_config] configure_spi_master(); //! [run_config] //! [main_setup] //! [main_use_case] //! [select_slave] spi_select_slave(&spi_master_instance, &slave, true); //! [select_slave] //! [write] spi_write_buffer_wait(&spi_master_instance, buffer, BUF_LENGTH); //! [write] //! [deselect_slave] spi_select_slave(&spi_master_instance, &slave, false); //! [deselect_slave] //! [inf_loop] while (true) { /* Infinite loop */ } //! [inf_loop] //! [main_use_case] }
/** * \brief Write data to the display controller * * This functions sets the pin D/C# before writing to the controller. Different * data write function is called based on the selected interface. * * \param data the data to write */ void ssd1306_write_data(uint8_t data) { spi_select_slave(&ssd1306_master, &ssd1306_slave, true); port_pin_set_output_level(SSD1306_DC_PIN, true); spi_write_buffer_wait(&ssd1306_master, &data, 1); spi_select_slave(&ssd1306_master, &ssd1306_slave, false); }
void rom_erase() { rom_write_enable(); while(rom_status() & 0x1); spi_select_slave(SPI_SLAVE_ROM); spi_send_recv(ROM_COMMAND_ERASE_CHIP); spi_select_slave(SPI_SLAVE_NONE); }
void test_spi_select_slave(void) { delay_ms(1); spi_select_slave(SPI0, SPI_SELECTOR_0); TEST_ASSERT_TRUE((SPI0->SPI_MR & SPI_MR_PCS_MASK) >> 16 == 0b0000); spi_select_slave(SPI0, SPI_SELECTOR_1); TEST_ASSERT_TRUE((SPI0->SPI_MR & SPI_MR_PCS_MASK) >> 16 == 0b0001); spi_select_slave(SPI0, SPI_SELECTOR_2); TEST_ASSERT_TRUE((SPI0->SPI_MR & SPI_MR_PCS_MASK) >> 16 == 0b0011); }
int main (void) { system_init(); while ( !system_clock_source_is_ready(SYSTEM_CLOCK_SOURCE_DPLL) ) { } // Disable the pin select for the CAN Controller fnc_can_controller_disable(); // Perform the SERCOM configuration for this board bastian_complete_sercom_setup(); // TCC Configuration tcc_configure_function(); // Counter Configuration tcc_callback_configuration(); // Timer Callback Configuration // Select Slave spi_select_slave(&spi_master, &spi_shield, false); // Wait the necessary time for the chip to restart inProgress = true; intProgressTimer = 100; // wait for 11ms while ( inProgress ) { } // Read the status from the on-board CAN controller spi_select_slave(&spi_master, &spi_CAN_controller, true); spi_write_buffer_wait(&spi_master, wr_can_buffer_startup, SYSTEM_SLAVE_TX_SINGLE_BYTE); spi_select_slave(&spi_master, &spi_CAN_controller, false); // Wait the necessary time for the chip to restart inProgress = true; intProgressTimer = 50; // wait for 11ms while ( inProgress ) { } spi_select_slave(&spi_master, &spi_CAN_controller, true); spi_transceive_buffer_job(&spi_master, &wr_can_buffer_startup[1], rd_buffer, SYSTEM_SLAVE_STATUS_TRANSACTION_LENGTH); //spi_select_slave(&spi_master, &spi_CAN_controller, false); // inProgress = true; // intProgressTimer = 10; // wait for 2ms // while ( inProgress ) { } // // spi_select_slave(&spi_master, &spi_CAN_controller, true); // spi_transceive_buffer_job(&spi_master, wr_can_buffer, rd_buffer, SYSTEM_SLAVE_STATUS_TRANSACTION_LENGTH); // Main Loop while (1) { } }
uint8_t rom_status() { uint8_t status; spi_select_slave(SPI_SLAVE_ROM); spi_send_recv(ROM_COMMAND_READ_STATUS); status = spi_send_recv(0xFF); spi_select_slave(SPI_SLAVE_NONE); return status; }
void rom_read(uint32_t address, uint8_t *buffer, uint32_t size) { while(rom_status() & 0x1); spi_select_slave(SPI_SLAVE_ROM); spi_send_recv(ROM_COMMAND_READ_DATA); spi_send_recv((address >> 16) & 0xFF); spi_send_recv((address >> 8) & 0xFF); spi_send_recv(address & 0xFF); while(size--) *buffer++ = spi_send_recv(0xFF); spi_select_slave(SPI_SLAVE_NONE); }
enum ab1815_status ab1815_write(struct ab1815_t *clock, uint8_t offset, uint8_t *buf, uint8_t length) { uint8_t buffer[length + 1]; enum ab1815_status ret_code = ab1815_status_ERROR; buffer[0] = AB1815_SPI_WRITE(offset); memcpy(buffer + 1, buf, length); spi_select_slave(clock->spi_bus, clock->slave, true); if(spi_write_buffer_wait(clock->spi_bus, buffer, length + 1) == STATUS_OK) { ret_code = ab1815_status_OK; } spi_select_slave(clock->spi_bus, clock->slave, false); return ret_code; };
static sint8 spi_rw(uint8* pu8Mosi, uint8* pu8Miso, uint16 u16Sz) { uint8 u8Dummy = 0; uint8 u8SkipMosi = 0, u8SkipMiso = 0; uint16_t txd_data = 0; uint16_t rxd_data = 0; if (!pu8Mosi) { pu8Mosi = &u8Dummy; u8SkipMosi = 1; } else if(!pu8Miso) { pu8Miso = &u8Dummy; u8SkipMiso = 1; } else { return M2M_ERR_BUS_FAIL; } spi_select_slave(&master, &slave_inst, true); while (u16Sz) { txd_data = *pu8Mosi; while (!spi_is_ready_to_write(&master)) ; while(spi_write(&master, txd_data) != STATUS_OK) ; /* Read SPI master data register. */ while (!spi_is_ready_to_read(&master)) ; while (spi_read(&master, &rxd_data) != STATUS_OK) ; *pu8Miso = rxd_data; u16Sz--; if (!u8SkipMiso) pu8Miso++; if (!u8SkipMosi) pu8Mosi++; } while (!spi_is_write_complete(&master)) ; spi_select_slave(&master, &slave_inst, false); return M2M_SUCCESS; }
enum ab1815_status ab1815_read(struct ab1815_t *clock, uint8_t offset, uint8_t *buf, uint8_t length) { uint8_t address = AB1815_SPI_READ(offset); enum ab1815_status ret_code = ab1815_status_ERROR; spi_select_slave(clock->spi_bus, clock->slave, true); if(spi_write_buffer_wait(clock->spi_bus, &address, 1) == STATUS_OK) { if(spi_read_buffer_wait(clock->spi_bus, buf, length, SPI_DUMMY) == STATUS_OK) { ret_code = ab1815_status_OK; } } spi_select_slave(clock->spi_bus, clock->slave, false); return ret_code; };
/** * \internal * \brief Test: Sends data at different baud rates. * * This test sends (writes) a byte to the slave and receives the data * at different baudrate testing up to the maximum allowed level. * * Transmission and reception are carried out by polling. * * \param test Current test case. */ static void run_baud_test(const struct test_case *test) { uint32_t test_baud = 1000000; uint8_t txd_data = 0x55; uint8_t rxd_data = 0; bool max_baud = true; /* Skip test if initialization failed */ test_assert_true(test, spi_init_success, "Skipping test due to failed initialization"); /* Structure for SPI configuration */ struct spi_config config; /* Configure the SPI master */ spi_get_config_defaults(&config); config.mux_setting = CONF_SPI_MASTER_SPI_MUX; config.pinmux_pad0 = CONF_SPI_MASTER_DATA_IN_PIN_MUX; config.pinmux_pad1 = PINMUX_UNUSED; config.pinmux_pad2 = CONF_SPI_MASTER_DATA_OUT_PIN_MUX; config.pinmux_pad3 = CONF_SPI_MASTER_SCK_PIN_MUX; do { spi_disable(&master); config.mode_specific.master.baudrate = test_baud; spi_init(&master, CONF_SPI_MASTER_MODULE, &config); spi_enable(&master); /* Send data to slave */ spi_select_slave(&master, &slave_inst, true); spi_write_buffer_wait(&master, &txd_data, 1); spi_read_buffer_wait(&slave, &rxd_data, 1, 0); spi_select_slave(&master, &slave_inst, false); if (txd_data != rxd_data) { max_baud = false; break; } test_baud += 1000000; } while (test_baud <= 24000000); /* Output the result */ test_assert_true(test, max_baud, "Test failed at baudrate: %lu", test_baud); }
/*---------------------------------------------------------------------------*/ void st7565s_arch_spi_select(bool is_data) { spi_select_slave(&esd_spi_master_instance, &st7565s_spi_slave, true); configure_miso(true); port_pin_set_output_level(DISPLAY_CMD_DATA_PIN, is_data); }
/** * \brief Complete write operation. * * \param pad amount of dummy data (bytes) to write to keep 32 bits alignment * in the internal FIFO. */ void ksz8851_fifo_write_end(uint32_t pad) { uint8_t outbuf[5]; if (pad > 0) { spi_write_buffer_wait(&ksz8851snl_master, outbuf, 4 - pad); } spi_select_slave(&ksz8851snl_master, &ksz8851snl_slave, false); }
/*---------------------------------------------------------------------------*/ void st7565s_arch_spi_deselect(void) { port_pin_set_output_level(DISPLAY_CMD_DATA_PIN, false); configure_miso(false); spi_select_slave(&esd_spi_master_instance, &st7565s_spi_slave, false); }
void test_spi_write() { // Copy of test_spi_write_ready() spi_enable(SPI0); spi_select_slave(SPI0, SPI_SELECTOR_0); TEST_ASSERT_TRUE(spi_tx_ready(SPI0)); spi_write(SPI0, 0b01011010); TEST_ASSERT_FALSE(spi_tx_ready(SPI0)); delay_ms(1); TEST_ASSERT_TRUE(spi_tx_ready(SPI0)); }
void test_spi_read_ready() { delay_ms(1); spi_enable(SPI0); spi_select_slave(SPI0, SPI_SELECTOR_0); spi_read(SPI0); spi_write(SPI0, 0b00011100); TEST_ASSERT_FALSE(spi_rx_ready(SPI0)); delay_ms(1); TEST_ASSERT_TRUE(spi_rx_ready(SPI0)); }
//! [hal_spiSlaveSel] uint8_t hal_spiSlaveSel(void * p_spi, bool action) { if (p_spi == NULL) { // LOG_ERR("SPI was not initialized!"); return 0; } if (action) { //! [select_slave] hal_enterCritical(); spi_select_slave(&st_masterInst, (spiDesc_t *)p_spi, true); //! [select_slave] } else { //! [deselect_slave] spi_select_slave(&st_masterInst, (spiDesc_t *)p_spi, false); hal_exitCritical(); //! [deselect_slave] } return 1; } //! [hal_spiSlaveSel]
bool spi_setup_transfer(SpiTransfer* rq) { if (!rq->acknowledgement_try_count && rq->acknowledgement_mode != kSPINoAcknowledgement) { rq->acknowledgement_mode = kSPINoAcknowledgement; } if (!rq->buffer_size_bytes && rq->acknowledgement_mode == kSPINoAcknowledgement) { // No data to transfer; xfer complete. if (rq->deselect_slave_when_finished) spi_select_slave(rq->slave, false); if (rq->transfer_complete_callback) rq->transfer_complete_callback(rq); return false; } if (rq->receive_offset < rq->buffer_size_bytes && rq->receive_offset + rq->receive_bytes > rq->buffer_size_bytes) rq->receive_bytes = rq->buffer_size_bytes - rq->receive_offset; spi_select_slave(rq->slave, true); rq->slave->control->current_byte = 0; // Start the transfer by writing data. The interrupt will finish things off. if (rq->buffer_size_bytes) { if (rq->use_transmit_constant) { *chip_spi_transfer_register(rq->slave->control->port) = rq->transmit_constant; } else { *chip_spi_transfer_register(rq->slave->control->port) = ((uint8_t*) rq->transfer_buffer)[rq->slave->control->current_byte]; } } else { *chip_spi_transfer_register(rq->slave->control->port) = rq->acknowledgement_request_byte; } return true; }
void test_spi_transmission_complete() { delay_ms(1); spi_enable(SPI0); spi_select_slave(SPI0, SPI_SELECTOR_0); spi_write(SPI0, 0b01011010); spi_write(SPI0, 0b01011011); TEST_ASSERT_FALSE(SPI0->SPI_SR & (0x1u << 1)); TEST_ASSERT_FALSE(SPI0->SPI_SR & (0x1u << 9)); delay_ms(1); TEST_ASSERT_TRUE(SPI0->SPI_SR & (0x1u << 1)); TEST_ASSERT_TRUE(SPI0->SPI_SR & (0x1u << 9)); }
int main(void) { //! [main_start] /* Initialize system */ //! [system_init] system_init(); //! [system_init] //! [run_config] configure_spi_master(); //! [run_config] //! [run_callback_config] configure_spi_master_callbacks(); //! [run_callback_config] //! [main_start] //! [main_use_case] //! [inf_loop] while (true) { /* Infinite loop */ if (!port_pin_get_input_level(BUTTON_0_PIN)) { //! [select_slave] spi_select_slave(&spi_master_instance, &slave, true); //! [select_slave] //! [write and read] spi_transceive_buffer_job(&spi_master_instance, wr_buffer,rd_buffer,BUF_LENGTH); //! [write and read] //! [wait] while (!transrev_complete_spi_master) { /////* Wait for write and read complete */ } //! [wait] //! [deselect_slave] spi_select_slave(&spi_master_instance, &slave, false); //! [deselect_slave] } } //! [inf_loop] //! [main_use_case] }
/** * \internal * \brief Test: Send data by polling & receive with interrupt. * * This test sends (writes) an array of data to the slave by polling and * receives (reads) the buffer back with interrupt and compares. * * \param test Current test case. */ static void run_buffer_polled_write_interrupt_read_test (const struct test_case *test) { uint16_t i; uint16_t timeout_cycles; /* Skip test if initialization failed */ test_assert_true(test, spi_init_success, "Skipping test due to failed initialization"); /* Start the test */ transfer_complete = false; timeout_cycles = 1000; spi_select_slave(&master, &slave_inst, true); spi_read_buffer_job(&slave, rx_buf, BUFFER_LENGTH, 0); spi_write_buffer_wait(&master, tx_buf, BUFFER_LENGTH); /* Wait until reception completes */ do { timeout_cycles--; if (transfer_complete) { break; } } while (timeout_cycles != 0); spi_select_slave(&master, &slave_inst, false); test_assert_true(test, timeout_cycles > 0, "Timeout in reception"); /* Compare received data with transmitted data */ if (transfer_complete) { for (i = 0; i < BUFFER_LENGTH; i++) { test_assert_true(test, tx_buf[i] == rx_buf[i], "Bytes differ at buffer index %d : %d != %d", i, tx_buf[i], rx_buf[i]); } } }
void rom_write(uint32_t address, const uint8_t *buffer, uint32_t size) { int i; while(size >= 256) { rom_write_enable(); while(rom_status() & 0x1); spi_select_slave(SPI_SLAVE_ROM); spi_send_recv(ROM_COMMAND_PAGE_PROGRAM); spi_send_recv((address >> 16) & 0xFF); spi_send_recv((address >> 8) & 0xFF); spi_send_recv(address & 0xFF); for(i = 0; i < 256; i++) spi_send_recv(*buffer++); spi_select_slave(SPI_SLAVE_NONE); size -= 256; address += 256; } if(size) { rom_write_enable(); while(rom_status() & 0x1); spi_select_slave(SPI_SLAVE_ROM); spi_send_recv(ROM_COMMAND_PAGE_PROGRAM); spi_send_recv((address >> 16) & 0xFF); spi_send_recv((address >> 8) & 0xFF); spi_send_recv(address & 0xFF); for(i = 0; i < size; i++) spi_send_recv(*buffer++); spi_select_slave(SPI_SLAVE_NONE); } }
/** * \brief Read internal fifo buffer. * * \param buf the buffer to store the data from the fifo buffer. * \param len the amount of data to read. */ void ksz8851_fifo_read(uint8_t *buf, uint32_t len) { uint8_t tmpbuf[9]; spi_select_slave(&ksz8851snl_master, &ksz8851snl_slave, true); tmpbuf[0] = FIFO_READ; /* Perform SPI transfer. */ spi_transceive_buffer_wait(&ksz8851snl_master, tmpbuf, tmpbuf, 9); spi_read_buffer_wait(&ksz8851snl_master, buf, len, 0xff); /* Read CRC (don't care). */ spi_read_buffer_wait(&ksz8851snl_master, tmpbuf, 4, 0xff); len += 4; /* Keep internal memory alignment. */ len &= 3; if (len) { spi_read_buffer_wait(&ksz8851snl_master, tmpbuf, len, 0xff); } spi_select_slave(&ksz8851snl_master, &ksz8851snl_slave, false); }
/** * \brief Start to write internal fifo buffer. * * \param tot_len the total amount of data to write. */ void ksz8851_fifo_write_begin(uint32_t tot_len) { uint8_t outbuf[5]; static uint8_t frameID = 0; spi_select_slave(&ksz8851snl_master, &ksz8851snl_slave, true); /* Prepare control word and byte count. */ outbuf[0] = FIFO_WRITE; outbuf[1] = frameID++ & 0x3f; outbuf[2] = 0; outbuf[3] = tot_len & 0xff; outbuf[4] = tot_len >> 8; /* Perform SPI transfer. */ spi_write_buffer_wait(&ksz8851snl_master, outbuf, 5); }