Exemple #1
0
OSStatus host_platform_spi_transfer( bus_transfer_direction_t dir, uint8_t* buffer, uint16_t buffer_length )
{
  OSStatus result;
  
  pdc_packet_t pdc_spi_packet = { (uint32_t)buffer, buffer_length };
  Pdc* spi_pdc  = spi_get_pdc_base( wifi_spi.port );
  
  platform_mcu_powersave_disable();
  
  platform_gpio_output_low( &wifi_spi_pins[WIFI_PIN_SPI_CS] );
  
  pdc_tx_init( spi_pdc, &pdc_spi_packet, NULL);
  
  if ( dir == BUS_READ ) {
    pdc_rx_init( spi_pdc, &pdc_spi_packet, NULL);
    
    spi_enable_interrupt(wifi_spi.port, SPI_IER_RXBUFF );
    pdc_enable_transfer( spi_pdc, PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN );
  } 
  
  if ( dir == BUS_WRITE ) {
    spi_enable_interrupt( wifi_spi.port, SPI_IER_ENDTX );
    pdc_enable_transfer( spi_pdc, PERIPH_PTCR_TXTEN );
  }
  
  result = mico_rtos_get_semaphore( &spi_transfer_finished_semaphore, 100 );
  
  platform_gpio_output_high( &wifi_spi_pins[WIFI_PIN_SPI_CS] );
  
  platform_mcu_powersave_enable();
  
  return result;
  
}
Exemple #2
0
/**
 * \brief Initialize SPI as slave.
 */
static void spi_slave_initialize(void)
{
	uint32_t i;

	/* Reset status */
	gs_spi_status.ul_total_block_number = 0;
	gs_spi_status.ul_total_command_number = 0;
	for (i = 0; i < NB_STATUS_CMD; i++) {
		gs_spi_status.ul_cmd_list[i] = 0;
	}
	gs_ul_spi_state = SLAVE_STATE_IDLE;
	gs_ul_spi_cmd = RC_SYN;

	puts("-I- Initialize SPI as slave \r");
	/* Configure an SPI peripheral. */
	spi_enable_clock(SPI_SLAVE_BASE);
	spi_disable(SPI_SLAVE_BASE);
	spi_reset(SPI_SLAVE_BASE);
	spi_set_slave_mode(SPI_SLAVE_BASE);
	spi_disable_mode_fault_detect(SPI_SLAVE_BASE);
	spi_set_peripheral_chip_select_value(SPI_SLAVE_BASE, SPI_CHIP_SEL);
	spi_set_clock_polarity(SPI_SLAVE_BASE, SPI_CHIP_SEL, SPI_CLK_POLARITY);
	spi_set_clock_phase(SPI_SLAVE_BASE, SPI_CHIP_SEL, SPI_CLK_PHASE);
	spi_set_bits_per_transfer(SPI_SLAVE_BASE, SPI_CHIP_SEL, SPI_CSR_BITS_8_BIT);
	spi_enable_interrupt(SPI_SLAVE_BASE, SPI_IER_RDRF);
	spi_enable(SPI_SLAVE_BASE);

	/* Start waiting command. */
	spi_slave_transfer(&gs_ul_spi_cmd, sizeof(gs_ul_spi_cmd));
}
Exemple #3
0
/**
 * \brief Write internal fifo buffer.
 *
 * \param buf the buffer to send to the fifo buffer.
 * \param tot_len the total amount of data to write.
 * \param len the size of the first pbuf to write from the pbuf chain.
 */
void ksz8851_fifo_write(uint8_t *buf, uint32_t tot_len, uint32_t len)
{
    static uint8_t frameID = 0;
    pdc_packet_t g_pdc_spi_tx_packet;
    pdc_packet_t g_pdc_spi_rx_packet;
    pdc_packet_t g_pdc_spi_tx_npacket;
    pdc_packet_t g_pdc_spi_rx_npacket;

    /* Prepare control word and byte count. */
    tmpbuf[0] = FIFO_WRITE;
    tmpbuf[1] = frameID++ & 0x3f;
    tmpbuf[2] = 0;
    tmpbuf[3] = tot_len & 0xff;
    tmpbuf[4] = tot_len >> 8;

    /* Prepare PDC transfer. */
    g_pdc_spi_tx_packet.ul_addr = (uint32_t) tmpbuf;
    g_pdc_spi_tx_packet.ul_size = 5;
    g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
    g_pdc_spi_rx_packet.ul_size = 5;
    g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
    g_pdc_spi_tx_npacket.ul_size = len;
    g_pdc_spi_rx_npacket.ul_addr = (uint32_t) tmpbuf;
    g_pdc_spi_rx_npacket.ul_size = len;
    pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
    pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
    pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);
    pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);

    spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_ENDRX);
}
Exemple #4
0
/**
 * \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)
{
    pdc_packet_t g_pdc_spi_tx_packet;
    pdc_packet_t g_pdc_spi_rx_packet;
    pdc_packet_t g_pdc_spi_tx_npacket;
    pdc_packet_t g_pdc_spi_rx_npacket;

    tmpbuf[0] = FIFO_READ;

    /* Prepare PDC transfer. */
    g_pdc_spi_tx_packet.ul_addr = (uint32_t) tmpbuf;
    g_pdc_spi_tx_packet.ul_size = 9;
    g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
    g_pdc_spi_rx_packet.ul_size = 9;
    g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
    g_pdc_spi_tx_npacket.ul_size = len;
    g_pdc_spi_rx_npacket.ul_addr = (uint32_t) buf;
    g_pdc_spi_rx_npacket.ul_size = len;
    pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
    pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
    pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);
    pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);

    spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_RXBUFF);
}
/*! \brief Initialize the SPI in slave mode and enable the spi interrupt.
 */
static void spi_slave_init(volatile void *spi, uint8_t mode)
{
	/* Enable Clock for SPI module */
	sysclk_enable_module(POWER_RED_REG0, PRSPI_bm);

	/* Configure SPI pins for slave */
	/* Set MISO as output high, and set MOSI, SS , SCK as input */

	gpio_configure_pin(SPI_SCK, IOPORT_DIR_INPUT);
	gpio_configure_pin(SPI_MOSI, IOPORT_DIR_INPUT);
	gpio_configure_pin(SPI_SS, IOPORT_DIR_INPUT);
	gpio_configure_pin(SPI_MISO, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT);

	/* Set the clock mode */
	spi_set_clock_mode(spi, mode);

	/* Enable SPI as slave */
	spi_enable_slave_mode(spi);
        
        /* Set the interrupt call back */
        spi_set_interrupt_callback(spi_interrupt_callback);
          
	/* Enable SPI interrupt */
	spi_enable_interrupt(spi);
}
Exemple #6
0
/**
 * \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)
{
	pdc_packet_t g_pdc_spi_tx_packet;
	pdc_packet_t g_pdc_spi_rx_packet;
	pdc_packet_t g_pdc_spi_tx_npacket;
	pdc_packet_t g_pdc_spi_rx_npacket;

	memset( cmdBuf.uc, '\0', sizeof cmdBuf );
	cmdBuf.uc[0] = FIFO_READ;
	spi_clear_ovres();

	/* Prepare PDC transfer. */
	g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
	g_pdc_spi_tx_packet.ul_size = 9;
	g_pdc_spi_rx_packet.ul_addr = (uint32_t) respBuf.uc;
	g_pdc_spi_rx_packet.ul_size = 9;

	g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
	g_pdc_spi_tx_npacket.ul_size = len;
	g_pdc_spi_rx_npacket.ul_addr = (uint32_t) buf;
	g_pdc_spi_rx_npacket.ul_size = len;
	pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
	pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
	pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);

spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_RXBUFF | SPI_IER_OVRES);

	pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
}
Exemple #7
0
/**
@ingroup spi_function
@brief Send an array of bytes to to the SPI bus.

@note Can only be used if SPI_USE_BUFFER are enabled in spi_iha_defs.h

@see spi_iha_defs.h for SPI_USE_BUFFER setup.

@return SPI_OK: OK byte send to SPI bus or put in tx_buffer.\n
SPI_NO_ROOM_IN_TX_BUFFER: Buffer full no data send\n
SPI_ILLEGAL_INSTANCE: instance is null.
@param spi to send to.
@param *buf pointer to buffer to be send.
@param len no of bytes to send.
*/
uint8_t spi_send_bytes(spi_p spi, uint8_t buf[], uint8_t len) {
	uint8_t result = SPI_OK;
	uint32_t value;
	uint8_t tmp = 0;	
	
	if (spi == NULL) {
		return SPI_ILLEGAL_INSTANCE;
	}

	// Select correct instance
	if (_this != spi ) {
		_select_instance(spi);
	}

	// Critical section
	 	{
 		// disable interrupt
		spi_disable_interrupt(_spi_base, SPI_IDR_TDRE | SPI_IDR_RDRF);

		// Check if buffer is free
		if (len > fifo_get_free_size(spi->_spi_tx_fifo_desc)) {
			result = SPI_NO_ROOM_IN_TX_BUFFER;
		} else {
			// If SPI in idle send the first byte
			if (!_spi_active) {
				_spi_active = 1;
					
				// Send first byte
				value = SPI_TDR_TD(buf[0]) | SPI_TDR_PCS(spi_get_pcs(spi->_cs_pin));
				if (len == 1) {
					// It was last byte
					value |= SPI_TDR_LASTXFER;
				}					

				// Send byte
				_spi_base->SPI_TDR = value;
				//spi_enable_interrupt(_spi_base, SPI_IER_TDRE);
				tmp = 1;
			}
				
			// Put in the tx buffer
			for (uint8_t i = tmp; i < len; i++) {
				value = SPI_TDR_TD(buf[i]) | SPI_TDR_PCS(spi_get_pcs(spi->_cs_pin));
				if (i == len-1) {
					// It was last byte
					value |= SPI_TDR_LASTXFER;
				}
				if ( fifo_push_uint32(spi->_spi_tx_fifo_desc, value) == FIFO_ERROR_OVERFLOW ) {
					result = SPI_NO_ROOM_IN_TX_BUFFER;			
				}
			}
		}

 		// restore interrupt state
		spi_enable_interrupt(_spi_base, SPI_IER_TDRE | SPI_IER_RDRF);
	}
	return result;
}
Exemple #8
0
/**
 * \brief Write internal fifo buffer.
 *
 * \param buf the buffer to send to the fifo buffer.
 * \param ulActualLength the total amount of data to write.
 * \param ulFIFOLength the size of the first pbuf to write from the pbuf chain.
 */
