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
/************************************
 * TRANSFER FUNCTIONS				*
 ***********************************/
int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    MBED_ASSERT(tx != (void*)0);
    if(tx_length == 0) return 0;
    Pdc *pdc_base;
    IRQn_Type irq_n = (IRQn_Type)0;
    pdc_packet_t packet;

    pSERIAL_S(obj)->acttra = true; /* flag for active transmit transfer */

    irq_n = get_serial_irq_num(obj);

    /* Get board USART PDC base address and enable transmitter. */
    pdc_base = usart_get_pdc_base(_USART(obj));
    pdc_enable_transfer(pdc_base, PERIPH_PTCR_TXTEN);

    packet.ul_addr = (uint32_t)tx;
    packet.ul_size = (uint32_t)tx_length;

    pdc_tx_init(pdc_base, &packet, NULL);
    usart_enable_interrupt(_USART(obj), US_IER_TXBUFE);

    NVIC_ClearPendingIRQ(irq_n);
    NVIC_DisableIRQ(irq_n);
    NVIC_SetVector(irq_n, (uint32_t)handler);
    NVIC_EnableIRQ(irq_n);

    return 0;
}
Exemple #3
0
void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    MBED_ASSERT(rx != (void*)0);
    if(rx_length == 0) return 0;
    Pdc *pdc_base;
    IRQn_Type irq_n = (IRQn_Type)0;
    pdc_packet_t packet;

    pSERIAL_S(obj)->actrec = true; /* flag for active receive transfer */
    if (event == SERIAL_EVENT_RX_CHARACTER_MATCH) { /* if event is character match alone */
        pSERIAL_S(obj)->events = SERIAL_EVENT_RX_CHARACTER_MATCH;
    }

    irq_n = get_serial_irq_num(obj);

    serial_set_char_match(obj, char_match);

    /* Get board USART PDC base address and enable transmitter. */
    pdc_base = usart_get_pdc_base(_USART(obj));
    pdc_enable_transfer(pdc_base, PERIPH_PTCR_RXTEN);
    packet.ul_addr = (uint32_t)rx;
    packet.ul_size = (uint32_t)rx_length;
    pdc_rx_init(pdc_base, &packet, NULL);

    usart_enable_interrupt(_USART(obj), (US_IER_RXBUFF | US_IER_OVRE | US_IER_FRAME | US_IER_PARE));

    NVIC_ClearPendingIRQ(irq_n);
    NVIC_DisableIRQ(irq_n);
    NVIC_SetVector(irq_n, (uint32_t)handler);
    NVIC_EnableIRQ(irq_n);

}
platform_result_t platform_uart_transmit_bytes( platform_uart_driver_t* driver, const uint8_t* data_out, uint32_t size )
{
    UNUSED_PARAMETER(driver);
    UNUSED_PARAMETER(data_out);
    UNUSED_PARAMETER(size);
    pdc_packet_t dma_packet;

    /* Limitation: SAM4S doesn't support DMA transfer from embedded flash.
     * If data_out address is not within RAM range, use normal write to THR.
     */
    if ( data_out >= (const uint8_t*)RAM_START_ADDR && data_out < (const uint8_t*)RAM_END_ADDR )
    {
        /* Initialise TPR and TCR register values. TNPR and TNCR are unused */
        dma_packet.ul_addr = (uint32_t)data_out;
        dma_packet.ul_size = (uint32_t)size;
        pdc_tx_init( usart_get_pdc_base( driver->peripheral->peripheral ), &dma_packet, NULL );

        /* Enable Tx DMA transmission */
        pdc_enable_transfer( usart_get_pdc_base( driver->peripheral->peripheral ), PERIPH_PTCR_TXTEN );

        host_rtos_get_semaphore( &driver->tx_dma_complete, NEVER_TIMEOUT, WICED_FALSE );
    }
    else
    {
        while ( size > 0 )
        {
            usart_putchar( driver->peripheral->peripheral, (uint32_t)*data_out++ );
            size--;
        }
    }

    return PLATFORM_SUCCESS;
}
Exemple #5
0
platform_result_t sam4s_spi_transfer_internal( const platform_spi_t* spi, const uint8_t* data_out, uint8_t* data_in, uint32_t data_length )
{
    Pdc*         spi_pdc  = spi_get_pdc_base( spi->peripheral );
    pdc_packet_t pdc_spi_packet;

    pdc_spi_packet.ul_addr = (uint32_t)data_in;
    pdc_spi_packet.ul_size = (uint32_t)data_length;
    pdc_rx_init( spi_pdc, &pdc_spi_packet, NULL );

    pdc_spi_packet.ul_addr = (uint32_t)data_out;
    pdc_spi_packet.ul_size = (uint32_t)data_length;
    pdc_tx_init( spi_pdc, &pdc_spi_packet, NULL );

    /* Enable the RX and TX PDC transfer requests */
    pdc_enable_transfer( spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN );

    /* Waiting transfer done*/
    while ( ( spi_read_status( spi->peripheral ) & SPI_SR_RXBUFF ) == 0 )
    {
    }

    /* Disable the RX and TX PDC transfer requests */
    pdc_disable_transfer(spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);

    return PLATFORM_SUCCESS;
}
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
/**
 * \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 #8
0
/**
 * \brief Application entry point for pdc_uart example.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	/* Initialize the SAM system */
	sysclk_init();
	board_init();    

	/* Initialize the UART console */
	configure_console();

	/* Output example information */
	puts(STRING_HEADER);

	/* Get pointer to UART PDC register base */
	g_p_uart_pdc = uart_get_pdc_base(CONSOLE_UART);

	/* Initialize PDC data packet for transfer */
	g_pdc_uart_packet.ul_addr = (uint32_t) g_uc_pdc_buffer;
	g_pdc_uart_packet.ul_size = BUFFER_SIZE;

	/* Configure PDC for data receive */
	pdc_rx_init(g_p_uart_pdc, &g_pdc_uart_packet, NULL);

	/* Enable PDC transfers */
	pdc_enable_transfer(g_p_uart_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);

	/* Enable UART IRQ */
	uart_enable_interrupt(CONSOLE_UART, UART_IER_RXBUFF);

	/* Enable UART interrupt */
	NVIC_EnableIRQ(CONSOLE_UART_IRQn);

	while (1) {
	}
}
Exemple #9
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);
}
Exemple #10
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 #11
0
void SVPWM(float DCM1_X, float DCM1_Y, float DCM1_Z) {
	/* Fill duty cycle buffer for channel #0 - #2, duty cycle is calculated by fraction of period value */
	g_us_duty_buffer[0] = DCM1_X * (PERIOD_VALUE);
	g_us_duty_buffer[1] = DCM1_Y * (PERIOD_VALUE);
	g_us_duty_buffer[2] = DCM1_Z * (PERIOD_VALUE);
		
	/* Configure the PDC transfer packet and enable PDC transfer */
	g_pdc_tx_packet.ul_addr = (uint32_t) (&(g_us_duty_buffer[0]));
	g_pdc_tx_packet.ul_size = DUTY_BUFFER_LENGTH;
	pdc_tx_init(PDC_PWM, &g_pdc_tx_packet, 0);
	pdc_enable_transfer(PDC_PWM, PERIPH_PTCR_TXTEN);		
}
/*
 * For internal use only.
 * If is_transmitting is false then configure the PDC to receive len bytes into
 * data.  If is_transmitting is true then configure the PDC to write len bytes
 * from data.
 * If notification_semaphore is not NULL, then the user is passing in their
 * own notification semaphore, and the semaphore is associated with the PDC
 * structure so it can be 'given' when the PDC transfer completes.  If
 * notification_semaphore is NULL then the driver will have its own internal
 * notification semaphore that it will use to only exit the send or receive
 * function when the PDC transfer has completed.
 */
