Skip to content

Commit d451f69

Browse files
authored
Merge pull request #9 from adafruit/ticks_ms
Support ticks in os.
2 parents 011056a + 2ee52c4 commit d451f69

File tree

5 files changed

+67
-3
lines changed

5 files changed

+67
-3
lines changed

atmel-samd/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,9 @@ void samd21_init(void) {
316316

317317
board_init();
318318

319+
// SysTick millisecond timer initialization.
320+
SysTick_Config(system_cpu_clock_get_hz() / 1000);
321+
319322
// Uncomment to init PIN_PA17 for debugging.
320323
// struct port_config pin_conf;
321324
// port_get_config_defaults(&pin_conf);

atmel-samd/modutime.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,27 @@ STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
6464
}
6565
STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_us_obj, time_sleep_us);
6666

67+
STATIC mp_obj_t time_ticks_ms(void) {
68+
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & MP_SMALL_INT_POSITIVE_MASK);
69+
}
70+
STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_ms_obj, time_ticks_ms);
71+
72+
STATIC mp_obj_t time_ticks_diff(mp_obj_t start_in, mp_obj_t end_in) {
73+
// we assume that the arguments come from ticks_xx so are small ints
74+
uint32_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
75+
uint32_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
76+
return MP_OBJ_NEW_SMALL_INT((end - start) & MP_SMALL_INT_POSITIVE_MASK);
77+
}
78+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(time_ticks_diff_obj, time_ticks_diff);
79+
6780
STATIC const mp_map_elem_t time_module_globals_table[] = {
6881
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) },
6982

7083
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj },
7184
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&time_sleep_ms_obj },
7285
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&time_sleep_us_obj },
86+
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&time_ticks_ms_obj },
87+
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&time_ticks_diff_obj },
7388
};
7489

7590
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);

atmel-samd/mphalport.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,35 @@ void mp_hal_delay_us(mp_uint_t delay) {
210210
}
211211
delay_us(delay);
212212
}
213+
214+
// Global millisecond tick count (driven by SysTick interrupt handler).
215+
volatile uint32_t systick_ticks_ms = 0;
216+
217+
void SysTick_Handler(void) {
218+
// SysTick interrupt handler called when the SysTick timer reaches zero
219+
// (every millisecond).
220+
systick_ticks_ms += 1;
221+
// Keep the counter within the range of 31 bit uint values since that's the
222+
// max value for micropython 'small' ints.
223+
systick_ticks_ms = systick_ticks_ms > (0xFFFFFFFF >> 1) ? 0 : systick_ticks_ms;
224+
}
225+
226+
// Interrupt flags that will be saved and restored during disable/Enable
227+
// interrupt functions below.
228+
static irqflags_t irq_flags;
229+
230+
void mp_hal_disable_all_interrupts(void) {
231+
// Disable all interrupt sources for timing critical sections.
232+
// Disable ASF-based interrupts.
233+
irq_flags = cpu_irq_save();
234+
// Disable SysTick interrupt.
235+
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
236+
}
237+
238+
void mp_hal_enable_all_interrupts(void) {
239+
// Enable all interrupt sources after timing critical sections.
240+
// Restore SysTick interrupt.
241+
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
242+
// Restore ASF-based interrupts.
243+
cpu_irq_restore(irq_flags);
244+
}

atmel-samd/mphalport.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,21 @@
2727
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
2828
#define __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
2929

30+
#include "py/obj.h"
31+
3032
#define USB_RX_BUF_SIZE 128
3133

32-
static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; }
34+
// Global millisecond tick count (driven by SysTick interrupt).
35+
extern volatile uint32_t systick_ticks_ms;
36+
37+
static inline mp_uint_t mp_hal_ticks_ms(void) {
38+
return systick_ticks_ms;
39+
}
40+
3341
void mp_hal_set_interrupt_char(int c);
3442

43+
void mp_hal_disable_all_interrupts(void);
44+
45+
void mp_hal_enable_all_interrupts(void);
46+
3547
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__

atmel-samd/samdneopixel.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "asf/common2/services/delay/delay.h"
22
#include "asf/sam0/drivers/port/port.h"
33

4+
#include "mphalport.h"
5+
46
#include "samdneopixel.h"
57

68
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
1113
PortGroup* port;
1214

1315
// Turn off interrupts of any kind during timing-sensitive code.
14-
irqflags_t flags = cpu_irq_save();
16+
mp_hal_disable_all_interrupts();
1517

1618
port = port_get_group_from_gpio_pin(pin);
1719
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
7880
}
7981

8082
// Turn on interrupts after timing-sensitive code.
81-
cpu_irq_restore(flags);
83+
mp_hal_enable_all_interrupts();
8284

8385
// 50ms delay to let pixels latch to the data that was just sent.
8486
// This could be optimized to only occur before pixel writes when necessary,

0 commit comments

Comments
 (0)