diff options
Diffstat (limited to 'atmel-samd/mphalport.c')
| -rw-r--r-- | atmel-samd/mphalport.c | 204 |
1 files changed, 24 insertions, 180 deletions
diff --git a/atmel-samd/mphalport.c b/atmel-samd/mphalport.c index c1aebe08a..dc23c7190 100644 --- a/atmel-samd/mphalport.c +++ b/atmel-samd/mphalport.c @@ -1,51 +1,35 @@ #include <string.h> -#include "autoreload.h" -#include "compiler.h" -#include "asf/common/services/sleepmgr/sleepmgr.h" -#include "asf/common/services/usb/class/cdc/device/udi_cdc.h" -#include "asf/common2/services/delay/delay.h" -#include "asf/sam0/drivers/port/port.h" -#include "asf/sam0/drivers/sercom/usart/usart.h" #include "lib/mp-readline/readline.h" #include "lib/utils/interrupt_char.h" #include "py/mphal.h" #include "py/mpstate.h" #include "py/runtime.h" #include "py/smallint.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/time/__init__.h" +#include "supervisor/shared/autoreload.h" + +#include "hal/include/hal_atomic.h" +#include "hal/include/hal_delay.h" +#include "hal/include/hal_gpio.h" +#include "hal/include/hal_sleep.h" #include "mpconfigboard.h" #include "mphalport.h" - -// Store received characters on our own so that we can filter control characters -// and act immediately on CTRL-C for example. -// This is adapted from asf/thirdparty/wireless/addons/sio2host - -// Receive buffer -static uint8_t usb_rx_buf[USB_RX_BUF_SIZE]; - -// Receive buffer head -static volatile uint8_t usb_rx_buf_head; - -// Receive buffer tail -static volatile uint8_t usb_rx_buf_tail; - -// Number of bytes in receive buffer -volatile uint8_t usb_rx_count; - -volatile bool mp_cdc_enabled = false; +#include "reset.h" +#include "usb.h" extern struct usart_module usart_instance; // Read by main to know when USB is connected. volatile bool mp_msc_enabled = false; -bool mp_msc_enable() { +bool mp_msc_enable(void) { mp_msc_enabled = true; return true; } -void mp_msc_disable() { +void mp_msc_disable(void) { mp_msc_enabled = false; } @@ -71,165 +55,33 @@ void usb_rts_notify(uint8_t port, bool set) { return; } -void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding) { - reset_on_disconnect = coding->dwDTERate == 1200; -} - -void usb_rx_notify(void) { - irqflags_t flags; - if (mp_cdc_enabled) { - while (udi_cdc_is_rx_ready()) { - uint8_t c; - - // Introduce a critical section to avoid buffer corruption. We use - // cpu_irq_save instead of cpu_irq_disable because we don't know the - // current state of IRQs. They may have been turned off already and - // we don't want to accidentally turn them back on. - flags = cpu_irq_save(); - // If our buffer is full, then don't get another character otherwise - // we'll lose a previous character. - if (usb_rx_count >= USB_RX_BUF_SIZE) { - cpu_irq_restore(flags); - break; - } - - uint8_t current_tail = usb_rx_buf_tail; - // Pretend we've received a character so that any nested calls to - // this function have to consider the spot we've reserved. - if ((USB_RX_BUF_SIZE - 1) == usb_rx_buf_tail) { - // Reached the end of buffer, revert back to beginning of - // buffer. - usb_rx_buf_tail = 0x00; - } else { - usb_rx_buf_tail++; - } - // The count of characters present in receive buffer is - // incremented. - usb_rx_count++; - // WARNING(tannewt): This call can call us back with the next - // character! - c = udi_cdc_getc(); - - if (c == mp_interrupt_char) { - // We consumed a character rather than adding it to the rx - // buffer so undo the modifications we made to count and the - // tail. - usb_rx_count--; - usb_rx_buf_tail = current_tail; - cpu_irq_restore(flags); - mp_keyboard_interrupt(); - // Don't put the interrupt into the buffer, just continue. - continue; - } - - // We put the next character where we expected regardless of whether - // the next character was already loaded in the buffer. - usb_rx_buf[current_tail] = c; - - cpu_irq_restore(flags); - } - } -} - -int receive_usb(void) { - if (usb_rx_count == 0) { - return 0; - } - - // Copy from head. - cpu_irq_disable(); - int data = usb_rx_buf[usb_rx_buf_head]; - usb_rx_buf_head++; - usb_rx_count--; - if ((USB_RX_BUF_SIZE) == usb_rx_buf_head) { - usb_rx_buf_head = 0; - } - cpu_irq_enable(); - - // Call usb_rx_notify if we just emptied a spot in the buffer. - if (usb_rx_count == USB_RX_BUF_SIZE - 1) { - usb_rx_notify(); - } - return data; -} +// void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding) { +// reset_on_disconnect = coding->dwDTERate == 1200; +// } int mp_hal_stdin_rx_chr(void) { for (;;) { #ifdef MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_LOOP #endif - // Check to see if we've been CTRL-Ced by autoreload or the user. Raise the exception if so. - if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) { - mp_handle_pending(); - } - - #ifdef USB_REPL - if (reload_next_character) { - return CHAR_CTRL_D; - } - if (usb_rx_count > 0) { + // if (reload_next_character) { + // return CHAR_CTRL_D; + // } + if (usb_bytes_available()) { #ifdef MICROPY_HW_LED_RX - port_pin_toggle_output_level(MICROPY_HW_LED_RX); + gpio_toggle_pin_level(MICROPY_HW_LED_RX); #endif - return receive_usb(); + return usb_read(); } - #endif - #ifdef UART_REPL - uint16_t temp; - if (usart_read_wait(&usart_instance, &temp) == STATUS_OK) { - #ifdef MICROPY_HW_LED_RX - port_pin_toggle_output_level(MICROPY_HW_LED_RX); - #endif - return temp; - } - #endif - // TODO(tannewt): Switch to callback/interrupt based UART so it can work - // with the sleepmgr. - sleepmgr_enter_sleep(); } } void mp_hal_stdout_tx_strn(const char *str, size_t len) { #ifdef MICROPY_HW_LED_TX - port_pin_toggle_output_level(MICROPY_HW_LED_TX); + gpio_toggle_pin_level(MICROPY_HW_LED_TX); #endif - #ifdef UART_REPL - usart_write_buffer_wait(&usart_instance, (uint8_t*) str, len); - #endif - - #ifdef CIRCUITPY_BOOT_OUTPUT_FILE - if (boot_output_file != NULL) { - UINT bytes_written = 0; - f_write(boot_output_file, str, len, &bytes_written); - } - #endif - - #ifdef USB_REPL - // Always make sure there is enough room in the usb buffer for the outgoing - // string. If there isn't we risk getting caught in a loop within the usb - // code as it tries to send all the characters it can't buffer. - uint32_t start = 0; - uint64_t start_tick = common_hal_time_monotonic(); - uint64_t duration = 0; - if (mp_cdc_enabled) { - while (start < len && duration < 10) { - uint8_t buffer_space = udi_cdc_get_free_tx_buffer(); - uint8_t transmit = min(len - start, buffer_space); - if (transmit > 0) { - if (udi_cdc_write_buf(str + start, transmit) > 0) { - // It didn't transmit successfully so give up. - break; - } - } - start += transmit; - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - duration = (common_hal_time_monotonic() - start_tick); - } - } - #endif + usb_write(str, len); } void mp_hal_delay_ms(mp_uint_t delay) { @@ -252,18 +104,10 @@ void mp_hal_delay_us(mp_uint_t delay) { delay_us(delay); } -// Interrupt flags that will be saved and restored during disable/Enable -// interrupt functions below. -static irqflags_t irq_flags; - void mp_hal_disable_all_interrupts(void) { - // Disable all interrupt sources for timing critical sections. - // Disable ASF-based interrupts. - irq_flags = cpu_irq_save(); + common_hal_mcu_disable_interrupts(); } void mp_hal_enable_all_interrupts(void) { - // Enable all interrupt sources after timing critical sections. - // Restore ASF-based interrupts. - cpu_irq_restore(irq_flags); + common_hal_mcu_enable_interrupts(); } |