void freertos_start_pdc_transfer(
		freertos_dma_event_control_t *dma_event_control,
		const uint8_t *data, size_t len, void *pdc_base_address,
		SemaphoreHandle_t notification_semaphore, bool is_transmitting)
{
	pdc_packet_t pdc_packet;

	/* Remember which semaphore is to be used to indicate the end of
	transmission.  If notification_semaphore is NULL then either no
	semaphore is being used, or the driver is using an internal notification
	semaphore because it is configured to wait until the transmit has
	completed before returning. */
	if (notification_semaphore != NULL) {
		dma_event_control->transaction_complete_notification_semaphore =
				notification_semaphore;
	}

	/* Ensure the notification semaphore starts in the expected state in case
	the previous PDC transfer didn't complete for any reason. */
	if (dma_event_control->transaction_complete_notification_semaphore !=
			NULL) {
		xSemaphoreTake(
				dma_event_control->transaction_complete_notification_semaphore,
				0);
	}

	/* Configure the PDC to transmit or receive parameters. */
	pdc_packet.ul_addr = (uint32_t) data;
	pdc_packet.ul_size = (uint32_t) len;

	if (is_transmitting == true) {
		pdc_disable_transfer(pdc_base_address, PERIPH_PTCR_TXTDIS);
		pdc_tx_init(pdc_base_address, &pdc_packet, NULL);
		pdc_enable_transfer(pdc_base_address, PERIPH_PTCR_TXTEN);
	} else {
		pdc_disable_transfer(pdc_base_address, PERIPH_PTCR_RXTDIS);
		pdc_rx_init(pdc_base_address, &pdc_packet, NULL);
		pdc_enable_transfer(pdc_base_address, PERIPH_PTCR_RXTEN);
	}
}
Exemple #13
0
/**
 *  \brief usart_hard_handshaking_example application entry point.
 *
 *  \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	uint8_t uc_char;
	uint8_t uc_flag;

	/* Initialize the system. */
	sysclk_init();
	board_init();

	/* Configure UART for debug message output. */
	configure_console();

	/* Output example information. */
	puts(STRING_HEADER);

	/* Initialize board USART. */
	configure_usart();

	/* Initialize TC0. */
	configure_tc();

	/* Get board USART PDC base address and enable receiver. */
	g_p_pdc = usart_get_pdc_base(BOARD_USART);
	g_st_packet.ul_addr = (uint32_t)gs_puc_buffer;
	g_st_packet.ul_size = BUFFER_SIZE;
	g_st_nextpacket.ul_addr = (uint32_t)gs_puc_nextbuffer;
	g_st_nextpacket.ul_size = BUFFER_SIZE;
	pdc_rx_init(g_p_pdc, &g_st_packet, &g_st_nextpacket);
	pdc_enable_transfer(g_p_pdc, PERIPH_PTCR_RXTEN);

	usart_enable_interrupt(BOARD_USART, US_IER_RXBUFF);

	/* Start the Timer counter. */
	tc_start(TC0, 0);

	while (1) {
		uc_char = 0;
		uc_flag = uart_read(CONSOLE_UART, &uc_char);
		if (!uc_flag) {
			switch (uc_char) {
			case 'd':
			case 'D':
				usart_write_line(BOARD_USART, (char *)gs_dump_buffer);
				break;
			default:
				break;
			}
		}
	}
}
Exemple #14
0
/**
 * \brief Interrupt handler for the PWM controller.
 */
void PWM_Handler(void)
{
	uint32_t pdc_status = pwm_get_interrupt_status(PWM);

	if ((pdc_status & PWM_PDC_TX_END) == PWM_PDC_TX_END) {
		/* Set up the PDC controller */
		g_pdc_tx_packet.ul_addr = (uint32_t) (&g_us_duty_buffer[0]);
		g_pdc_tx_packet.ul_size = DUTY_BUFFER_LENGTH;

		/* Initialize the PDC transfer */
		pdc_tx_init(PDC_PWM, &g_pdc_tx_packet, 0);

		/* Send the PWM value */
		pdc_enable_transfer(PDC_PWM, PERIPH_PTCR_TXTEN);
	}
}
Exemple #15
0
/**
 * \brief Read a register value.
 *
 * \param reg the register address to modify.
 *
 * \return the register value.
 */
uint16_t ksz8851_reg_read(uint16_t reg)
{
    pdc_packet_t g_pdc_spi_tx_packet;
    pdc_packet_t g_pdc_spi_rx_packet;
    uint16_t cmd = 0;
    uint16_t res = 0;

    gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);

    /* Move register address to cmd bits 9-2, make 32-bit address. */
    cmd = (reg << 2) & REG_ADDR_MASK;

    /* Last 2 bits still under "don't care bits" handled with byte enable. */
    /* Select byte enable for command. */
    if (reg & 2) {
        /* Odd word address writes bytes 2 and 3 */
        cmd |= (0xc << 10);
    } else {
        /* Even word address write bytes 0 and 1 */
        cmd |= (0x3 << 10);
    }

    /* Add command read code. */
    cmd |= CMD_READ;
    tmpbuf[0] = cmd >> 8;
    tmpbuf[1] = cmd & 0xff;
    tmpbuf[2] = CONFIG_SPI_MASTER_DUMMY;
    tmpbuf[3] = CONFIG_SPI_MASTER_DUMMY;

    /* Prepare PDC transfer. */
    g_pdc_spi_tx_packet.ul_addr = (uint32_t) tmpbuf;
    g_pdc_spi_tx_packet.ul_size = 4;
    g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
    g_pdc_spi_rx_packet.ul_size = 4;
    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, 0);
    pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, 0);
    pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
    while (!(spi_read_status(KSZ8851SNL_SPI) & SPI_SR_ENDRX))
        ;

    gpio_set_pin_high(KSZ8851SNL_CSN_GPIO);

    res = (tmpbuf[3] << 8) | tmpbuf[2];
    return res;
}
Exemple #16
0
/**
 * \brief Write dummy data to the internal fifo buffer.
 *
 * \param len the amount of dummy data to write.
 */
void ksz8851_fifo_dummy(uint32_t len)
{
    pdc_packet_t g_pdc_spi_tx_packet;
    pdc_packet_t g_pdc_spi_rx_packet;

    /* Prepare PDC transfer. */
    g_pdc_spi_tx_packet.ul_addr = (uint32_t) tmpbuf;
    g_pdc_spi_tx_packet.ul_size = len;
    g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
    g_pdc_spi_rx_packet.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, 0);
    pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, 0);
    pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);

    while (!(spi_read_status(KSZ8851SNL_SPI) & SPI_SR_ENDRX))
        ;
}
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 #18
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 #19
0
OSStatus platform_uart_transmit_bytes( platform_uart_driver_t* driver, const uint8_t* data_out, uint32_t size )
{
    OSStatus      err = kNoErr;
    pdc_packet_t  pdc_uart_packet;

    platform_mcu_powersave_disable();

#ifndef NO_MICO_RTOS
    mico_rtos_lock_mutex( &driver->tx_mutex );
#endif

    require_action_quiet( ( driver != NULL ) && ( data_out != NULL ) && ( size != 0 ), exit, err = kParamErr);

    /* reset DMA transmission result. the result is assigned in interrupt handler */
    driver->last_transmit_result                    = kGeneralErr;
    driver->tx_size                                 = size;

    pdc_uart_packet.ul_addr = (uint32_t) data_out;
    pdc_uart_packet.ul_size = size;
    pdc_tx_init( usart_get_pdc_base( driver->peripheral->port ), &pdc_uart_packet, NULL);

    /* Enable Tx DMA transmission */
    pdc_enable_transfer( usart_get_pdc_base( driver->peripheral->port ), PERIPH_PTCR_TXTEN );

#ifndef NO_MICO_RTOS
    mico_rtos_get_semaphore( &driver->tx_complete, MICO_NEVER_TIMEOUT );
#else
    while( driver->tx_complete == false);
    driver->tx_complete = false;
#endif

exit:
#ifndef NO_MICO_RTOS
    mico_rtos_unlock_mutex( &driver->tx_mutex );
#endif
    platform_mcu_powersave_enable();
    return err;
}
Exemple #20
0
/**
 * \brief Perform SPI master transfer.
 *
 * \param pbuf Pointer to buffer to transfer.
 * \param size Size of the buffer. 
 */
