mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-11-09 04:31:37 +08:00
[BACKPORT] px4_fmu-v6xrt: Add dshot support
This commit is contained in:
committed by
David Sidrane
parent
0ed3f143f1
commit
c0c7dd2c3b
@@ -80,6 +80,8 @@ def get_timer_groups(timer_config_file, verbose=False):
|
||||
max_num_channels = 16 # Just add a fixed number of timers
|
||||
timers = [str(i) for i in range(max_num_channels)]
|
||||
dshot_support = {str(i): False for i in range(max_num_channels)}
|
||||
for i in range(8): # First 8 channels support dshot
|
||||
dshot_support[str(i)] = True
|
||||
break
|
||||
|
||||
if timer:
|
||||
|
||||
@@ -12,6 +12,7 @@ CONFIG_DRIVERS_BAROMETER_MS5611=y
|
||||
CONFIG_DRIVERS_CAMERA_CAPTURE=y
|
||||
CONFIG_DRIVERS_CAMERA_TRIGGER=y
|
||||
CONFIG_DRIVERS_DISTANCE_SENSOR_LIGHTWARE_LASER_I2C=y
|
||||
CONFIG_DRIVERS_DSHOT=y
|
||||
CONFIG_DRIVERS_GPS=y
|
||||
CONFIG_DRIVERS_IMU_BOSCH_BMI088=y
|
||||
CONFIG_DRIVERS_IMU_INVENSENSE_ICM20602=y
|
||||
|
||||
@@ -83,6 +83,7 @@ CONFIG_IMXRT_ENET=y
|
||||
CONFIG_IMXRT_FLEXCAN1=y
|
||||
CONFIG_IMXRT_FLEXCAN2=y
|
||||
CONFIG_IMXRT_FLEXCAN3=y
|
||||
CONFIG_IMXRT_FLEXIO1=y
|
||||
CONFIG_IMXRT_FLEXSPI2=y
|
||||
CONFIG_IMXRT_GPIO13_IRQ=y
|
||||
CONFIG_IMXRT_GPIO1_0_15_IRQ=y
|
||||
|
||||
@@ -117,8 +117,8 @@ const struct clock_configuration_s g_initial_clkconfig = {
|
||||
.flexio1_clk_root =
|
||||
{
|
||||
.enable = 1,
|
||||
.div = 1,
|
||||
.mux = FLEXIO1_CLK_ROOT_OSC_RC_48M_DIV2,
|
||||
.div = 2,
|
||||
.mux = FLEXIO1_CLK_ROOT_SYS_PLL3_DIV2,
|
||||
},
|
||||
.flexio2_clk_root =
|
||||
{
|
||||
|
||||
@@ -91,14 +91,14 @@
|
||||
|
||||
|
||||
constexpr io_timers_t io_timers[MAX_IO_TIMERS] = {
|
||||
initIOPWM(PWM::FlexPWM1, PWM::Submodule0),
|
||||
initIOPWM(PWM::FlexPWM1, PWM::Submodule1),
|
||||
initIOPWM(PWM::FlexPWM1, PWM::Submodule2),
|
||||
initIOPWM(PWM::FlexPWM2, PWM::Submodule0),
|
||||
initIOPWM(PWM::FlexPWM2, PWM::Submodule1),
|
||||
initIOPWM(PWM::FlexPWM2, PWM::Submodule2),
|
||||
initIOPWM(PWM::FlexPWM2, PWM::Submodule3),
|
||||
initIOPWM(PWM::FlexPWM3, PWM::Submodule0),
|
||||
initIOPWMDshot(PWM::FlexPWM1, PWM::Submodule0, GPIO_FLEXIO1_FLEXIO23_1, 23),
|
||||
initIOPWMDshot(PWM::FlexPWM1, PWM::Submodule1, GPIO_FLEXIO1_FLEXIO25_1, 25),
|
||||
initIOPWMDshot(PWM::FlexPWM1, PWM::Submodule2, GPIO_FLEXIO1_FLEXIO27_1, 27),
|
||||
initIOPWMDshot(PWM::FlexPWM2, PWM::Submodule0, GPIO_FLEXIO1_FLEXIO06_1, 6),
|
||||
initIOPWMDshot(PWM::FlexPWM2, PWM::Submodule1, GPIO_FLEXIO1_FLEXIO08_1, 8),
|
||||
initIOPWMDshot(PWM::FlexPWM2, PWM::Submodule2, GPIO_FLEXIO1_FLEXIO10_1, 10),
|
||||
initIOPWMDshot(PWM::FlexPWM2, PWM::Submodule3, GPIO_FLEXIO1_FLEXIO19_1, 19),
|
||||
initIOPWMDshot(PWM::FlexPWM3, PWM::Submodule0, GPIO_FLEXIO1_FLEXIO29_1, 29),
|
||||
initIOPWM(PWM::FlexPWM3, PWM::Submodule1),
|
||||
initIOPWM(PWM::FlexPWM3, PWM::Submodule3),
|
||||
initIOPWM(PWM::FlexPWM4, PWM::Submodule0),
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2023 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
px4_add_library(arch_dshot
|
||||
dshot.c
|
||||
)
|
||||
target_compile_options(arch_dshot PRIVATE ${MAX_CUSTOM_OPT_LEVEL})
|
||||
@@ -0,0 +1,230 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2023 PX4 Development Team. All rights reserved.
|
||||
* Author: Peter van der Perk <peter.vanderperk@nxp.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include <px4_platform_common/px4_config.h>
|
||||
#include <px4_platform_common/micro_hal.h>
|
||||
#include <imxrt_flexio.h>
|
||||
#include <px4_arch/dshot.h>
|
||||
#include <px4_arch/io_timer.h>
|
||||
#include <drivers/drv_dshot.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
|
||||
#define DSHOT_TIMERS FLEXIO_SHIFTBUFNIS_COUNT
|
||||
#define DSHOT_THROTTLE_POSITION 5u
|
||||
#define DSHOT_TELEMETRY_POSITION 4u
|
||||
#define NIBBLES_SIZE 4u
|
||||
#define DSHOT_NUMBER_OF_NIBBLES 3u
|
||||
|
||||
typedef struct dshot_handler_t {
|
||||
bool init;
|
||||
uint32_t data_seg1;
|
||||
uint32_t irq_data;
|
||||
} dshot_handler_t;
|
||||
|
||||
static dshot_handler_t dshot_inst[DSHOT_TIMERS] = {};
|
||||
|
||||
struct flexio_dev_s *flexio_s;
|
||||
|
||||
static int flexio_irq_handler(int irq, void *context, void *arg)
|
||||
{
|
||||
|
||||
uint32_t flags = flexio_s->ops->get_shifter_status_flags(flexio_s);
|
||||
uint32_t instance;
|
||||
|
||||
for (instance = 0; flags && instance < DSHOT_TIMERS; instance++) {
|
||||
if (flags & (1 << instance)) {
|
||||
flexio_s->ops->disable_shifter_status_interrupts(flexio_s, (1 << instance));
|
||||
flexio_s->ops->disable_timer_status_interrupts(flexio_s, (1 << instance));
|
||||
|
||||
if (dshot_inst[instance].irq_data != 0) {
|
||||
uint32_t buf_adr = flexio_s->ops->get_shifter_buffer_address(flexio_s, FLEXIO_SHIFTER_BUFFER, instance);
|
||||
putreg32(dshot_inst[instance].irq_data, IMXRT_FLEXIO1_BASE + buf_adr);
|
||||
dshot_inst[instance].irq_data = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq)
|
||||
{
|
||||
uint32_t timer_compare;
|
||||
|
||||
if (dshot_pwm_freq == 150000) {
|
||||
timer_compare = 0x2F8A;
|
||||
|
||||
} else if (dshot_pwm_freq == 300000) {
|
||||
timer_compare = 0x2F45;
|
||||
|
||||
} else if (dshot_pwm_freq == 600000) {
|
||||
timer_compare = 0x2F22;
|
||||
|
||||
} else if (dshot_pwm_freq == 1200000) {
|
||||
timer_compare = 0x2F11;
|
||||
|
||||
} else {
|
||||
// Not supported Dshot frequency
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Init FlexIO peripheral */
|
||||
|
||||
flexio_s = imxrt_flexio_initialize(1);
|
||||
up_enable_irq(IMXRT_IRQ_FLEXIO1);
|
||||
irq_attach(IMXRT_IRQ_FLEXIO1, flexio_irq_handler, flexio_s);
|
||||
|
||||
for (unsigned channel = 0; (channel_mask != 0) && (channel < DSHOT_TIMERS); channel++) {
|
||||
if (channel_mask & (1 << channel)) {
|
||||
uint8_t timer = timer_io_channels[channel].timer_index;
|
||||
|
||||
if (io_timers[timer].dshot.pinmux == 0) { // board does not configure dshot on this pin
|
||||
continue;
|
||||
}
|
||||
|
||||
imxrt_config_gpio(io_timers[timer].dshot.pinmux);
|
||||
|
||||
struct flexio_shifter_config_s shft_cfg;
|
||||
shft_cfg.timer_select = channel;
|
||||
shft_cfg.timer_polarity = FLEXIO_SHIFTER_TIMER_POLARITY_ON_POSITIVE;
|
||||
shft_cfg.pin_config = FLEXIO_PIN_CONFIG_OUTPUT;
|
||||
shft_cfg.pin_select = io_timers[timer].dshot.flexio_pin;
|
||||
shft_cfg.pin_polarity = FLEXIO_PIN_ACTIVE_HIGH;
|
||||
shft_cfg.shifter_mode = FLEXIO_SHIFTER_MODE_TRANSMIT;
|
||||
shft_cfg.parallel_width = 0;
|
||||
shft_cfg.input_source = FLEXIO_SHIFTER_INPUT_FROM_PIN;
|
||||
shft_cfg.shifter_stop = FLEXIO_SHIFTER_STOP_BIT_LOW;
|
||||
shft_cfg.shifter_start = FLEXIO_SHIFTER_START_BIT_DISABLED_LOAD_DATA_ON_ENABLE;
|
||||
|
||||
flexio_s->ops->set_shifter_config(flexio_s, channel, &shft_cfg);
|
||||
|
||||
struct flexio_timer_config_s tmr_cfg;
|
||||
tmr_cfg.trigger_select = (4 * channel) + 1;
|
||||
tmr_cfg.trigger_polarity = FLEXIO_TIMER_TRIGGER_POLARITY_ACTIVE_LOW;
|
||||
tmr_cfg.trigger_source = FLEXIO_TIMER_TRIGGER_SOURCE_INTERNAL;
|
||||
tmr_cfg.pin_config = FLEXIO_PIN_CONFIG_OUTPUT_DISABLED;
|
||||
tmr_cfg.pin_select = 0;
|
||||
tmr_cfg.pin_polarity = FLEXIO_PIN_ACTIVE_LOW;
|
||||
tmr_cfg.timer_mode = FLEXIO_TIMER_MODE_DUAL8_BIT_BAUD_BIT;
|
||||
tmr_cfg.timer_output = FLEXIO_TIMER_OUTPUT_ONE_NOT_AFFECTED_BY_RESET;
|
||||
tmr_cfg.timer_decrement = FLEXIO_TIMER_DEC_SRC_ON_FLEX_IO_CLOCK_SHIFT_TIMER_OUTPUT;
|
||||
tmr_cfg.timer_reset = FLEXIO_TIMER_RESET_NEVER;
|
||||
tmr_cfg.timer_disable = FLEXIO_TIMER_DISABLE_ON_TIMER_COMPARE;
|
||||
tmr_cfg.timer_enable = FLEXIO_TIMER_ENABLE_ON_TRIGGER_HIGH;
|
||||
tmr_cfg.timer_stop = FLEXIO_TIMER_STOP_BIT_DISABLED;
|
||||
tmr_cfg.timer_start = FLEXIO_TIMER_START_BIT_DISABLED;
|
||||
tmr_cfg.timer_compare = timer_compare;
|
||||
flexio_s->ops->set_timer_config(flexio_s, channel, &tmr_cfg);
|
||||
|
||||
dshot_inst[channel].init = true;
|
||||
}
|
||||
}
|
||||
|
||||
flexio_s->ops->enable(flexio_s, true);
|
||||
|
||||
return channel_mask;
|
||||
}
|
||||
|
||||
void up_dshot_trigger(void)
|
||||
{
|
||||
uint32_t buf_adr;
|
||||
|
||||
for (uint8_t motor_number = 0; (motor_number < DSHOT_TIMERS); motor_number++) {
|
||||
if (dshot_inst[motor_number].init && dshot_inst[motor_number].data_seg1 != 0) {
|
||||
buf_adr = flexio_s->ops->get_shifter_buffer_address(flexio_s, FLEXIO_SHIFTER_BUFFER, motor_number);
|
||||
putreg32(dshot_inst[motor_number].data_seg1, IMXRT_FLEXIO1_BASE + buf_adr);
|
||||
}
|
||||
}
|
||||
|
||||
flexio_s->ops->clear_timer_status_flags(flexio_s, 0xFF);
|
||||
flexio_s->ops->enable_shifter_status_interrupts(flexio_s, 0xFF);
|
||||
}
|
||||
|
||||
uint64_t dshot_expand_data(uint16_t packet)
|
||||
{
|
||||
unsigned int mask;
|
||||
unsigned int index = 0;
|
||||
uint64_t expanded = 0x0;
|
||||
|
||||
for (mask = 0x8000; mask != 0; mask >>= 1) {
|
||||
if (packet & mask) {
|
||||
expanded = expanded | ((uint64_t)0x3 << index);
|
||||
|
||||
} else {
|
||||
expanded = expanded | ((uint64_t)0x1 << index);
|
||||
}
|
||||
|
||||
index = index + 3;
|
||||
}
|
||||
|
||||
return expanded;
|
||||
}
|
||||
|
||||
/**
|
||||
* bits 1-11 - throttle value (0-47 are reserved, 48-2047 give 2000 steps of throttle resolution)
|
||||
* bit 12 - dshot telemetry enable/disable
|
||||
* bits 13-16 - XOR checksum
|
||||
**/
|
||||
void dshot_motor_data_set(unsigned motor_number, uint16_t throttle, bool telemetry)
|
||||
{
|
||||
if (motor_number < DSHOT_TIMERS && dshot_inst[motor_number].init) {
|
||||
uint16_t packet = 0;
|
||||
uint16_t checksum = 0;
|
||||
|
||||
packet |= throttle << DSHOT_THROTTLE_POSITION;
|
||||
packet |= ((uint16_t)telemetry & 0x01) << DSHOT_TELEMETRY_POSITION;
|
||||
|
||||
uint16_t csum_data = packet;
|
||||
|
||||
/* XOR checksum calculation */
|
||||
csum_data >>= NIBBLES_SIZE;
|
||||
|
||||
for (unsigned i = 0; i < DSHOT_NUMBER_OF_NIBBLES; i++) {
|
||||
checksum ^= (csum_data & 0x0F); // XOR data by nibbles
|
||||
csum_data >>= NIBBLES_SIZE;
|
||||
}
|
||||
|
||||
packet |= (checksum & 0x0F);
|
||||
|
||||
uint64_t dshot_expanded = dshot_expand_data(packet);
|
||||
dshot_inst[motor_number].data_seg1 = (uint32_t)(dshot_expanded & 0xFFFFFF);
|
||||
dshot_inst[motor_number].irq_data = (uint32_t)(dshot_expanded >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
int up_dshot_arm(bool armed)
|
||||
{
|
||||
return io_timer_set_enable(armed, IOTimerChanMode_Dshot, IO_TIMER_ALL_MODES_CHANNELS);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2023 PX4 Development Team. All rights reserved.
|
||||
* Author: Peter van der Perk <peter.vanderperk@nxp.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drivers/drv_pwm_output.h>
|
||||
|
||||
|
||||
/* The structure which contains configuration for DShot
|
||||
*/
|
||||
typedef struct dshot_conf_t {
|
||||
uint32_t pinmux;
|
||||
uint32_t flexio_pin;
|
||||
} dshot_conf_t;
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include "dshot.h"
|
||||
|
||||
#pragma once
|
||||
__BEGIN_DECLS
|
||||
@@ -86,6 +87,7 @@ typedef struct io_timers_t {
|
||||
uint32_t clock_register; /* SIM_SCGCn */
|
||||
uint32_t clock_bit; /* SIM_SCGCn bit pos */
|
||||
uint32_t vectorno; /* IRQ number */
|
||||
dshot_conf_t dshot;
|
||||
} io_timers_t;
|
||||
|
||||
typedef struct io_timers_channel_mapping_element_t {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2023 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../../../imxrt/include/px4_arch/dshot.h"
|
||||
@@ -0,0 +1,712 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2019 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <px4_arch/io_timer.h>
|
||||
#include <px4_arch/hw_description.h>
|
||||
#include <px4_platform_common/constexpr_util.h>
|
||||
#include <px4_platform_common/px4_config.h>
|
||||
#include <px4_platform/io_timer_init.h>
|
||||
|
||||
#include <hardware/imxrt_tmr.h>
|
||||
#include <hardware/imxrt_flexpwm.h>
|
||||
#include <imxrt_gpio.h>
|
||||
#include <imxrt_iomuxc.h>
|
||||
#include <hardware/imxrt_pinmux.h>
|
||||
|
||||
#include <board_config.h>
|
||||
#if !defined(CONFIG_ARCH_CHIP_MIMXRT1176DVMAA)
|
||||
# error "This code has only been validated with IMXRT1176. Make sure it is correct before using it on another board."
|
||||
#endif
|
||||
|
||||
|
||||
static inline constexpr timer_io_channels_t initIOTimerChannel(const io_timers_t io_timers_conf[MAX_IO_TIMERS],
|
||||
PWM::FlexPWMConfig pwm_config, IOMUX::Pad pad)
|
||||
{
|
||||
timer_io_channels_t ret{};
|
||||
PWM::FlexPWM pwm {};
|
||||
|
||||
// FlexPWM Muxing Options
|
||||
switch (pwm_config.module) {
|
||||
case PWM::PWM1_PWM_A:
|
||||
pwm = PWM::FlexPWM1;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_23) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_23_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN23;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_00) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_00_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN31;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_25) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_25_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN25;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_02) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_02_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_27) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_27_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN27;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_04) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_04_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN3;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_38) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_38_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN6;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::PWM1_PWM_B:
|
||||
pwm = PWM::FlexPWM1;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_24) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_24_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN24;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_01) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_01_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_26) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_26_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN26;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_03) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_03_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_28) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_28_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN28;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_05) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_05_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN4;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_39) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_39_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN7;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::PWM1_PWM_X:
|
||||
pwm = PWM::FlexPWM1;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_06) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_06_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN5;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_07) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_07_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN6;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_08) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_08_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN7;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_09) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_09_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN8;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case PWM::PWM2_PWM_A:
|
||||
pwm = PWM::FlexPWM2;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_06) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_06_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN6;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_24) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_24_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN23;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_08) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_08_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN8;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_26) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_26_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN25;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_10) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_10_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN10;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_28) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_28_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN27;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_19) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_19_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN19;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::PWM2_PWM_B:
|
||||
pwm = PWM::FlexPWM2;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_07) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_07_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN7;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_25) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_25_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN24;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_09) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_09_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN9;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_27) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_27_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN26;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_11) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_11_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN11;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_AD_29) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT4 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_29_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN28;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_20) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_20_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN20;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::PWM2_PWM_X:
|
||||
pwm = PWM::FlexPWM2;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_10) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_10_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN9;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_11) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_11_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN10;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_12) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_12_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN11;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_13) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_13_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN12;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case PWM::PWM3_PWM_A:
|
||||
pwm = PWM::FlexPWM3;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_29) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_29_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN29;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_EMC_B2_00) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B2_00_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT2 | GPIO_PIN10;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_31) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_31_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN31;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_EMC_B2_02) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B2_02_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN12;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_33) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_33_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN1;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_EMC_B2_04) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B2_04_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN14;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_21) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_21_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN21;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_EMC_B2_06) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B2_06_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN16;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::PWM3_PWM_B:
|
||||
pwm = PWM::FlexPWM3;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_30) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_30_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN30;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_EMC_B2_01) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B2_01_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN11;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_32) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_32_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN0;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_EMC_B2_03) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B2_03_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN13;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_34) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_34_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN2;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_EMC_B2_05) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B2_05_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN15;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_22) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_22_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN22;
|
||||
|
||||
} else if (pad == IOMUX::Pad::GPIO_EMC_B2_07) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B2_07_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT8 | GPIO_PIN17;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case PWM::PWM3_PWM_X:
|
||||
pwm = PWM::FlexPWM3;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_14) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_14_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN13;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_15) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_15_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN14;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_16) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_16_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN15;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_17) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_17_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN16;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::PWM4_PWM_A:
|
||||
pwm = PWM::FlexPWM4;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_00) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_00_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN0;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_02) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_02_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN2;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_04) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_04_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN4;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_17) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_17_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN17;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::PWM4_PWM_B:
|
||||
pwm = PWM::FlexPWM4;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_01) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_01_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_03) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_03_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN3;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_05) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_05_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN5;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_EMC_B1_18) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT1 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_EMC_B1_18_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT1 | GPIO_PIN18;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case PWM::PWM4_PWM_X:
|
||||
pwm = PWM::FlexPWM4;
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_18) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_18_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN17;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_19) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_19_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN18;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_20) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_20_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN19;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
if (pad == IOMUX::Pad::GPIO_AD_21) {
|
||||
ret.gpio_out = GPIO_PERIPH | GPIO_ALT11 | GPIO_PADMUX(IMXRT_PADMUX_GPIO_AD_21_INDEX);
|
||||
ret.gpio_portpin = GPIO_PORT9 | GPIO_PIN20;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
constexpr_assert(ret.gpio_out != 0, "Invalid PWM/Pad config");
|
||||
ret.gpio_out |= IOMUX_CMOS_OUTPUT | IOMUX_PULL_NONE | IOMUX_DRIVE_HIGHSTRENGTH | IOMUX_SLEW_FAST;
|
||||
|
||||
switch (pwm_config.module) {
|
||||
case PWM::PWM1_PWM_A:
|
||||
case PWM::PWM2_PWM_A:
|
||||
case PWM::PWM3_PWM_A:
|
||||
case PWM::PWM4_PWM_A:
|
||||
ret.val_offset = PWMA_VAL;
|
||||
break;
|
||||
|
||||
case PWM::PWM1_PWM_B:
|
||||
case PWM::PWM2_PWM_B:
|
||||
case PWM::PWM3_PWM_B:
|
||||
case PWM::PWM4_PWM_B:
|
||||
ret.val_offset = PWMB_VAL;
|
||||
break;
|
||||
|
||||
case PWM::PWM1_PWM_X:
|
||||
case PWM::PWM2_PWM_X:
|
||||
case PWM::PWM3_PWM_X:
|
||||
case PWM::PWM4_PWM_X:
|
||||
ret.val_offset = PWMX_VAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
constexpr_assert(false, "not implemented");
|
||||
}
|
||||
|
||||
switch (pwm_config.submodule) {
|
||||
case PWM::Submodule0:
|
||||
ret.sub_module = SM0;
|
||||
ret.sub_module_bits = MCTRL_LDOK(1 << SM0);
|
||||
break;
|
||||
|
||||
case PWM::Submodule1:
|
||||
ret.sub_module = SM1;
|
||||
ret.sub_module_bits = MCTRL_LDOK(1 << SM1);
|
||||
break;
|
||||
|
||||
case PWM::Submodule2:
|
||||
ret.sub_module = SM2;
|
||||
ret.sub_module_bits = MCTRL_LDOK(1 << SM2);
|
||||
break;
|
||||
|
||||
case PWM::Submodule3:
|
||||
ret.sub_module = SM3;
|
||||
ret.sub_module_bits = MCTRL_LDOK(1 << SM3);
|
||||
break;
|
||||
}
|
||||
|
||||
ret.gpio_in = 0; // TODO (not used yet)
|
||||
|
||||
// find timer index
|
||||
ret.timer_index = 0xff;
|
||||
const uint32_t timer_base = getFlexPWMBaseRegister(pwm);
|
||||
|
||||
for (int i = 0; i < MAX_IO_TIMERS; ++i) {
|
||||
if (io_timers_conf[i].base == timer_base && io_timers_conf[i].submodle == ret.sub_module) {
|
||||
ret.timer_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr_assert(ret.timer_index != 0xff, "Timer not found");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline constexpr io_timers_t initIOPWM(PWM::FlexPWM pwm, PWM::FlexPWMSubmodule sub)
|
||||
{
|
||||
io_timers_t ret{};
|
||||
|
||||
ret.base = getFlexPWMBaseRegister(pwm);
|
||||
ret.submodle = sub;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline constexpr io_timers_t initIOPWMDshot(PWM::FlexPWM pwm, PWM::FlexPWMSubmodule sub, uint32_t pinmux,
|
||||
uint32_t flexio_pin)
|
||||
{
|
||||
io_timers_t ret{};
|
||||
|
||||
ret.base = getFlexPWMBaseRegister(pwm);
|
||||
ret.submodle = sub;
|
||||
ret.dshot.pinmux = pinmux;
|
||||
ret.dshot.flexio_pin = flexio_pin;
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user