atmel-samd: Implement time.ticks_ms function using SysTick timer, add global interrupt enable/disable functions.

This commit is contained in:
Tony DiCola 2016-10-13 04:59:43 +00:00
parent 011056af15
commit 903bc8d04e
5 changed files with 58 additions and 3 deletions

View File

@ -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);

View File

@ -64,12 +64,18 @@ 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 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 },
};
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);

View File

@ -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 > 2147483647L ? 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 ASF-based interrupts.
cpu_irq_restore(irq_flags);
// Restore SysTick interrupt.
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
}

View File

@ -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__

View File

@ -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,