void ksz8851_fifo_write(uint8_t *buf, uint32_t ulActualLength, uint32_t ulFIFOLength)
{
	static uint8_t frameID = 0;

	pdc_packet_t g_pdc_spi_tx_packet;
	pdc_packet_t g_pdc_spi_rx_packet;
	pdc_packet_t g_pdc_spi_tx_npacket;
	pdc_packet_t g_pdc_spi_rx_npacket;

	/* Prepare control word and byte count. */
	cmdBuf.uc[0] = FIFO_WRITE;
	cmdBuf.uc[1] = frameID++ & 0x3f;
	cmdBuf.uc[2] = 0;
	cmdBuf.uc[3] = ulActualLength & 0xff;
	cmdBuf.uc[4] = ulActualLength >> 8;

	spi_clear_ovres();

	/* Prepare PDC transfer. */
	g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
	g_pdc_spi_tx_packet.ul_size = 5;

	g_pdc_spi_rx_packet.ul_addr = (uint32_t) respBuf.uc;
	g_pdc_spi_rx_packet.ul_size = 5;

	g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
	g_pdc_spi_tx_npacket.ul_size = ulFIFOLength;

	g_pdc_spi_rx_npacket.ul_addr = (uint32_t) tmpbuf;
	g_pdc_spi_rx_npacket.ul_size = ulFIFOLength;

	pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
	pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
	#if( TX_USES_RECV == 1 )
		pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);
		spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_ENDRX | SPI_IER_OVRES);
		pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
	#else
		spi_enable_interrupt(KSZ8851SNL_SPI, SPI_SR_TXBUFE | SPI_IER_OVRES);
		pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_TXTEN);
	#endif
}
Exemple #9
0
static void _spi_init_base(Spi * spi_base)
{
	spi_enable_clock(spi_base);
	spi_disable(spi_base);
	spi_reset(spi_base);
	spi_set_lastxfer(spi_base);
	spi_set_master_mode(spi_base);
	spi_disable_mode_fault_detect(spi_base);
	spi_set_variable_peripheral_select(spi_base);
	spi_enable_interrupt(_spi_base, SPI_IER_RDRF);
	
	// spi_enable_loopback(spi_base); // ??????????????????
}
void spi_master_transfer(spi_t *obj, void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t handler, uint32_t event, DMAUsage hint)
{
	uint32_t pdcenable=0;
	
	if(tx){
		pdc_packet_t pdc_packet_tx;
		pdc_packet_tx.ul_addr=(uint32_t)tx;
		pdc_packet_tx.ul_size=tx_length;
		
		pdcenable|=PERIPH_PTCR_TXTEN;
		/* Configure PDC for data send */
		pdc_tx_init(obj->spi.pdc, &pdc_packet_tx, NULL);
	}
	
	if(rx){
		pdc_rx_clear_cnt(obj->spi.pdc);
		pdc_packet_t pdc_packet_rx;
		pdc_packet_rx.ul_addr=(uint32_t)rx;
		pdc_packet_rx.ul_size=rx_length;
		pdcenable|=PERIPH_PTCR_RXTEN;
		
		/* Configure PDC for data receive */
		pdc_rx_init(obj->spi.pdc, &pdc_packet_rx, NULL);
	}
	
	obj->spi.dma_usage=hint;
	obj->spi.event=event;
	
	gCallbackHandler[obj->spi.module_number]=handler;

	NVIC_ClearPendingIRQ(obj->spi.irq_type);

	/* Enable SPI interrupt */
	NVIC_EnableIRQ(obj->spi.irq_type);

	/* Enable SPI IRQ */
	spi_enable_interrupt(obj->spi.spi_base, SPI_IER_RXBUFF| SPI_IER_TXBUFE | SPI_IER_MODF | SPI_IER_OVRES);
	
	/* Enable PDC transfers */
	pdc_enable_transfer(obj->spi.pdc, pdcenable );
	
}
Exemple #11
0
/*
*	Initialise the SPI interface as a SLAVE
*
*/
void spi_slave_initialize(void)
{
	NVIC_DisableIRQ(SPI_IRQn);
	NVIC_ClearPendingIRQ(SPI_IRQn);
	NVIC_SetPriority(SPI_IRQn, 0);
	NVIC_EnableIRQ(SPI_IRQn);

	/* Configure an SPI peripheral. */
	spi_enable_clock(SPI_SLAVE_BASE);
	spi_disable(SPI_SLAVE_BASE);
	spi_reset(SPI_SLAVE_BASE);
	spi_set_slave_mode(SPI_SLAVE_BASE);
	spi_disable_mode_fault_detect(SPI_SLAVE_BASE);
	spi_set_peripheral_chip_select_value(SPI_SLAVE_BASE, SPI_CHIP_PCS);
	spi_set_clock_polarity(SPI_SLAVE_BASE, SPI_CHIP_SEL, SPI_CLK_POLARITY);
	spi_set_clock_phase(SPI_SLAVE_BASE, SPI_CHIP_SEL, SPI_CLK_PHASE);
	spi_set_bits_per_transfer(SPI_SLAVE_BASE, SPI_CHIP_SEL, SPI_CSR_BITS_8_BIT);
	spi_enable_interrupt(SPI_SLAVE_BASE, SPI_IER_RDRF);
	spi_enable(SPI_SLAVE_BASE);
}
Exemple #12
0
uint8_t spi_send_byte(spi_p spi, uint8_t byte, uint8_t last_byte)
{
	uint8_t result = SPI_OK;
	uint32_t value;
	
	if (spi == NULL) {
		return SPI_ILLEGAL_INSTANCE;
	}

	// Select correct instance
	if (_this != spi ) {
		_select_instance(spi);
	}

	// Critical section
	{
		// disable interrupt
		spi_disable_interrupt(_spi_base, SPI_IDR_TDRE | SPI_IDR_RDRF);
		
		value = SPI_TDR_TD(byte) | SPI_TDR_PCS(spi_get_pcs(spi->_cs_pin));
		if (last_byte) {
			value |= SPI_TDR_LASTXFER;
		}

		// If SPI in idle send the byte
		if (!_spi_active) {
			_spi_active = 1;

			// Send byte
			_spi_base->SPI_TDR = value;
		} else {
			// Put in the TX buffer
			if ( fifo_push_uint32(spi->_spi_tx_fifo_desc, value) == FIFO_ERROR_UNDERFLOW )
				result = SPI_NO_ROOM_IN_TX_BUFFER;
		}
		// Enable interrupt
		spi_enable_interrupt(_spi_base, SPI_IER_TDRE | SPI_IER_RDRF);
	}

	return result;
}
Exemple #13
0
/**
 * \ingroup freertos_spi_peripheral_control_group
 * \brief Initiate a completely asynchronous multi-byte write operation on an
 * SPI peripheral.
 *
 * freertos_spi_write_packet_async() is an ASF specific FreeRTOS driver function.
 * It configures the SPI peripheral DMA controller (PDC) to transmit data on the
 * SPI port, then returns.  freertos_spi_write_packet_async() does not wait for
 * the transmission to complete before returning.
 *
 * The FreeRTOS SPI driver is initialized using a call to
 * freertos_spi_master_init().  The freertos_driver_parameters.options_flags
 * parameter passed into the initialization function defines the driver behavior.
 * freertos_spi_write_packet_async() can only be used if the
 * freertos_driver_parameters.options_flags parameter passed to the initialization
 * function had the WAIT_TX_COMPLETE bit clear.
 *
 * freertos_spi_write_packet_async() is an advanced function and readers are
 * recommended to also reference the application note and examples that
 * accompany the FreeRTOS ASF drivers.  freertos_spi_write_packet() is a version
 * that does not exit until the PDC transfer is complete, but still allows other
 * RTOS tasks to execute while the transmission is in progress.
 *
 * The FreeRTOS ASF driver both installs and handles the SPI PDC interrupts.
 * Users do not need to concern themselves with interrupt handling, and must
 * not install their own interrupt handler.
 *
 * \param p_spi    The handle to the SPI peripheral returned by the
 *     freertos_spi_master_init() call used to initialise the peripheral.
 * \param data    A pointer to the data to be transmitted.
 * \param len    The number of bytes to transmit.
 * \param block_time_ticks    The FreeRTOS ASF SPI driver is initialized using a
 *     call to freertos_spi_master_init().  The
 *     freertos_driver_parameters.options_flags parameter passed to the
 *     initialization function defines the driver behavior.  If
 *     freertos_driver_parameters.options_flags had the USE_TX_ACCESS_MUTEX bit
 *     set, then the driver will only write to the SPI peripheral if it has
 *     first gained exclusive access to it.  block_time_ticks specifies the
 *     maximum amount of time the driver will wait to get exclusive access
 *     before aborting the write operation.  Other tasks will execute during any
 *     waiting time.  block_time_ticks is specified in RTOS tick periods.  To
 *     specify a block time in milliseconds, divide the milliseconds value by
 *     portTICK_RATE_MS, and pass the result in block_time_ticks.
 *     portTICK_RATE_MS is defined by FreeRTOS.
 * \param notification_semaphore    The RTOS task that calls the transmit
 *     function exits the transmit function as soon as the transmission starts.
 *     The data being transmitted by the PDC must not be modified until after
 *     the transmission has completed.  The PDC interrupt (handled internally by
 *     the FreeRTOS ASF driver) 'gives' the semaphore when the PDC transfer
 *     completes.  The notification_semaphore therefore provides a mechanism for
 *     the calling task to know when the PDC has finished accessing the data.
 *     The calling task can call standard FreeRTOS functions to block on the
 *     semaphore until the PDC interrupt occurs.  Other RTOS tasks will execute
 *     while the the calling task is in the Blocked state.  The semaphore must
 *     be created using the FreeRTOS vSemaphoreCreateBinary() API function
 *     before it is used as a parameter.
 *
 * \return     ERR_INVALID_ARG is returned if an input parameter is invalid.
 *     ERR_TIMEOUT is returned if block_time_ticks passed before exclusive
 *     access to the SPI peripheral could be obtained.  STATUS_OK is returned if
 *     the PDC was successfully configured to perform the SPI write operation.
 */