static void spi_master_transfer(void *p_tbuf, uint32_t tsize, void *p_rbuf,
		uint32_t rsize)
{
	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_spim_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_spim_pdc, &pdc_spi_packet, NULL);
	
	/* Enable the RX and TX PDC transfer requests */
	pdc_enable_transfer(g_p_spim_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);

	/* Waiting transfer done*/
	while((spi_read_status(SPI_MASTER_BASE) & SPI_SR_RXBUFF) == 0);
	
	/* Disable the RX and TX PDC transfer requests */
	pdc_disable_transfer(g_p_spim_pdc, PERIPH_PTCR_RXTDIS |
			PERIPH_PTCR_TXTDIS);
}
/*
 * For internal use only.
 * Configures the Rx DMA to receive data into free space within the Rx buffer.
 */
static void configure_rx_dma(uint32_t uart_index,
		enum buffer_operations operation_performed)
{
	freertos_pdc_rx_control_t *rx_buffer_definition;

	rx_buffer_definition = &(rx_buffer_definitions[uart_index]);

	/* How much space is there between the start of the DMA buffer and the
	current read pointer?  */

	if (((uint32_t)rx_buffer_definition->next_byte_to_read) ==
			rx_buffer_definition->rx_pdc_parameters.ul_addr) {
		/* The read pointer and the write pointer are equal.  If this function
		was called because data was added to the buffer, then there is no free
		space in the buffer remaining.  If this function was called because data
		was removed from the buffer, then the space remaining is from the write
		pointer up to the end of the buffer. */
		if (operation_performed == data_added) {
			rx_buffer_definition->rx_pdc_parameters.ul_size = 0UL;
		} else {
			rx_buffer_definition->rx_pdc_parameters.ul_size =
				rx_buffer_definition->past_rx_buffer_end_address - rx_buffer_definition->rx_pdc_parameters.ul_addr;
		}
	} else if (((uint32_t)rx_buffer_definition->next_byte_to_read) >
			rx_buffer_definition->rx_pdc_parameters.ul_addr) {
		/* The read pointer is ahead of the write pointer.  The space available
		is up to the write pointer to ensure unread data is not overwritten. */
		rx_buffer_definition->rx_pdc_parameters.ul_size =
			((uint32_t) rx_buffer_definition->next_byte_to_read) - rx_buffer_definition->rx_pdc_parameters.ul_addr;
	} else {
		/* The write pointer is ahead of the read pointer so the space
		available is up to the end of the buffer. */
		rx_buffer_definition->rx_pdc_parameters.ul_size =
			rx_buffer_definition->past_rx_buffer_end_address - rx_buffer_definition->rx_pdc_parameters.ul_addr;
	}

	configASSERT((rx_buffer_definition->rx_pdc_parameters.ul_addr+
			rx_buffer_definition->rx_pdc_parameters.ul_size) <=
			rx_buffer_definition->past_rx_buffer_end_address);

	if (rx_buffer_definition->rx_pdc_parameters.ul_size > 0) {
		/* Restart the DMA to receive into whichever space was calculated
		as remaining.  First clear any characters that might already be in the
		registers. */
		pdc_rx_init(
				all_uart_definitions[uart_index].pdc_base_address, &rx_buffer_definition->rx_pdc_parameters,
				NULL);
		pdc_enable_transfer(
				all_uart_definitions[uart_index].pdc_base_address,
				PERIPH_PTCR_RXTEN);
		uart_enable_interrupt(
				all_uart_definitions[uart_index].peripheral_base_address,
				UART_IER_ENDRX | UART_IER_RXRDY);
	} else {
		/* The write pointer has reached the read pointer.  There is no
		more room so the DMA is not re-enabled until a read has created
		space. */
		uart_disable_interrupt(
				all_uart_definitions[uart_index].peripheral_base_address,
				UART_IDR_ENDRX | UART_IDR_RXRDY);
	}
}
/**
 * \brief Set a given number of pixels to the same color
 *
 * Use this function to write a certain number of pixels to the same color
 * within a set limit.
 *
 * Limits have to be set prior to calling this function, e.g.:
 * \code
 * ili9341_set_top_left_limit(0, 0);
 * ili9341_set_bottom_right_limit(320, 240);
 * ...
 * \endcode
 *
 * \param color The color to write to the display
 * \param count The number of pixels to write with this color
 */
