Merge remote-tracking branch 'adafruit/7.1.x' into merge_7.1
This commit is contained in:
commit
b12d2063d0
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@ -35,7 +35,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Get CP deps
|
||||
run: python tools/ci_fetch_deps.py test ${{ github.ref }}
|
||||
run: python tools/ci_fetch_deps.py test ${{ github.sha }}
|
||||
- name: CircuitPython version
|
||||
run: |
|
||||
git describe --dirty --tags || git log --parents HEAD~4..
|
||||
@ -141,7 +141,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Get CP deps
|
||||
run: python tools/ci_fetch_deps.py mpy-cross-mac ${{ github.ref }}
|
||||
run: python tools/ci_fetch_deps.py mpy-cross-mac ${{ github.sha }}
|
||||
- name: CircuitPython version
|
||||
run: |
|
||||
git describe --dirty --tags
|
||||
@ -197,7 +197,7 @@ jobs:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Get CP deps
|
||||
run: python tools/ci_fetch_deps.py docs ${{ github.ref }}
|
||||
run: python tools/ci_fetch_deps.py docs ${{ github.sha }}
|
||||
- name: CircuitPython version
|
||||
run: |
|
||||
git describe --dirty --tags
|
||||
@ -269,7 +269,7 @@ jobs:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Get CP deps
|
||||
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.ref }}
|
||||
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.sha }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install -y gettext
|
||||
|
2
.github/workflows/create_website_pr.yml
vendored
2
.github/workflows/create_website_pr.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Get CP deps
|
||||
run: python tools/ci_fetch_deps.py website ${{ github.ref }}
|
||||
run: python tools/ci_fetch_deps.py website ${{ github.sha }}
|
||||
- name: Install deps
|
||||
run: |
|
||||
pip install -r requirements-dev.txt
|
||||
|
2
.github/workflows/ports_windows.yml
vendored
2
.github/workflows/ports_windows.yml
vendored
@ -70,7 +70,7 @@ jobs:
|
||||
submodules: false
|
||||
fetch-depth: 1
|
||||
- name: Get CP deps
|
||||
run: python tools/ci_fetch_deps.py windows ${{ github.ref }}
|
||||
run: python tools/ci_fetch_deps.py windows ${{ github.sha }}
|
||||
- name: CircuitPython version
|
||||
run: |
|
||||
git describe --dirty --tags
|
||||
|
@ -107,6 +107,6 @@ void common_hal_bleio_gc_collect(void) {
|
||||
}
|
||||
|
||||
|
||||
void bleio_background(void) {
|
||||
void bleio_hci_background(void) {
|
||||
bleio_adapter_background(&common_hal_bleio_adapter_obj);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "att.h"
|
||||
#include "hci.h"
|
||||
|
||||
void bleio_background(void);
|
||||
void bleio_hci_background(void);
|
||||
void bleio_reset(void);
|
||||
|
||||
typedef struct {
|
||||
|
@ -54,12 +54,33 @@
|
||||
#endif
|
||||
|
||||
static frequencyio_frequencyin_obj_t *active_frequencyins[TC_INST_NUM];
|
||||
volatile uint8_t reference_tc = 0xff;
|
||||
volatile uint8_t reference_tc;
|
||||
#ifdef SAM_D5X_E5X
|
||||
static uint8_t dpll_gclk;
|
||||
|
||||
#if !BOARD_HAS_CRYSTAL
|
||||
static uint8_t osculp32k_gclk;
|
||||
#endif
|
||||
|
||||
void frequencyin_emergency_cancel_capture(uint8_t index) {
|
||||
#endif
|
||||
|
||||
void frequencyin_reset(void) {
|
||||
for (uint8_t i = 0; i < TC_INST_NUM; i++) {
|
||||
active_frequencyins[i] = NULL;
|
||||
}
|
||||
|
||||
reference_tc = 0xff;
|
||||
#ifdef SAM_D5X_E5X
|
||||
dpll_gclk = 0xff;
|
||||
|
||||
#if !BOARD_HAS_CRYSTAL
|
||||
osculp32k_gclk = 0xff;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void frequencyin_emergency_cancel_capture(uint8_t index) {
|
||||
frequencyio_frequencyin_obj_t* self = active_frequencyins[index];
|
||||
|
||||
NVIC_DisableIRQ(self->TC_IRQ);
|
||||
@ -93,7 +114,7 @@ void frequencyin_interrupt_handler(uint8_t index) {
|
||||
|
||||
uint64_t current_ns = common_hal_time_monotonic_ns();
|
||||
|
||||
for (uint8_t i = 0; i <= (TC_INST_NUM - 1); i++) {
|
||||
for (uint8_t i = 0; i < TC_INST_NUM; i++) {
|
||||
if (active_frequencyins[i] != NULL) {
|
||||
frequencyio_frequencyin_obj_t* self = active_frequencyins[i];
|
||||
Tc* tc = tc_insts[self->tc_index];
|
||||
@ -143,7 +164,7 @@ void frequencyin_interrupt_handler(uint8_t index) {
|
||||
ref_tc->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF;
|
||||
}
|
||||
|
||||
void frequencyin_reference_tc_init() {
|
||||
static void frequencyin_reference_tc_init(void) {
|
||||
if (reference_tc == 0xff) {
|
||||
return;
|
||||
}
|
||||
@ -154,9 +175,6 @@ void frequencyin_reference_tc_init() {
|
||||
// use the DPLL we setup so that the reference_tc and freqin_tc(s)
|
||||
// are using the same clock frequency.
|
||||
#ifdef SAM_D5X_E5X
|
||||
if (dpll_gclk == 0xff) {
|
||||
frequencyin_samd51_start_dpll();
|
||||
}
|
||||
set_timer_handler(true, reference_tc, TC_HANDLER_FREQUENCYIN);
|
||||
turn_on_clocks(true, reference_tc, dpll_gclk);
|
||||
#endif
|
||||
@ -178,7 +196,7 @@ void frequencyin_reference_tc_init() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool frequencyin_reference_tc_enabled() {
|
||||
static bool frequencyin_reference_tc_enabled(void) {
|
||||
if (reference_tc == 0xff) {
|
||||
return false;
|
||||
}
|
||||
@ -186,7 +204,7 @@ bool frequencyin_reference_tc_enabled() {
|
||||
return tc->COUNT16.CTRLA.bit.ENABLE;
|
||||
}
|
||||
|
||||
void frequencyin_reference_tc_enable(bool enable) {
|
||||
static void frequencyin_reference_tc_enable(bool enable) {
|
||||
if (reference_tc == 0xff) {
|
||||
return;
|
||||
}
|
||||
@ -195,56 +213,69 @@ void frequencyin_reference_tc_enable(bool enable) {
|
||||
}
|
||||
|
||||
#ifdef SAM_D5X_E5X
|
||||
void frequencyin_samd51_start_dpll() {
|
||||
static bool frequencyin_samd51_start_dpll(void) {
|
||||
if (clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t free_gclk = find_free_gclk(1);
|
||||
if (free_gclk == 0xff) {
|
||||
dpll_gclk = 0xff;
|
||||
return;
|
||||
dpll_gclk = find_free_gclk(1);
|
||||
if (dpll_gclk == 0xff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(free_gclk);
|
||||
// TC4-7 can only have a max of 100MHz source
|
||||
// DPLL1 frequency equation with [X]OSC32K as source: 98.304MHz = 32768(2999 + 1 + 0/32)
|
||||
// Will also enable the Lock Bypass due to low-frequency sources causing DPLL unlocks
|
||||
// as outlined in the Errata (1.12.1)
|
||||
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0) | OSCCTRL_DPLLRATIO_LDR(2999);
|
||||
#if BOARD_HAS_CRYSTAL
|
||||
// we can use XOSC32K directly as the source
|
||||
OSC32KCTRL->XOSC32K.bit.EN32K = 1;
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(1) | OSCCTRL_DPLLCTRLB_LBYPASS;
|
||||
#else
|
||||
// can't use OSCULP32K directly; need to setup a GCLK as a reference,
|
||||
// which must be done in samd/clocks.c to avoid waiting for sync
|
||||
return;
|
||||
//OSC32KCTRL->OSCULP32K.bit.EN32K = 1;
|
||||
//OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(0);
|
||||
#endif
|
||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
|
||||
#if BOARD_HAS_CRYSTAL
|
||||
// we can use XOSC32K directly as the source. It has already been initialized in clocks.c
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg =
|
||||
OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC32_Val) | OSCCTRL_DPLLCTRLB_LBYPASS;
|
||||
#else
|
||||
// We can't use OSCULP32K directly. Set up a GCLK controlled by it
|
||||
// Then use that GCLK as the reference oscillator for the DPLL.
|
||||
osculp32k_gclk = find_free_gclk(1);
|
||||
if (osculp32k_gclk == 0xff) {
|
||||
return false;
|
||||
}
|
||||
enable_clock_generator(osculp32k_gclk, GCLK_GENCTRL_SRC_OSCULP32K_Val, 1);
|
||||
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(OSCCTRL_GCLK_ID_FDPLL1);
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg =
|
||||
OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_GCLK_Val) | OSCCTRL_DPLLCTRLB_LBYPASS;
|
||||
#endif
|
||||
|
||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while (!(OSCCTRL->Dpll[1].DPLLSTATUS.bit.LOCK || OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY)) {}
|
||||
enable_clock_generator(free_gclk, GCLK_GENCTRL_SRC_DPLL1_Val, 1);
|
||||
dpll_gclk = free_gclk;
|
||||
|
||||
enable_clock_generator(dpll_gclk, GCLK_GENCTRL_SRC_DPLL1_Val, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void frequencyin_samd51_stop_dpll() {
|
||||
static void frequencyin_samd51_stop_dpll(void) {
|
||||
if (!clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
disable_clock_generator(dpll_gclk);
|
||||
if (dpll_gclk != 0xff) {
|
||||
disable_clock_generator(dpll_gclk);
|
||||
dpll_gclk = 0xff;
|
||||
}
|
||||
|
||||
#if !BOARD_HAS_CRYSTAL
|
||||
if (osculp32k_gclk != 0xff) {
|
||||
disable_clock_generator(osculp32k_gclk);
|
||||
osculp32k_gclk = 0xff;
|
||||
}
|
||||
#endif
|
||||
|
||||
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = 0;
|
||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = 0;
|
||||
OSCCTRL->Dpll[1].DPLLRATIO.reg = 0;
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = 0;
|
||||
|
||||
while (OSCCTRL->Dpll[1].DPLLSYNCBUSY.bit.ENABLE) {
|
||||
}
|
||||
dpll_gclk = 0xff;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -421,7 +452,7 @@ void common_hal_frequencyio_frequencyin_deinit(frequencyio_frequencyin_obj_t* se
|
||||
self->pin = NO_PIN;
|
||||
|
||||
bool check_active = false;
|
||||
for (uint8_t i = 0; i <= (TC_INST_NUM - 1); i++) {
|
||||
for (uint8_t i = 0; i < TC_INST_NUM; i++) {
|
||||
if (active_frequencyins[i] != NULL) {
|
||||
check_active = true;
|
||||
}
|
||||
|
@ -46,14 +46,7 @@ typedef struct {
|
||||
} frequencyio_frequencyin_obj_t;
|
||||
|
||||
void frequencyin_interrupt_handler(uint8_t index);
|
||||
void frequencyin_emergency_cancel_capture(uint8_t index);
|
||||
void frequencyin_reference_tc_init(void);
|
||||
void frequencyin_reference_tc_enable(bool enable);
|
||||
bool frequencyin_reference_tc_enabled(void);
|
||||
#ifdef SAM_D5X_E5X
|
||||
void frequencyin_samd51_start_dpll(void);
|
||||
void frequencyin_samd51_stop_dpll(void);
|
||||
#endif
|
||||
void frequencyin_reset(void);
|
||||
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_FREQUENCYIO_FREQUENCYIN_H
|
||||
|
@ -71,6 +71,10 @@
|
||||
#include "common-hal/busio/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_FREQUENCYIO
|
||||
#include "common-hal/frequencyio/FrequencyIn.h"
|
||||
#endif
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
#if CIRCUITPY_PULSEIO
|
||||
@ -388,6 +392,10 @@ void reset_port(void) {
|
||||
i2sout_reset();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_FREQUENCYIO
|
||||
frequencyin_reset();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_TOUCHIO && CIRCUITPY_TOUCHIO_USE_NATIVE
|
||||
touchin_reset();
|
||||
#endif
|
||||
@ -399,7 +407,7 @@ void reset_port(void) {
|
||||
#if CIRCUITPY_PWMIO
|
||||
pwmout_reset();
|
||||
#endif
|
||||
#if CIRCUITPY_PWMIO || CIRCUITPY_AUDIOIO
|
||||
#if CIRCUITPY_PWMIO || CIRCUITPY_AUDIOIO || CIRCUITPY_FREQUENCYIO
|
||||
reset_timers();
|
||||
#endif
|
||||
|
||||
|
@ -26,6 +26,9 @@
|
||||
|
||||
// qstrs specific to this port, only needed if they aren't auto-generated
|
||||
|
||||
// Prevent uncrustify from modifying these lines.
|
||||
// *FORMAT-OFF*
|
||||
|
||||
// Entries for sys.path
|
||||
Q(/sd)
|
||||
Q(/sd/lib)
|
||||
|
@ -86,7 +86,7 @@ void board_init(void) {
|
||||
|
||||
common_hal_busio_spi_never_reset(spi);
|
||||
|
||||
displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
|
||||
displayio_fourwire_obj_t *bus = &displays[0].fourwire_bus;
|
||||
bus->base.type = &displayio_fourwire_type;
|
||||
|
||||
common_hal_displayio_fourwire_construct(
|
||||
@ -99,7 +99,7 @@ void board_init(void) {
|
||||
0, // polarity
|
||||
0 // phase
|
||||
);
|
||||
displayio_display_obj_t* display = &displays[0].display;
|
||||
displayio_display_obj_t *display = &displays[0].display;
|
||||
display->base.type = &displayio_display_type;
|
||||
|
||||
// workaround as board_init() is called before reset_port() in main.c
|
||||
|
@ -207,7 +207,7 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self,
|
||||
uint32_t tx_register = (uint32_t)&pwm_hw->slice[self->left_pwm.slice].cc;
|
||||
if (self->stereo) {
|
||||
// Shift the destination if we are outputting to both PWM channels.
|
||||
tx_register += self->left_pwm.channel * sizeof(uint16_t);
|
||||
tx_register += self->left_pwm.ab_channel * sizeof(uint16_t);
|
||||
}
|
||||
|
||||
self->pacing_timer = pacing_timer;
|
||||
|
@ -109,8 +109,11 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
|
||||
// set up as GPIO by the bitbangio.I2C object.
|
||||
//
|
||||
// Sets pins to open drain, high, and input.
|
||||
//
|
||||
// Do not use the default supplied clock stretching timeout here.
|
||||
// It is too short for some devices. Use the busio timeout instead.
|
||||
shared_module_bitbangio_i2c_construct(&self->bitbangio_i2c, scl, sda,
|
||||
frequency, timeout);
|
||||
frequency, BUS_TIMEOUT_US);
|
||||
|
||||
self->baudrate = i2c_init(self->peripheral, frequency);
|
||||
|
||||
|
@ -25,8 +25,8 @@ void common_hal_countio_counter_construct(countio_counter_obj_t *self,
|
||||
mp_raise_RuntimeError(translate("PWM slice already in use"));
|
||||
}
|
||||
|
||||
uint8_t channel = pwm_gpio_to_channel(self->pin_a);
|
||||
if (!pwmio_claim_slice_channels(self->slice_num)) {
|
||||
uint8_t ab_channel = pwm_gpio_to_channel(self->pin_a);
|
||||
if (!pwmio_claim_slice_ab_channels(self->slice_num)) {
|
||||
mp_raise_RuntimeError(translate("PWM slice channel A already in use"));
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ void common_hal_countio_counter_deinit(countio_counter_obj_t *self) {
|
||||
pwm_set_enabled(self->slice_num, false);
|
||||
pwm_set_irq_enabled(self->slice_num, false);
|
||||
|
||||
pwmio_release_slice_channels(self->slice_num);
|
||||
pwmio_release_slice_ab_channels(self->slice_num);
|
||||
|
||||
reset_pin_number(self->pin_a);
|
||||
|
||||
@ -98,13 +98,14 @@ void common_hal_countio_counter_reset(countio_counter_obj_t *self) {
|
||||
void counter_interrupt_handler(void) {
|
||||
uint32_t mask = pwm_get_irq_status_mask();
|
||||
|
||||
uint8_t i = 1, pos = 1;
|
||||
uint8_t i = 1;
|
||||
uint8_t pos = 0;
|
||||
while (!(i & mask)) {
|
||||
i = i << 1;
|
||||
++pos;
|
||||
}
|
||||
|
||||
countio_counter_obj_t *self = MP_STATE_PORT(counting)[pos - 1];
|
||||
countio_counter_obj_t *self = MP_STATE_PORT(counting)[pos];
|
||||
if (self != NULL) {
|
||||
pwm_clear_irq(self->slice_num);
|
||||
self->count += 65536;
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "src/rp2_common/hardware_flash/include/hardware/flash.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
|
||||
extern uint32_t __flash_binary_start;
|
||||
static const uint32_t flash_binary_start = (uint32_t)&__flash_binary_start;
|
||||
@ -45,13 +46,19 @@ static void write_page(uint32_t page_addr, uint32_t offset, uint32_t len, uint8_
|
||||
// Write a whole page to flash, buffering it first and then erasing and rewriting it
|
||||
// since we can only write a whole page at a time.
|
||||
if (offset == 0 && len == FLASH_PAGE_SIZE) {
|
||||
// disable interrupts to prevent core hang on rp2040
|
||||
common_hal_mcu_disable_interrupts();
|
||||
flash_range_program(RMV_OFFSET(page_addr), bytes, FLASH_PAGE_SIZE);
|
||||
common_hal_mcu_enable_interrupts();
|
||||
} else {
|
||||
uint8_t buffer[FLASH_PAGE_SIZE];
|
||||
memcpy(buffer, (uint8_t *)page_addr, FLASH_PAGE_SIZE);
|
||||
memcpy(buffer + offset, bytes, len);
|
||||
common_hal_mcu_disable_interrupts();
|
||||
flash_range_program(RMV_OFFSET(page_addr), buffer, FLASH_PAGE_SIZE);
|
||||
common_hal_mcu_enable_interrupts();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void erase_and_write_sector(uint32_t address, uint32_t len, uint8_t *bytes) {
|
||||
@ -60,8 +67,11 @@ static void erase_and_write_sector(uint32_t address, uint32_t len, uint8_t *byte
|
||||
uint8_t buffer[FLASH_SECTOR_SIZE];
|
||||
memcpy(buffer, (uint8_t *)CIRCUITPY_INTERNAL_NVM_START_ADDR, FLASH_SECTOR_SIZE);
|
||||
memcpy(buffer + address, bytes, len);
|
||||
// disable interrupts to prevent core hang on rp2040
|
||||
common_hal_mcu_disable_interrupts();
|
||||
flash_range_erase(RMV_OFFSET(CIRCUITPY_INTERNAL_NVM_START_ADDR), FLASH_SECTOR_SIZE);
|
||||
flash_range_program(RMV_OFFSET(CIRCUITPY_INTERNAL_NVM_START_ADDR), buffer, FLASH_SECTOR_SIZE);
|
||||
common_hal_mcu_enable_interrupts();
|
||||
}
|
||||
|
||||
void common_hal_nvm_bytearray_get_bytes(const nvm_bytearray_obj_t *self,
|
||||
|
@ -42,7 +42,7 @@
|
||||
uint32_t target_slice_frequencies[NUM_PWM_SLICES];
|
||||
uint32_t slice_variable_frequency;
|
||||
|
||||
#define CHANNELS_PER_SLICE 2
|
||||
#define AB_CHANNELS_PER_SLICE 2
|
||||
static uint32_t channel_use;
|
||||
static uint32_t never_reset_channel;
|
||||
|
||||
@ -58,11 +58,11 @@ static uint32_t never_reset_channel;
|
||||
// So 65534 should be the maximum top value, and we'll set CC to be TOP+1 as appropriate.
|
||||
#define MAX_TOP 65534
|
||||
|
||||
static uint32_t _mask(uint8_t slice, uint8_t channel) {
|
||||
return 1 << (slice * CHANNELS_PER_SLICE + channel);
|
||||
static uint32_t _mask(uint8_t slice, uint8_t ab_channel) {
|
||||
return 1 << (slice * AB_CHANNELS_PER_SLICE + ab_channel);
|
||||
}
|
||||
|
||||
bool pwmio_claim_slice_channels(uint8_t slice) {
|
||||
bool pwmio_claim_slice_ab_channels(uint8_t slice) {
|
||||
uint32_t channel_use_mask_a = _mask(slice, 0);
|
||||
uint32_t channel_use_mask_b = _mask(slice, 1);
|
||||
|
||||
@ -78,37 +78,37 @@ bool pwmio_claim_slice_channels(uint8_t slice) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void pwmio_release_slice_channels(uint8_t slice) {
|
||||
void pwmio_release_slice_ab_channels(uint8_t slice) {
|
||||
uint32_t channel_mask = _mask(slice, 0);
|
||||
channel_use &= ~channel_mask;
|
||||
channel_mask = _mask(slice, 1);
|
||||
channel_use &= ~channel_mask;
|
||||
}
|
||||
|
||||
void pwmout_never_reset(uint8_t slice, uint8_t channel) {
|
||||
never_reset_channel |= _mask(slice, channel);
|
||||
void pwmout_never_reset(uint8_t slice, uint8_t ab_channel) {
|
||||
never_reset_channel |= _mask(slice, ab_channel);
|
||||
}
|
||||
|
||||
void pwmout_reset_ok(uint8_t slice, uint8_t channel) {
|
||||
never_reset_channel &= ~_mask(slice, channel);
|
||||
void pwmout_reset_ok(uint8_t slice, uint8_t ab_channel) {
|
||||
never_reset_channel &= ~_mask(slice, ab_channel);
|
||||
}
|
||||
|
||||
void common_hal_pwmio_pwmout_never_reset(pwmio_pwmout_obj_t *self) {
|
||||
pwmout_never_reset(self->slice, self->channel);
|
||||
pwmout_never_reset(self->slice, self->ab_channel);
|
||||
|
||||
never_reset_pin_number(self->pin->number);
|
||||
}
|
||||
|
||||
void common_hal_pwmio_pwmout_reset_ok(pwmio_pwmout_obj_t *self) {
|
||||
pwmout_reset_ok(self->slice, self->channel);
|
||||
pwmout_reset_ok(self->slice, self->ab_channel);
|
||||
}
|
||||
|
||||
void pwmout_reset(void) {
|
||||
// Reset all slices
|
||||
for (size_t slice = 0; slice < NUM_PWM_SLICES; slice++) {
|
||||
bool reset = true;
|
||||
for (size_t channel = 0; channel < CHANNELS_PER_SLICE; channel++) {
|
||||
uint32_t channel_use_mask = _mask(slice, channel);
|
||||
for (size_t ab_channel = 0; ab_channel < AB_CHANNELS_PER_SLICE; ab_channel++) {
|
||||
uint32_t channel_use_mask = _mask(slice, ab_channel);
|
||||
if ((never_reset_channel & channel_use_mask) != 0) {
|
||||
reset = false;
|
||||
continue;
|
||||
@ -124,8 +124,8 @@ void pwmout_reset(void) {
|
||||
}
|
||||
}
|
||||
|
||||
pwmout_result_t pwmout_allocate(uint8_t slice, uint8_t channel, bool variable_frequency, uint32_t frequency) {
|
||||
uint32_t channel_use_mask = _mask(slice, channel);
|
||||
pwmout_result_t pwmout_allocate(uint8_t slice, uint8_t ab_channel, bool variable_frequency, uint32_t frequency) {
|
||||
uint32_t channel_use_mask = _mask(slice, ab_channel);
|
||||
|
||||
// Check the channel first.
|
||||
if ((channel_use & channel_use_mask) != 0) {
|
||||
@ -171,15 +171,15 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
|
||||
}
|
||||
|
||||
uint8_t slice = pwm_gpio_to_slice_num(pin->number);
|
||||
uint8_t channel = pwm_gpio_to_channel(pin->number);
|
||||
uint8_t ab_channel = pwm_gpio_to_channel(pin->number);
|
||||
|
||||
int r = pwmout_allocate(slice, channel, variable_frequency, frequency);
|
||||
int r = pwmout_allocate(slice, ab_channel, variable_frequency, frequency);
|
||||
if (r != PWMOUT_OK) {
|
||||
return r;
|
||||
}
|
||||
|
||||
self->slice = slice;
|
||||
self->channel = channel;
|
||||
self->ab_channel = ab_channel;
|
||||
|
||||
if (target_slice_frequencies[slice] != frequency) {
|
||||
// Reset the counter and compare values.
|
||||
@ -202,11 +202,11 @@ bool common_hal_pwmio_pwmout_deinited(pwmio_pwmout_obj_t *self) {
|
||||
return self->pin == NULL;
|
||||
}
|
||||
|
||||
void pwmout_free(uint8_t slice, uint8_t channel) {
|
||||
uint32_t channel_mask = _mask(slice, channel);
|
||||
void pwmout_free(uint8_t slice, uint8_t ab_channel) {
|
||||
uint32_t channel_mask = _mask(slice, ab_channel);
|
||||
channel_use &= ~channel_mask;
|
||||
never_reset_channel &= ~channel_mask;
|
||||
uint32_t slice_mask = ((1 << CHANNELS_PER_SLICE) - 1) << (slice * CHANNELS_PER_SLICE);
|
||||
uint32_t slice_mask = ((1 << AB_CHANNELS_PER_SLICE) - 1) << (slice * AB_CHANNELS_PER_SLICE);
|
||||
if ((channel_use & slice_mask) == 0) {
|
||||
target_slice_frequencies[slice] = 0;
|
||||
slice_variable_frequency &= ~(1 << slice);
|
||||
@ -218,7 +218,7 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) {
|
||||
if (common_hal_pwmio_pwmout_deinited(self)) {
|
||||
return;
|
||||
}
|
||||
pwmout_free(self->slice, self->channel);
|
||||
pwmout_free(self->slice, self->ab_channel);
|
||||
reset_pin_number(self->pin->number);
|
||||
self->pin = NULL;
|
||||
}
|
||||
@ -235,13 +235,13 @@ extern void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self, uin
|
||||
compare_count = ((uint32_t)duty * self->top + MAX_TOP / 2) / MAX_TOP;
|
||||
}
|
||||
// compare_count is the CC register value, which should be TOP+1 for 100% duty cycle.
|
||||
pwm_set_chan_level(self->slice, self->channel, compare_count);
|
||||
pwm_set_chan_level(self->slice, self->ab_channel, compare_count);
|
||||
// Wait for wrap so that we know our new cc value has been applied. Clear
|
||||
// the internal interrupt and then wait for it to be set. Worst case, we
|
||||
// wait a full cycle.
|
||||
pwm_hw->intr = 1 << self->channel;
|
||||
while ((pwm_hw->en & (1 << self->channel)) != 0 &&
|
||||
(pwm_hw->intr & (1 << self->channel)) == 0 &&
|
||||
pwm_hw->intr = 1 << self->slice;
|
||||
while ((pwm_hw->en & (1 << self->slice)) != 0 &&
|
||||
(pwm_hw->intr & (1 << self->slice)) == 0 &&
|
||||
!mp_hal_is_interrupted()) {
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H
|
||||
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H
|
||||
#ifndef MICROPY_INCLUDED_RASPBERRY_PI_COMMON_HAL_PWMIO_PWMOUT_H
|
||||
#define MICROPY_INCLUDED_RASPBERRY_PI_COMMON_HAL_PWMIO_PWMOUT_H
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
|
||||
@ -34,8 +34,8 @@
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const mcu_pin_obj_t *pin;
|
||||
uint8_t slice;
|
||||
uint8_t channel;
|
||||
uint8_t slice; // 0-7
|
||||
uint8_t ab_channel; // 0-1: A or B slice channel
|
||||
bool variable_frequency;
|
||||
uint16_t duty_cycle;
|
||||
uint32_t actual_frequency;
|
||||
@ -46,13 +46,13 @@ void pwmout_reset(void);
|
||||
// Private API for AudioPWMOut.
|
||||
void pwmio_pwmout_set_top(pwmio_pwmout_obj_t *self, uint16_t top);
|
||||
// Private APIs for RGBMatrix
|
||||
enum pwmout_result_t pwmout_allocate(uint8_t slice, uint8_t channel, bool variable_frequency, uint32_t frequency);
|
||||
void pwmout_free(uint8_t slice, uint8_t channel);
|
||||
void pwmout_never_reset(uint8_t slice, uint8_t channel);
|
||||
void pwmout_reset_ok(uint8_t slice, uint8_t channel);
|
||||
enum pwmout_result_t pwmout_allocate(uint8_t slice, uint8_t ab_channel, bool variable_frequency, uint32_t frequency);
|
||||
void pwmout_free(uint8_t slice, uint8_t ab_channel);
|
||||
void pwmout_never_reset(uint8_t slice, uint8_t ab_channel);
|
||||
void pwmout_reset_ok(uint8_t slice, uint8_t ab_channel);
|
||||
|
||||
// Private API for countio to claim both channels on a slice
|
||||
bool pwmio_claim_slice_channels(uint8_t slice);
|
||||
void pwmio_release_slice_channels(uint8_t slice);
|
||||
// Private API for countio to claim both ab_channels on a slice
|
||||
bool pwmio_claim_slice_ab_channels(uint8_t slice);
|
||||
void pwmio_release_slice_ab_channels(uint8_t slice);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PWMIO_PWMOUT_H
|
||||
#endif // MICROPY_INCLUDED_RASPBERRY_PI_COMMON_HAL_PWMIO_PWMOUT_H
|
||||
|
@ -20,6 +20,7 @@ LD_FILE = boards/STM32F401xd_fs.ld
|
||||
CIRCUITPY_AESIO = 0
|
||||
CIRCUITPY_AUDIOCORE = 0
|
||||
CIRCUITPY_AUDIOPWMIO = 0
|
||||
CIRCUITPY_BLEIO_HCI = 0
|
||||
CIRCUITPY_BUSDEVICE = 0
|
||||
CIRCUITPY_BITMAPTOOLS = 0
|
||||
CIRCUITPY_FRAMEBUFFERIO = 0
|
||||
|
@ -17,6 +17,7 @@ LD_FILE = boards/STM32F411_fs.ld
|
||||
CIRCUITPY_AUDIOCORE = 0
|
||||
CIRCUITPY_AUDIOPWMIO = 0
|
||||
CIRCUITPY_BITMAPTOOLS = 0
|
||||
CIRCUITPY_BLEIO_HCI = 0
|
||||
CIRCUITPY_BUSDEVICE = 0
|
||||
CIRCUITPY_GIFIO = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
|
@ -15,8 +15,7 @@ LD_FILE = boards/STM32F411_fs.ld
|
||||
# Too big for the flash
|
||||
CIRCUITPY_AUDIOCORE = 0
|
||||
CIRCUITPY_AUDIOPWMIO = 0
|
||||
CIRCUITPY_KEYPAD = 0
|
||||
CIRCUITPY_MIDI = 0
|
||||
CIRCUITPY_MSGPACK = 0
|
||||
CIRCUITPY_BITMAPTOOLS = 0
|
||||
CIRCUITPY_BLEIO_HCI = 0
|
||||
CIRCUITPY_MSGPACK = 0
|
||||
CIRCUITPY_VECTORIO = 0
|
||||
|
@ -37,6 +37,10 @@
|
||||
#include "supervisor/shared/autoreload.h"
|
||||
#include "supervisor/shared/stack.h"
|
||||
|
||||
#if CIRCUITPY_BLEIO_HCI
|
||||
#include "common-hal/_bleio/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_DISPLAYIO
|
||||
#include "shared-module/displayio/__init__.h"
|
||||
#endif
|
||||
@ -69,6 +73,10 @@ static void supervisor_background_tasks(void *unused) {
|
||||
|
||||
assert_heap_ok();
|
||||
|
||||
#if CIRCUITPY_BLEIO_HCI
|
||||
bleio_hci_background();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_DISPLAYIO
|
||||
displayio_background();
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user