status_code_t freertos_spi_write_packet_async(freertos_spi_if p_spi,
		const uint8_t *data, size_t len, portTickType block_time_ticks,
		xSemaphoreHandle notification_semaphore)
{
	status_code_t return_value;
	portBASE_TYPE spi_index;
	Spi *spi_base;

	spi_base = (Spi *) p_spi;
	spi_index = get_pdc_peripheral_details(all_spi_definitions, MAX_SPIS,
			(void *) spi_base);

	/* Don't do anything unless a valid SPI pointer was used. */
	if (spi_index < MAX_SPIS) {
		return_value = freertos_obtain_peripheral_access_mutex(
				&(tx_dma_control[spi_index]), &block_time_ticks);

		if (return_value == STATUS_OK) {
			freertos_start_pdc_tx(&(tx_dma_control[spi_index]),
					data, len,
					all_spi_definitions[spi_index].pdc_base_address,
					notification_semaphore);

			/* Catch the end of transmission so the access mutex can be
			returned, and the task notified (if it supplied a notification
			semaphore).  The interrupt can be enabled here because the ENDTX
			signal from the PDC to the peripheral will have been de-asserted when
			the next transfer was configured. */
			spi_enable_interrupt(spi_base, SPI_IER_ENDTX);

			return_value = freertos_optionally_wait_transfer_completion(
					&(tx_dma_control[spi_index]),
					notification_semaphore,
					block_time_ticks);
		}
	} else {
		return_value = ERR_INVALID_ARG;
	}

	return return_value;
}
Exemple #14
0
/**
 * \brief Set SPI slave transfer.
 *
 * \param p_buf Pointer to buffer to transfer.
 * \param size Size of the buffer. 
 */
