commit
d451f690ef
@ -316,6 +316,9 @@ void samd21_init(void) {
|
|||||||
|
|
||||||
board_init();
|
board_init();
|
||||||
|
|
||||||
|
// SysTick millisecond timer initialization.
|
||||||
|
SysTick_Config(system_cpu_clock_get_hz() / 1000);
|
||||||
|
|
||||||
// Uncomment to init PIN_PA17 for debugging.
|
// Uncomment to init PIN_PA17 for debugging.
|
||||||
// struct port_config pin_conf;
|
// struct port_config pin_conf;
|
||||||
// port_get_config_defaults(&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_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[] = {
|
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___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), (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_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_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);
|
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);
|
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__
|
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
|
||||||
#define __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
|
#define __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
#define USB_RX_BUF_SIZE 128
|
#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_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__
|
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "asf/common2/services/delay/delay.h"
|
#include "asf/common2/services/delay/delay.h"
|
||||||
#include "asf/sam0/drivers/port/port.h"
|
#include "asf/sam0/drivers/port/port.h"
|
||||||
|
|
||||||
|
#include "mphalport.h"
|
||||||
|
|
||||||
#include "samdneopixel.h"
|
#include "samdneopixel.h"
|
||||||
|
|
||||||
void samd_neopixel_write(uint32_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz) {
|
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;
|
PortGroup* port;
|
||||||
|
|
||||||
// Turn off interrupts of any kind during timing-sensitive code.
|
// 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);
|
port = port_get_group_from_gpio_pin(pin);
|
||||||
pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code.
|
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.
|
// 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.
|
// 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,
|
// This could be optimized to only occur before pixel writes when necessary,
|
||||||
|
Loading…
Reference in New Issue
Block a user