/**
 * \brief Wait the end of busy on DAT0 line
 *
 * \return true if success, otherwise false
 */
static bool sd_mmc_spi_wait_busy(void)
{
	uint8_t line = 0xFF;
	uint16_t dummy = 0xFF;

	/* Delay before check busy
	 * Nbr timing minimum = 8 cylces
	 */
	spi_read_buffer_wait(&sd_mmc_master, &line, 1,
			dummy);

	/* Wait end of busy signal
	 * Nec timing: 0 to unlimited
	 * However a timeout is used.
	 * 200 000 * 8 cycles
	 */
	uint32_t nec_timeout = 200000;
	spi_read_buffer_wait(&sd_mmc_master, &line, 1,
			dummy);
	do {
		spi_read_buffer_wait(&sd_mmc_master, &line, 1,
			dummy);
		if (!(nec_timeout--)) {
			return false;
		}
	} while (line != 0xFF);
	return true;
}
/*!
* @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, &reg_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;
}
/**
 * \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;
}
bool sd_mmc_spi_read_word(uint32_t* value)
{
	uint16_t dummy = 0xFF;

	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
		if (!sd_mmc_spi_start_read_block()) {
			return false;
		}
	}
	// Read data
	spi_read_buffer_wait(&sd_mmc_master, (uint8_t *)&value, 4,
			dummy);
	*value = le32_to_cpu(*value);
	sd_mmc_spi_transfert_pos += 4;

	if (!(sd_mmc_spi_transfert_pos % sd_mmc_spi_block_size)) {
		// End of block
		sd_mmc_spi_stop_read_block();
	}
	return true;
}
int main(void)
{
//! [main_start]
	uint8_t result = 0;
	uint16_t i;
	uint32_t delay;

	/* Initialize system */
//! [system_init]
	system_clock_config(CLOCK_RESOURCE_XO_26_MHZ, CLOCK_FREQ_26_MHZ);
	for (i = 0; i < BUF_LENGTH; i++) {
		buffer_expect[i] = i;
		buffer_rx[i] = 0;
	}
//! [system_init]

//! [run_config_gpio]
	configure_gpio();
//! [run_config_gpio]
//! [run_config_spi]
	configure_spi_slave();
//! [run_config_spi]
//! [main_start]

//! [main_use_case]
//! [read]
	memset(buffer_rx, 0x0, BUF_LENGTH);
	while(spi_read_buffer_wait(&spi_slave_instance, buffer_rx, BUF_LENGTH,
		0x00) != STATUS_OK) {
		/* Wait for transfer from the master */
	}
//! [read]
//! [compare]
	for (i = 0; i < BUF_LENGTH; i++) {
		if(buffer_rx[i] != buffer_expect[i]) {
			result++;
		}
	}
//! [compare]
//! [inf_loop]
	while (true) {
		/* Infinite loop */
		if (result) {
			gpio_pin_toggle_output_level(LED_0_PIN);
			/* Add a short delay to see LED toggle */
			delay = 300000;
			while(delay--) {
			}
		} else {
			gpio_pin_toggle_output_level(LED_0_PIN);
			/* Add a short delay to see LED toggle */
			delay = 3000000;
			while(delay--) {
			}
		}
	}
//! [inf_loop]
//! [main_use_case]
}
/**
 * \brief Executed the end of a read block transfer
 */
static void sd_mmc_spi_stop_read_block(void)
{
	uint8_t crc[2];
	uint16_t dummy = 0xFF;
	// Read 16-bit CRC (not cheked)
	spi_read_buffer_wait(&sd_mmc_master, crc, 2,
			dummy);
}
Exemple #7
0
/**
* \brief Read response on SPI from PC
*
* return Status
* \param[in]  rx_buf  Pointer to receive the data
* \param[in]  length  The length of the read data
* \param[out] rx_buf  Pointer to store the received SPI character
*/
bool adp_interface_read_response(uint8_t* rx_buf, uint16_t length)
{
	bool status;

	/* Send SPI start condition */
	adp_interface_send_start();	
	status = spi_read_buffer_wait(&edbg_spi, rx_buf, length, 0xFF);
	/* Send SPI end condition */
	adp_interface_send_stop();

	return status;
}
/**
 * \brief Function for fetching length of file to be programmed
 *
 * Master initially transmits 4 bytes - which is the length of the
 * the data to be programmed to the device.
 */
