/*!
* @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, &reg_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;
}
示例#2
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;
}
示例#3
0
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;
}
示例#4
0
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();
}
示例#5
0
/**
 * \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);
}
示例#6
0
/**
 * \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;
}
示例#7
0
文件: ssd1306.c 项目: InSoonPark/asf
/**
 * \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);
}
示例#8
0
文件: ssd1306.c 项目: InSoonPark/asf
/**
 * \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);
}
示例#9
0
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]
}
示例#10
0
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]
}
示例#12
0
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);
}
示例#14
0
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
	}
}
示例#15
0
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) {
		
	}
}
示例#16
0
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;
};
示例#17
0
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;
};
示例#18
0
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]);
		}
	}
}
示例#22
0
/*
 * @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
}
示例#23
0
文件: main.c 项目: rmnsfx/DVA141
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);
}
示例#24
0
文件: main.c 项目: rmnsfx/DVA141
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);
}
示例#26
0
文件: target.c 项目: kamejoko80/emb6
/*==============================================================================
  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() */
示例#27
0
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
}
示例#28
0
/*
 * @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);
}