Skip to content

Commit

Permalink
Add hardware_gpio accessors for Schmitt, slew rate, drive strength (f…
Browse files Browse the repository at this point in the history
…ixes #290)
  • Loading branch information
Wren6991 committed Jun 1, 2021
1 parent 5384b6b commit 48c0890
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 1 deletion.
27 changes: 26 additions & 1 deletion src/host/hardware_gpio/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_DRIVE_STRENGTH_4MA;
}

void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive){

}

enum gpio_drive_strength gpio_get_drive_strength(uint gpio){
return GPIO_SLEW_RATE_FAST;
}


void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enable) {

}
Expand Down Expand Up @@ -115,4 +140,4 @@ void gpio_set_input_enabled(uint gpio, bool enable) {

void gpio_init_mask(uint gpio_mask) {

}
}
23 changes: 23 additions & 0 deletions src/host/hardware_gpio/include/hardware/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down
47 changes: 47 additions & 0 deletions src/rp2_common/hardware_gpio/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
84 changes: 84 additions & 0 deletions src/rp2_common/hardware_gpio/include/hardware/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -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
*
Expand Down

0 comments on commit 48c0890

Please sign in to comment.