commit
d451f690ef
@ -316,6 +316,9 @@ void samd21_init(void) {
|
||||
|
||||
board_init();
|
||||
|
||||
// SysTick millisecond timer initialization.
|
||||
SysTick_Config(system_cpu_clock_get_hz() / 1000);
|
||||
|
||||
// Uncomment to init PIN_PA17 for debugging.
|
||||
// struct port_config pin_conf;
|
||||
// port_get_config_defaults(&pin_conf);
|
||||
|
@ -64,12 +64,27 @@ STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_us_obj, time_sleep_us);
|
||||
|
||||
STATIC mp_obj_t time_ticks_ms(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & MP_SMALL_INT_POSITIVE_MASK);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_ms_obj, time_ticks_ms);
|
||||
|
||||
STATIC mp_obj_t time_ticks_diff(mp_obj_t start_in, mp_obj_t end_in) {
|
||||
// we assume that the arguments come from ticks_xx so are small ints
|
||||
uint32_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
|
||||
uint32_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
|
||||
return MP_OBJ_NEW_SMALL_INT((end - start) & MP_SMALL_INT_POSITIVE_MASK);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(time_ticks_diff_obj, time_ticks_diff);
|
||||
|
||||
STATIC const mp_map_elem_t time_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&time_sleep_ms_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&time_sleep_us_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&time_ticks_ms_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&time_ticks_diff_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
|
||||
|
@ -210,3 +210,35 @@ void mp_hal_delay_us(mp_uint_t delay) {
|
||||
}
|
||||
delay_us(delay);
|
||||
}
|
||||
|
||||
// Global millisecond tick count (driven by SysTick interrupt handler).
|
||||
volatile uint32_t systick_ticks_ms = 0;
|
||||
|
||||
void SysTick_Handler(void) {
|
||||
// SysTick interrupt handler called when the SysTick timer reaches zero
|
||||
// (every millisecond).
|
||||
systick_ticks_ms += 1;
|
||||
// Keep the counter within the range of 31 bit uint values since that's the
|
||||
// max value for micropython 'small' ints.
|
||||
systick_ticks_ms = systick_ticks_ms > (0xFFFFFFFF >> 1) ? 0 : systick_ticks_ms;
|
||||
}
|
||||
|
||||
// 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();
|
||||
// Disable SysTick interrupt.
|
||||
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
|
||||
}
|
||||
|
||||
void mp_hal_enable_all_interrupts(void) {
|
||||
// Enable all interrupt sources after timing critical sections.
|
||||
// Restore SysTick interrupt.
|
||||
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
|
||||
// Restore ASF-based interrupts.
|
||||
cpu_irq_restore(irq_flags);
|
||||
}
|
||||
|
@ -27,9 +27,21 @@
|
||||
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
|
||||
#define __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
#define USB_RX_BUF_SIZE 128
|
||||
|
||||
static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; }
|
||||
// Global millisecond tick count (driven by SysTick interrupt).
|
||||
extern volatile uint32_t systick_ticks_ms;
|
||||
|
||||
static inline mp_uint_t mp_hal_ticks_ms(void) {
|
||||
return systick_ticks_ms;
|
||||
}
|
||||
|
||||
void mp_hal_set_interrupt_char(int c);
|
||||
|
||||
void mp_hal_disable_all_interrupts(void);
|
||||
|
||||
void mp_hal_enable_all_interrupts(void);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "asf/common2/services/delay/delay.h"
|
||||
#include "asf/sam0/drivers/port/port.h"
|
||||
|
||||
#include "mphalport.h"
|
||||
|
||||
#include "samdneopixel.h"
|
||||
|
||||
void samd_neopixel_write(uint32_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz) {
|
||||
@ -11,7 +13,7 @@ void samd_neopixel_write(uint32_t pin, uint8_t *pixels, uint32_t numBytes, bool
|
||||
PortGroup* port;
|
||||
|
||||
// Turn off interrupts of any kind during timing-sensitive code.
|
||||
irqflags_t flags = cpu_irq_save();
|
||||
mp_hal_disable_all_interrupts();
|
||||
|
||||
port = port_get_group_from_gpio_pin(pin);
|
||||
pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code.
|
||||
@ -78,7 +80,7 @@ void samd_neopixel_write(uint32_t pin, uint8_t *pixels, uint32_t numBytes, bool
|
||||
}
|
||||
|
||||
// Turn on interrupts after timing-sensitive code.
|
||||
cpu_irq_restore(flags);
|
||||
mp_hal_enable_all_interrupts();
|
||||
|
||||
// 50ms delay to let pixels latch to the data that was just sent.
|
||||
// This could be optimized to only occur before pixel writes when necessary,
|
||||
|
Loading…
Reference in New Issue
Block a user