|
|
|
@@ -45,7 +45,9 @@
|
|
|
|
|
|
|
|
|
|
#include "arm_internal.h"
|
|
|
|
|
|
|
|
|
|
#define FLEXIO_BASE IMXRT_FLEXIO1_BASE
|
|
|
|
|
#define FLEXIO1_BASE IMXRT_FLEXIO1_BASE
|
|
|
|
|
#define FLEXIO2_BASE IMXRT_FLEXIO2_BASE
|
|
|
|
|
|
|
|
|
|
#define DSHOT_TIMERS FLEXIO_SHIFTBUFNIS_COUNT
|
|
|
|
|
#define DSHOT_THROTTLE_POSITION 5u
|
|
|
|
|
#define DSHOT_TELEMETRY_POSITION 4u
|
|
|
|
@@ -98,77 +100,80 @@ static uint32_t dshot_mask;
|
|
|
|
|
static uint32_t bdshot_recv_mask;
|
|
|
|
|
static uint32_t bdshot_parsed_recv_mask;
|
|
|
|
|
|
|
|
|
|
static inline uint32_t flexio_getreg32(uint32_t offset)
|
|
|
|
|
static uint32_t flexio1_base_addr = FLEXIO1_BASE;
|
|
|
|
|
static uint32_t flexio2_base_addr = FLEXIO2_BASE;
|
|
|
|
|
|
|
|
|
|
static inline uint32_t flexio_getreg32(uint32_t flexio_base, uint32_t offset)
|
|
|
|
|
{
|
|
|
|
|
return getreg32(FLEXIO_BASE + offset);
|
|
|
|
|
return getreg32(flexio_base + offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void flexio_modifyreg32(unsigned int offset,
|
|
|
|
|
static inline void flexio_modifyreg32(uint32_t flexio_base, unsigned int offset,
|
|
|
|
|
uint32_t clearbits,
|
|
|
|
|
uint32_t setbits)
|
|
|
|
|
{
|
|
|
|
|
modifyreg32(FLEXIO_BASE + offset, clearbits, setbits);
|
|
|
|
|
modifyreg32(flexio_base + offset, clearbits, setbits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void flexio_putreg32(uint32_t value, uint32_t offset)
|
|
|
|
|
static inline void flexio_putreg32(uint32_t flexio_base, uint32_t value, uint32_t offset)
|
|
|
|
|
{
|
|
|
|
|
putreg32(value, FLEXIO_BASE + offset);
|
|
|
|
|
putreg32(value, flexio_base + offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void enable_shifter_status_interrupts(uint32_t mask)
|
|
|
|
|
static inline void enable_shifter_status_interrupts(uint32_t flexio_base, uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
flexio_modifyreg32(IMXRT_FLEXIO_SHIFTSIEN_OFFSET, 0, mask);
|
|
|
|
|
flexio_modifyreg32(flexio_base, IMXRT_FLEXIO_SHIFTSIEN_OFFSET, 0, mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void disable_shifter_status_interrupts(uint32_t mask)
|
|
|
|
|
static inline void disable_shifter_status_interrupts(uint32_t flexio_base, uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
flexio_modifyreg32(IMXRT_FLEXIO_SHIFTSIEN_OFFSET, mask, 0);
|
|
|
|
|
flexio_modifyreg32(flexio_base, IMXRT_FLEXIO_SHIFTSIEN_OFFSET, mask, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline uint32_t get_shifter_status_flags(void)
|
|
|
|
|
static inline uint32_t get_shifter_status_flags(uint32_t flexio_base)
|
|
|
|
|
{
|
|
|
|
|
return flexio_getreg32(IMXRT_FLEXIO_SHIFTSTAT_OFFSET);
|
|
|
|
|
return flexio_getreg32(flexio_base, IMXRT_FLEXIO_SHIFTSTAT_OFFSET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void clear_shifter_status_flags(uint32_t mask)
|
|
|
|
|
static inline void clear_shifter_status_flags(uint32_t flexio_base, uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
flexio_putreg32(mask, IMXRT_FLEXIO_SHIFTSTAT_OFFSET);
|
|
|
|
|
flexio_putreg32(flexio_base, mask, IMXRT_FLEXIO_SHIFTSTAT_OFFSET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void enable_timer_status_interrupts(uint32_t mask)
|
|
|
|
|
static inline void enable_timer_status_interrupts(uint32_t flexio_base, uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
flexio_modifyreg32(IMXRT_FLEXIO_TIMIEN_OFFSET, 0, mask);
|
|
|
|
|
flexio_modifyreg32(flexio_base, IMXRT_FLEXIO_TIMIEN_OFFSET, 0, mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void disable_timer_status_interrupts(uint32_t mask)
|
|
|
|
|
static inline void disable_timer_status_interrupts(uint32_t flexio_base, uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
flexio_modifyreg32(IMXRT_FLEXIO_TIMIEN_OFFSET, mask, 0);
|
|
|
|
|
flexio_modifyreg32(flexio_base, IMXRT_FLEXIO_TIMIEN_OFFSET, mask, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline uint32_t get_timer_status_flags(void)
|
|
|
|
|
static inline uint32_t get_timer_status_flags(uint32_t flexio_base)
|
|
|
|
|
{
|
|
|
|
|
return flexio_getreg32(IMXRT_FLEXIO_TIMSTAT_OFFSET);
|
|
|
|
|
return flexio_getreg32(flexio_base, IMXRT_FLEXIO_TIMSTAT_OFFSET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void clear_timer_status_flags(uint32_t mask)
|
|
|
|
|
static inline void clear_timer_status_flags(uint32_t flexio_base, uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
flexio_putreg32(mask, IMXRT_FLEXIO_TIMSTAT_OFFSET);
|
|
|
|
|
flexio_putreg32(flexio_base, mask, IMXRT_FLEXIO_TIMSTAT_OFFSET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void flexio_dshot_output(uint32_t channel, uint32_t pin, uint32_t timcmp, bool inverted)
|
|
|
|
|
static void flexio_dshot_output(uint32_t flexio_base, uint32_t channel, uint32_t pin, uint32_t timcmp, bool inverted)
|
|
|
|
|
{
|
|
|
|
|
/* Disable Shifter */
|
|
|
|
|
flexio_putreg32(0, IMXRT_FLEXIO_SHIFTCTL0_OFFSET + channel * 0x4);
|
|
|
|
|
flexio_putreg32(flexio_base, 0, IMXRT_FLEXIO_SHIFTCTL0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* No start bit, stop bit low */
|
|
|
|
|
flexio_putreg32(FLEXIO_SHIFTCFG_INSRC(FLEXIO_SHIFTER_INPUT_FROM_PIN) |
|
|
|
|
|
flexio_putreg32(flexio_base, FLEXIO_SHIFTCFG_INSRC(FLEXIO_SHIFTER_INPUT_FROM_PIN) |
|
|
|
|
|
FLEXIO_SHIFTCFG_PWIDTH(0) |
|
|
|
|
|
FLEXIO_SHIFTCFG_SSTOP(FLEXIO_SHIFTER_STOP_BIT_LOW) |
|
|
|
|
|
FLEXIO_SHIFTCFG_SSTART(FLEXIO_SHIFTER_START_BIT_DISABLED_LOAD_DATA_ON_ENABLE),
|
|
|
|
|
IMXRT_FLEXIO_SHIFTCFG0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* Transmit mode, output to FXIO pin, inverted output for bdshot */
|
|
|
|
|
flexio_putreg32(FLEXIO_SHIFTCTL_TIMSEL(channel) |
|
|
|
|
|
flexio_putreg32(flexio_base, FLEXIO_SHIFTCTL_TIMSEL(channel) |
|
|
|
|
|
FLEXIO_SHIFTCTL_TIMPOL(FLEXIO_SHIFTER_TIMER_POLARITY_ON_POSITIVE) |
|
|
|
|
|
FLEXIO_SHIFTCTL_PINCFG(FLEXIO_PIN_CONFIG_OUTPUT) |
|
|
|
|
|
FLEXIO_SHIFTCTL_PINSEL(pin) |
|
|
|
|
@@ -177,7 +182,7 @@ static void flexio_dshot_output(uint32_t channel, uint32_t pin, uint32_t timcmp,
|
|
|
|
|
IMXRT_FLEXIO_SHIFTCTL0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* Start transmitting on trigger, disable on compare */
|
|
|
|
|
flexio_putreg32(FLEXIO_TIMCFG_TIMOUT(FLEXIO_TIMER_OUTPUT_ONE_NOT_AFFECTED_BY_RESET) |
|
|
|
|
|
flexio_putreg32(flexio_base, FLEXIO_TIMCFG_TIMOUT(FLEXIO_TIMER_OUTPUT_ONE_NOT_AFFECTED_BY_RESET) |
|
|
|
|
|
FLEXIO_TIMCFG_TIMDEC(FLEXIO_TIMER_DEC_SRC_ON_FLEX_IO_CLOCK_SHIFT_TIMER_OUTPUT) |
|
|
|
|
|
FLEXIO_TIMCFG_TIMRST(FLEXIO_TIMER_RESET_NEVER) |
|
|
|
|
|
FLEXIO_TIMCFG_TIMDIS(FLEXIO_TIMER_DISABLE_ON_TIMER_COMPARE) |
|
|
|
|
@@ -186,10 +191,10 @@ static void flexio_dshot_output(uint32_t channel, uint32_t pin, uint32_t timcmp,
|
|
|
|
|
FLEXIO_TIMCFG_TSTART(FLEXIO_TIMER_START_BIT_DISABLED),
|
|
|
|
|
IMXRT_FLEXIO_TIMCFG0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
flexio_putreg32(timcmp, IMXRT_FLEXIO_TIMCMP0_OFFSET + channel * 0x4);
|
|
|
|
|
flexio_putreg32(flexio_base, timcmp, IMXRT_FLEXIO_TIMCMP0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* Baud mode, Trigger on shifter write */
|
|
|
|
|
flexio_putreg32(FLEXIO_TIMCTL_TRGSEL((4 * channel) + 1) |
|
|
|
|
|
flexio_putreg32(flexio_base, FLEXIO_TIMCTL_TRGSEL((4 * channel) + 1) |
|
|
|
|
|
FLEXIO_TIMCTL_TRGPOL(FLEXIO_TIMER_TRIGGER_POLARITY_ACTIVE_LOW) |
|
|
|
|
|
FLEXIO_TIMCTL_TRGSRC(FLEXIO_TIMER_TRIGGER_SOURCE_INTERNAL) |
|
|
|
|
|
FLEXIO_TIMCTL_PINCFG(FLEXIO_PIN_CONFIG_OUTPUT_DISABLED) |
|
|
|
|
@@ -202,20 +207,22 @@ static void flexio_dshot_output(uint32_t channel, uint32_t pin, uint32_t timcmp,
|
|
|
|
|
|
|
|
|
|
static int flexio_irq_handler(int irq, void *context, void *arg)
|
|
|
|
|
{
|
|
|
|
|
uint32_t flags = get_shifter_status_flags();
|
|
|
|
|
uint32_t flexio_base = *(uint32_t *) arg;
|
|
|
|
|
|
|
|
|
|
uint32_t flags = get_shifter_status_flags(flexio_base);
|
|
|
|
|
uint32_t channel;
|
|
|
|
|
|
|
|
|
|
for (channel = 0; flags && channel < DSHOT_TIMERS; channel++) {
|
|
|
|
|
if (flags & (1 << channel)) {
|
|
|
|
|
disable_shifter_status_interrupts(1 << channel);
|
|
|
|
|
if ((flags & (1 << channel)) && timer_io_channels[channel].flex_io_base == flexio_base) {
|
|
|
|
|
disable_shifter_status_interrupts(flexio_base, 1 << channel);
|
|
|
|
|
|
|
|
|
|
if (dshot_inst[channel].state == DSHOT_START) {
|
|
|
|
|
dshot_inst[channel].state = DSHOT_12BIT_FIFO;
|
|
|
|
|
flexio_putreg32(dshot_inst[channel].irq_data, IMXRT_FLEXIO_SHIFTBUF0_OFFSET + channel * 0x4);
|
|
|
|
|
flexio_putreg32(flexio_base, dshot_inst[channel].irq_data, IMXRT_FLEXIO_SHIFTBUF0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
} else if (dshot_inst[channel].state == BDSHOT_RECEIVE) {
|
|
|
|
|
dshot_inst[channel].state = BDSHOT_RECEIVE_COMPLETE;
|
|
|
|
|
dshot_inst[channel].raw_response = flexio_getreg32(IMXRT_FLEXIO_SHIFTBUFBIS0_OFFSET + channel * 0x4);
|
|
|
|
|
dshot_inst[channel].raw_response = flexio_getreg32(flexio_base, IMXRT_FLEXIO_SHIFTBUFBIS0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
bdshot_recv_mask |= (1 << channel);
|
|
|
|
|
|
|
|
|
@@ -227,13 +234,13 @@ static int flexio_irq_handler(int irq, void *context, void *arg)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flags = get_timer_status_flags();
|
|
|
|
|
flags = get_timer_status_flags(flexio_base);
|
|
|
|
|
|
|
|
|
|
for (channel = 0; flags; (channel = (channel + 1) % DSHOT_TIMERS)) {
|
|
|
|
|
flags = get_timer_status_flags();
|
|
|
|
|
flags = get_timer_status_flags(flexio_base);
|
|
|
|
|
|
|
|
|
|
if (flags & (1 << channel)) {
|
|
|
|
|
clear_timer_status_flags(1 << channel);
|
|
|
|
|
if ((flags & (1 << channel)) && timer_io_channels[channel].flex_io_base == flexio_base) {
|
|
|
|
|
clear_timer_status_flags(flexio_base, 1 << channel);
|
|
|
|
|
|
|
|
|
|
if (dshot_inst[channel].state == DSHOT_12BIT_FIFO) {
|
|
|
|
|
dshot_inst[channel].state = DSHOT_12BIT_TRANSFERRED;
|
|
|
|
@@ -242,21 +249,21 @@ static int flexio_irq_handler(int irq, void *context, void *arg)
|
|
|
|
|
dshot_inst[channel].state = DSHOT_TRANSMIT_COMPLETE;
|
|
|
|
|
|
|
|
|
|
} else if (dshot_inst[channel].bdshot && dshot_inst[channel].state == DSHOT_12BIT_TRANSFERRED) {
|
|
|
|
|
disable_shifter_status_interrupts(1 << channel);
|
|
|
|
|
disable_shifter_status_interrupts(flexio_base, 1 << channel);
|
|
|
|
|
dshot_inst[channel].state = BDSHOT_RECEIVE;
|
|
|
|
|
|
|
|
|
|
/* Transmit done, disable timer and reconfigure to receive*/
|
|
|
|
|
flexio_putreg32(0x0, IMXRT_FLEXIO_TIMCTL0_OFFSET + channel * 0x4);
|
|
|
|
|
flexio_putreg32(flexio_base, 0x0, IMXRT_FLEXIO_TIMCTL0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* Input data from pin, no start/stop bit*/
|
|
|
|
|
flexio_putreg32(FLEXIO_SHIFTCFG_INSRC(FLEXIO_SHIFTER_INPUT_FROM_PIN) |
|
|
|
|
|
flexio_putreg32(flexio_base, FLEXIO_SHIFTCFG_INSRC(FLEXIO_SHIFTER_INPUT_FROM_PIN) |
|
|
|
|
|
FLEXIO_SHIFTCFG_PWIDTH(0) |
|
|
|
|
|
FLEXIO_SHIFTCFG_SSTOP(FLEXIO_SHIFTER_STOP_BIT_DISABLE) |
|
|
|
|
|
FLEXIO_SHIFTCFG_SSTART(FLEXIO_SHIFTER_START_BIT_DISABLED_LOAD_DATA_ON_SHIFT),
|
|
|
|
|
IMXRT_FLEXIO_SHIFTCFG0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* Shifter receive mdoe, on FXIO pin input */
|
|
|
|
|
flexio_putreg32(FLEXIO_SHIFTCTL_TIMSEL(channel) |
|
|
|
|
|
flexio_putreg32(flexio_base, FLEXIO_SHIFTCTL_TIMSEL(channel) |
|
|
|
|
|
FLEXIO_SHIFTCTL_TIMPOL(FLEXIO_SHIFTER_TIMER_POLARITY_ON_POSITIVE) |
|
|
|
|
|
FLEXIO_SHIFTCTL_PINCFG(FLEXIO_PIN_CONFIG_OUTPUT_DISABLED) |
|
|
|
|
|
FLEXIO_SHIFTCTL_PINSEL(timer_io_channels[channel].dshot.flexio_pin) |
|
|
|
|
@@ -265,10 +272,10 @@ static int flexio_irq_handler(int irq, void *context, void *arg)
|
|
|
|
|
IMXRT_FLEXIO_SHIFTCTL0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* Make sure there no shifter flags high from transmission */
|
|
|
|
|
clear_shifter_status_flags(1 << channel);
|
|
|
|
|
clear_shifter_status_flags(flexio_base, 1 << channel);
|
|
|
|
|
|
|
|
|
|
/* Enable on pin transition, resychronize through reset on rising edge */
|
|
|
|
|
flexio_putreg32(FLEXIO_TIMCFG_TIMOUT(FLEXIO_TIMER_OUTPUT_ONE_AFFECTED_BY_RESET) |
|
|
|
|
|
flexio_putreg32(flexio_base, FLEXIO_TIMCFG_TIMOUT(FLEXIO_TIMER_OUTPUT_ONE_AFFECTED_BY_RESET) |
|
|
|
|
|
FLEXIO_TIMCFG_TIMDEC(FLEXIO_TIMER_DEC_SRC_ON_FLEX_IO_CLOCK_SHIFT_TIMER_OUTPUT) |
|
|
|
|
|
FLEXIO_TIMCFG_TIMRST(FLEXIO_TIMER_RESET_ON_TIMER_PIN_RISING_EDGE) |
|
|
|
|
|
FLEXIO_TIMCFG_TIMDIS(FLEXIO_TIMER_DISABLE_ON_TIMER_COMPARE) |
|
|
|
|
@@ -278,10 +285,10 @@ static int flexio_irq_handler(int irq, void *context, void *arg)
|
|
|
|
|
IMXRT_FLEXIO_TIMCFG0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* Enable on pin transition, resychronize through reset on rising edge */
|
|
|
|
|
flexio_putreg32(bdshot_tcmp, IMXRT_FLEXIO_TIMCMP0_OFFSET + channel * 0x4);
|
|
|
|
|
flexio_putreg32(flexio_base, bdshot_tcmp, IMXRT_FLEXIO_TIMCMP0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* Trigger on FXIO pin transition, Baud mode */
|
|
|
|
|
flexio_putreg32(FLEXIO_TIMCTL_TRGSEL(2 * timer_io_channels[channel].dshot.flexio_pin) |
|
|
|
|
|
flexio_putreg32(flexio_base, FLEXIO_TIMCTL_TRGSEL(2 * timer_io_channels[channel].dshot.flexio_pin) |
|
|
|
|
|
FLEXIO_TIMCTL_TRGPOL(FLEXIO_TIMER_TRIGGER_POLARITY_ACTIVE_HIGH) |
|
|
|
|
|
FLEXIO_TIMCTL_TRGSRC(FLEXIO_TIMER_TRIGGER_SOURCE_INTERNAL) |
|
|
|
|
|
FLEXIO_TIMCTL_PINCFG(FLEXIO_PIN_CONFIG_OUTPUT_DISABLED) |
|
|
|
|
@@ -291,7 +298,7 @@ static int flexio_irq_handler(int irq, void *context, void *arg)
|
|
|
|
|
IMXRT_FLEXIO_TIMCTL0_OFFSET + channel * 0x4);
|
|
|
|
|
|
|
|
|
|
/* Enable shifter interrupt for receiving data */
|
|
|
|
|
enable_shifter_status_interrupts(1 << channel);
|
|
|
|
|
enable_shifter_status_interrupts(flexio_base, 1 << channel);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -300,34 +307,72 @@ static int flexio_irq_handler(int irq, void *context, void *arg)
|
|
|
|
|
return OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq, bool enable_bidirectional_dshot)
|
|
|
|
|
{
|
|
|
|
|
/* Calculate dshot timings based on dshot_pwm_freq */
|
|
|
|
|
dshot_tcmp = 0x2F00 | (((BOARD_FLEXIO_PREQ / (dshot_pwm_freq * 3) / 2) - 1) & 0xFF);
|
|
|
|
|
bdshot_tcmp = 0x2900 | (((BOARD_FLEXIO_PREQ / (dshot_pwm_freq * 5 / 4) / 2) - 3) & 0xFF);
|
|
|
|
|
|
|
|
|
|
/* Clock FlexIO peripheral */
|
|
|
|
|
imxrt_clockall_flexio1();
|
|
|
|
|
bool flexio1_channels = false;
|
|
|
|
|
bool flexio2_channels = false;
|
|
|
|
|
|
|
|
|
|
/* Reset FlexIO peripheral */
|
|
|
|
|
flexio_modifyreg32(IMXRT_FLEXIO_CTRL_OFFSET, 0,
|
|
|
|
|
FLEXIO_CTRL_SWRST_MASK);
|
|
|
|
|
flexio_putreg32(0, IMXRT_FLEXIO_CTRL_OFFSET);
|
|
|
|
|
for (unsigned i = 0; (channel_mask != 0) && (i < DSHOT_TIMERS); i++) {
|
|
|
|
|
if (channel_mask & (1 << i)) {
|
|
|
|
|
if (timer_io_channels[i].flex_io_base == FLEXIO1_BASE) {
|
|
|
|
|
PX4_INFO("Flexio1 channel found");
|
|
|
|
|
flexio1_channels = true;
|
|
|
|
|
|
|
|
|
|
/* Initialize FlexIO peripheral */
|
|
|
|
|
flexio_modifyreg32(IMXRT_FLEXIO_CTRL_OFFSET,
|
|
|
|
|
(FLEXIO_CTRL_DOZEN_MASK |
|
|
|
|
|
FLEXIO_CTRL_DBGE_MASK |
|
|
|
|
|
FLEXIO_CTRL_FASTACC_MASK |
|
|
|
|
|
FLEXIO_CTRL_FLEXEN_MASK),
|
|
|
|
|
(FLEXIO_CTRL_DBGE(1) |
|
|
|
|
|
FLEXIO_CTRL_FASTACC(1) |
|
|
|
|
|
FLEXIO_CTRL_FLEXEN(0)));
|
|
|
|
|
} else if (timer_io_channels[i].flex_io_base == FLEXIO2_BASE) {
|
|
|
|
|
PX4_INFO("Flexio2 channel found");
|
|
|
|
|
flexio2_channels = true;
|
|
|
|
|
|
|
|
|
|
/* FlexIO IRQ handling */
|
|
|
|
|
up_enable_irq(IMXRT_IRQ_FLEXIO1);
|
|
|
|
|
irq_attach(IMXRT_IRQ_FLEXIO1, flexio_irq_handler, 0);
|
|
|
|
|
} else {PX4_ERR("Invalid flexio base defined");}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flexio1_channels) { // FlexIO peripheral 1
|
|
|
|
|
/* Clock FlexIO peripheral */
|
|
|
|
|
imxrt_clockall_flexio1();
|
|
|
|
|
/* Reset FlexIO 1 peripheral */
|
|
|
|
|
flexio_modifyreg32(FLEXIO1_BASE, IMXRT_FLEXIO_CTRL_OFFSET, 0,
|
|
|
|
|
FLEXIO_CTRL_SWRST_MASK);
|
|
|
|
|
flexio_putreg32(FLEXIO1_BASE, 0, IMXRT_FLEXIO_CTRL_OFFSET);
|
|
|
|
|
|
|
|
|
|
/* Initialize FlexIO 1 peripheral */
|
|
|
|
|
flexio_modifyreg32(FLEXIO1_BASE, IMXRT_FLEXIO_CTRL_OFFSET,
|
|
|
|
|
(FLEXIO_CTRL_DOZEN_MASK |
|
|
|
|
|
FLEXIO_CTRL_DBGE_MASK |
|
|
|
|
|
FLEXIO_CTRL_FASTACC_MASK |
|
|
|
|
|
FLEXIO_CTRL_FLEXEN_MASK),
|
|
|
|
|
(FLEXIO_CTRL_DBGE(1) |
|
|
|
|
|
FLEXIO_CTRL_FASTACC(1) |
|
|
|
|
|
FLEXIO_CTRL_FLEXEN(0)));
|
|
|
|
|
/* FlexIO IRQ handling */
|
|
|
|
|
up_enable_irq(IMXRT_IRQ_FLEXIO1);
|
|
|
|
|
irq_attach(IMXRT_IRQ_FLEXIO1, flexio_irq_handler, &flexio1_base_addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flexio2_channels) { // FlexIO peripheral 2
|
|
|
|
|
/* Clock FlexIO peripheral */
|
|
|
|
|
imxrt_clockall_flexio2();
|
|
|
|
|
/* Reset FlexIO 2 peripheral */
|
|
|
|
|
flexio_modifyreg32(FLEXIO2_BASE, IMXRT_FLEXIO_CTRL_OFFSET, 0,
|
|
|
|
|
FLEXIO_CTRL_SWRST_MASK);
|
|
|
|
|
flexio_putreg32(FLEXIO2_BASE, 0, IMXRT_FLEXIO_CTRL_OFFSET);
|
|
|
|
|
|
|
|
|
|
/* Initialize FlexIO 2 peripheral */
|
|
|
|
|
flexio_modifyreg32(FLEXIO2_BASE, IMXRT_FLEXIO_CTRL_OFFSET,
|
|
|
|
|
(FLEXIO_CTRL_DOZEN_MASK |
|
|
|
|
|
FLEXIO_CTRL_DBGE_MASK |
|
|
|
|
|
FLEXIO_CTRL_FASTACC_MASK |
|
|
|
|
|
FLEXIO_CTRL_FLEXEN_MASK),
|
|
|
|
|
(FLEXIO_CTRL_DBGE(1) |
|
|
|
|
|
FLEXIO_CTRL_FASTACC(1) |
|
|
|
|
|
FLEXIO_CTRL_FLEXEN(0)));
|
|
|
|
|
|
|
|
|
|
up_enable_irq(IMXRT_IRQ_FLEXIO2);
|
|
|
|
|
irq_attach(IMXRT_IRQ_FLEXIO2, flexio_irq_handler, &flexio2_base_addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dshot_mask = 0x0;
|
|
|
|
|
|
|
|
|
@@ -342,7 +387,9 @@ int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq, bool enable_bi
|
|
|
|
|
|
|
|
|
|
dshot_inst[channel].bdshot = enable_bidirectional_dshot;
|
|
|
|
|
|
|
|
|
|
flexio_dshot_output(channel, timer_io_channels[channel].dshot.flexio_pin, dshot_tcmp, dshot_inst[channel].bdshot);
|
|
|
|
|
flexio_dshot_output(timer_io_channels[channel].flex_io_base, channel, timer_io_channels[channel].dshot.flexio_pin,
|
|
|
|
|
dshot_tcmp,
|
|
|
|
|
dshot_inst[channel].bdshot);
|
|
|
|
|
|
|
|
|
|
dshot_inst[channel].init = true;
|
|
|
|
|
|
|
|
|
@@ -351,8 +398,16 @@ int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq, bool enable_bi
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flexio_modifyreg32(IMXRT_FLEXIO_CTRL_OFFSET, 0,
|
|
|
|
|
FLEXIO_CTRL_FLEXEN_MASK);
|
|
|
|
|
if (flexio1_channels) {
|
|
|
|
|
flexio_modifyreg32(FLEXIO1_BASE, IMXRT_FLEXIO_CTRL_OFFSET, 0,
|
|
|
|
|
FLEXIO_CTRL_FLEXEN_MASK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flexio2_channels) {
|
|
|
|
|
flexio_modifyreg32(FLEXIO2_BASE, IMXRT_FLEXIO_CTRL_OFFSET, 0,
|
|
|
|
|
FLEXIO_CTRL_FLEXEN_MASK);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return channel_mask;
|
|
|
|
|
}
|
|
|
|
@@ -417,7 +472,6 @@ void up_bdshot_erpm(void)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int up_bdshot_num_erpm_ready(void)
|
|
|
|
|
{
|
|
|
|
|
int num_ready = 0;
|
|
|
|
@@ -470,12 +524,36 @@ void up_bdshot_status(void)
|
|
|
|
|
|
|
|
|
|
void up_dshot_trigger(void)
|
|
|
|
|
{
|
|
|
|
|
bool flexio1_channels = false;
|
|
|
|
|
bool flexio2_channels = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; (i < DSHOT_TIMERS); i++) {
|
|
|
|
|
if (dshot_inst[i].init && dshot_inst[i].data_seg1 != 0) {
|
|
|
|
|
|
|
|
|
|
if (timer_io_channels[i].flex_io_base == FLEXIO1_BASE) {
|
|
|
|
|
flexio1_channels = true;
|
|
|
|
|
|
|
|
|
|
} else if (timer_io_channels[i].flex_io_base == FLEXIO2_BASE) {
|
|
|
|
|
flexio2_channels = true;
|
|
|
|
|
|
|
|
|
|
} else {PX4_ERR("Invalid flexio base defined");}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calc data now since we're not event driven
|
|
|
|
|
if (bdshot_recv_mask != 0x0) {
|
|
|
|
|
up_bdshot_erpm();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clear_timer_status_flags(0xFF);
|
|
|
|
|
if (flexio1_channels) {
|
|
|
|
|
clear_timer_status_flags(FLEXIO1_BASE, 0xFF);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flexio2_channels) {
|
|
|
|
|
clear_timer_status_flags(FLEXIO2_BASE, 0xFF);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (uint8_t channel = 0; (channel < DSHOT_TIMERS); channel++) {
|
|
|
|
|
if (dshot_inst[channel].bdshot && (bdshot_recv_mask & (1 << channel)) == 0) {
|
|
|
|
@@ -483,15 +561,26 @@ void up_dshot_trigger(void)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dshot_inst[channel].init && dshot_inst[channel].data_seg1 != 0) {
|
|
|
|
|
flexio_putreg32(dshot_inst[channel].data_seg1, IMXRT_FLEXIO_SHIFTBUF0_OFFSET + channel * 0x4);
|
|
|
|
|
flexio_putreg32(timer_io_channels[channel].flex_io_base, dshot_inst[channel].data_seg1,
|
|
|
|
|
IMXRT_FLEXIO_SHIFTBUF0_OFFSET + channel * 0x4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bdshot_recv_mask = 0x0;
|
|
|
|
|
|
|
|
|
|
clear_timer_status_flags(0xFF);
|
|
|
|
|
enable_shifter_status_interrupts(0xFF);
|
|
|
|
|
enable_timer_status_interrupts(0xFF);
|
|
|
|
|
if (flexio1_channels) {
|
|
|
|
|
clear_timer_status_flags(FLEXIO1_BASE, 0xFF);
|
|
|
|
|
enable_shifter_status_interrupts(FLEXIO1_BASE, 0xFF);
|
|
|
|
|
enable_timer_status_interrupts(FLEXIO1_BASE, 0xFF);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flexio2_channels) {
|
|
|
|
|
clear_timer_status_flags(FLEXIO2_BASE, 0xFF);
|
|
|
|
|
enable_shifter_status_interrupts(FLEXIO2_BASE, 0xFF);
|
|
|
|
|
enable_timer_status_interrupts(FLEXIO2_BASE, 0xFF);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Expand packet from 16 bits 48 to get T0H and T1H timing */
|
|
|
|
@@ -522,6 +611,7 @@ uint64_t dshot_expand_data(uint16_t packet)
|
|
|
|
|
**/
|
|
|
|
|
void dshot_motor_data_set(unsigned channel, uint16_t throttle, bool telemetry)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (channel < DSHOT_TIMERS && dshot_inst[channel].init) {
|
|
|
|
|
uint16_t csum_data;
|
|
|
|
|
uint16_t packet = 0;
|
|
|
|
@@ -554,13 +644,14 @@ void dshot_motor_data_set(unsigned channel, uint16_t throttle, bool telemetry)
|
|
|
|
|
dshot_inst[channel].state = DSHOT_START;
|
|
|
|
|
|
|
|
|
|
if (dshot_inst[channel].bdshot) {
|
|
|
|
|
flexio_putreg32(timer_io_channels[channel].flex_io_base, 0x0, IMXRT_FLEXIO_TIMCTL0_OFFSET + channel * 0x4);
|
|
|
|
|
disable_shifter_status_interrupts(timer_io_channels[channel].flex_io_base, 1 << channel);
|
|
|
|
|
|
|
|
|
|
flexio_putreg32(0x0, IMXRT_FLEXIO_TIMCTL0_OFFSET + channel * 0x4);
|
|
|
|
|
disable_shifter_status_interrupts(1 << channel);
|
|
|
|
|
flexio_dshot_output(timer_io_channels[channel].flex_io_base, channel, timer_io_channels[channel].dshot.flexio_pin,
|
|
|
|
|
dshot_tcmp,
|
|
|
|
|
dshot_inst[channel].bdshot);
|
|
|
|
|
|
|
|
|
|
flexio_dshot_output(channel, timer_io_channels[channel].dshot.flexio_pin, dshot_tcmp, dshot_inst[channel].bdshot);
|
|
|
|
|
|
|
|
|
|
clear_timer_status_flags(0xFF);
|
|
|
|
|
clear_timer_status_flags(timer_io_channels[channel].flex_io_base, 0xFF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|