static void spi_slave_transfer(void *p_tbuf, uint32_t tsize, void *p_rbuf,
		uint32_t rsize)
{
	uint32_t spi_ier;
	pdc_packet_t pdc_spi_packet;

	pdc_spi_packet.ul_addr = (uint32_t)p_rbuf;
	pdc_spi_packet.ul_size = rsize;
	pdc_rx_init(g_p_spis_pdc, &pdc_spi_packet, NULL);

	pdc_spi_packet.ul_addr = (uint32_t)p_tbuf;
	pdc_spi_packet.ul_size = tsize;
	pdc_tx_init(g_p_spis_pdc, &pdc_spi_packet, NULL);
	
	/* Enable the RX and TX PDC transfer requests */
	pdc_enable_transfer(g_p_spis_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);

	/* Transfer done handler is in ISR */
	spi_ier = SPI_IER_NSSR | SPI_IER_RXBUFF;
	spi_enable_interrupt(SPI_SLAVE_BASE, spi_ier) ;
}
Exemple #15
0
OSStatus host_platform_spi_transfer( bus_transfer_direction_t dir, uint8_t* buffer, uint16_t buffer_length )
{
    OSStatus result;
    uint8_t *junk;

    MCU_CLOCKS_NEEDED();
#ifdef USE_OWN_SPI_DRV
	pdc_packet_t pdc_spi_packet;

	pdc_spi_packet.ul_addr = (uint32_t)buffer;
	pdc_spi_packet.ul_size = buffer_length;
	pdc_tx_init(spi_m_pdc, &pdc_spi_packet, NULL);

    if ( dir == BUS_READ ) {
	    pdc_spi_packet.ul_addr = (uint32_t)buffer;
	    pdc_spi_packet.ul_size = buffer_length;
    } 
	if ( dir == BUS_WRITE ) {
        junk = malloc(buffer_length);
	    pdc_spi_packet.ul_addr = (uint32_t)junk;
	    pdc_spi_packet.ul_size = buffer_length;
    }
	pdc_rx_init(spi_m_pdc, &pdc_spi_packet, NULL);
#if 0
	if ( dir == BUS_WRITE ) {
		spi_enable_interrupt(SPI_MASTER_BASE, SPI_IER_ENDTX);
	    NVIC_EnableIRQ(SPI_IRQn);
	}
	else {
		spi_enable_interrupt(SPI_MASTER_BASE, SPI_IER_ENDRX);
	    NVIC_EnableIRQ(SPI_IRQn);
	}
#endif	
    //platform_log("dir = %d, len = %d",dir, buffer_length);//TBD
#ifndef HARD_CS_NSS0	
	mico_gpio_output_low( MICO_GPIO_15 );
#endif
	/* Enable the RX and TX PDC transfer requests */
    pdc_enable_transfer(spi_m_pdc, PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN);//pdc buffer address increase automatic.
    //platform_log("pdc status = 0x%x",pdc_read_status(spi_m_pdc));

#ifndef NO_MICO_RTOS
    result = mico_rtos_get_semaphore( &spi_transfer_finished_semaphore, 100 );
#else
    /* Waiting transfer done*/
	while((spi_read_status(SPI_MASTER_BASE) & SPI_SR_RXBUFF) == 0) {
        __asm("wfi");
    }
#endif
	if ( dir == BUS_WRITE ) {
        if (junk) 
            free(junk);
    }
	/* Disable the RX and TX PDC transfer requests */
    pdc_disable_transfer(spi_m_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);

#ifndef HARD_CS_NSS0	
	mico_gpio_output_high( MICO_GPIO_15 );
#endif
#if 1
    //clear PDC Perph Status flags
	pdc_spi_packet.ul_addr = NULL;
	pdc_spi_packet.ul_size = 3;
	pdc_tx_init(spi_m_pdc, &pdc_spi_packet, NULL);
	pdc_rx_init(spi_m_pdc, &pdc_spi_packet, NULL);
#endif
#else //spi_master_vec :

    tx_dscr[0].data   = buffer;
    tx_dscr[0].length = buffer_length;
    tx_dscr[1].data   = NULL;
    tx_dscr[1].length = 0;
    
    //if ( dir == BUS_READ ) {
        rx_dscr[0].data   = buffer;
        rx_dscr[0].length = buffer_length;
    //} else {
    //    rx_dscr[0].data   = &junk;
    //    rx_dscr[0].length = 0;
    //}
    rx_dscr[1].data   = NULL;
    rx_dscr[1].length = 0;
#ifndef HARD_CS_NSS0	
    mico_gpio_output_low( MICO_GPIO_15 );
#endif 
    if (spi_master_vec_transceive_buffer_wait(&spi_master, tx_dscr, rx_dscr) != STATUS_OK) {
        platform_log("STATUS = -1");
        return kGeneralErr;
    }
#ifndef HARD_CS_NSS0	   
    mico_gpio_output_high( MICO_GPIO_15 );
#endif
#endif /* USE_OWN_SPI_DR */
    MCU_CLOCKS_NOT_NEEDED();
#ifdef USE_OWN_SPI_DRV
    return result;
#else
    return 0;
#endif
}
Exemple #16
0
OSStatus host_platform_bus_init( void )
{
#ifndef USE_OWN_SPI_DRV 
	struct spi_master_vec_config spi; 
#else
	pdc_packet_t pdc_spi_packet;
#endif
    OSStatus result;

    MCU_CLOCKS_NEEDED();

	spi_disable_interrupt(SPI_MASTER_BASE, 0xffffffff);
    //Disable_global_interrupt();//TBD!

    result = mico_rtos_init_semaphore( &spi_transfer_finished_semaphore, 1 );
    if ( result != kNoErr )
    {
        return result;
    }
    
    mico_gpio_initialize( (mico_gpio_t)MICO_GPIO_9, INPUT_PULL_UP );
    //ioport_port_mask_t ul_mask = ioport_pin_to_mask(CREATE_IOPORT_PIN(PORTA,24));
    //pio_set_input(PIOA,ul_mask, PIO_PULLUP|PIO_DEBOUNCE);
    mico_gpio_enable_IRQ( (mico_gpio_t)MICO_GPIO_9, IRQ_TRIGGER_RISING_EDGE, spi_irq_handler, NULL );
#ifndef HARD_CS_NSS0	
    mico_gpio_initialize( MICO_GPIO_15, OUTPUT_PUSH_PULL);//spi ss/cs 
	mico_gpio_output_high( MICO_GPIO_15 );//MICO_GPIO_15 TBD!
#else
	ioport_set_pin_peripheral_mode(SPI_NPCS0_GPIO, SPI_NPCS0_FLAGS);//TBD!
#endif
    /* set PORTB 01 to high to put WLAN module into g_SPI mode */
    mico_gpio_initialize( (mico_gpio_t)WL_GPIO0, OUTPUT_PUSH_PULL );
    mico_gpio_output_high( (mico_gpio_t)WL_GPIO0 );
#ifdef USE_OWN_SPI_DRV 
#if (SAMG55)
	/* Enable the peripheral and set SPI mode. */
	flexcom_enable(BOARD_FLEXCOM_SPI);
	flexcom_set_opmode(BOARD_FLEXCOM_SPI, FLEXCOM_SPI);
#else
	/* Configure an SPI peripheral. */
	pmc_enable_periph_clk(SPI_ID);
#endif
    //Init pdc, and clear RX TX.
    spi_m_pdc = spi_get_pdc_base(SPI_MASTER_BASE);

	pdc_spi_packet.ul_addr = NULL;
	pdc_spi_packet.ul_size = 3;
	pdc_tx_init(spi_m_pdc, &pdc_spi_packet, NULL);
	pdc_rx_init(spi_m_pdc, &pdc_spi_packet, NULL);

	spi_disable(SPI_MASTER_BASE);
	spi_reset(SPI_MASTER_BASE);
	spi_set_lastxfer(SPI_MASTER_BASE);
	spi_set_master_mode(SPI_MASTER_BASE);
	spi_disable_mode_fault_detect(SPI_MASTER_BASE);
#ifdef HARD_CS_NSS0
	//spi_enable_peripheral_select_decode(SPI_MASTER_BASE);
	//spi_set_peripheral_chip_select_value(SPI_MASTER_BASE, SPI_CHIP_SEL);
	spi_set_peripheral_chip_select_value(SPI_MASTER_BASE, SPI_CHIP_PCS); //use soft nss comment here
#endif
	spi_set_clock_polarity(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CLK_POLARITY);
	spi_set_clock_phase(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CLK_PHASE);
	spi_set_bits_per_transfer(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_CSR_BITS_8_BIT);
	spi_set_baudrate_div(SPI_MASTER_BASE, SPI_CHIP_SEL, (sysclk_get_cpu_hz() / SPI_BAUD_RATE));
	spi_set_transfer_delay(SPI_MASTER_BASE, SPI_CHIP_SEL, SPI_DLYBS, SPI_DLYBCT);

    /* Must be lower priority than the value of configMAX_SYSCALL_INTERRUPT_PRIORITY */
    /* otherwise FreeRTOS will not be able to mask the interrupt */
    /* keep in mind that ARMCM3 interrupt priority logic is inverted, the highest value */
    /* is the lowest priority */
	/* Configure SPI interrupts . */
    spi_enable_interrupt(SPI_MASTER_BASE, SPI_IER_RXBUFF);
    //spi_enable_interrupt(SPI_MASTER_BASE, SPI_IER_NSSR | SPI_IER_RXBUFF);
	
	NVIC_DisableIRQ(SPI_IRQn);
    //irq_register_handler(SPI_IRQn, 3);
	NVIC_ClearPendingIRQ(SPI_IRQn);
	NVIC_SetPriority(SPI_IRQn, 3);
	NVIC_EnableIRQ(SPI_IRQn);

    spi_enable(SPI_MASTER_BASE);
#else
    spi.baudrate = SPI_BAUD_RATE;
	if (STATUS_OK != spi_master_vec_init(&spi_master, SPI_MASTER_BASE, &spi)) {
		return -1;
	}

	spi_master_vec_enable(&spi_master);
#endif
    //if (!Is_global_interrupt_enabled())
    //    Enable_global_interrupt();
    MCU_CLOCKS_NOT_NEEDED();

    return kNoErr;
}
Exemple #17
0
/**
 * \ingroup freertos_spi_peripheral_control_group
 * \brief Initiate a completely asynchronous multi-byte read operation on an SPI
 * peripheral.
 *
 * freertos_spi_read_packet_async() is an ASF specific FreeRTOS driver function.
 * It configures the SPI peripheral DMA controller (PDC) to read data from the
 * SPI port, then returns.  freertos_spi_read_packet_async() does not wait for
 * the reception to complete before returning.
 *
 * The FreeRTOS ASF SPI driver is initialized using a call to
 * freertos_spi_master_init().  The freertos_driver_parameters.options_flags
 * parameter passed into the initialization function defines the driver behavior.
 * freertos_spi_read_packet_async() can only be used if the
 * freertos_driver_parameters.options_flags parameter passed to the initialization
 * function had the WAIT_RX_COMPLETE bit clear.
 *
 * freertos_spi_read_packet_async() is an advanced function and readers are
 * recommended to also reference the application note and examples that
 * accompany the FreeRTOS ASF drivers.  freertos_spi_read_packet() is a version
 * that does not exit until the PDC transfer is complete, but still allows other
 * RTOS tasks to execute while the transmission is in progress.
 *
 * The FreeRTOS ASF driver both installs and handles the SPI PDC interrupts.
 * Users do not need to concern themselves with interrupt handling, and must
 * not install their own interrupt handler.
 *
 * \param p_spi    The handle to the SPI port returned by the
 *     freertos_spi_master_init() call used to initialise the port.
 * \param data    A pointer to the buffer into which received data is to be
 *     written.
 * \param len    The number of bytes to receive.
 * \param block_time_ticks    The FreeRTOS ASF SPI driver is initialized using a
 *     call to freertos_spi_master_init().  The
 *     freertos_driver_parameters.options_flags parameter passed to the
 *     initialization function defines the driver behavior.  If
 *     freertos_driver_parameters.options_flags had the USE_RX_ACCESS_MUTEX bit
 *     set, then the driver will only read from the SPI peripheral if it has
 *     first gained exclusive access to it.  block_time_ticks specifies the
 *     maximum amount of time the driver will wait to get exclusive access
 *     before aborting the read operation.  Other tasks will execute during any
 *     waiting time.  block_time_ticks is specified in RTOS tick periods.  To
 *     specify a block time in milliseconds, divide the milliseconds value by
 *     portTICK_RATE_MS, and pass the result in block_time_ticks.
 *     portTICK_RATE_MS is defined by FreeRTOS.
 * \param notification_semaphore    The RTOS task that calls the receive
 *     function exits the receive function as soon as the reception starts.
 *     The data being received by the PDC cannot normally be processed until
 *     after the reception has completed.  The PDC interrupt (handled internally
 *     by the FreeRTOS ASF driver) 'gives' the semaphore when the PDC transfer
 *     completes.  The notification_semaphore therefore provides a mechanism for
 *     the calling task to know when the PDC has read the requested number of
 *     bytes.  The calling task can call standard FreeRTOS functions to block on
 *     the semaphore until the PDC interrupt occurs.  Other RTOS tasks will
 *     execute while the the calling task is in the Blocked state.  The
 *     semaphore must be created using the FreeRTOS vSemaphoreCreateBinary() API
 *     function before it is used as a parameter.
 *
 * \return     ERR_INVALID_ARG is returned if an input parameter is invalid.
 *     ERR_TIMEOUT is returned if block_time_ticks passed before exclusive
 *     access to the SPI peripheral could be obtained.  STATUS_OK is returned if
 *     the PDC was successfully configured to perform the SPI read operation.
 */