void ili9341_duplicate_pixel(const ili9341_color_t color, uint32_t count)
{
	/* Sanity check to make sure that the pixel count is not zero */
	Assert(count > 0);

	ili9341_send_command(ILI9341_CMD_MEMORY_WRITE);

#if defined(ILI9341_DMA_ENABLED)
	ili9341_color_t chunk_buf[ILI9341_DMA_CHUNK_SIZE];
	uint32_t chunk_len;

#  if SAM
	Pdc *SPI_DMA = spi_get_pdc_base(CONF_ILI9341_SPI);
	pdc_packet_t spi_pdc_data;

	pdc_enable_transfer(SPI_DMA, PERIPH_PTCR_TXTEN);
	spi_pdc_data.ul_addr = (uint32_t)chunk_buf;
#  elif UC3
	pdca_set_transfer_size(CONF_ILI9341_PDCA_CHANNEL,
			PDCA_TRANSFER_SIZE_BYTE);
	pdca_set_peripheral_select(CONF_ILI9341_PDCA_CHANNEL,
			CONF_ILI9341_PDCA_PID);
#  endif

	for (uint32_t i = 0; i < ILI9341_DMA_CHUNK_SIZE; i++) {
		chunk_buf[i] = le16_to_cpu(color);
	}

	while (count)
	{
		chunk_len = min(ILI9341_DMA_CHUNK_SIZE, count);

		ili9341_wait_for_send_done();

#  if SAM
		spi_pdc_data.ul_size = (uint32_t)sizeof(ili9341_color_t) * chunk_len;
		pdc_tx_init(SPI_DMA, NULL, &spi_pdc_data);
#  elif UC3
		pdca_reload_channel(CONF_ILI9341_PDCA_CHANNEL, chunk_buf,
				(uint32_t)sizeof(ili9341_color_t) * chunk_len);
		pdca_enable(CONF_ILI9341_PDCA_CHANNEL);
#  endif

		count -= chunk_len;
	}

	ili9341_wait_for_send_done();
	ili9341_deselect_chip();

#  if SAM
	pdc_disable_transfer(SPI_DMA, PERIPH_PTCR_TXTEN);
#  elif UC3
	pdca_disable(CONF_ILI9341_PDCA_CHANNEL);
#  endif
#else
	while (count--) {
		ili9341_send_byte(color);
		ili9341_send_byte(color >> 8);
	}

	ili9341_wait_for_send_done();
	ili9341_deselect_chip();
#endif
}
Exemple #23
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 #24
0
/**
 * \brief Application entry point for PWM PDC example.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	uint32_t i;
	uint8_t uc_key;
	uint8_t c_numkey;

	/* Initialize the SAM system */
	sysclk_init();
	board_init();

	/* Configure the console uart for debug infomation */
	configure_console();

	/* Output example information */
	puts(STRING_HEADER);

	/* Enable PWM peripheral clock */
	pmc_enable_periph_clk(ID_PWM);

	/* Disable PWM channel of LED1 and LED0 */
	pwm_channel_disable(PWM, PIN_PWM_LED0_CHANNEL);
	pwm_channel_disable(PWM, PIN_PWM_LED1_CHANNEL);

	/*
	 * In PWM synchronisation mode the channel0 is used as reference channel,
	 * so it is necessary to disable, configure and enable it.
	 */
	if (PIN_PWM_LED0_CHANNEL && PIN_PWM_LED1_CHANNEL) {
		pwm_channel_disable(PWM, 0);
	}

	/* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */
	pwm_clock_t clock_setting = {
		.ul_clka = PWM_FREQUENCY * PERIOD_VALUE,
		.ul_clkb = 0,
		.ul_mck = sysclk_get_cpu_hz()
	};
	pwm_init(PWM, &clock_setting);

	/* Initialize PWM channels outputs */
	pwm_output_t channel_output = {
		/* Disable override PWMH outputs */
		.b_override_pwmh = false,
		/* Disable override PWML outputs */
		.b_override_pwml = false,
		/* Set override PWMH output level as HIGH */
		.override_level_pwmh = PWM_HIGH,
		/* Set override PWML output level as LOW */
		.override_level_pwml = PWM_LOW
	};

	/* Initialize PWM synchronous channels */
	pwm_channel_t sync_channel = {
		/* Use PWM clock A as source clock */
		.ul_prescaler = PWM_CMR_CPRE_CLKA,
		/* Period value of output waveform */
		.ul_period = PERIOD_VALUE,
		/* Duty cycle value of output waveform */
		.ul_duty = INIT_DUTY_VALUE,
		/* Set it as a synchronous channel */
		.b_sync_ch = true,
		/* Enable dead-time generator */
		.b_deadtime_generator = true,
		/* Dead-time value for PWMH output */
		.us_deadtime_pwmh = INIT_DEAD_TIME,
		/* Dead-time value for PWML output */
		.us_deadtime_pwml = INIT_DEAD_TIME,
		/* Disable override PWMH outputs */
		.output_selection.b_override_pwmh = false,
		/* Disable override PWML outputs */
		.output_selection.b_override_pwml = false
	};

	/*
	 * In PWM synchronisation mode the channel0 is used as reference channel,
	 * so it is necessary to disable, configure and enable it.
	 */
	if (PIN_PWM_LED0_CHANNEL && PIN_PWM_LED1_CHANNEL) {
		sync_channel.channel = 0;
		pwm_channel_init(PWM, &sync_channel);
	}

	/* Initialize PWM channel of LED1 */
	sync_channel.channel = PIN_PWM_LED1_CHANNEL;
	pwm_channel_init(PWM, &sync_channel);

	/* Initialize PWM channel of LED2 */
	sync_channel.channel = PIN_PWM_LED0_CHANNEL;
	pwm_channel_init(PWM, &sync_channel);

	/*
	 * Initialize PWM synchronous channels
	 * Synchronous Update Mode: Automatic update duty cycle value by the PDC
	 * and automatic update of synchronous channels. The update occurs when
	 * the Update Period elapses (MODE 2).
	 * Synchronous Update Period = MAX_SYNC_UPDATE_PERIOD.
	 */
	pwm_sync_init(PWM, PWM_SYNC_UPDATE_MODE_2, MAX_SYNC_UPDATE_PERIOD);

	/*
	 * Request PDC transfer as soon as the synchronous update period elapses
	 * (comparison unit is ignored).
	 */
	pwm_pdc_set_request_mode(PWM, PWM_PDC_UPDATE_PERIOD_ELAPSED, (1 << 0));

	/* Configure interrupt for PDC transfer */
	NVIC_DisableIRQ(PWM_IRQn);
	NVIC_ClearPendingIRQ(PWM_IRQn);
	NVIC_SetPriority(PWM_IRQn, 0);
	NVIC_EnableIRQ(PWM_IRQn);
	pwm_pdc_enable_interrupt(PWM, PWM_PDC_TX_END);

	/* Fill duty cycle buffer for channel #0 and #1 */
	/*
	 * For PWM channel 0 and 1, duty cycle ranges from
	 * MIN_DUTY_CYCLE to MAX_DUTY_CYCLE
	 */
	for (i = 0; i < (DUTY_BUFFER_LENGTH / 3); i++) {
		g_us_duty_buffer[i * 3] = (i + INIT_DUTY_VALUE);
		g_us_duty_buffer[i * 3 + 1] = (i + INIT_DUTY_VALUE);
		g_us_duty_buffer[i * 3 + 2] = (i + INIT_DUTY_VALUE);
	}

	/* Configure the PDC transfer packet and enable PDC transfer */
	g_pdc_tx_packet.ul_addr = (uint32_t) (&(g_us_duty_buffer[0]));
	g_pdc_tx_packet.ul_size = DUTY_BUFFER_LENGTH;
	pdc_tx_init(PDC_PWM, &g_pdc_tx_packet, 0);
	pdc_enable_transfer(PDC_PWM, PERIPH_PTCR_TXTEN);

	/* Enable all synchronous channels by enabling channel 0 */
	/*
	 * In PWM synchronisation mode the channel0 is used as reference channel,
	 * so it is necessary to disable, configure and enable it.
	 */
	if (PIN_PWM_LED0_CHANNEL && PIN_PWM_LED1_CHANNEL) {
		pwm_channel_enable(PWM, 0);
	}
	pwm_channel_enable(PWM, PIN_PWM_LED0_CHANNEL);
	pwm_channel_enable(PWM, PIN_PWM_LED1_CHANNEL);

	while (1) {
		display_menu();
		while (uart_read(CONSOLE_UART, &uc_key));

		switch (uc_key) {
		case 'u':
		case 'U':
			printf("Input update period must be between 0 and %d.\r\n",
					(int)MAX_SYNC_UPDATE_PERIOD);
			c_numkey = get_num_value();
			if (c_numkey <= MAX_SYNC_UPDATE_PERIOD) {
				/* Set new synchronous update period value */
				pwm_sync_change_period(PWM, c_numkey);
				printf("Synchronous update period has been changed to %d.\r\n", (int)c_numkey);

			} else {
				printf("Wrong value, expected value must be one of 0 to %d!\r\n", (int)MAX_SYNC_UPDATE_PERIOD);
			}
			break;
		case 'd':
		case 'D':
			printf("Input dead time for channel #0 must be between %d and %d.\r\n", INIT_DUTY_VALUE, PERIOD_VALUE);
			c_numkey = get_num_value();

			if (c_numkey <= PERIOD_VALUE) {
				/* Set new dead time value for channel 0 */
				pwm_channel_update_dead_time(PWM, &sync_channel,
						c_numkey, c_numkey);
				/* Update all synchronous channels */
				pwm_sync_unlock_update(PWM);
				printf("Dead time has been changed to %d.\r\n", (int)c_numkey);

			} else {
				printf("Wrong value, expected value must be one of %d to %d!\r\n", INIT_DUTY_VALUE, PERIOD_VALUE);
			}
			break;
		case 'o':
		case 'O':
			if (channel_output.b_override_pwmh
					&& channel_output.b_override_pwml) {
				/* Disable override outputs of channel 0 synchronously */
				channel_output.b_override_pwmh = false;
				channel_output.b_override_pwml = false;
				pwm_channel_update_output(PWM, &sync_channel,
						&channel_output, true);
				puts("PWM Channel #0 output override has been disabled.\r\n");
			}
			else {
				/* Enable override outputs of channel 0 synchronously */
				channel_output.b_override_pwmh = true;
				channel_output.b_override_pwml = true;
				pwm_channel_update_output(PWM, &sync_channel,
						&channel_output, true);
				puts("PWM Channel #0 output has been overridden.\r\n");

			}
			break;
		default:
			puts("Unknown input!\r\n");
			break;
		}
	}
}
Exemple #25
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 #26
0
/**
 * \brief DSP task core function.
 *
 * \param pvParameters Junk parameter.
 */
