void platform_wifi_spi_rx_dma_irq(void) { uint8_t junk1; uint16_t junk2; pdc_packet_t pdc_spi_packet = { 0, 1 }; Pdc* spi_pdc = spi_get_pdc_base( wifi_spi.port ); uint32_t status = spi_read_status( wifi_spi.port ); uint32_t mask = spi_read_interrupt_mask( wifi_spi.port ); if ( ( mask & SPI_IMR_RXBUFF ) && ( status & SPI_SR_RXBUFF ) ) { pdc_disable_transfer( spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS ); pdc_rx_init( spi_pdc, &pdc_spi_packet, NULL ); pdc_tx_init( spi_pdc, &pdc_spi_packet, NULL ); spi_disable_interrupt( wifi_spi.port, SPI_IER_RXBUFF ); } if ( ( mask & SPI_IMR_ENDTX ) && ( status & SPI_SR_ENDTX ) ) { pdc_disable_transfer( spi_pdc, PERIPH_PTCR_TXTDIS ); pdc_tx_init( spi_pdc, &pdc_spi_packet, NULL ); spi_disable_interrupt( wifi_spi.port, SPI_IER_ENDTX ); /* Clear SPI RX data in a SPI send sequence */ spi_read( wifi_spi.port, &junk2, &junk1); } mico_rtos_set_semaphore( &spi_transfer_finished_semaphore ); }
/** * \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); }
/************************************ * 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; }
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; }
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; }
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; }
/** * \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 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); }
/** * \brief This function transmits a message. * * \note This function transmits characters via the specified UART. * If so configured, the function waits until all characters are inserted * in the transmission queue. In this case, the watchdog timer must be * reloaded to avoid a program reset. * * \param chn Communication channel [0, 1] * \param buffer Pointer to information to transmit * \param len Number of characters to transmit * * \retval Number of characters sent */ uint16_t buart_if_write(uint8_t chn, const void *buffer, uint16_t len) { #if !defined(CONF_BOARD_UART0) || !defined(CONF_BOARD_UART1) UNUSED(buffer); UNUSED(len); #endif /* check uart is open */ if (!buart_chn_open[chn]) { return 0; } switch (chn) { #ifdef CONF_BOARD_UART0 case 0: if (len > TX_UART_BUF0_SIZE) { return 0; } while (pdc_read_tx_counter(g_p_uart_pdc0) > 0) { } memcpy(&buart_comm_data_0.puc_tq_buf[0], buffer, len); g_st_uart_tx_packet0.ul_addr = (uint32_t)&buart_comm_data_0.puc_tq_buf[0]; g_st_uart_tx_packet0.ul_size = len; pdc_tx_init(g_p_uart_pdc0, &g_st_uart_tx_packet0, NULL); return len; #endif #ifdef CONF_BOARD_UART1 case 1: if (len > TX_UART_BUF1_SIZE) { return 0; } while (pdc_read_tx_counter(g_p_uart_pdc1) > 0) { } memcpy(&buart_comm_data_1.puc_tq_buf[0], buffer, len); g_st_uart_tx_packet1.ul_addr = (uint32_t)&buart_comm_data_1.puc_tq_buf[0]; g_st_uart_tx_packet1.ul_size = len; pdc_tx_init(g_p_uart_pdc1, &g_st_uart_tx_packet1, NULL); return len; #endif default: return 0; } }
/** * \brief The AES interrupt call back function under PDC mode. */ static void aes_pdc_callback(void) { state = true; pdc_disable_transfer(g_p_aes_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); pdc_tx_init(g_p_aes_pdc, &g_pdc_tx_packet, NULL); pdc_rx_init(g_p_aes_pdc, &g_pdc_rx_packet, NULL); }
/** * \brief Interrupt handler for UART interrupt. */ void console_uart_irq_handler(void) { /* Get UART status and check if PDC receive buffer is full */ if ((uart_get_status(CONSOLE_UART) & UART_SR_RXBUFF) == UART_SR_RXBUFF) { /* Configure PDC for data transfer (RX and TX) */ pdc_rx_init(g_p_uart_pdc, &g_pdc_uart_packet, NULL); pdc_tx_init(g_p_uart_pdc, &g_pdc_uart_packet, NULL); } }
void platform_uart_irq( platform_uart_driver_t* driver ) { uint32_t status = usart_get_status( driver->peripheral->peripheral ); uint32_t mask = usart_get_interrupt_mask( driver->peripheral->peripheral ); Pdc* pdc_register = usart_get_pdc_base( driver->peripheral->peripheral ); /* ENDTX flag is set when Tx DMA transfer is done */ if ( ( mask & US_IMR_ENDTX ) && ( status & US_CSR_ENDTX ) ) { pdc_packet_t dma_packet; /* ENDTX is cleared when TCR or TNCR is set to a non-zero value, which effectively * starts another Tx DMA transaction. To work around this, disable Tx before * performing a dummy Tx init. */ pdc_disable_transfer( usart_get_pdc_base( driver->peripheral->peripheral ), PERIPH_PTCR_TXTDIS ); dma_packet.ul_addr = (uint32_t)0; dma_packet.ul_size = (uint32_t)1; pdc_tx_init( usart_get_pdc_base( USART1 ), &dma_packet, NULL ); /* Notifies waiting thread that Tx DMA transfer is complete */ host_rtos_set_semaphore( &driver->tx_dma_complete, WICED_TRUE ); } /* ENDRX flag is set when RCR is 0. RNPR and RNCR values are then copied into * RPR and RCR, respectively, while the Tx tranfer continues. We now need to * prepare RNPR and RNCR for the next iteration. */ if ( ( mask & US_IMR_ENDRX ) && ( status & US_CSR_ENDRX ) ) { pdc_register->PERIPH_RNPR = (uint32_t)driver->rx_ring_buffer->buffer; pdc_register->PERIPH_RNCR = (uint32_t)driver->rx_ring_buffer->size; } /* RXRDY interrupt is triggered and flag is set when a new character has been * received but not yet read from the US_RHR. When this interrupt executes, * the DMA engine already read the character out from the US_RHR and RXRDY flag * is no longer asserted. The code below updates the ring buffer parameters * to keep them current */ if ( mask & US_CSR_RXRDY ) { driver->rx_ring_buffer->tail = driver->rx_ring_buffer->size - pdc_register->PERIPH_RCR; // Notify thread if sufficient data are available if ( ( driver->rx_transfer_size > 0 ) && ( ring_buffer_used_space( driver->rx_ring_buffer ) >= driver->rx_transfer_size ) ) { host_rtos_set_semaphore( &driver->rx_dma_complete, WICED_TRUE ); driver->rx_transfer_size = 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); }
/** * \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); } }
/** * \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; }
/** * \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)) ; }
/** * \brief DACC interrupt handler. */ void DACC_Handler(void) { uint32_t isr = dacc_get_interrupt_status(DACC); /** Check if one PDC buffer has been received. */ if (isr & DACC_ISR_ENDTX) { /** Add cur_dac_buffer as next transfert for PDC. */ g_pdc_nextpacket.ul_addr = (uint32_t) dacc_out_buffer[cur_dac_buffer]; g_pdc_nextpacket.ul_size = SAMPLE_BLOCK_SIZE; pdc_tx_init(dacc_pdc, NULL, &g_pdc_nextpacket); /** Notify DSP task to start data processing. */ xSemaphoreGiveFromISR(dacc_notification_semaphore, &higher_priority_task_woken); /** Use next PDC buffer for ADC and DACC. */ cur_dac_buffer = (cur_dac_buffer + 1) % 3; } }
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 ); }
/** * \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 }
/** * \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) ; }
/* * 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); } }
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; }
/** * \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); }
/** * \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 {
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 }
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; }
/** * \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; }
/** * \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; } } }
/** * \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); } } }
/** * \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) { } }