status_code_t freertos_spi_read_packet_async(freertos_spi_if p_spi,
		uint8_t *data, uint32_t len, portTickType block_time_ticks,
		xSemaphoreHandle notification_semaphore)
{
	status_code_t return_value;
	pdc_packet_t pdc_tx_packet;
	portBASE_TYPE spi_index;
	Spi *spi_base;
	volatile uint16_t junk_value;

	spi_base = (Spi *) p_spi;
	spi_index = get_pdc_peripheral_details(all_spi_definitions, MAX_SPIS,
			(void *) spi_base);

	/* Don't do anything unless a valid SPI pointer was used. */
	if (spi_index < MAX_SPIS) {
		/* Because the peripheral is half duplex, there is only one access mutex
		and the rx uses the tx mutex. */
		return_value = freertos_obtain_peripheral_access_mutex(
				&(tx_dma_control[spi_index]), &block_time_ticks);

		if (return_value == STATUS_OK) {
			/* Data must be sent for data to be received.  Set the receive
			buffer to all 0xffs so it can also be used as the send buffer. */
			memset((void *)data, 0xff, (size_t)len);

			/* Ensure Rx is already empty. */
			while(spi_is_rx_full(all_spi_definitions[spi_index].peripheral_base_address) != 0) {
				junk_value = ((Spi*) all_spi_definitions[spi_index].peripheral_base_address)->SPI_RDR;
				(void) junk_value;
			}

			/* Start the PDC reception, although nothing is received until the
			SPI is also transmitting. */
			freertos_start_pdc_rx(&(rx_dma_control[spi_index]),
					data, len,
					all_spi_definitions[spi_index].pdc_base_address,
					notification_semaphore);

			/* Start the transmit so data is also received. */
			pdc_tx_packet.ul_addr = (uint32_t)data;
			pdc_tx_packet.ul_size = (uint32_t)len;
			pdc_disable_transfer(
					all_spi_definitions[spi_index].pdc_base_address,
					PERIPH_PTCR_TXTDIS);
			pdc_tx_init(
					all_spi_definitions[spi_index].pdc_base_address, &pdc_tx_packet,
					NULL);
			pdc_enable_transfer(
					all_spi_definitions[spi_index].pdc_base_address,
					PERIPH_PTCR_TXTEN);

			/* Catch the end of reception so the access mutex can be returned,
			and the task notified (if it supplied a notification semaphore).
			The interrupt can be enabled here because the ENDRX	signal from the
			PDC to the peripheral will have been de-asserted when the next
			transfer was configured. */
			spi_enable_interrupt(spi_base, SPI_IER_ENDRX);

			return_value = freertos_optionally_wait_transfer_completion(
					&(rx_dma_control[spi_index]),
					notification_semaphore,
					block_time_ticks);
		}
	} else {
		return_value = ERR_INVALID_ARG;
	}

	return return_value;
}
Exemple #18
0
/**
 * \ingroup freertos_spi_peripheral_control_group
 * \brief Initializes the FreeRTOS ASF SPI master driver for the specified SPI port.
 *
 * freertos_spi_master_init() is an ASF specific FreeRTOS driver function.  It
 * must be called before any other ASF specific FreeRTOS driver functions
 * attempt to access the same SPI port.
 *
 * If freertos_driver_parameters->operation_mode equals SPI_MASTER then
 * freertos_spi_master_init() will configure the SPI port for master mode
 * operation and enable the peripheral.  If
 * freertos_driver_parameters->operation_mode equals any other value then
 * freertos_spi_master_init() will not take any action.
 *
 * Other ASF SPI functions, such as those to set the SPI clock rate and other
 * bus parameters, can be called after freertos_spi_master_init() has completed
 * successfully.
 *
 * The FreeRTOS ASF driver both installs and handles the SPI PDC interrupts.
 * Users do not need to concern themselves with interrupt handling, and must
 * not install their own interrupt handler.
 *
 * This driver is provided with an application note, and an example project that
 * demonstrates the use of this function.
 *
 * \param p_spi    The SPI peripheral being initialized.
 * \param freertos_driver_parameters    Defines the driver behavior.  See the
 *    freertos_peripheral_options_t documentation, and the application note that
 *    accompanies the ASF specific FreeRTOS functions.
 *
 * \return If the initialization completes successfully then a handle that can
 *     be used with FreeRTOS SPI read and write functions is returned.  If
 *     the initialisation fails then NULL is returned.
 */
