/** * \brief Interrupt handler. Record the number of bytes received, * and then restart a read transfer on the UART if the transfer was stopped. */ void TC_UART_Handler(void) { uint32_t ul_status; uint32_t ul_byte_total = 0; /* Read TC_UART Status. */ ul_status = tc_get_status(TC_UART, TC_UART_CHN); /* RC compare. */ if ((ul_status & TC_SR_CPCS) == TC_SR_CPCS) { #ifdef CONF_BOARD_UART0 if (buart_chn_open[0]) { /* Flush PDC buffer. */ ul_byte_total = UART_BUFFER_SIZE - pdc_read_rx_counter(g_p_uart_pdc0); if (ul_byte_total > 0) { if (ul_byte_total == num_bytes_rx_uart0) { /* Disable timer. */ tc_stop(TC_UART, TC_UART_CHN); /* Log current size */ gs_ul_size_uart_buf0 = ul_byte_total; /* Stop DMA UART_RX -> force Uart Handler*/ g_st_uart_rx_packet0.ul_size = 0; pdc_rx_init(g_p_uart_pdc0, &g_st_uart_rx_packet0, NULL); } else { num_bytes_rx_uart0 = ul_byte_total; } } else { num_bytes_rx_uart0 = 0; } } #endif #ifdef CONF_BOARD_UART1 if (buart_chn_open[1]) { /* Flush PDC buffer. */ ul_byte_total = UART_BUFFER_SIZE - pdc_read_rx_counter(g_p_uart_pdc1); if (ul_byte_total > 0) { if (ul_byte_total == num_bytes_rx_uart1) { /* Disable timer. */ tc_stop(TC_UART, TC_UART_CHN); /* Log current size */ gs_ul_size_uart_buf1 = ul_byte_total; /* Stop DMA UART_RX -> force Uart Handler*/ g_st_uart_rx_packet1.ul_size = 0; pdc_rx_init(g_p_uart_pdc1, &g_st_uart_rx_packet1, NULL); } else { num_bytes_rx_uart1 = ul_byte_total; } } else { num_bytes_rx_uart1 = 0; } } #endif } }
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; }
/** * \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); }
/** * \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 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) { } }
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 ); }
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; }
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); }
/** * \brief Interrupt handler for USART. * * Increment the number of bytes received in the current second and start * another transfer if the desired bps has not been met yet. * */ void USART_Handler(void) { uint32_t ul_status; tc_stop(TC0, 0); /* Read USART status. */ ul_status = usart_get_status(BOARD_USART); /* Receive buffer is full. */ if (ul_status & US_CSR_RXBUFF) { g_ul_bytes_received += 2 * BUFFER_SIZE; if (g_ul_bytes_received < MAX_BPS) { /* Restart transfer if BPS is not high enough. */ 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); } else { /* Otherwise disable interrupt. */ usart_disable_interrupt(BOARD_USART, US_IDR_RXBUFF); } memcpy(gs_dump_buffer, gs_puc_buffer, BUFFER_SIZE); } tc_start(TC0, 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); }
/** * \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); } }
/** @brief Interruption handler for USART1 * */ void USART1_Handler(void) { uint32_t ul_status; uint16_t us_wr_idx, us_data_count; uint16_t us_end_size, us_free_size, us_part_size; /* Read USART Status. */ ul_status = usart_get_status(USART1); /* Receive buffer is full. */ if (ul_status & US_CSR_ENDRX) { /* manage data */ us_wr_idx = busart_comm_data_1.us_wq_idx; us_data_count = busart_comm_data_1.us_rq_count; us_free_size = RX_USART_BUF1_SIZE - us_data_count; if (gs_ul_size_usart_buf1 <= us_free_size) { /* there is enough space to write all data */ us_end_size = RX_USART_BUF1_SIZE - us_wr_idx; if (us_end_size >= gs_ul_size_usart_buf1) { /* there is no overflow of us_wq_idx */ memcpy(&busart_comm_data_1.puc_rq_buf[us_wr_idx], gs_puc_usart_buf1, gs_ul_size_usart_buf1); /* update counters */ busart_comm_data_1.us_rq_count += gs_ul_size_usart_buf1; busart_comm_data_1.us_wq_idx += gs_ul_size_usart_buf1; } else { /* there is overflow of us_wq_idx -> write in 2 * steps */ memcpy(&busart_comm_data_1.puc_rq_buf[us_wr_idx], gs_puc_usart_buf1, us_end_size); us_part_size = gs_ul_size_usart_buf1 - us_end_size; memcpy(&busart_comm_data_1.puc_rq_buf[0], &gs_puc_usart_buf1[us_end_size], us_part_size); /* update counters */ busart_comm_data_1.us_rq_count += gs_ul_size_usart_buf1; busart_comm_data_1.us_wq_idx = us_part_size; } } else { /* there is not enough space to write all data */ tc_start(TC_USART, TC_USART_CHN); } /* change RX buffer */ gs_ul_size_usart_buf1 = USART_BUFFER_SIZE; /* Restart read on buffer. */ g_st_usart_rx_packet1.ul_addr = (uint32_t)gs_puc_usart_buf1; g_st_usart_rx_packet1.ul_size = USART_BUFFER_SIZE; pdc_rx_init(g_p_usart_pdc1, &g_st_usart_rx_packet1, NULL); /* Restart timer. */ tc_start(TC_USART, TC_USART_CHN); } }
/** * \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; } } } }
/** * \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 Interrupt handler for TC0. * * Display the number of bytes received during the last second and the total * number of bytes received, and then restart a read transfer on the USART if it * was stopped. */ void TC0_Handler(void) { uint32_t ul_status; static uint32_t bytes_total = 0; /* Read TC0 status. */ ul_status = tc_get_status(TC0, 0); /* RC compare. */ if ((ul_status & TC_SR_CPCS) == TC_SR_CPCS) { if((pdc_read_rx_counter(g_p_pdc) != 0) && (pdc_read_rx_counter(g_p_pdc) != BUFFER_SIZE)) { if(pdc_read_rx_next_counter(g_p_pdc) == 0) { g_ul_bytes_received += (2 * BUFFER_SIZE - pdc_read_rx_counter(g_p_pdc)); } else { g_ul_bytes_received += (BUFFER_SIZE - pdc_read_rx_counter(g_p_pdc)); } memset(gs_dump_buffer, 0, BUFFER_SIZE); memcpy(gs_dump_buffer, gs_puc_buffer, BUFFER_SIZE - pdc_read_rx_counter(g_p_pdc)); } else if((pdc_read_rx_counter(g_p_pdc) == BUFFER_SIZE) && (pdc_read_rx_next_counter(g_p_pdc) == 0)) { g_ul_bytes_received += BUFFER_SIZE; memcpy(gs_dump_buffer, gs_puc_buffer, BUFFER_SIZE); } /* Display info. */ bytes_total += g_ul_bytes_received; memset(g_puc_string, 0, BUFFER_SIZE); sprintf((char *)g_puc_string, "Bps: %4lu; Tot: %6lu\r\n", (unsigned long)g_ul_bytes_received, (unsigned long)bytes_total); usart_write_line(BOARD_USART, (char *)g_puc_string); /* Resume transfer */ 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); usart_enable_interrupt(BOARD_USART, US_IER_RXBUFF); g_ul_bytes_received = 0; } }
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); } }
void SPI_Handler(void) { //uint32_t status; pdc_packet_t pdc_spi_packet; //status = spi_read_status(SPI_MASTER_BASE); //spi_disable_interrupt(SPI_MASTER_BASE, 0xffffffff); //pdc_disable_transfer(spi_m_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); /* clear interrupt */ pdc_spi_packet.ul_addr = NULL; pdc_spi_packet.ul_size = 3; pdc_rx_init(spi_m_pdc, &pdc_spi_packet, NULL); //platform_log("status= %x",status); //don't enabel printf in IRQ Handler wwd_irq();//pdc int //if(status & SPI_SR_NSSR) { // if ( status & SPI_SR_RXBUFF ) { // spi_slave_transfer(gs_uc_spi_s_tbuffer, COMM_BUFFER_SIZE, // gs_uc_spi_s_rbuffer, COMM_BUFFER_SIZE); // } //} }
/** * \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); }
/** * \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; }
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; }
/* * 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); } }
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 }
/** * \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) { } }
/** * \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; }