static uint32_t get_length(void)
{
	uint8_t read_buffer[4];
	uint32_t len = 0;

	/* Read 4 bytes of data from master */
	while (spi_read_buffer_wait(&slave, read_buffer, 4, dummy) != STATUS_OK);
	MSB0W(len) = read_buffer[0];
	MSB1W(len) = read_buffer[1];
	MSB2W(len) = read_buffer[2];
	MSB3W(len) = read_buffer[3];

	return len;
}
/**
 * \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);
}
Exemple #10
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;
};
/**
 * \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);
}
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;
}
/**
 * \brief Sends the correct TOKEN on the line to start a read block transfer
 *
 * \return true if success, otherwise false
 *         with a update of \ref sd_mmc_spi_err.
 */
static bool sd_mmc_spi_start_read_block(void)
{
	uint32_t i;
	uint8_t token;
	uint16_t dummy = 0xFF;

	Assert(!(sd_mmc_spi_transfert_pos % sd_mmc_spi_block_size));

	/* Wait for start data token:
	 * The read timeout is the Nac timing.
	 * Nac must be computed trough CSD values,
	 * or it is 100ms for SDHC / SDXC
	 * Compute the maximum timeout:
	 * Frequency maximum = 25MHz
	 * 1 byte = 8 cycles
	 * 100ms = 312500 x spi_read_buffer_wait() maximum
	 */
	token = 0;
	i = 500000;
	do {
		if (i-- == 0) {
			sd_mmc_spi_err = SD_MMC_SPI_ERR_READ_TIMEOUT;
			sd_mmc_spi_debug("%s: Read blocks timeout\n\r", __func__);
			return false;
		}
		spi_read_buffer_wait(&sd_mmc_master, &token, 1,
			dummy);
		if (SPI_TOKEN_DATA_ERROR_VALID(token)) {
			Assert(SPI_TOKEN_DATA_ERROR_ERRORS & token);
			if (token & (SPI_TOKEN_DATA_ERROR_ERROR
					| SPI_TOKEN_DATA_ERROR_ECC_ERROR
					| SPI_TOKEN_DATA_ERROR_CC_ERROR)) {
				sd_mmc_spi_debug("%s: CRC data error token\n\r", __func__);
				sd_mmc_spi_err = SD_MMC_SPI_ERR_READ_CRC;
			} else {
				sd_mmc_spi_debug("%s: Out of range data error token\n\r", __func__);
				sd_mmc_spi_err = SD_MMC_SPI_ERR_OUT_OF_RANGE;
			}
			return false;
		}
	} while (token != SPI_TOKEN_SINGLE_MULTI_READ);

	return true;
}
bool sd_mmc_spi_start_read_blocks(void *dest, uint16_t nb_block)
{
	uint32_t pos;
	uint16_t dummy = 0xFF;

	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));
		if (!sd_mmc_spi_start_read_block()) {
			return false;
		}

		// Read block
		spi_read_buffer_wait(&sd_mmc_master, &((uint8_t*)dest)[pos],
			sd_mmc_spi_block_size, dummy);
		pos += sd_mmc_spi_block_size;
		sd_mmc_spi_transfert_pos += sd_mmc_spi_block_size;

		sd_mmc_spi_stop_read_block();
	}
	return true;
}
Exemple #15
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
}
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
}
Exemple #17
0
/*==============================================================================
  hal_spiRead()
 =============================================================================*/
uint8_t hal_spiRead(uint8_t * p_reg, uint16_t i_length)
{
	spi_read_buffer_wait(&st_masterInst,p_reg,i_length,0);
	return *p_reg;
} /* hal_spiRead() */
/**
 * \brief Function for fetching data to be programmed
 *
 * This function will read \ref len number of bytes from master for
 * programming the device.
 *
 * \param buffer pointer to the buffer to store data from SPI master
 * \param len    length of the data that will be sent by SPI master
 */
static void fetch_data(uint8_t *buffer, uint16_t len)
{
	/* Read \ref len number of bytes from master */
	while (spi_read_buffer_wait(&slave, buffer, len, dummy) != STATUS_OK);
}