Add hardware_gpio accessors for Schmitt, slew rate, drive strength (fixes #290) (#464)

This commit is contained in:
Luke Wren 2021-06-01 20:25:11 +01:00 committed by GitHub
parent d026118499
commit 30041d8513
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 180 additions and 1 deletions

View File

@ -39,6 +39,31 @@ void gpio_set_oeover(uint gpio, uint value) {
}
void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled){
}
bool gpio_is_input_hysteresis_enabled(uint gpio){
return true;
}
void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew){
}
enum gpio_slew_rate gpio_get_slew_rate(uint gpio){
return GPIO_SLEW_RATE_FAST;
}
void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive){
}
enum gpio_drive_strength gpio_get_drive_strength(uint gpio){
return GPIO_DRIVE_STRENGTH_4MA;
}
void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enable) {
}

View File

@ -27,6 +27,17 @@ enum gpio_function {
GPIO_FUNC_NULL = 0xf,
};
enum gpio_slew_rate {
GPIO_SLEW_RATE_SLOW = 0, ///< Slew rate limiting enabled
GPIO_SLEW_RATE_FAST = 1 ///< Slew rate limiting disabled
};
enum gpio_drive_strength {
GPIO_DRIVE_STRENGTH_2MA = 0, ///< 2 mA nominal drive strength
GPIO_DRIVE_STRENGTH_4MA = 1, ///< 4 mA nominal drive strength
GPIO_DRIVE_STRENGTH_8MA = 2, ///< 8 mA nominal drive strength
GPIO_DRIVE_STRENGTH_12MA = 3 ///< 12 mA nominal drive strength
};
#define GPIO_OUT 1
#define GPIO_IN 0
@ -58,6 +69,18 @@ void gpio_set_oeover(uint gpio, uint value);
void gpio_set_input_enabled(uint gpio, bool enable);
void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled);
bool gpio_is_input_hysteresis_enabled(uint gpio);
void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew);
enum gpio_slew_rate gpio_get_slew_rate(uint gpio);
void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive);
enum gpio_drive_strength gpio_get_drive_strength(uint gpio);
// Configure a GPIO for direct input/output from software
void gpio_init(uint gpio);

View File

@ -82,6 +82,53 @@ void gpio_set_oeover(uint gpio, uint value) {
);
}
void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled) {
invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
if (enabled)
hw_set_bits(&padsbank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
else
hw_clear_bits(&padsbank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
}
bool gpio_is_input_hysteresis_enabled(uint gpio) {
invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
return (padsbank0_hw->io[gpio] & PADS_BANK0_GPIO0_SCHMITT_BITS) != 0;
}
void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew) {
invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
hw_write_masked(&padsbank0_hw->io[gpio],
(uint)slew << PADS_BANK0_GPIO0_SLEWFAST_LSB,
PADS_BANK0_GPIO0_SLEWFAST_BITS
);
}
enum gpio_slew_rate gpio_get_slew_rate(uint gpio) {
invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
return (enum gpio_slew_rate)((padsbank0_hw->io[gpio]
& PADS_BANK0_GPIO0_SLEWFAST_BITS)
>> PADS_BANK0_GPIO0_SLEWFAST_LSB);
}
// Enum encoding should match hardware encoding on RP2040
static_assert(PADS_BANK0_GPIO0_DRIVE_VALUE_8MA == GPIO_DRIVE_STRENGTH_8MA, "");
void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive) {
invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
hw_write_masked(&padsbank0_hw->io[gpio],
(uint)drive << PADS_BANK0_GPIO0_DRIVE_LSB,
PADS_BANK0_GPIO0_DRIVE_BITS
);
}
enum gpio_drive_strength gpio_get_drive_strength(uint gpio) {
invalid_params_if(GPIO, gpio >= NUM_BANK0_GPIOS);
return (enum gpio_drive_strength)((padsbank0_hw->io[gpio]
& PADS_BANK0_GPIO0_DRIVE_BITS)
>> PADS_BANK0_GPIO0_DRIVE_LSB);
}
static void gpio_irq_handler(void) {
io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
&iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;

View File

@ -140,6 +140,31 @@ enum gpio_override {
GPIO_OVERRIDE_HIGH = 3, ///< drive high/enable output
};
/*! \brief Slew rate limiting levels for GPIO outputs
* \ingroup hardware_gpio
*
* Slew rate limiting increases the minimum rise/fall time when a GPIO output
* is lightly loaded, which can help to reduce electromagnetic emissions.
* \sa gpio_set_slew_rate
*/
enum gpio_slew_rate {
GPIO_SLEW_RATE_SLOW = 0, ///< Slew rate limiting enabled
GPIO_SLEW_RATE_FAST = 1 ///< Slew rate limiting disabled
};
/*! \brief Drive strength levels for GPIO outputs
* \ingroup hardware_gpio
*
* Drive strength levels for GPIO outputs.
* \sa gpio_set_drive_strength
*/
enum gpio_drive_strength {
GPIO_DRIVE_STRENGTH_2MA = 0, ///< 2 mA nominal drive strength
GPIO_DRIVE_STRENGTH_4MA = 1, ///< 4 mA nominal drive strength
GPIO_DRIVE_STRENGTH_8MA = 2, ///< 8 mA nominal drive strength
GPIO_DRIVE_STRENGTH_12MA = 3 ///< 12 mA nominal drive strength
};
// ----------------------------------------------------------------------------
// Pad Controls + IO Muxing
// ----------------------------------------------------------------------------
@ -246,6 +271,65 @@ void gpio_set_oeover(uint gpio, uint value);
*/
void gpio_set_input_enabled(uint gpio, bool enabled);
/*! \brief Enable/disable GPIO input hysteresis (Schmitt trigger)
* \ingroup hardware_gpio
*
* Enable or disable the Schmitt trigger hysteresis on a given GPIO. This is
* enabled on all GPIOs by default. Disabling input hysteresis can lead to
* inconsistent readings when the input signal has very long rise or fall
* times, but slightly reduces the GPIO's input delay.
*
* \sa gpio_is_input_hysteresis_enabled
* \param gpio GPIO number
* \param enabled true to enable input hysteresis on specified GPIO
*/
void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled);
/*! \brief Determine whether input hysteresis is enabled on a specified GPIO
* \ingroup hardware_gpio
*
* \sa gpio_set_input_hysteresis_enabled
* \param gpio GPIO number
*/
bool gpio_is_input_hysteresis_enabled(uint gpio);
/*! \brief Set slew rate for a specified GPIO
* \ingroup hardware_gpio
*
* \sa gpio_get_slew_rate
* \param gpio GPIO number
* \param slew GPIO output slew rate
*/
void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew);
/*! \brief Determine current slew rate for a specified GPIO
* \ingroup hardware_gpio
*
* \sa gpio_set_slew_rate
* \param gpio GPIO number
* \return Current slew rate of that GPIO
*/
enum gpio_slew_rate gpio_get_slew_rate(uint gpio);
/*! \brief Set drive strength for a specified GPIO
* \ingroup hardware_gpio
*
* \sa gpio_get_drive_strength
* \param gpio GPIO number
* \param drive GPIO output drive strength
*/
void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive);
/*! \brief Determine current slew rate for a specified GPIO
* \ingroup hardware_gpio
*
* \sa gpio_set_drive_strength
* \param gpio GPIO number
* \return Current drive strength of that GPIO
*/
enum gpio_drive_strength gpio_get_drive_strength(uint gpio);
/*! \brief Enable or disable interrupts for specified GPIO
* \ingroup hardware_gpio
*