/*! * @brief Sends data to BMG160 via SPI * * @param[in] dev_addr Device I2C slave address (not used) * * @param[in] reg_addr Address of destination register * * @param[in] reg_data Pointer to data buffer to be sent * * @param[in] length Length of the data to be sent * * @retval 0 BMG160_SUCCESS * @retval -1 BMG160_ERROR * */ int8_t bmg_spi_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t length) { enum status_code bmg_write_stat = STATUS_NO_CHANGE; /* This variable is used to avoid infinite loops. */ uint16_t loop_count; spi_select_slave(&spi_master_instance, &bmg160_spi_slave, true); loop_count = 0; do { bmg_write_stat = spi_write_buffer_wait(&spi_master_instance, ®_addr, 1); loop_count++; }while(bmg_write_stat != STATUS_OK && loop_count < 100); loop_count = 0; do { bmg_write_stat = spi_write_buffer_wait(&spi_master_instance, reg_data, length); loop_count++; }while(bmg_write_stat != STATUS_OK && loop_count < 100); spi_select_slave(&spi_master_instance, &bmg160_spi_slave, false); if (bmg_write_stat != STATUS_OK) { return -1; } return 0; }
/** * \brief Executed the end of a multi blocks write transfer * * \return true if success, otherwise false * with a update of \ref sd_mmc_spi_err. */ static bool sd_mmc_spi_stop_multiwrite_block(void) { uint8_t value; if (1 == sd_mmc_spi_nb_block) { return true; // Single block write } if (sd_mmc_spi_nb_block > (sd_mmc_spi_transfert_pos / sd_mmc_spi_block_size)) { return true; // It is not the End of multi write } // Delay before start write block: // Nwr timing minimum = 8 cylces value = 0xFF; spi_write_buffer_wait(&sd_mmc_master, &value, 1); // Send stop token value = SPI_TOKEN_STOP_TRAN; spi_write_buffer_wait(&sd_mmc_master, &value, 1); // Wait busy if (!sd_mmc_spi_wait_busy()) { sd_mmc_spi_err = SD_MMC_SPI_ERR_WRITE_TIMEOUT; sd_mmc_spi_debug("%s: Stop write blocks timeout\n\r", __func__); return false; } return true; }
bool sd_mmc_spi_start_write_blocks(const void *src, uint16_t nb_block) { uint32_t pos; sd_mmc_spi_err = SD_MMC_SPI_NO_ERR; pos = 0; while (nb_block--) { Assert(sd_mmc_spi_nb_block > (sd_mmc_spi_transfert_pos / sd_mmc_spi_block_size)); sd_mmc_spi_start_write_block(); // Write block spi_write_buffer_wait(&sd_mmc_master, &((uint8_t*)src)[pos], sd_mmc_spi_block_size); pos += sd_mmc_spi_block_size; sd_mmc_spi_transfert_pos += sd_mmc_spi_block_size; if (!sd_mmc_spi_stop_write_block()) { return false; } // Do not check busy of last block // but delay it to mci_wait_end_of_write_blocks() if (nb_block) { // Wait busy due to data programmation if (!sd_mmc_spi_wait_busy()) { sd_mmc_spi_err = SD_MMC_SPI_ERR_WRITE_TIMEOUT; sd_mmc_spi_debug("%s: Write blocks timeout\n\r", __func__); return false; } } } return true; }
bool sd_mmc_spi_write_word(uint32_t value) { sd_mmc_spi_err = SD_MMC_SPI_NO_ERR; Assert(sd_mmc_spi_nb_block > (sd_mmc_spi_transfert_pos / sd_mmc_spi_block_size)); if (!(sd_mmc_spi_transfert_pos % sd_mmc_spi_block_size)) { // New block sd_mmc_spi_start_write_block(); } // Write data value = cpu_to_le32(value); spi_write_buffer_wait(&sd_mmc_master, (uint8_t*)&value, 4); sd_mmc_spi_transfert_pos += 4; if (!(sd_mmc_spi_transfert_pos % sd_mmc_spi_block_size)) { // End of block if (!sd_mmc_spi_stop_write_block()) { return false; } // Wait busy due to data programmation if (!sd_mmc_spi_wait_busy()) { sd_mmc_spi_err = SD_MMC_SPI_ERR_WRITE_TIMEOUT; sd_mmc_spi_debug("%s: Write blocks timeout\n\r", __func__); return false; } } return sd_mmc_spi_stop_multiwrite_block(); }
/** * \brief Sends the correct TOKEN on the line to start a write block transfer */ static void sd_mmc_spi_start_write_block(void) { uint8_t dummy = 0xFF; Assert(!(sd_mmc_spi_transfert_pos % sd_mmc_spi_block_size)); // Delay before start write block: // Nwr timing minimum = 8 cylces spi_write_buffer_wait(&sd_mmc_master,&dummy, 1); // Send start token uint8_t token; if (1 == sd_mmc_spi_nb_block) { token = SPI_TOKEN_SINGLE_WRITE; } else { token = SPI_TOKEN_MULTI_WRITE; } spi_write_buffer_wait(&sd_mmc_master,&token, 1); }
/** * \brief Waits the TOKEN which notify the end of write block transfer * * \return true if success, otherwise false * with a update of \ref sd_mmc_spi_err. */ static bool sd_mmc_spi_stop_write_block(void) { uint8_t resp; uint16_t crc; uint16_t dummy = 0xFF; // Send CRC crc = 0xFFFF; /// CRC is disabled in SPI mode spi_write_buffer_wait(&sd_mmc_master, (uint8_t *)&crc, 2); // Receiv data response token spi_read_buffer_wait(&sd_mmc_master, &resp, 1, dummy); if (!SPI_TOKEN_DATA_RESP_VALID(resp)) { sd_mmc_spi_err = SD_MMC_SPI_ERR; sd_mmc_spi_debug("%s: Invalid Data Response Token 0x%x\n\r", __func__, resp); return false; } // Check data response switch (SPI_TOKEN_DATA_RESP_CODE(resp)) { case SPI_TOKEN_DATA_RESP_ACCEPTED: break; case SPI_TOKEN_DATA_RESP_CRC_ERR: sd_mmc_spi_err = SD_MMC_SPI_ERR_WRITE_CRC; sd_mmc_spi_debug("%s: Write blocks, SD_MMC_SPI_ERR_CRC, resp 0x%x\n\r", __func__, resp); return false; case SPI_TOKEN_DATA_RESP_WRITE_ERR: default: sd_mmc_spi_err = SD_MMC_SPI_ERR_WRITE; sd_mmc_spi_debug("%s: Write blocks SD_MMC_SPI_ERR_WR, resp 0x%x\n\r", __func__, resp); return false; } return true; }
/** * \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); }
/** * \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); }
int main(void) { //! [main_start] /* Initialize system */ //! [system_init] system_init(); //! [system_init] //! [run_config] configure_spi_slave(); //! [run_config] //! [main_start] //! [main_use_case] //! [write] while (spi_write_buffer_wait(&spi_slave_instance, buffer, BUF_LENGTH) != STATUS_OK) { /* Wait for transfer from master */ } //! [write] //! [inf_loop] while (true) { /* Infinite loop */ } //! [inf_loop] //! [main_use_case] }
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] }
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] }
int cph_deca_spi_write(uint16_t headerLength, const uint8_t *headerBuffer, uint32_t bodylength, const uint8_t *bodyBuffer) { status_code_t result = STATUS_OK; cph_deca_spi_ss_select(); if ((result = spi_write_buffer_wait(&spi_master_instance, headerBuffer, headerLength)) == STATUS_OK) { result = spi_write_buffer_wait(&spi_master_instance, bodyBuffer, bodylength); } cph_deca_spi_ss_deselect(); if (result != STATUS_OK) { printf("writetospi_serial timeout\r\n"); } return result; }
/** * \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 sd_mmc_spi_send_clock(void) { uint8_t i; uint8_t dummy = 0xFF; sd_mmc_spi_err = SD_MMC_SPI_NO_ERR; //! Send 80 cycles for (i = 0; i < 10; i++) { spi_write_buffer_wait(&sd_mmc_master, &dummy, 1); // 8 cycles } }
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) { } }
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; };
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; };
int cph_deca_spi_read(uint16_t headerLength, const uint8_t *headerBuffer, uint32_t readlength, uint8_t *readBuffer) { status_code_t result = STATUS_OK; cph_deca_spi_ss_select(); if ((result = spi_write_buffer_wait(&spi_master_instance, headerBuffer, headerLength)) == STATUS_OK) { result = spi_read_buffer_wait(&spi_master_instance, readBuffer, readlength, 0xff); } cph_deca_spi_ss_deselect(); if (result != STATUS_OK) { printf("readfromspi_serial timeout\r\n"); } return result; }
/** * \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); }
/** * \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); }
/** * \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]); } } }
/* * @brief spi_isr SPI isr call back handler * * @param return kick_scheduler_t * */ kick_scheduler_t spi_isr(void) { #ifdef SPI_IN_INTERRUPT_MODE /* save the byte just received in the RX buffer */ switch (spi_vars.returnType) { case SPI_FIRSTBYTE: if (spi_vars.numTxedBytes==0) { spi_read_buffer_wait(&master, spi_vars.pNextRxByte, 1, 0); } break; case SPI_BUFFER: spi_read_buffer_wait(&master, spi_vars.pNextRxByte, 1, 0); spi_vars.pNextRxByte++; break; case SPI_LASTBYTE: spi_read_buffer_wait(&master, spi_vars.pNextRxByte, 1, 0); break; } /* one byte less to go */ spi_vars.pNextTxByte++; spi_vars.numTxedBytes++; spi_vars.txBytesLeft--; if (spi_vars.txBytesLeft>0) { /* write next byte to TX buffer */ spi_write_buffer_wait(&master, spi_vars.pNextTxByte, 1); } else { /* put CS signal high to signal end of transmission to slave */ if (spi_vars.isLast==SPI_LAST) { /* Stop the SPI transaction by setting SEL high */ spi_select_slave(&master, &slave, false); } /* SPI is not busy anymore */ spi_vars.busy = 0; /* SPI is done! */ if (spi_vars.callback!=NULL) { /* call the callback */ spi_vars.callback(); /* kick the OS */ return KICK_SCHEDULER; } } return DO_NOT_KICK_SCHEDULER; #else /* this should never happen! */ while(1); /* we can not print from within the BSP. Instead we blink the error LED */ leds_error_blink(); /* reset the board */ board_reset(); /* execution will not reach here, statement to make compiler happy */ return DO_NOT_KICK_SCHEDULER; #endif }
void SPI_Write_ADXL(uint8_t* data) { port_pin_set_output_level(PIN_PA06, 0); spi_write_buffer_wait(&spi_master_instance_ADXL, data, 2); port_pin_set_output_level(PIN_PA06, 1); }
void SPI_Write_AD5421(uint8_t* data) { port_pin_set_output_level(PIN_PA18, 0); spi_write_buffer_wait(&spi_master_instance_AD5421, data, 3); port_pin_set_output_level(PIN_PA18, 1); }
/** * \brief Write internal fifo buffer. * * \param buf the buffer to send to the fifo buffer. * \param len the size of the pbuf element to write. */ void ksz8851_fifo_write(uint8_t *buf, uint32_t len) { /* Perform SPI transfer. */ spi_write_buffer_wait(&ksz8851snl_master, buf, len); }
/*============================================================================== hal_spiWrite() =============================================================================*/ void hal_spiWrite(uint8_t * c_value, uint16_t i_length) { if (spi_write_buffer_wait(&st_masterInst,c_value,i_length) != STATUS_OK) // LOG_ERR("%s\n\r","SPI write error!"); ; } /* hal_spiWrite() */
bool sd_mmc_spi_adtc_start(sdmmc_cmd_def_t cmd, uint32_t arg, uint16_t block_size, uint16_t nb_block, bool access_block) { uint8_t dummy = 0xFF; uint8_t cmd_token[6]; uint8_t ncr_timeout; uint8_t r1; //! R1 response uint16_t dummy2 = 0xFF; UNUSED(access_block); Assert(cmd & SDMMC_RESP_PRESENT); // Always a response in SPI mode sd_mmc_spi_err = SD_MMC_SPI_NO_ERR; // Encode SPI command cmd_token[0] = SPI_CMD_ENCODE(SDMMC_CMD_GET_INDEX(cmd)); cmd_token[1] = arg >> 24; cmd_token[2] = arg >> 16; cmd_token[3] = arg >> 8; cmd_token[4] = arg; cmd_token[5] = sd_mmc_spi_crc7(cmd_token, 5); // 8 cycles to respect Ncs timing // Note: This byte does not include start bit "0", // thus it is ignored by card. spi_write_buffer_wait(&sd_mmc_master, &dummy, 1); // Send command spi_write_buffer_wait(&sd_mmc_master, cmd_token, sizeof(cmd_token)); // Wait for response // Two retry will be done to manage the Ncr timing between command and reponse // Ncr: Min. 1x8 clock cycle, Max. 8x8 clock cycles // WORKAROUND for no compliance card (Atmel Internal ref. SD13): r1 = 0xFF; // Ignore first byte because Ncr min. = 8 clock cylces spi_read_buffer_wait(&sd_mmc_master, &r1, 1, dummy2); ncr_timeout = 7; while (1) { spi_read_buffer_wait(&sd_mmc_master, &r1, 1, dummy2); // 8 cycles if ((r1 & R1_SPI_ERROR) == 0) { // Valid R1 response break; } if (--ncr_timeout == 0) { // Here Valid R1 response received sd_mmc_spi_debug("%s: cmd %02d, arg 0x%08lX, R1 timeout\n\r", __func__, (int)SDMMC_CMD_GET_INDEX(cmd), arg); sd_mmc_spi_err = SD_MMC_SPI_ERR_RESP_TIMEOUT; return false; } } // Save R1 (Specific to SPI interface) in 32 bit response // The R1_SPI_IDLE bit can be checked by high level sd_mmc_spi_response_32 = r1; // Manage error in R1 if (r1 & R1_SPI_COM_CRC) { sd_mmc_spi_debug("%s: cmd %02d, arg 0x%08lx, r1 0x%02x, R1_SPI_COM_CRC\n\r", __func__, (int)SDMMC_CMD_GET_INDEX(cmd), arg, r1); sd_mmc_spi_err = SD_MMC_SPI_ERR_RESP_CRC; return false; } if (r1 & R1_SPI_ILLEGAL_COMMAND) { sd_mmc_spi_debug("%s: cmd %02d, arg 0x%08lx, r1 0x%x, R1 ILLEGAL_COMMAND\n\r", __func__, (int)SDMMC_CMD_GET_INDEX(cmd), arg, r1); sd_mmc_spi_err = SD_MMC_SPI_ERR_ILLEGAL_COMMAND; return false; } if (r1 & ~R1_SPI_IDLE) { // Other error sd_mmc_spi_debug("%s: cmd %02d, arg 0x%08lx, r1 0x%x, R1 error\n\r", __func__, (int)SDMMC_CMD_GET_INDEX(cmd), arg, r1); sd_mmc_spi_err = SD_MMC_SPI_ERR; return false; } // Manage other responses if (cmd & SDMMC_RESP_BUSY) { if (!sd_mmc_spi_wait_busy()) { sd_mmc_spi_err = SD_MMC_SPI_ERR_RESP_BUSY_TIMEOUT; sd_mmc_spi_debug("%s: cmd %02d, arg 0x%08lx, Busy signal always high\n\r", __func__, (int)SDMMC_CMD_GET_INDEX(cmd), arg); return false; } } if (cmd & SDMMC_RESP_8) { sd_mmc_spi_response_32 = 0; spi_read_buffer_wait(&sd_mmc_master, (uint8_t *)&sd_mmc_spi_response_32, 1, dummy2); sd_mmc_spi_response_32 = le32_to_cpu(sd_mmc_spi_response_32); } if (cmd & SDMMC_RESP_32) { spi_read_buffer_wait(&sd_mmc_master, (uint8_t *)&sd_mmc_spi_response_32, 4, dummy2); sd_mmc_spi_response_32 = be32_to_cpu(sd_mmc_spi_response_32); } sd_mmc_spi_block_size = block_size; sd_mmc_spi_nb_block = nb_block; sd_mmc_spi_transfert_pos = 0; return true; // Command complete }
/* * @brief spi_txrx SPI transmit and receive the data * * @param bufTx Transmit Buffer * @param lenbufTx Length of transmit buffer * @param returnType * @param bufRx SPI Rx Buffer * @param Max Length of Rx Buffer size * @param isFirst * @param isLast * */ void spi_txrx(uint8_t* bufTx, uint8_t lenbufTx, spi_return_t returnType, uint8_t* bufRx, uint8_t maxLenBufRx, spi_first_t isFirst, spi_last_t isLast) { uint8_t spi_byte; #ifdef SPI_IN_INTERRUPT_MODE /* Disable the interrupts */ cpu_irq_disable(); #endif /* register spi frame to send */ spi_vars.pNextTxByte = bufTx; spi_vars.numTxedBytes = 0; spi_vars.txBytesLeft = lenbufTx; spi_vars.returnType = returnType; spi_vars.pNextRxByte = bufRx; spi_vars.maxRxBytes = maxLenBufRx; spi_vars.isFirst = isFirst; spi_vars.isLast = isLast; /* SPI is now busy */ spi_vars.busy = 1; /* lower CS signal to have slave listening */ if (spi_vars.isFirst==SPI_FIRST) { /* Start SPI transaction by pulling SEL low */ port_pin_set_level(AT86RFX_SPI_CS, SET_LOW); cpu_delay_us(10); } #ifdef SPI_IN_INTERRUPT_MODE /* implementation 1. use a callback function when transaction finishes */ /* Send the Read command byte */ spi_write_buffer_wait(&master, spi_vars.pNextTxByte, 1); /* re-enable interrupts */ cpu_irq_enable(); #else /* implementation 2. busy wait for each byte to be sent */ /* send all bytes */ while (spi_vars.txBytesLeft > 0) { /* write next byte to TX buffer */ /* Send the Read command byte */ spi_byte = *spi_vars.pNextTxByte; spi_txrx_data(&spi_byte); /* save the byte just received in the RX buffer */ switch (spi_vars.returnType) { case SPI_FIRSTBYTE: if (spi_vars.numTxedBytes==0) { *spi_vars.pNextRxByte = spi_byte; } break; case SPI_BUFFER: *spi_vars.pNextRxByte = spi_byte; spi_vars.pNextRxByte++; break; case SPI_LASTBYTE: *spi_vars.pNextRxByte = spi_byte; break; } /* one byte less to go */ spi_vars.pNextTxByte++; spi_vars.numTxedBytes++; spi_vars.txBytesLeft--; } /* put CS signal high to signal end of transmission to slave */ if (spi_vars.isLast==SPI_LAST) { /* Stop the SPI transaction by setting SEL high */ port_pin_set_level(AT86RFX_SPI_CS, SET_HIGH); } /* SPI is not busy anymore */ spi_vars.busy = 0; #endif }
/** * \brief Function for sending acknowledgement to SPI Master * * This function will send an acknowledgement byte 's' to the master to * indicate the master that it has received and programmed the data. */ static void send_ack(void) { uint8_t ack = 's'; spi_write_buffer_wait(&slave, &ack, 1); }