static void dsp_task(void *pvParameters)
{
	uint32_t i, j;
	uint32_t adc_potentiometer = 0;
	const float32_t display_factor = 700;
	float32_t bin;
	float32_t tmp;

	/* Just to avoid compiler warnings. */
	UNUSED(pvParameters);

	/* Wait for user to read instructions. */
	WAIT_FOR_TOUCH_EVENT;

	dsp_configure_button2();
	dsp_configure_tc();
	dsp_configure_adc();
	dsp_configure_dacc();
	dsp_sin_init();

	/* Enable PDC transfer. */
	dsp_clean_buffer(dacc_out_buffer[0], SAMPLE_BLOCK_SIZE);
	dsp_clean_buffer(dacc_out_buffer[1], SAMPLE_BLOCK_SIZE);
	dsp_clean_buffer(dacc_out_buffer[2], SAMPLE_BLOCK_SIZE);
	g_pdc_packet.ul_addr = (uint32_t) dacc_out_buffer[0];
	g_pdc_packet.ul_size = SAMPLE_BLOCK_SIZE;
	g_pdc_nextpacket.ul_addr = (uint32_t) dacc_out_buffer[1];
	g_pdc_nextpacket.ul_size = SAMPLE_BLOCK_SIZE;
	pdc_tx_init(dacc_pdc, &g_pdc_packet, &g_pdc_nextpacket);
	pdc_enable_transfer(dacc_pdc, PERIPH_PTCR_TXTEN);

	/* Start Timer counter 0 channel 0 for ADC-DACC trigger. */
	tc_start(TC0, 1);

	/** DSP task loop. */
	while (1) {
		/* Using input wave signal. */
		if (g_mode_select == 1) {
			if (xSemaphoreTake(dacc_notification_semaphore,
					max_block_time_ticks)) {
				/* Copy dsp_sfx into wav_in_buffer and prepare Q15 format. */
				for (i = 0, j = 0; i < 512; ++j) {
					tmp = (((dsp_sfx[offset] - (float) 128)) / 100);

					/* Store Audio sample real part in memory. */
					wav_in_buffer[i++] = tmp;

					/* Store Audio sample imaginary part in memory. */
					wav_in_buffer[i++] = 0;

					/* Prepare buffer for DACC. */
					dacc_out_buffer[cur_dac_buffer][j] = (uint16_t)((tmp * 100
							* sin_buffer[slider_pos][j]) + 128);

					/* Update the wave file offset pointer. */
					if (offset < dsp_sfx_size - 1) {
						offset++;
					} else {
						offset = WAVE_OFFSET;
					}
				}
			} else {
				/* Ensure we take the semaphore. */
				continue;
			}
		} else {
			/* Using generated input sinus signal. */
			if (xSemaphoreTake(dacc_notification_semaphore,
					max_block_time_ticks)) {
				/*
				 * Read potentiometer value and generate
				 * sinus signal accordingly.
				 */
				adc_potentiometer_old = adc_potentiometer;
				adc_potentiometer = (afec_channel_get_value(AFEC0,
						ADC_CHANNEL_POTENTIOMETER));
				adc_potentiometer = adc_potentiometer * 10000 / 4096;
				if (adc_potentiometer > adc_potentiometer_old &&
						adc_potentiometer -
						adc_potentiometer_old < ADC_POTENTIOMETER_NOISE) {
					adc_potentiometer = adc_potentiometer_old;
				} else if (adc_potentiometer_old > adc_potentiometer &&
						adc_potentiometer_old -
						adc_potentiometer < ADC_POTENTIOMETER_NOISE) {
					adc_potentiometer = adc_potentiometer_old;
				}

				/* Generate the sinus signal. */
				dsp_sin_input(adc_potentiometer);

				/* Prepare buffer for DACC. */
				for (i = 0, j = 0; i < 512; ++j, i += 2) {
					/*
					 * 2048 is the 0 position for DACC.
					 * 50 is an amplification factor.
					 */
					dacc_out_buffer[cur_dac_buffer][j] =
					(uint16_t)((wav_in_buffer[i] * sin_buffer[slider_pos][j])
							* 50 + 2048);
				}

			}
		}

		afec_start_software_conversion(AFEC0);

		/* Perform FFT and bin Magnitude calculation */
		arm_float_to_q15(wav_in_buffer, cfft_q15, SAMPLE_BLOCK_SIZE * 2);
		arm_cfft_radix4_init_q15(&cfft_instance, SAMPLE_BLOCK_SIZE, 0, 1);
		arm_cfft_radix4_q15(&cfft_instance, cfft_q15);
		arm_cmplx_mag_q15(cfft_q15, mag_in_buffer_q15, SAMPLE_BLOCK_SIZE);
		arm_q15_to_float(mag_in_buffer_q15, mag_in_buffer, 128);

		/*
		 * Prepare bins rendering for web page and display.
		 * Limit to 99, even if we got 128 magnitudes to display.
		 * Bins are printed using col, incremented by mean of 2 to keep
		 * a clean rendering. Hence we cannot render all the magnitudes,
		 * because of the screen width. It would require a 128*2 space.
		 */
		for (i = 0; i < 99; ++i) {
			bin = (mag_in_buffer[i] * display_factor);
			if (bin > 0) {
				if (bin > 98) {
					bin = 98;
				}
				mag_in_buffer_int[i] = (uint32_t)bin;
			} else {
				mag_in_buffer_int[i] = 0;
			}
		}

		/* Notify GFX task to start refreshing screen (if necessary). */
		if (g_mode_select == 1 || (g_mode_select == 0 &&
				adc_potentiometer != adc_potentiometer_old)) {
			xSemaphoreGive(gfx_notification_semaphore);
		}
	}
}
Exemple #27
0
/**
 * \brief pio_capture Application entry point.
 *
 * \return Unused (ANSI-C compatibility).
 *
 */
