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; }
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 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); }
/************************************ * 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; }
platform_result_t platform_uart_deinit( platform_uart_driver_t* driver ) { usart_disable_interrupt( driver->peripheral->peripheral, 0xffffffff ); NVIC_DisableIRQ( platform_uarts_irq_numbers[driver->peripheral->uart_id] ); pdc_disable_transfer( usart_get_pdc_base( driver->peripheral->peripheral ), PERIPH_PTCR_TXTDIS | PERIPH_PTCR_RXTDIS ); usart_disable_tx( driver->peripheral->peripheral ); usart_disable_rx( driver->peripheral->peripheral ); sysclk_disable_peripheral_clock( driver->peripheral->peripheral_id ); platform_gpio_deinit( driver->peripheral->tx_pin ); platform_gpio_deinit( driver->peripheral->rx_pin ); if ( driver->peripheral->cts_pin != NULL ) { platform_gpio_deinit( driver->peripheral->cts_pin ); } if ( driver->peripheral->rts_pin != NULL ) { platform_gpio_deinit( driver->peripheral->rts_pin ); } host_rtos_deinit_semaphore( &driver->tx_dma_complete ); host_rtos_deinit_semaphore( &driver->rx_dma_complete ); driver->peripheral = NULL; memset( driver, 0, sizeof(platform_uart_driver_t) ); return WICED_SUCCESS; }
/** * \brief Application entry point for pdc_usart 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 USART PDC register base */ g_p_usart_pdc = usart_get_pdc_base(CONSOLE_UART); /* Initialize PDC data packet for transfer */ g_pdc_usart_packet.ul_addr = (uint32_t) g_uc_pdc_buffer; g_pdc_usart_packet.ul_size = BUFFER_SIZE; /* Configure PDC for data receive */ pdc_rx_init(g_p_usart_pdc, &g_pdc_usart_packet, NULL); /* Enable PDC transfers */ pdc_enable_transfer(g_p_usart_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); /* Enable USART IRQ */ usart_enable_interrupt(CONSOLE_UART, US_IER_RXBUFF); /* Enable USART interrupt */ NVIC_EnableIRQ(CONSOLE_USART_IRQn); while (1) { } }
void serial_tx_abort_asynch(serial_t *obj) { /* Sanity check arguments */ MBED_ASSERT(obj); Pdc *pdc_base; usart_disable_interrupt(_USART(obj), US_IER_TXBUFE); pdc_base = usart_get_pdc_base(_USART(obj)); pdc_disable_transfer(pdc_base, PERIPH_PTCR_TXTEN); pSERIAL_S(obj)->acttra = false; }
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; }
void serial_rx_abort_asynch(serial_t *obj) { IRQn_Type irq_n = (IRQn_Type)0; /* Sanity check arguments */ MBED_ASSERT(obj); Pdc *pdc_base; usart_disable_interrupt(_USART(obj), US_IER_RXBUFF); pdc_base = usart_get_pdc_base(_USART(obj)); pdc_disable_transfer(pdc_base, PERIPH_PTCR_RXTEN); irq_n = get_serial_irq_num(obj); NVIC_ClearPendingIRQ(irq_n); NVIC_DisableIRQ(irq_n); pSERIAL_S(obj)->actrec = false; }
/** * \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; } } } }
OSStatus platform_uart_deinit( platform_uart_driver_t* driver ) { OSStatus err = kNoErr; platform_mcu_powersave_disable(); require_action_quiet( ( driver != NULL ), exit, err = kParamErr); usart_disable_interrupt( driver->peripheral->port, 0xffffffff ); NVIC_DisableIRQ( platform_flexcom_irq_numbers[driver->peripheral->uart_id] ); pdc_disable_transfer( usart_get_pdc_base( driver->peripheral->port ), PERIPH_PTCR_TXTDIS | PERIPH_PTCR_RXTDIS ); usart_disable_tx( driver->peripheral->port ); usart_disable_rx( driver->peripheral->port ); if( pmc_is_periph_clk_enabled( driver->peripheral->peripheral_id ) == 1 ) { flexcom_disable( driver->peripheral->flexcom_base ); } platform_gpio_deinit( driver->peripheral->tx_pin ); platform_gpio_deinit( driver->peripheral->rx_pin ); if ( driver->peripheral->cts_pin != NULL ) { platform_gpio_deinit( driver->peripheral->cts_pin ); } if ( driver->peripheral->rts_pin != NULL ) { platform_gpio_deinit( driver->peripheral->rts_pin ); } #ifndef NO_MICO_RTOS mico_rtos_deinit_semaphore(&driver->rx_complete); mico_rtos_deinit_semaphore(&driver->tx_complete); #endif driver->peripheral = NULL; memset( driver, 0, sizeof(platform_uart_driver_t) ); exit: platform_mcu_powersave_enable(); return err; }
/** * \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) { } }
/** * \brief This function opens an USART * * \note Opening of the specified USART implies initializing local variables and * opening required hardware with the following configuration: * - bauds as specified * - 8 bits, no parity, 1 stop bit * - enable interrupts * * \param chn Communication channel [0, 1] * \param bauds Communication speed in bauds * * \retval true on success. * \retval false on failure. */ int8_t busart_if_open(uint8_t chn, uint32_t bauds) { #if defined(CONF_BOARD_USART0_RXD) || defined(CONF_BOARD_USART1_RXD) sam_usart_opt_t usart_console_settings; /* Expected baud rate. */ usart_console_settings.baudrate = bauds; /* Configure channel mode (Normal, Automatic, Local_loopback or * Remote_loopback) */ usart_console_settings.channel_mode = US_MR_CHMODE_NORMAL; /* Initialize value for USART mode register */ usart_console_settings.parity_type = US_MR_PAR_NO; usart_console_settings.char_length = US_MR_CHRL_8_BIT; usart_console_settings.stop_bits = US_MR_NBSTOP_1_BIT; #else UNUSED(bauds); #endif /* check usart and it is close */ if (chn >= 2) { return false; } if (busart_chn_open[chn]) { return false; } switch (chn) { #ifdef CONF_BOARD_USART0_RXD case 0: { /* Configure PMC. */ pmc_enable_periph_clk(ID_USART0); /* Configure USART. */ usart_init_rs232(USART0, &usart_console_settings, sysclk_get_peripheral_hz()); /* Assign buffers to pointers */ busart_comm_data_0.puc_tq_buf = ptr_tx_usart_buf0; busart_comm_data_0.puc_rq_buf = ptr_rx_usart_buf0; busart_comm_data_0.us_rq_count = 0; busart_comm_data_0.us_rq_idx = 0; busart_comm_data_0.us_wq_idx = 0; /* Get board USART0 PDC base address and enable receiver and * transmitter. */ g_p_usart_pdc0 = usart_get_pdc_base(USART0); pdc_enable_transfer(g_p_usart_pdc0, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); /* Start receiving data and start timer. */ g_st_usart_rx_packet0.ul_addr = (uint32_t)gs_puc_usart_buf0; g_st_usart_rx_packet0.ul_size = USART_BUFFER_SIZE; pdc_rx_init(g_p_usart_pdc0, &g_st_usart_rx_packet0, NULL); /* Stop transmitting data */ g_st_usart_tx_packet0.ul_addr = (uint32_t)busart_comm_data_0.puc_tq_buf; g_st_usart_tx_packet0.ul_size = 0; pdc_tx_init(g_p_usart_pdc0, &g_st_usart_tx_packet0, NULL); gs_ul_size_usart_buf0 = USART_BUFFER_SIZE; /* Transfer to PDC communication mode, disable RXRDY interrupt * and enable RXBUFF interrupt. */ usart_disable_interrupt(USART0, US_IDR_RXRDY); usart_enable_interrupt(USART0, US_IER_RXBUFF); /* Enable the receiver and transmitter. */ usart_enable_tx(USART0); usart_enable_rx(USART0); /* Configure and enable interrupt of USART. */ NVIC_SetPriority((IRQn_Type)USART0_IRQn, USART0_PRIO); NVIC_EnableIRQ(USART0_IRQn); busart_chn_open[chn] = true; num_bytes_rx_usart0 = 0; /* Configure TC usart */ _configure_TC_usart(); tc_start(TC_USART, TC_USART_CHN); return true; } break; #endif #ifdef CONF_BOARD_USART1_RXD case 1: { /* Configure PMC. */ pmc_enable_periph_clk(ID_USART1); /* Configure USART. */ usart_init_rs232(USART1, &usart_console_settings, sysclk_get_peripheral_hz()); /* Assign buffers to pointers */ busart_comm_data_1.puc_tq_buf = ptr_tx_usart_buf1; busart_comm_data_1.puc_rq_buf = ptr_rx_usart_buf1; busart_comm_data_1.us_rq_count = 0; busart_comm_data_1.us_rq_idx = 0; busart_comm_data_1.us_wq_idx = 0; /* Get board USART1 PDC base address and enable receiver and * transmitter. */ g_p_usart_pdc1 = usart_get_pdc_base(USART1); pdc_enable_transfer(g_p_usart_pdc1, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); /* Start receiving data and start timer. */ 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); /* Stop transmitting data */ g_st_usart_tx_packet1.ul_addr = (uint32_t)busart_comm_data_1.puc_tq_buf; g_st_usart_tx_packet1.ul_size = 0; pdc_tx_init(g_p_usart_pdc1, &g_st_usart_tx_packet1, NULL); gs_ul_size_usart_buf1 = USART_BUFFER_SIZE; /* Transfer to PDC communication mode, disable RXRDY interrupt * and enable RXBUFF interrupt. */ usart_disable_interrupt(USART1, US_IDR_RXRDY); usart_enable_interrupt(USART1, US_IER_RXBUFF); /* Enable the receiver and transmitter. */ usart_enable_tx(USART1); usart_enable_rx(USART1); /* Configure and enable interrupt of USART. */ NVIC_SetPriority((IRQn_Type)USART1_IRQn, USART1_PRIO); NVIC_EnableIRQ(USART1_IRQn); busart_chn_open[chn] = true; num_bytes_rx_usart1 = 0; /* Configure TC usart */ _configure_TC_usart(); tc_start(TC_USART, TC_USART_CHN); return true; } break; #endif default: return false; } }
OSStatus platform_uart_init( platform_uart_driver_t* driver, const platform_uart_t* peripheral, const platform_uart_config_t* config, ring_buffer_t* optional_ring_buffer ) { pdc_packet_t pdc_uart_packet, pdc_uart_tx_packet; OSStatus err = kNoErr; sam_usart_opt_t settings; bool hardware_shaking = false; platform_mcu_powersave_disable(); require_action_quiet( ( driver != NULL ) && ( peripheral != NULL ) && ( config != NULL ), exit, err = kParamErr); require_action_quiet( (optional_ring_buffer->buffer != NULL ) && (optional_ring_buffer->size != 0), exit, err = kUnsupportedErr); driver->rx_size = 0; driver->tx_size = 0; driver->rx_ring_buffer = optional_ring_buffer; driver->last_transmit_result = kNoErr; driver->last_receive_result = kNoErr; driver->peripheral = (platform_uart_t*)peripheral; #ifndef NO_MICO_RTOS mico_rtos_init_semaphore( &driver->tx_complete, 1 ); mico_rtos_init_semaphore( &driver->rx_complete, 1 ); mico_rtos_init_semaphore( &driver->sem_wakeup, 1 ); mico_rtos_init_mutex ( &driver->tx_mutex ); #else driver->tx_complete = false; driver->rx_complete = false; #endif /* Set Tx and Rx pin mode to UART peripheral */ platform_gpio_peripheral_pin_init( peripheral->tx_pin, ( peripheral->tx_pin_mux_mode | IOPORT_MODE_PULLUP ) ); platform_gpio_peripheral_pin_init( peripheral->rx_pin, ( peripheral->rx_pin_mux_mode | IOPORT_MODE_PULLUP ) ); /* Init CTS and RTS pins (if available) */ if ( peripheral->cts_pin != NULL && (config->flow_control == FLOW_CONTROL_CTS || config->flow_control == FLOW_CONTROL_CTS_RTS) ) { hardware_shaking = true; platform_gpio_peripheral_pin_init( peripheral->cts_pin, ( peripheral->cts_pin_mux_mode | IOPORT_MODE_PULLUP ) ); } if ( peripheral->rts_pin != NULL && (config->flow_control == FLOW_CONTROL_CTS || config->flow_control == FLOW_CONTROL_CTS_RTS) ) { hardware_shaking = true; platform_gpio_peripheral_pin_init( peripheral->rts_pin, ( peripheral->rts_pin_mux_mode | IOPORT_MODE_PULLUP ) ); } /* Enable the clock. */ if( pmc_is_periph_clk_enabled( peripheral->peripheral_id ) == 0 ) { flexcom_enable( peripheral->flexcom_base ); } flexcom_set_opmode( peripheral->flexcom_base, FLEXCOM_USART ); /* Enable the receiver and transmitter. */ usart_reset_tx( peripheral->port ); usart_reset_rx( peripheral->port ); /* Disable all the interrupts. */ usart_disable_interrupt( peripheral->port, 0xffffffff ); switch ( config->parity ) { case NO_PARITY: settings.parity_type = US_MR_PAR_NO; break; case EVEN_PARITY: settings.parity_type = US_MR_PAR_EVEN; break; case ODD_PARITY: settings.parity_type = US_MR_PAR_ODD; break; default: err = kParamErr; goto exit; } switch ( config->data_width) { case DATA_WIDTH_5BIT: settings.char_length = US_MR_CHRL_5_BIT; break; case DATA_WIDTH_6BIT: settings.char_length = US_MR_CHRL_6_BIT; break; case DATA_WIDTH_7BIT: settings.char_length = US_MR_CHRL_7_BIT; break; case DATA_WIDTH_8BIT: settings.char_length = US_MR_CHRL_8_BIT; break; case DATA_WIDTH_9BIT: settings.char_length = US_MR_MODE9; break; default: err = kParamErr; goto exit; } settings.baudrate = config->baud_rate; settings.stop_bits = ( config->stop_bits == STOP_BITS_1 ) ? US_MR_NBSTOP_1_BIT : US_MR_NBSTOP_2_BIT; settings.channel_mode= US_MR_CHMODE_NORMAL; /* Configure USART in serial mode. */ if (!hardware_shaking) { usart_init_rs232( peripheral->port, &settings, sysclk_get_peripheral_hz()); } else { usart_init_hw_handshaking( peripheral->port, &settings, sysclk_get_peripheral_hz()); } /* Enable uart interrupt */ NVIC_SetPriority( platform_flexcom_irq_numbers[peripheral->uart_id], 0x06 ); NVIC_EnableIRQ( platform_flexcom_irq_numbers[peripheral->uart_id] ); /* Enable PDC transmit */ pdc_enable_transfer( usart_get_pdc_base( peripheral->port ), PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN ); pdc_disable_transfer( usart_get_pdc_base( driver->peripheral->port ), PERIPH_PTCR_TXTDIS ); pdc_uart_packet.ul_addr = (uint32_t)driver->rx_ring_buffer->buffer; pdc_uart_packet.ul_size = (uint32_t)driver->rx_ring_buffer->size; pdc_rx_init( usart_get_pdc_base( peripheral->port ), &pdc_uart_packet, &pdc_uart_packet ); pdc_uart_tx_packet.ul_addr = (uint32_t)0; pdc_uart_tx_packet.ul_size = (uint32_t)1; pdc_tx_init( usart_get_pdc_base( driver->peripheral->port ), &pdc_uart_tx_packet, NULL ); usart_enable_interrupt( peripheral->port, US_IER_ENDRX | US_IER_RXBUFF | US_IER_RXRDY | US_IER_ENDTX ); /* Enable the receiver and transmitter. */ usart_enable_tx( peripheral->port ); usart_enable_rx( peripheral->port ); exit: platform_mcu_powersave_enable( ); return err; }
/** * \brief Application entry point. * * Initialize the IrDA and start the main loop. * * \return Unused (ANSI-C compatibility). */ int main(void) { uint8_t uc_char; /* Initialize the SAM system. */ sysclk_init(); board_init(); /* Configure UART for debug message output. */ configure_console(); /* Output example information. */ puts(STRING_HEADER); /* Initialize board 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); puts("-I- Press t to transmit, press r to receive...\r"); /* Main loop. */ while (1) { uc_char = 0; uart_read(CONSOLE_UART, (uint8_t *)&uc_char); switch (uc_char) { case 't': case 'T': g_uc_state = STATE_TRANSMIT; /* Enable transmitter. */ func_transmitter(); g_st_packet.ul_addr = (uint32_t)g_uc_send_data; g_st_packet.ul_size = BUFFER_SIZE; pdc_tx_init(g_p_pdc, &g_st_packet, NULL); usart_enable_interrupt(BOARD_USART, US_IER_TXBUFE); while (!g_ul_sent_done) { } puts("-I- Sent Done!\r"); g_ul_sent_done = false; g_uc_state = STATE_IDLE; puts("-I- Press t to transmit, press r to receive...\r"); break; case 'r': case 'R': g_uc_state = STATE_RECEIVE; /* Enable receiver. */ puts("-I- IrDA receive mode\r"); func_receiver(); g_st_packet.ul_addr = (uint32_t)g_uc_recv_data; g_st_packet.ul_size = BUFFER_SIZE; pdc_rx_init(g_p_pdc, &g_st_packet, NULL); usart_enable_interrupt(BOARD_USART, US_IER_RXBUFF); while (!g_ul_recv_done) { } puts("-I- Received Done! \r"); dump_recv_buf(g_uc_recv_data, BUFFER_SIZE); memset(g_uc_recv_data, 0, BUFFER_SIZE); g_uc_state = STATE_IDLE; g_ul_recv_done = false; puts("-I- Press t to transmit, press r to receive...\r"); break; default: break; } } }
platform_result_t platform_uart_init( platform_uart_driver_t* driver, const platform_uart_t* peripheral, const platform_uart_config_t* config, wiced_ring_buffer_t* optional_ring_buffer ) { sam_usart_opt_t settings; UNUSED_PARAMETER(driver); UNUSED_PARAMETER(peripheral); UNUSED_PARAMETER(config); UNUSED_PARAMETER(optional_ring_buffer); pdc_packet_t dma_packet; if ( config->flow_control != FLOW_CONTROL_DISABLED ) { return WICED_UNSUPPORTED; } memset( &settings, 0, sizeof( settings ) ); switch ( config->data_width ) { case DATA_WIDTH_5BIT: settings.char_length = US_MR_CHRL_5_BIT; break; case DATA_WIDTH_6BIT: settings.char_length = US_MR_CHRL_6_BIT; break; case DATA_WIDTH_7BIT: settings.char_length = US_MR_CHRL_7_BIT; break; case DATA_WIDTH_8BIT: settings.char_length = US_MR_CHRL_8_BIT; break; case DATA_WIDTH_9BIT: default: return WICED_UNSUPPORTED; } switch ( config->parity ) { case ODD_PARITY: settings.parity_type = US_MR_PAR_ODD; break; case EVEN_PARITY: settings.parity_type = US_MR_PAR_EVEN; break; case NO_PARITY: settings.parity_type = US_MR_PAR_NO; break; default: break; } switch ( config->stop_bits ) { case STOP_BITS_1: settings.stop_bits = US_MR_NBSTOP_1_BIT; break; case STOP_BITS_2: settings.stop_bits = US_MR_NBSTOP_2_BIT; break; default: break; } settings.baudrate = config->baud_rate; settings.channel_mode = US_MR_CHMODE_NORMAL; driver->peripheral = peripheral; // /* Initialise TX and RX complete semaphores */ host_rtos_init_semaphore( &driver->tx_dma_complete ); host_rtos_init_semaphore( &driver->rx_dma_complete ); /* Set Tx and Rx pin mode to UART peripheral */ platform_gpio_peripheral_pin_init( peripheral->tx_pin, ( IOPORT_MODE_MUX_A | IOPORT_MODE_PULLUP ) ); platform_gpio_peripheral_pin_init( peripheral->rx_pin, ( IOPORT_MODE_MUX_A | IOPORT_MODE_PULLUP ) ); /* Init CTS and RTS pins (if available) */ if ( peripheral->cts_pin != NULL ) { platform_gpio_peripheral_pin_init( peripheral->cts_pin, ( IOPORT_MODE_MUX_A | IOPORT_MODE_PULLUP ) ); } if ( peripheral->rts_pin != NULL ) { platform_gpio_peripheral_pin_init( peripheral->rts_pin, ( IOPORT_MODE_MUX_A | IOPORT_MODE_PULLUP ) ); } /* Enable the peripheral clock in the PMC. */ sysclk_enable_peripheral_clock( peripheral->peripheral_id ); /* Enable the receiver and transmitter. */ usart_reset_tx( peripheral->peripheral ); usart_reset_rx( peripheral->peripheral ); /* Configure USART in serial mode. */ usart_init_rs232( peripheral->peripheral, &settings, CPU_CLOCK_HZ ); /* Disable all the interrupts. */ usart_disable_interrupt( peripheral->peripheral, 0xffffffff ); /* Enable uart interrupt */ NVIC_SetPriority( platform_uarts_irq_numbers[peripheral->uart_id], 0x06 ); NVIC_EnableIRQ( platform_uarts_irq_numbers[peripheral->uart_id] ); /* Enable PDC transmit */ pdc_enable_transfer( usart_get_pdc_base( peripheral->peripheral ), PERIPH_PTCR_TXTEN | PERIPH_PTCR_RXTEN ); driver->rx_ring_buffer = optional_ring_buffer; dma_packet.ul_addr = (uint32_t)driver->rx_ring_buffer->buffer; dma_packet.ul_size = (uint32_t)driver->rx_ring_buffer->size; pdc_rx_init( usart_get_pdc_base( peripheral->peripheral ), &dma_packet, &dma_packet ); usart_enable_interrupt( peripheral->peripheral, US_IER_ENDRX | US_IER_RXBUFF | US_IER_RXRDY | US_IER_ENDTX ); /* Enable the receiver and transmitter. */ usart_enable_tx( peripheral->peripheral ); usart_enable_rx( peripheral->peripheral ); return PLATFORM_SUCCESS; }
GCodeResult SetColours(GCodeBuffer& gb, const StringRef& reply) { if (busy) // if we sent something { if ((DotStarUsart->US_CSR & US_CSR_ENDTX) == 0) // if we are still sending { return GCodeResult::notFinished; } busy = false; // we finished the last transfer } bool seen = false; uint32_t red = 0, green = 0, blue = 0, brightness = 16, numLeds = MaxChunkSize, following = 0; gb.TryGetUIValue('R', red, seen); gb.TryGetUIValue('U', green, seen); gb.TryGetUIValue('B', blue, seen); gb.TryGetUIValue('Y', brightness, seen); gb.TryGetUIValue('S', numLeds, seen); gb.TryGetUIValue('F', following, seen); if (!seen || (numLeds == 0 && !needStartFrame && !following)) { return GCodeResult::ok; } if (numRemaining != 0) { numLeds = numRemaining; // we have come back to do another chunk } // Set up the data in the DMA buffer. // Sending at least 32 zero bits (start frame) tells the LEDs that this is new data starting with the first LED in the strip. // The first 1 bit indicates the start of the data frame for the first LED. // There is a half-bit delay in each LED before the data is shifted out to the next LED. This means that we need to send at least an extra N/2 bits of data, // where N is the number of LEDs in the strip. The datasheet says to send 32 bits of 1 but this is only sufficient for up to 64 LEDs. Sending 1s can lead to a spurious // white LED at the end if we don't provide data for all the LEDs. So instead we send 32 or more bits of zeros. // See https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/ for more. unsigned int spaceLeft = MaxChunkSize; uint32_t *p = chunkBuffer; if (needStartFrame) { *p++ = 0; // start frame --spaceLeft; // one less slot available for data totalSent = 0; } // Can we fit the remaining data and stop bits in the buffer? unsigned int numStopWordsNeeded = (following) ? 0 : min<unsigned int>((numLeds + totalSent + 63)/64, MaxChunkSize - 1); unsigned int thisChunk; if (numLeds + numStopWordsNeeded <= spaceLeft) { thisChunk = numLeds; } else { thisChunk = min<unsigned int>(spaceLeft, numLeds - 1); numStopWordsNeeded = 0; } numRemaining = numLeds - thisChunk; totalSent += thisChunk; needStartFrame = (numRemaining == 0 && following == 0); for (unsigned int i = 0; i < thisChunk; ++i) { // According to the Adafruit web site, current production uses the order BGR *p++ = (brightness & 31) | 0xE0 | ((blue & 255) << 8) | ((green & 255) << 16) | ((red & 255) << 24); // LED frame } for (unsigned int i = 0; i < numStopWordsNeeded; ++i) { *p++ = 0; // append some stop bits } // DMA the data DotStarUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_TXDIS; // reset transmitter and receiver, disable transmitter Pdc * const usartPdc = usart_get_pdc_base(DotStarUsart); usartPdc->PERIPH_PTCR = PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS; // disable the PDC usartPdc->PERIPH_TPR = reinterpret_cast<uint32_t>(&chunkBuffer); usartPdc->PERIPH_TCR = 4 * (p - chunkBuffer); // number of bytes to transfer usartPdc->PERIPH_PTCR = PERIPH_PTCR_TXTEN; // enable the PDC to send data DotStarUsart->US_CR = US_CR_TXEN; // enable transmitter busy = true; return (numRemaining == 0) ? GCodeResult::ok : GCodeResult::notFinished; }
/** * \brief Application entry point. * * Configure USART in synchronous master/slave mode to start a transmission * between two boards. * \return Unused. */ int main(void) { uint8_t uc_char; /* Initialize the SAM system. */ sysclk_init(); board_init(); /* Configure UART for debug message output. */ configure_console(); /* Output example information. */ puts(STRING_HEADER); /* Display main menu. */ display_main_menu(); /* Configure USART. */ configure_usart(SYNC_MASTER, g_ul_freq[g_uc_freq_idx]); /* 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); g_uc_transfer_mode = SYNC_MASTER; g_uc_state = STATE_WRITE; puts("-- USART in MASTER mode --\r"); while (1) { uc_char = 0; scanf("%c", (char *)&uc_char); switch (uc_char) { case '0': case '1': case '2': case '3': g_uc_freq_idx = uc_char - '0'; printf("-- The clock freq is: %luHz.\r\n", (unsigned long)g_ul_freq[g_uc_freq_idx]); configure_usart(SYNC_MASTER, g_ul_freq[g_uc_freq_idx]); break; case 'i': case 'I': if (g_uc_transfer_mode == SYNC_MASTER) { printf("-- USART is MASTER at %luHz.\r\n", (unsigned long)g_ul_freq[g_uc_freq_idx]); } else { puts("-- USART is SLAVE \r"); } break; case 's': case 'S': if (g_uc_transfer_mode == SYNC_MASTER) { g_uc_transfer_mode = SYNC_SLAVE; configure_usart(SYNC_SLAVE, g_ul_freq[g_uc_freq_idx]); puts("-- USART in SLAVE mode --\r"); } else { if (g_uc_transfer_mode == SYNC_SLAVE) { g_uc_transfer_mode = SYNC_MASTER; configure_usart(SYNC_MASTER, g_ul_freq[g_uc_freq_idx]); puts("-- USART in MASTER mode --\r"); } } break; case 'w': case 'W': g_uc_state = STATE_WRITE; g_st_packet.ul_addr = (uint32_t)tran_buff; g_st_packet.ul_size = BUFFER_SIZE; pdc_tx_init(g_p_pdc, &g_st_packet, NULL); usart_enable_interrupt(BOARD_USART, US_IER_TXBUFE); while (!g_ul_sent_done) { } if (g_ul_sent_done) { printf("-- %s sent done --\r\n", g_uc_transfer_mode ? "MASTER" : "SLAVE"); } break; case 'r': case 'R': g_uc_state = STATE_READ; if (g_uc_transfer_mode == SYNC_MASTER) { puts("----USART MASTER Read----\r"); } else { puts("----USART SLAVE Read----\r"); } g_st_packet.ul_addr = (uint32_t)g_c_recv_buff; g_st_packet.ul_size = BUFFER_SIZE; pdc_rx_init(g_p_pdc, &g_st_packet, NULL); usart_enable_interrupt(BOARD_USART, US_IER_RXBUFF); while (!g_ul_recv_done) { } if (g_ul_recv_done) { if (strncmp((char*)g_c_recv_buff, tran_buff, BUFFER_SIZE)) { puts(" -F-: Failed!\r"); } else { /* successfully received */ dump_info((char*)g_c_recv_buff, BUFFER_SIZE); } puts("----END of read----\r"); memset(g_c_recv_buff, 0, sizeof(g_c_recv_buff)); g_ul_recv_done = false; } break; case 'm': case 'M': display_main_menu(); break; default: break; } } }