freertos_spi_if freertos_spi_master_init(Spi *p_spi,
		const freertos_peripheral_options_t *const freertos_driver_parameters)
{
	portBASE_TYPE spi_index;
	bool is_valid_operating_mode;
	freertos_spi_if return_value;
	const enum peripheral_operation_mode valid_operating_modes[] = {SPI_MASTER};

	/* Find the index into the all_spi_definitions array that holds details of
	the p_spi peripheral. */
	spi_index = get_pdc_peripheral_details(all_spi_definitions, MAX_SPIS,
			(void *) p_spi);

	/* Check the requested operating mode is valid for the peripheral. */
	is_valid_operating_mode = check_requested_operating_mode(
			freertos_driver_parameters->operation_mode,
			valid_operating_modes,
			sizeof(valid_operating_modes) /
			sizeof(enum peripheral_operation_mode));

	/* Don't do anything unless a valid p_spi pointer was used, and a valid
	operating mode was requested. */
	if ((spi_index < MAX_SPIS) && (is_valid_operating_mode == true)) {
		/* This function must be called exactly once per supported spi.  Check it
		has not been called	before. */
		configASSERT(memcmp((void *) &(tx_dma_control[spi_index]),
				&null_dma_control,
				sizeof(null_dma_control)) == 0);
		configASSERT(memcmp((void *) &(rx_dma_control[spi_index]),
				&null_dma_control,
				sizeof(null_dma_control)) == 0);

		/* Ensure everything is disabled before configuration. */
		spi_disable(all_spi_definitions[spi_index].peripheral_base_address);
		pdc_disable_transfer(
				all_spi_definitions[spi_index].pdc_base_address,
				(PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS));
		spi_disable_interrupt(
				all_spi_definitions[spi_index].peripheral_base_address,
				MASK_ALL_INTERRUPTS);

		switch (freertos_driver_parameters->operation_mode) {
		case SPI_MASTER:
			/* Call the standard ASF init function. */
			spi_master_init(
					all_spi_definitions[spi_index].peripheral_base_address);
			break;

		default:
			/* No other modes are currently supported. */
			break;
		}

		/* Create any required peripheral access mutexes and transaction complete
		semaphores.  This peripheral is half duplex so only a single access
		mutex is required. */
		create_peripheral_control_semaphores(
				freertos_driver_parameters->options_flags,
				&(tx_dma_control[spi_index]),
				&(rx_dma_control[spi_index]));

		/* Configure and enable the SPI interrupt in the interrupt controller. */
		configure_interrupt_controller(
				all_spi_definitions[spi_index].peripheral_irq,
				freertos_driver_parameters->interrupt_priority);

		/* Error interrupts are always enabled. */
		spi_enable_interrupt(
				all_spi_definitions[spi_index].peripheral_base_address,
				IER_ERROR_INTERRUPTS);

		/* Finally, enable the peripheral. */
		spi_enable(all_spi_definitions[spi_index].peripheral_base_address);

		return_value = (freertos_spi_if)p_spi;
	} else {
		return_value = NULL;
	}

	return return_value;
}
Exemple #19
0
/**
 * \brief Test SPI transfer.
 *
 * This test tests SPI read/write.
 *
 * \param test Current test case.
 */
static void run_spi_trans_test(const struct test_case *test)
{
	spi_status_t rc;
	uint16_t     spi_data;
	uint8_t      spi_pcs;

	spi_reset(CONF_TEST_SPI);
	spi_set_lastxfer(CONF_TEST_SPI);
	spi_set_master_mode(CONF_TEST_SPI);
	spi_disable_mode_fault_detect(CONF_TEST_SPI);
	spi_set_peripheral_chip_select_value(CONF_TEST_SPI, CONF_TEST_SPI_NPCS);
	spi_set_clock_polarity(CONF_TEST_SPI,
		CONF_TEST_SPI_NPCS, SPI_CLK_POLARITY);
	spi_set_clock_phase(CONF_TEST_SPI, CONF_TEST_SPI_NPCS, SPI_CLK_PHASE);
	spi_set_bits_per_transfer(CONF_TEST_SPI,
		CONF_TEST_SPI_NPCS, SPI_CSR_BITS_8_BIT);
	spi_set_baudrate_div(CONF_TEST_SPI,
		CONF_TEST_SPI_NPCS,
		(sysclk_get_cpu_hz() / TEST_CLOCK));
	spi_set_transfer_delay(CONF_TEST_SPI,
		CONF_TEST_SPI_NPCS, SPI_DLYBS, SPI_DLYBCT);
	spi_set_variable_peripheral_select(CONF_TEST_SPI);
	spi_enable_loopback(CONF_TEST_SPI);

	/* Test read/write timeout: should return SPI_ERROR_TIMEOUT. */
	rc = spi_write(CONF_TEST_SPI, TEST_PATTERN, TEST_PCS, 1);
	test_assert_true(test, rc == SPI_ERROR_TIMEOUT,
		"Test SPI Write timeout: return code should not be %d", rc);

	rc = spi_read(CONF_TEST_SPI, &spi_data, &spi_pcs);
	test_assert_true(test, rc == SPI_ERROR_TIMEOUT,
		"Test SPI Read timeout: return code should not be %d", rc);

	spi_enable(CONF_TEST_SPI);
	spi_enable_interrupt(CONF_TEST_SPI, SPI_IER_TDRE|SPI_IER_RDRF);
	NVIC_EnableIRQ((IRQn_Type)CONF_TEST_SPI_ID);

	/* Test write: should return OK. */
	rc = spi_write(CONF_TEST_SPI, TEST_PATTERN, TEST_PCS, 1);
	test_assert_true(test, rc == SPI_OK,
		"Test SPI Write: return code should not be %d", rc);

	/* Test read: should return OK with what is sent. */
	rc = spi_read(CONF_TEST_SPI, &spi_data, &spi_pcs);
	test_assert_true(test, rc == SPI_OK,
		"Test SPI Read: return code should not be %d", rc);
	test_assert_true(test, spi_data == TEST_PATTERN,
		"Unexpected SPI data: %x, should be %x",
		spi_data, TEST_PATTERN);
	test_assert_true(test, spi_pcs == TEST_PCS,
		"Unexpected SPI PCS: %x, should be %x",
		spi_pcs, TEST_PCS);

	/* Check interrupts. */
	test_assert_true(test, g_b_spi_interrupt_tx_ready,
		"Test SPI TX interrupt not detected");
	test_assert_true(test, g_b_spi_interrupt_rx_ready,
		"Test SPI RX interrupt not detected");

	/* Done, disable SPI and all interrupts. */
	spi_disable_loopback(CONF_TEST_SPI);
	spi_disable(CONF_TEST_SPI);
	spi_disable_interrupt(CONF_TEST_SPI, 0xFFFFFFFF);
	NVIC_DisableIRQ((IRQn_Type)CONF_TEST_SPI_ID);
}
Exemple #20
0
/*
 * Configure the SPI hardware, including SPI clock speed, mode, delays, chip select pins
 * It uses values listed in
 */