int main(void)
{
	uint8_t uc_i;
	uint32_t ul_length;
	uint32_t ul_mode;
	uint8_t uc_key;
	static uint8_t uc_rx_even_only;
	static uint8_t uc_tx_without_en;

	/* Initialize the SAM system. */
	sysclk_init();
	board_init();

	/* Configure UART for debug message output. */
	configure_console();

	/* Configure PIOA clock. */
	pmc_enable_periph_clk(ID_PIOA);
	pmc_enable_periph_clk(ID_PIOC);

	/* Configure PIO Capture handler */
	pio_capture_handler_set(capture_handler);

	/* Output example information. */
	puts(STRING_HEADER);

	printf("Frequency: %d MHz.\r\n",
			(uint8_t) (sysclk_get_cpu_hz() / 1000000));

	printf("Press r to Receive data on PIO Parallel Capture.\r\n");
	printf("Press s to Send data on PIO Parallel Capture.\r\n");
	uc_key = 0;
	while ((uc_key != 'r') && (uc_key != 's')) {
		uart_read(CONSOLE_UART, &uc_key);
	}
	if (uc_key == 'r') {
		printf("** RECEIVE mode **\r\n");

		/* Initialize PIO capture mode value. */
		ul_mode = 0;
		/* Set up the parallel capture mode data size as 8 bits. */
		ul_mode |= 0 << PIO_PCMR_DSIZE_Pos;

		printf("Press y to sample the data when both data enable pins are enabled.\r\n");
		printf("Press n to sample the data, don't care the status of the data enable pins.\r\n");
		uc_key = 0;
		while ((uc_key != 'y') && (uc_key != 'n')) {
			uart_read(CONSOLE_UART, &uc_key);
		}
		if (uc_key == 'y') {
			/* Sample the data when both data enable pins are enabled. */
			ul_mode &= ~PIO_PCMR_ALWYS;
			printf("Receive data when both data enable pins are enabled.\r\n");
		} else {
			/* Sample the data, don't care the status of the data enable pins. */
			ul_mode |= PIO_PCMR_ALWYS;
			printf("Receive data, don't care the status of the data enable pins.\r\n");
		}
		printf("Press y to sample all the data\r\n");
		printf("Press n to sample the data only one out of two.\r\n");
		uc_key = 0;
		while ((uc_key != 'y') && (uc_key != 'n')) {
			uart_read(CONSOLE_UART, &uc_key);
		}
		if (uc_key == 'y') {
			/* Sample all the data. */
			ul_mode &= ~PIO_PCMR_HALFS;
			printf("All data are sampled.\r\n");
		} else {
			/* Sample the data only one out of two. */
			ul_mode |= PIO_PCMR_HALFS;
			/* Only if half-Sampling is set, data with an even index are sampled. */
			ul_mode &= ~PIO_PCMR_FRSTS;
			printf("Only one out of two data is sampled, with an even index.\r\n");
		}

		/* Initialize PIO Parallel Capture function. */
		pio_capture_set_mode(PIOA, ul_mode);
		pio_capture_enable(PIOA);

		/* Disable all PIOA I/O line interrupt. */
		pio_disable_interrupt(PIOA, 0xFFFFFFFF);

		/* Configure and enable interrupt of PIO. */
		NVIC_DisableIRQ(PIOA_IRQn);
		NVIC_ClearPendingIRQ(PIOA_IRQn);
		NVIC_SetPriority(PIOA_IRQn, PIO_IRQ_PRI);
		NVIC_EnableIRQ(PIOA_IRQn);

		while (1) {
			g_uc_cbk_received = 0;

			/* Clear Receive buffer. */
			for (uc_i = 0; uc_i < SIZE_BUFF_RECEPT; uc_i++) {
				pio_rx_buffer[uc_i] = 0;
			}

			/* Set up PDC receive buffer, waiting for 64 bytes. */
			packet_t.ul_addr = (uint32_t) pio_rx_buffer;
			packet_t.ul_size = SIZE_BUFF_RECEPT;
			p_pdc = pio_capture_get_pdc_base(PIOA);
			pdc_rx_init(p_pdc, &packet_t, NULL);

			/* Enable PDC transfer. */
			pdc_enable_transfer(p_pdc, PERIPH_PTCR_RXTEN);

			/* Configure the PIO capture interrupt mask. */
			pio_capture_enable_interrupt(PIOA,
					(PIO_PCIER_ENDRX | PIO_PCIER_RXBUFF));

			printf("Waiting...\r\n");
			while (g_uc_cbk_received == 0) {
			}
		}
	} else if (uc_key == 's') {
		printf("** SEND mode **\r\n");
		printf("This is for debug purpose only !\r\n");
		printf("Frequency of PIO controller clock must be strictly superior");
		printf("to 2 times the frequency of the clock of the device which");
		printf(" generates the parallel data.\r\n");
		printf("\r\nPlease connect the second board, ");
		printf("and put it in receive mode.\r\n");

		/* Configure PIO pins which simulate as a sensor. */
		pio_configure_pin_group(PIOA, PIO_CAPTURE_CONTROL_PIN_MSK,
			PIO_CAPTURE_OUTPUT_PIN_FLAGS);
		pio_configure_pin_group(PIOC, PIO_CAPTURE_DATA_PINS_MASK,
			PIO_CAPTURE_OUTPUT_PIN_FLAGS);
		pio_set_pin_low(PIO_CAPTURE_EN1_IDX);
		pio_set_pin_low(PIO_CAPTURE_EN2_IDX);
		pio_set_pin_low(PIO_CAPTURE_CCLK_IDX);

		/* Enable sync. output data. */
		pio_enable_output_write(PIOC, PIO_CAPTURE_DATA_PINS_MASK);

		/* Initialize the capture data line. */
		pio_sync_output_write(PIOC, 0);

		printf("Press y to send data with data enable pins.\r\n");
		printf("Press n to send data without data enable pins.\r\n");

		uc_key = 0;
		while ((uc_key != 'y') && (uc_key != 'n')) {
			uart_read(CONSOLE_UART, &uc_key);
		}
		if (uc_key == 'y') {
			uc_tx_without_en = 0;
			printf("Send data with both data enable pins enabled.\r\n");
		} else {
			uc_tx_without_en = 1;
			printf("Send data without enabling the data enable pins.\r\n");
		}

		printf("Press y to indicate that receiver samples all data.\r\n");
		printf("Press n to indicate that receiver samples data with an even index.\r\n");
		uc_key = 0;
		while ((uc_key != 'y') && (uc_key != 'n')) {
			uart_read(CONSOLE_UART, &uc_key);
		}
		if (uc_key == 'y') {
			uc_rx_even_only = 0;
			printf("Receiver samples all data.\r\n");
		} else {
			uc_rx_even_only = 1;
			printf("Receiver samples data with an even index.\r\n");
		}

		ul_length = SIZE_BUFF_RECEPT * (1 + uc_rx_even_only);
		while (1) {
			if (uc_tx_without_en) {
				printf("\r\nSend data without enabling the data enable pins.\r\n");
			} else {
				printf("\r\nSend data with both data enable pins enabled.\r\n");
			}
			if (!uc_tx_without_en) {
				/* Set enable pins. */
				pio_set_pin_high(PIO_CAPTURE_EN1_IDX);
				pio_set_pin_high(PIO_CAPTURE_EN2_IDX);
			}
			for (uc_i = 0; uc_i < ul_length;) {
				/* Send data. */
				pio_sync_output_write(PIOC,
						(uc_i << PIO_CAPTURE_DATA_POS));
				/* Set clock. */
				pio_set_pin_high(PIO_CAPTURE_CCLK_IDX);
				delay_us(20);
				/* Clear clock. */
				pio_set_pin_low(PIO_CAPTURE_CCLK_IDX);
				delay_us(20);
				uc_i++;
			}
			if (!uc_tx_without_en) {
				/* Clear enable pins. */
				pio_set_pin_low(PIO_CAPTURE_EN1_IDX);
				pio_set_pin_low(PIO_CAPTURE_EN2_IDX);
			}
			printf("Press a key.\r\n");
			while (uart_read(CONSOLE_UART, &uc_key)) {
			}
		}
	}

	return 0;
}
/**
 *  \brief usart_rs485 Application entry point.
 *
 *  Configure USART in RS485 mode. If the application starts earlier, it acts
 *  as a receiver. Otherwise, it should be a transmitter.
 *
 *  \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	static uint8_t uc_sync = SYNC_CHAR;
	uint32_t time_elapsed = 0;
	uint32_t ul_i;

	/* Initialize the SAM system. */
	sysclk_init();
	board_init();

	/* Configure UART for debug message output. */
	configure_console();

	/* Output example information. */
	puts(STRING_HEADER);

	/* Configure USART. */
	configure_usart();

	/* Get board USART PDC base address and enable receiver and transmitter. */
	g_p_pdc = usart_get_pdc_base(BOARD_USART);
	pdc_enable_transfer(g_p_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);

	/* 1ms tick. */
	configure_systick();

	/* Initialize receiving buffer to distinguish with the sent frame. */
	memset(g_uc_receive_buffer, 0x0, BUFFER_SIZE);

	/*
	 * Enable transmitter here, and disable receiver first, to avoid receiving
	 * characters sent by itself. It's necessary for half duplex RS485.
	 */
	usart_enable_tx(BOARD_USART);
	usart_disable_rx(BOARD_USART);

	/* Send a sync character XON (0x11). */
	g_st_packet.ul_addr = (uint32_t)&uc_sync;
	g_st_packet.ul_size = 1;
	pdc_tx_init(g_p_pdc, &g_st_packet, NULL);

	/* Delay until the line is cleared, an estimated time used. */
	wait(50);

	/* Read the acknowledgement. */
	g_st_packet.ul_addr = (uint32_t)&uc_sync;
	g_st_packet.ul_size = 1;
	pdc_rx_init(g_p_pdc, &g_st_packet, NULL);

	/* Then enable receiver. */
	usart_enable_rx(BOARD_USART);

	/* Wait until time out or acknowledgement is received. */
	time_elapsed = get_tick_count();
	while (!usart_is_rx_buf_end(BOARD_USART)) {
		if (get_tick_count() - time_elapsed > TIMEOUT) {
			break;
		}
	}

	/* If acknowledgement received in a short time. */
	if (usart_is_rx_buf_end(BOARD_USART)) {
		/* Acknowledgement. */
		if (uc_sync == ACK_CHAR) {
			/* Act as transmitter, start transmitting. */
			g_state = TRANSMITTING;
			puts("-I- Start transmitting!\r");
			g_st_packet.ul_addr = (uint32_t)g_uc_transmit_buffer;
			g_st_packet.ul_size = PDC_BUF_SIZE;
			pdc_tx_init(g_p_pdc, &g_st_packet, NULL);

			/* Enable transmitting interrupt. */
			usart_enable_interrupt(BOARD_USART, US_IER_ENDTX);
		}
	} else {
		/* Start receiving, act as receiver. */
		g_st_packet.ul_addr = (uint32_t)&uc_sync;
		g_st_packet.ul_size = 1;
		pdc_rx_init(g_p_pdc, &g_st_packet, NULL);
		puts("-I- Receiving sync character.\r");
		while (!usart_is_rx_buf_end(BOARD_USART)) {
		}

		/* Sync character is received. */
		if (uc_sync == SYNC_CHAR) {
			/* SEND XOff as acknowledgement. */
			uc_sync = ACK_CHAR;

			/*
			 * Delay to prevent the character from being discarded by
			 * transmitter due to responding too soon.
			 */
			wait(100);
			pio_set_pin_high(PIN_RE_IDX);
			g_st_packet.ul_addr = (uint32_t)&uc_sync;
			g_st_packet.ul_size = 1;
			pdc_tx_init(g_p_pdc, &g_st_packet, NULL);

			g_state = RECEIVING;
			puts("-I- Start receiving!\r");
			g_st_packet.ul_addr = (uint32_t)g_uc_receive_buffer;
			g_st_packet.ul_size = PDC_BUF_SIZE;
			pdc_rx_init(g_p_pdc, &g_st_packet, NULL);
			pio_set_pin_low(PIN_RE_IDX);
			/* Enable receiving interrupt. */
			usart_enable_interrupt(BOARD_USART, US_IER_ENDRX);
		}
	}
	while (g_state != RECEIVED) {
	}

	ul_i = 0;
	/* Print received frame out. */
	while ((ul_i < BUFFER_SIZE) && (g_uc_receive_buffer[ul_i] != '\0')) {
		if (g_uc_transmit_buffer[ul_i] != g_uc_receive_buffer[ul_i]) {
			puts("-E- Error occurred while receiving!\r");
			/* Infinite loop here. */
			while (1) {
			}
		}
		ul_i++;
	}
	puts("-I- Received successfully!\r");

	while (1) {
	}
}
Exemple #29
0
/**
 * \internal
 * \brief Transmit PPLC command to Proxy PLC controller
 *
 *  \param uc_cmd           PPLC command to send
 *  \param us_addr          Address where is the data to apply command
 *  \param us_len           Number of bytes in operation
 *  \param ptr_buf          Pointer to data buffer
 *  \param uc_bytes_rep     Number of repetitions(only use in PPLC_CMD_WRITE_REP
 * command)
 *
 * \retval true if there is no error
 * \retval false if there is an error
 */
