summaryrefslogtreecommitdiff
path: root/atmel-samd
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2017-05-04 11:57:51 -0700
committerScott Shawcroft <scott.shawcroft@gmail.com>2017-05-04 11:57:51 -0700
commit5ad426124bf15a50edd6aeda50a228933dee8507 (patch)
tree13538488593fb23ef3c1b3443ead8effa593133f /atmel-samd
parent6512ccf32ec962c094117f9d8ec712f8c209e655 (diff)
atmel-samd: Move heap objects into MICROPY_PORT_ROOT_POINTERS so they don't get garbage collected while we are using them.
Diffstat (limited to 'atmel-samd')
-rw-r--r--atmel-samd/boards/circuitplayground_express/pins.c2
-rw-r--r--atmel-samd/common-hal/audioio/AudioOut.c137
-rw-r--r--atmel-samd/common-hal/pulseio/PulseOut.c34
-rw-r--r--atmel-samd/mpconfigport.h5
4 files changed, 89 insertions, 89 deletions
diff --git a/atmel-samd/boards/circuitplayground_express/pins.c b/atmel-samd/boards/circuitplayground_express/pins.c
index d7ef47de7..abaea0378 100644
--- a/atmel-samd/boards/circuitplayground_express/pins.c
+++ b/atmel-samd/boards/circuitplayground_express/pins.c
@@ -92,7 +92,7 @@ STATIC const mp_map_elem_t board_global_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACCELEROMETER_SDA), (mp_obj_t)&pin_PA00 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACCELEROMETER_SCL), (mp_obj_t)&pin_PA01 },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER_SHUTDOWN), (mp_obj_t)&pin_PA30 },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER_ENABLE), (mp_obj_t)&pin_PA30 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_PA21 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_PA20 },
diff --git a/atmel-samd/common-hal/audioio/AudioOut.c b/atmel-samd/common-hal/audioio/AudioOut.c
index b548d1164..9d7b922f1 100644
--- a/atmel-samd/common-hal/audioio/AudioOut.c
+++ b/atmel-samd/common-hal/audioio/AudioOut.c
@@ -49,11 +49,9 @@ extern uint8_t timer_refcount[TC_INST_NUM + TCC_INST_NUM];
extern const uint16_t prescaler[8];
// This timer is shared amongst all AudioOut objects under the assumption that
-// the code is single threaded.
-static struct tc_module* tc_instance;
-static struct dac_module* dac_instance;
-static struct events_resource* tc_event;
-static struct events_resource* dac_event;
+// the code is single threaded. The audioout_tc_instance, audioout_dac_instance,
+// audioout_tc_event, and audioout_dac_event pointers live in
+// MICROPY_PORT_ROOT_POINTERS so they don't get garbage collected.
// The AudioOut object is being currently played. Only it can pause the timer
// and change its frequency.
@@ -62,25 +60,22 @@ static audioio_audioout_obj_t* active_audioout;
static uint8_t refcount = 0;
void audioout_reset(void) {
- // Only reset DMA. PWMOut will reset the timer.
+ // Only reset DMA. PWMOut will reset the timer. Other code will reset the DAC.
refcount = 0;
- tc_instance = NULL;
- if (dac_instance != NULL) {
- dac_reset(dac_instance);
- }
- dac_instance = NULL;
+ MP_STATE_VM(audioout_tc_instance) = NULL;
+ MP_STATE_VM(audioout_dac_instance) = NULL;
- if (tc_event != NULL) {
- events_detach_user(tc_event, EVSYS_ID_USER_DAC_START);
- events_release(tc_event);
+ if (MP_STATE_VM(audioout_tc_event) != NULL) {
+ events_detach_user(MP_STATE_VM(audioout_tc_event), EVSYS_ID_USER_DAC_START);
+ events_release(MP_STATE_VM(audioout_tc_event));
}
- tc_event = NULL;
+ MP_STATE_VM(audioout_tc_event) = NULL;
- if (dac_event != NULL) {
- events_detach_user(dac_event, EVSYS_ID_USER_DMAC_CH_0);
- events_release(dac_event);
+ if (MP_STATE_VM(audioout_dac_event) != NULL) {
+ events_detach_user(MP_STATE_VM(audioout_dac_event), EVSYS_ID_USER_DMAC_CH_0);
+ events_release(MP_STATE_VM(audioout_dac_event));
}
- dac_event = NULL;
+ MP_STATE_VM(audioout_dac_event) = NULL;
dma_abort_job(&audio_dma);
}
@@ -90,8 +85,8 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
// Configure the DAC to output on input event and to output an empty event
// that triggers the DMA to load the next sample.
- dac_instance = gc_alloc(sizeof(struct dac_module), false);
- if (dac_instance == NULL) {
+ MP_STATE_VM(audioout_dac_instance) = gc_alloc(sizeof(struct dac_module), false);
+ if (MP_STATE_VM(audioout_dac_instance) == NULL) {
mp_raise_msg(&mp_type_MemoryError, "");
}
struct dac_config config_dac;
@@ -99,7 +94,7 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
config_dac.left_adjust = true;
config_dac.reference = DAC_REFERENCE_AVCC;
config_dac.clock_source = GCLK_GENERATOR_0;
- enum status_code status = dac_init(dac_instance, DAC, &config_dac);
+ enum status_code status = dac_init(MP_STATE_VM(audioout_dac_instance), DAC, &config_dac);
if (status != STATUS_OK) {
common_hal_audioio_audioout_deinit(self);
mp_raise_OSError(MP_EIO);
@@ -108,14 +103,12 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
struct dac_chan_config channel_config;
dac_chan_get_config_defaults(&channel_config);
- dac_chan_set_config(dac_instance, DAC_CHANNEL_0, &channel_config);
- dac_chan_enable(dac_instance, DAC_CHANNEL_0);
+ dac_chan_set_config(MP_STATE_VM(audioout_dac_instance), DAC_CHANNEL_0, &channel_config);
+ dac_chan_enable(MP_STATE_VM(audioout_dac_instance), DAC_CHANNEL_0);
struct dac_events events_dac = { .generate_event_on_buffer_empty = true,
.on_event_start_conversion = true };
- dac_enable_events(dac_instance, &events_dac);
-
- dac_enable(dac_instance);
+ dac_enable_events(MP_STATE_VM(audioout_dac_instance), &events_dac);
// Figure out which timer we are using.
Tc *t = NULL;
@@ -131,8 +124,8 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
mp_raise_RuntimeError("All timers in use");
return;
}
- tc_instance = gc_alloc(sizeof(struct tc_module), false);
- if (tc_instance == NULL) {
+ MP_STATE_VM(audioout_tc_instance) = gc_alloc(sizeof(struct tc_module), false);
+ if (MP_STATE_VM(audioout_tc_instance) == NULL) {
common_hal_audioio_audioout_deinit(self);
mp_raise_msg(&mp_type_MemoryError, "");
}
@@ -140,28 +133,28 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
// Don't bother setting the period. We set it before you playback anything.
struct tc_config config_tc;
tc_get_config_defaults(&config_tc);
-
config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV1;
config_tc.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;
- if (tc_init(tc_instance, t, &config_tc) != STATUS_OK) {
+ if (tc_init(MP_STATE_VM(audioout_tc_instance), t, &config_tc) != STATUS_OK) {
common_hal_audioio_audioout_deinit(self);
- mp_printf(&mp_plat_print, "tc \n");
mp_raise_OSError(MP_EIO);
return;
};
struct tc_events events_tc;
events_tc.generate_event_on_overflow = true;
- tc_enable_events(tc_instance, &events_tc);
+ events_tc.on_event_perform_action = false;
+ events_tc.event_action = TC_EVENT_ACTION_OFF;
+ tc_enable_events(MP_STATE_VM(audioout_tc_instance), &events_tc);
- tc_enable(tc_instance);
- tc_stop_counter(tc_instance);
+ tc_enable(MP_STATE_VM(audioout_tc_instance));
+ tc_stop_counter(MP_STATE_VM(audioout_tc_instance));
// Connect the timer overflow event, which happens at the target frequency,
// to the DAC conversion trigger.
- tc_event = gc_alloc(sizeof(struct events_resource), false);
- if (tc_event == NULL) {
+ MP_STATE_VM(audioout_tc_event) = gc_alloc(sizeof(struct events_resource), false);
+ if (MP_STATE_VM(audioout_tc_event) == NULL) {
common_hal_audioio_audioout_deinit(self);
mp_raise_msg(&mp_type_MemoryError, "");
}
@@ -185,24 +178,24 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
config.generator = generator;
config.path = EVENTS_PATH_ASYNCHRONOUS;
- if (events_allocate(tc_event, &config) != STATUS_OK ||
- events_attach_user(tc_event, EVSYS_ID_USER_DAC_START) != STATUS_OK) {
+ if (events_allocate(MP_STATE_VM(audioout_tc_event), &config) != STATUS_OK ||
+ events_attach_user(MP_STATE_VM(audioout_tc_event), EVSYS_ID_USER_DAC_START) != STATUS_OK) {
common_hal_audioio_audioout_deinit(self);
mp_raise_OSError(MP_EIO);
return;
}
// Connect the DAC to DMA
- dac_event = gc_alloc(sizeof(struct events_resource), false);
- if (dac_event == NULL) {
+ MP_STATE_VM(audioout_dac_event) = gc_alloc(sizeof(struct events_resource), false);
+ if (MP_STATE_VM(audioout_dac_event) == NULL) {
common_hal_audioio_audioout_deinit(self);
mp_raise_msg(&mp_type_MemoryError, "");
}
events_get_config_defaults(&config);
config.generator = EVSYS_ID_GEN_DAC_EMPTY;
config.path = EVENTS_PATH_ASYNCHRONOUS;
- if (events_allocate(dac_event, &config) != STATUS_OK ||
- events_attach_user(dac_event, EVSYS_ID_USER_DMAC_CH_0) != STATUS_OK) {
+ if (events_allocate(MP_STATE_VM(audioout_dac_event), &config) != STATUS_OK ||
+ events_attach_user(MP_STATE_VM(audioout_dac_event), EVSYS_ID_USER_DMAC_CH_0) != STATUS_OK) {
common_hal_audioio_audioout_deinit(self);
mp_raise_OSError(MP_EIO);
return;
@@ -239,26 +232,26 @@ void common_hal_audioio_audioout_construct_from_file(audioio_audioout_obj_t* sel
void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self) {
refcount--;
if (refcount == 0) {
- if (tc_instance != NULL) {
- tc_reset(tc_instance);
- gc_free(tc_instance);
- tc_instance = NULL;
+ if (MP_STATE_VM(audioout_tc_instance) != NULL) {
+ tc_reset(MP_STATE_VM(audioout_tc_instance));
+ gc_free(MP_STATE_VM(audioout_tc_instance));
+ MP_STATE_VM(audioout_tc_instance) = NULL;
}
- if (dac_instance != NULL) {
- dac_reset(dac_instance);
- gc_free(dac_instance);
- dac_instance = NULL;
+ if (MP_STATE_VM(audioout_dac_instance) != NULL) {
+ dac_reset(MP_STATE_VM(audioout_dac_instance));
+ gc_free(MP_STATE_VM(audioout_dac_instance));
+ MP_STATE_VM(audioout_dac_instance) = NULL;
}
- if (tc_event != NULL) {
- events_detach_user(tc_event, EVSYS_ID_USER_DAC_START);
- events_release(tc_event);
- gc_free(tc_event);
- tc_event = NULL;
+ if (MP_STATE_VM(audioout_tc_event) != NULL) {
+ events_detach_user(MP_STATE_VM(audioout_tc_event), EVSYS_ID_USER_DAC_START);
+ events_release(MP_STATE_VM(audioout_tc_event));
+ gc_free(MP_STATE_VM(audioout_tc_event));
+ MP_STATE_VM(audioout_tc_event) = NULL;
}
- if (dac_event != NULL) {
- events_release(dac_event);
- gc_free(dac_event);
- dac_event = NULL;
+ if (MP_STATE_VM(audioout_dac_event) != NULL) {
+ events_release(MP_STATE_VM(audioout_dac_event));
+ gc_free(MP_STATE_VM(audioout_dac_event));
+ MP_STATE_VM(audioout_dac_event) = NULL;
}
reset_pin(self->pin->pin);
}
@@ -274,17 +267,17 @@ static void set_timer_frequency(uint32_t frequency) {
break;
}
}
- uint8_t old_divisor = tc_instance->hw->COUNT16.CTRLA.bit.PRESCALER;
+ uint8_t old_divisor = MP_STATE_VM(audioout_tc_instance)->hw->COUNT16.CTRLA.bit.PRESCALER;
if (new_divisor != old_divisor) {
- tc_disable(tc_instance);
- tc_instance->hw->COUNT16.CTRLA.bit.PRESCALER = new_divisor;
- tc_enable(tc_instance);
+ tc_disable(MP_STATE_VM(audioout_tc_instance));
+ MP_STATE_VM(audioout_tc_instance)->hw->COUNT16.CTRLA.bit.PRESCALER = new_divisor;
+ tc_enable(MP_STATE_VM(audioout_tc_instance));
}
- while (tc_is_syncing(tc_instance)) {
+ while (tc_is_syncing(MP_STATE_VM(audioout_tc_instance))) {
/* Wait for sync */
}
- tc_instance->hw->COUNT16.CC[0].reg = new_top;
- while (tc_is_syncing(tc_instance)) {
+ MP_STATE_VM(audioout_tc_instance)->hw->COUNT16.CC[0].reg = new_top;
+ while (tc_is_syncing(MP_STATE_VM(audioout_tc_instance))) {
/* Wait for sync */
}
}
@@ -293,8 +286,10 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t* self, bool loop) {
common_hal_audioio_audioout_get_playing(self);
// Shut down any active playback.
if (active_audioout != NULL) {
- tc_stop_counter(tc_instance);
+ tc_stop_counter(MP_STATE_VM(audioout_tc_instance));
dma_abort_job(&audio_dma);
+ } else {
+ dac_enable(MP_STATE_VM(audioout_dac_instance));
}
struct dma_descriptor_config descriptor_config;
dma_descriptor_get_config_defaults(&descriptor_config);
@@ -314,15 +309,15 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t* self, bool loop) {
dma_start_transfer_job(&audio_dma);
set_timer_frequency(self->frequency);
- tc_start_counter(tc_instance);
+ tc_start_counter(MP_STATE_VM(audioout_tc_instance));
}
void common_hal_audioio_audioout_stop(audioio_audioout_obj_t* self) {
if (common_hal_audioio_audioout_get_playing(self)) {
- tc_stop_counter(tc_instance);
+ tc_stop_counter(MP_STATE_VM(audioout_tc_instance));
dma_abort_job(&audio_dma);
active_audioout = NULL;
- // TODO(tannewt): Disable the DAC to save power.
+ dac_disable(MP_STATE_VM(audioout_dac_instance));
}
}
diff --git a/atmel-samd/common-hal/pulseio/PulseOut.c b/atmel-samd/common-hal/pulseio/PulseOut.c
index be95a1418..32edd0856 100644
--- a/atmel-samd/common-hal/pulseio/PulseOut.c
+++ b/atmel-samd/common-hal/pulseio/PulseOut.c
@@ -39,8 +39,8 @@
#undef ENABLE
// This timer is shared amongst all PulseOut objects under the assumption that
-// the code is single threaded.
-static struct tc_module* tc_instance;
+// the code is single threaded. Its stored in MICROPY_PORT_ROOT_POINTERS so it
+// doesn't get garbage collected.
static uint8_t refcount = 0;
static __IO PORT_PINCFG_Type *active_pincfg = NULL;
@@ -69,7 +69,7 @@ void pulse_finish(struct tc_module *const module) {
return;
}
current_compare = (current_compare + pulse_buffer[pulse_index] * 3 / 4) & 0xffff;
- tc_set_compare_value(tc_instance, TC_COMPARE_CAPTURE_CHANNEL_0, current_compare);
+ tc_set_compare_value(MP_STATE_VM(pulseout_tc_instance), TC_COMPARE_CAPTURE_CHANNEL_0, current_compare);
if (pulse_index % 2 == 0) {
turn_on(active_pincfg);
}
@@ -77,7 +77,7 @@ void pulse_finish(struct tc_module *const module) {
void pulseout_reset() {
refcount = 0;
- tc_instance = 0;
+ MP_STATE_VM(pulseout_tc_instance) = NULL;
active_pincfg = NULL;
}
@@ -96,7 +96,7 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
if (t == NULL) {
mp_raise_RuntimeError("All timers in use");
}
- tc_instance = gc_alloc(sizeof(struct tc_module), false);
+ MP_STATE_VM(pulseout_tc_instance) = gc_alloc(sizeof(struct tc_module), false);
if (t == NULL) {
mp_raise_msg(&mp_type_MemoryError, "");
}
@@ -108,10 +108,10 @@ void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
config_tc.clock_prescaler = TC_CTRLA_PRESCALER_DIV64;
config_tc.wave_generation = TC_WAVE_GENERATION_NORMAL_FREQ;
- tc_init(tc_instance, t, &config_tc);
- tc_register_callback(tc_instance, pulse_finish, TC_CALLBACK_CC_CHANNEL0);
- tc_enable(tc_instance);
- tc_stop_counter(tc_instance);
+ tc_init(MP_STATE_VM(pulseout_tc_instance), t, &config_tc);
+ tc_register_callback(MP_STATE_VM(pulseout_tc_instance), pulse_finish, TC_CALLBACK_CC_CHANNEL0);
+ tc_enable(MP_STATE_VM(pulseout_tc_instance));
+ tc_stop_counter(MP_STATE_VM(pulseout_tc_instance));
}
refcount++;
@@ -136,9 +136,9 @@ void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) {
refcount--;
if (refcount == 0) {
- tc_reset(tc_instance);
- gc_free(tc_instance);
- tc_instance = NULL;
+ tc_reset(MP_STATE_VM(pulseout_tc_instance));
+ gc_free(MP_STATE_VM(pulseout_tc_instance));
+ MP_STATE_VM(pulseout_tc_instance) = NULL;
}
}
@@ -152,11 +152,11 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
pulse_length = length;
current_compare = pulses[0] * 3 / 4;
- tc_set_compare_value(tc_instance, TC_COMPARE_CAPTURE_CHANNEL_0, current_compare);
+ tc_set_compare_value(MP_STATE_VM(pulseout_tc_instance), TC_COMPARE_CAPTURE_CHANNEL_0, current_compare);
- tc_enable_callback(tc_instance, TC_CALLBACK_CC_CHANNEL0);
+ tc_enable_callback(MP_STATE_VM(pulseout_tc_instance), TC_CALLBACK_CC_CHANNEL0);
turn_on(active_pincfg);
- tc_start_counter(tc_instance);
+ tc_start_counter(MP_STATE_VM(pulseout_tc_instance));
while(pulse_index < length) {
// Do other things while we wait. The interrupts will handle sending the
@@ -166,7 +166,7 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
#endif
}
- tc_stop_counter(tc_instance);
- tc_disable_callback(tc_instance, TC_CALLBACK_CC_CHANNEL0);
+ tc_stop_counter(MP_STATE_VM(pulseout_tc_instance));
+ tc_disable_callback(MP_STATE_VM(pulseout_tc_instance), TC_CALLBACK_CC_CHANNEL0);
active_pincfg = NULL;
}
diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h
index 16d9cb075..f66feb4ce 100644
--- a/atmel-samd/mpconfigport.h
+++ b/atmel-samd/mpconfigport.h
@@ -192,6 +192,11 @@ extern const struct _mp_obj_module_t usb_hid_module;
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[8]; \
vstr_t *repl_line; \
+ struct tc_module* audioout_tc_instance; \
+ struct dac_module* audioout_dac_instance; \
+ struct events_resource* audioout_tc_event; \
+ struct events_resource* audioout_dac_event; \
+ struct tc_module* pulseout_tc_instance; \
FLASH_ROOT_POINTERS \
bool udi_msc_process_trans(void);