void AJ_WSL_SPI_InitializeSPIController(void)
{
    uint32_t config;

    /* Initialize and enable DMA controller. */
    pmc_enable_periph_clk(ID_DMAC);
    dmac_init(DMAC);
    dmac_set_priority_mode(DMAC, DMAC_PRIORITY_ROUND_ROBIN);
    dmac_enable(DMAC);

    /* Configure DMA TX channel. */
    config = 0;
    config |= DMAC_CFG_DST_PER(AJ_SPI_TX_INDEX) |
              DMAC_CFG_DST_H2SEL |
              DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG;
    dmac_channel_set_configuration(DMAC, AJ_DMA_TX_CHANNEL, config);

    /* Configure DMA RX channel. */
    config = 0;
    config |= DMAC_CFG_SRC_PER(AJ_SPI_RX_INDEX) |
              DMAC_CFG_SRC_H2SEL |
              DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG;
    dmac_channel_set_configuration(DMAC, AJ_DMA_RX_CHANNEL, config);

    /* Enable receive channel interrupt for DMAC. */
    uint8_t* interruptEnableAddress = AJ_SPI_ISER1_IEN_ADDR;
    *interruptEnableAddress = AJ_SPI_DMAC_IEN_BIT;

    dmac_enable_interrupt(DMAC, (1 << AJ_DMA_RX_CHANNEL));
    dmac_enable_interrupt(DMAC, (1 << AJ_DMA_TX_CHANNEL));
    //AJ_WSL_DMA_Setup();
    dmac_channel_disable(DMAC, AJ_DMA_TX_CHANNEL);
    dmac_channel_disable(DMAC, AJ_DMA_RX_CHANNEL);

    /*
     * Configure the hardware to enable SPI and some output pins
     */
    {
        pmc_enable_periph_clk(ID_PIOA);
        pmc_enable_periph_clk(ID_PIOB);
        pmc_enable_periph_clk(ID_PIOC);
        pmc_enable_periph_clk(ID_PIOD);


        // make all of these pins controlled by the right I/O controller
        pio_configure_pin_group(PIOA, 0xFFFFFFFF, PIO_TYPE_PIO_PERIPH_A);
        pio_configure_pin_group(PIOB, 0xFFFFFFFF, PIO_TYPE_PIO_PERIPH_B);
        pio_configure_pin_group(PIOC, 0xFFFFFFFF, PIO_TYPE_PIO_PERIPH_C);
        pio_configure_pin_group(PIOD, 0xFFFFFFFF, PIO_TYPE_PIO_PERIPH_D);


        /*
         * Reset the device by toggling the CHIP_POWER
         */
        ioport_set_pin_dir(AJ_WSL_SPI_CHIP_POWER_PIN, IOPORT_DIR_OUTPUT);
        ioport_set_pin_level(AJ_WSL_SPI_CHIP_POWER_PIN, IOPORT_PIN_LEVEL_LOW);
        AJ_Sleep(10);
        ioport_set_pin_level(AJ_WSL_SPI_CHIP_POWER_PIN, IOPORT_PIN_LEVEL_HIGH);


        /*
         * Reset the device by toggling the CHIP_PWD# signal
         */
        ioport_set_pin_dir(AJ_WSL_SPI_CHIP_PWD_PIN, IOPORT_DIR_OUTPUT);
        ioport_set_pin_level(AJ_WSL_SPI_CHIP_PWD_PIN, IOPORT_PIN_LEVEL_LOW);
        AJ_Sleep(10);
        ioport_set_pin_level(AJ_WSL_SPI_CHIP_PWD_PIN, IOPORT_PIN_LEVEL_HIGH);

        /* configure the pin that detects SPI data ready from the target chip */
        ioport_set_pin_dir(AJ_WSL_SPI_CHIP_SPI_INT_PIN, IOPORT_DIR_INPUT);
        ioport_set_pin_sense_mode(AJ_WSL_SPI_CHIP_SPI_INT_PIN, IOPORT_SENSE_LEVEL_LOW);

        pio_handler_set(PIOC, ID_PIOC, AJ_WSL_SPI_CHIP_SPI_INT_BIT, (PIO_PULLUP | PIO_IT_FALL_EDGE), &AJ_WSL_SPI_CHIP_SPI_ISR);
        pio_handler_set_priority(PIOD, (IRQn_Type) ID_PIOC, 0xB);
        pio_enable_interrupt(PIOC, AJ_WSL_SPI_CHIP_SPI_INT_BIT);
    }

    spi_enable_clock(AJ_WSL_SPI_DEVICE);
    spi_reset(AJ_WSL_SPI_DEVICE);
    spi_set_lastxfer(AJ_WSL_SPI_DEVICE);
    spi_set_master_mode(AJ_WSL_SPI_DEVICE);
    spi_disable_mode_fault_detect(AJ_WSL_SPI_DEVICE);
    spi_set_peripheral_chip_select_value(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS);
    spi_set_clock_polarity(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, AJ_WSL_SPI_CLOCK_POLARITY);
    spi_set_clock_phase(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, AJ_WSL_SPI_CLOCK_PHASE);
    spi_set_bits_per_transfer(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, SPI_CSR_BITS_8_BIT);
    spi_set_baudrate_div(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, (sysclk_get_cpu_hz() / AJ_WSL_SPI_CLOCK_RATE));
    spi_set_transfer_delay(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, AJ_WSL_SPI_DELAY_BEFORE_CLOCK, AJ_WSL_SPI_DELAY_BETWEEN_TRANSFERS);
    spi_set_fixed_peripheral_select(AJ_WSL_SPI_DEVICE);
    spi_configure_cs_behavior(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, SPI_CS_RISE_FORCED);

    spi_enable_interrupt(AJ_WSL_SPI_DEVICE, SPI_IER_TDRE | SPI_IER_RDRF);
    spi_enable(AJ_WSL_SPI_DEVICE);
}