static int8_t _pplc_cmd_op(uint8_t uc_cmd, uint16_t us_addr, uint16_t us_len,
		uint8_t *ptr_buf, uint8_t uc_bytes_rep)
{
	uint8_t *ptr_data_buf;
	uint16_t uc_num_tx_bytes;
	uint16_t us_data_len, us_data_len_acc;
	uint16_t us_address;

	Disable_global_interrupt();

	if (!uc_pplc_is_busy) {
		uc_pplc_is_busy = true;
		ptr_data_buf = ptr_buf;
		us_data_len = us_len;
		us_data_len_acc = 0;
		us_address = us_addr;

		while (us_data_len) {
			/* protection to data length */
			if (us_data_len > PDC_PPLC_BUFFER_SIZE) {
				us_data_len = PDC_PPLC_BUFFER_SIZE - 4;
			}

			uc_num_tx_bytes = us_data_len + 4;

			/* Configure PPLC Tx buffer */
			gs_pplc_tx_buffer[0] = uc_cmd;
			gs_pplc_tx_buffer[1] = (uint8_t)(us_address >> 8);
			gs_pplc_tx_buffer[2] = (uint8_t)(us_address);
			if (uc_cmd == PPLC_CMD_WRITE_REP) {
				gs_pplc_tx_buffer[3] = uc_bytes_rep;
			} else {
				gs_pplc_tx_buffer[3] = 0;
			}

			/* Fill data */
			if (uc_cmd == PPLC_CMD_READ) {
				memset(&gs_pplc_tx_buffer[4], 0, us_data_len);
			} else {
				memcpy(&gs_pplc_tx_buffer[4], ptr_data_buf, us_data_len);
			}

			/* Configure DMA channels */
			g_pplc_rx_packet.ul_addr = (uint32_t)gs_pplc_rx_buffer;
			g_pplc_rx_packet.ul_size = uc_num_tx_bytes;
			pdc_rx_init(g_pplc_pdc, &g_pplc_rx_packet, NULL);

			g_pplc_tx_packet.ul_addr = (uint32_t)gs_pplc_tx_buffer;
			g_pplc_tx_packet.ul_size = uc_num_tx_bytes;
			pdc_tx_init(g_pplc_pdc, &g_pplc_tx_packet, NULL);

			/* Enable the RX and TX PDC transfer requests */
			pdc_enable_transfer(g_pplc_pdc,
					PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);

			/* Waiting transfer done*/
			while ((spi_read_status(PPLC_SPI_MODULE) &
					SPI_SR_RXBUFF) == 0) {
			}

			/* Disable the RX and TX PDC transfer requests */
			pdc_disable_transfer(g_pplc_pdc,
					PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);

			/* copy rcv data */
			if (uc_cmd == PPLC_CMD_READ) {
				memcpy(ptr_data_buf, &gs_pplc_rx_buffer[4], us_data_len);
			}

			/* update buffer pointers */
			ptr_data_buf += us_data_len;
			us_address += us_data_len;
			/* update data length */
			us_data_len_acc += us_data_len;
			us_data_len = us_len - us_data_len_acc;
		}

		uc_pplc_is_busy = false;
		Enable_global_interrupt();
		return true;
	} else {
/**
 * \ingroup freertos_uart_peripheral_control_group
 * \brief Initializes the FreeRTOS ASF UART driver for the specified UART
 * port.
 *
 * freertos_uart_serial_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 UART port.
 *
 * If freertos_driver_parameters->operation_mode equals UART_RS232 then
 * freertos_uart_serial_init() will configure the UART port for standard RS232
 * operation.  If freertos_driver_parameters->operation_mode equals any other
 * value then freertos_uart_serial_init() will not take any action.
 *
 * Other ASF UART functions can be called after freertos_uart_serial_init()
 * has completed successfully.
 *
 * The FreeRTOS ASF driver both installs and handles the UART 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_uart    The UART peripheral being initialized.
 * \param uart_parameters    Structure that defines the UART bus and transfer
 *     parameters, such the baud rate and the number of data bits.
 *     sam_uart_opt_t is a standard ASF type (it is not FreeRTOS specific).
 * \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 UART read and write functions is returned.  If
 *     the initialisation fails then NULL is returned.
 */
freertos_uart_if freertos_uart_serial_init(Uart *p_uart,
		const sam_uart_opt_t *const uart_parameters,
		const freertos_peripheral_options_t *const freertos_driver_parameters)
{
	portBASE_TYPE uart_index;
	bool is_valid_operating_mode;
	freertos_uart_if return_value;
	const enum peripheral_operation_mode valid_operating_modes[] = {UART_RS232};

	/* Find the index into the all_uart_definitions array that holds details of
	the p_uart peripheral. */
	uart_index = get_pdc_peripheral_details(all_uart_definitions,
			MAX_UARTS,
			(void *) p_uart);

	/* 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_uart pointer was used, and a valid
	operating mode was requested. */
	if ((uart_index < MAX_UARTS) && (is_valid_operating_mode == true)) {
		/* This function must be called exactly once per supported UART.  Check it
		has not been called	before. */
		configASSERT(rx_buffer_definitions[uart_index].next_byte_to_read == NULL);

		/* Disable everything before enabling the clock. */
		uart_disable_tx(p_uart);
		uart_disable_rx(p_uart);
		pdc_disable_transfer(all_uart_definitions[uart_index].pdc_base_address,
				(PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS));

		/* Enable the peripheral clock in the PMC. */
		pmc_enable_periph_clk(
				all_uart_definitions[uart_index].peripheral_id);

		switch (freertos_driver_parameters->operation_mode) {
		case UART_RS232:
			/* Call the standard ASF init function. */
			uart_init(p_uart, uart_parameters);
			break;

		default:
			/* Other modes are not currently supported. */
			break;
		}

		/* Disable all the interrupts. */
		uart_disable_interrupt(p_uart, MASK_ALL_INTERRUPTS);

		/* Create any required peripheral access mutexes and transaction complete
		semaphores.  This peripheral is full duplex so only the Tx semaphores
		are created in the following function.  The the Rx semaphores are
		created	separately. */
		create_peripheral_control_semaphores(
				freertos_driver_parameters->options_flags,
				&(tx_dma_control[uart_index]),
				NULL /* The rx structures are not created in this function. */);

		/* Is the driver also going to receive? */
		if (freertos_driver_parameters->receive_buffer != NULL) {
			/* rx_event_semaphore is used to signal the arival of new data.  It
			must be a counting semaphore for the following reason:  If the Rx
			DMA places data at the end of its circular buffer it will give the
			semaphore to indicate the presence of unread data.  If it then
			receives more data, it will write this to the start of the circular
			buffer, then give the semaphore again.  Now, if a task reads data
			out of the same circular buffer, and requests less data than is
			available, but more than is available between the next read pointer
			and the end of the buffer, the actual amount returned will be
			capped to that available up to the end of the buffer only.  If this
			semaphore was a binary semaphore, it would then be 'taken' even
			though, unknown to the reading task, unread and therefore available
			data remained at the beginning of the buffer. */
			rx_buffer_definitions[uart_index].rx_event_semaphore =
					xSemaphoreCreateCounting(portMAX_DELAY, 0);
			configASSERT(rx_buffer_definitions[uart_index].rx_event_semaphore);

			/* The receive buffer is currently empty, so the DMA has control
			over the entire buffer. */
			rx_buffer_definitions[uart_index].rx_pdc_parameters.ul_addr =
					(uint32_t)freertos_driver_parameters->receive_buffer;
			rx_buffer_definitions[uart_index].rx_pdc_parameters.ul_size =
					freertos_driver_parameters->receive_buffer_size;
			pdc_rx_init(
					all_uart_definitions[uart_index].pdc_base_address,
					&(rx_buffer_definitions[uart_index].rx_pdc_parameters),
					NULL);

			/* Set the next byte to read to the start of the buffer as no data
			has yet been read. */
			rx_buffer_definitions[uart_index].next_byte_to_read =
					freertos_driver_parameters->receive_buffer;

			/* Remember the limits of entire buffer. */
			rx_buffer_definitions[uart_index].rx_buffer_start_address =
					rx_buffer_definitions[uart_index].rx_pdc_parameters.ul_addr;
			rx_buffer_definitions[uart_index].past_rx_buffer_end_address =
					rx_buffer_definitions[uart_index].rx_buffer_start_address +
					freertos_driver_parameters->receive_buffer_size;

			/* If the rx driver is to be thread aware, create an access control
			mutex. */
			if ((freertos_driver_parameters->options_flags &
					USE_RX_ACCESS_MUTEX) != 0) {
				rx_buffer_definitions[uart_index].rx_access_mutex =
					xSemaphoreCreateMutex();
				configASSERT(rx_buffer_definitions[uart_index].rx_access_mutex);
			}

			/* Catch the DMA running out of Rx space, and gaps in the
			reception.  These events are both used to signal that there is
			data available in the Rx buffer. */
			uart_enable_interrupt(p_uart, UART_IER_ENDRX | UART_IER_RXRDY);

			/* The Rx DMA is running all the time, so enable it now. */
			pdc_enable_transfer(
					all_uart_definitions[uart_index].pdc_base_address,
					PERIPH_PTCR_RXTEN);
		} else {
			/* next_byte_to_read is used to check to see if this function
			has been called before, so it must be set to something, even if
			it is not going to be used.  The value it is set to is not
			important, provided it is not zero (NULL). */
			rx_buffer_definitions[uart_index].next_byte_to_read = RX_NOT_USED;
		}

		/* Configure and enable the UART interrupt in the interrupt controller. */
		configure_interrupt_controller(all_uart_definitions[uart_index].peripheral_irq,
				freertos_driver_parameters->interrupt_priority);

		/* Error interrupts are always enabled. */
		uart_enable_interrupt(
				all_uart_definitions[uart_index].peripheral_base_address,
				IER_ERROR_INTERRUPTS);

		/* Finally, enable the receiver and transmitter. */
		uart_enable_tx(p_uart);
		uart_enable_rx(p_uart);

		return_value = (freertos_uart_if) p_uart;
	} else {
		return_value = NULL;
	}

	return return_value;
}