Continue to Site

# understanding the logic of drivestrength settings in efr32FG14

#### yefj

##### Advanced Member level 2
Hello , i have the following slew rate example.
the drive strength changes by a push of a button.
i know that somehow the output resistance is controlled here,but the code is not telling me how exactly they change the output resistance.
the main variable is shown bellow.
GPIO_DriveStrength_TypeDef driveStrength = gpioDriveStrengthStrongAlternateStrong
What is the dinamync for the drive strength in the example bellow?
Thanks.

reference manual:

Code:
/***************************************************************************//**
* @file main_gpio_slew_rate.c
* @brief Demonstrates the slew rate settings for the GPIO. A 1 MHz square wave
* is generated on a pin. The slew rate setting is changed by pressing PB0. The
* drive strength setting is changed by pressing PB1. The effects of these
* settings on the pin's slew rate can be observed by placing a 50uF capacitor
* on the output pin and observing the change in rise and fall times of the 1
* MHz square wave.
*******************************************************************************
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
*    claim that you wrote the original software. If you use this software
*    in a product, an acknowledgment in the product documentation would be
*    appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
*******************************************************************************
* # Evaluation Quality
* This code has been minimally tested to ensure that it builds and is suitable
* as a demonstration for evaluation purposes only. This code will be maintained
* at the sole discretion of Silicon Labs.
******************************************************************************/

#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_timer.h"
#include "em_emu.h"
#include "bsp.h"
#include "stdio.h"

#if defined(BSP_STK_BRD2204A) || defined(BSP_STK_BRD2102A) /* GG11 or TG11 STK square wave on PD1 */
#define SQUARE_WAVE_PORT gpioPortD
#define SQUARE_WAVE_PIN  1
#define SQUARE_WAVE_LOC TIMER_ROUTELOC0_CC0LOC_LOC2
#else /* All other STKs, square wave on PA0 */
#define SQUARE_WAVE_PORT gpioPortA
#define SQUARE_WAVE_PIN  0
#define SQUARE_WAVE_LOC TIMER_ROUTELOC0_CC0LOC_LOC0
#endif

/**************************************************************************//**
* @brief Setup GPIO interrupt for pushbuttons and PA0 output.
*****************************************************************************/
static void gpioSetup(void)
{
// Enable GPIO clock.
CMU_ClockEnable(cmuClock_GPIO, true);

// Configure PB0 as input and enable interrupt.
GPIO_PinModeSet(BSP_GPIO_PB0_PORT, BSP_GPIO_PB0_PIN, gpioModeInputPull, 1);
GPIO_ExtIntConfig(BSP_GPIO_PB0_PORT, BSP_GPIO_PB0_PIN, BSP_GPIO_PB0_PIN, false, true, true);

// Configure PB1 as input and enable interrupt.
GPIO_PinModeSet(BSP_GPIO_PB1_PORT, BSP_GPIO_PB1_PIN, gpioModeInputPull, 1);
GPIO_ExtIntConfig(BSP_GPIO_PB1_PORT, BSP_GPIO_PB1_PIN, BSP_GPIO_PB1_PIN, false, true, true);

NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
NVIC_EnableIRQ(GPIO_EVEN_IRQn);

NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
NVIC_EnableIRQ(GPIO_ODD_IRQn);

// Set PA0 to push-pull output
CMU_ClockEnable(cmuClock_GPIO, true);
GPIO_PinModeSet(SQUARE_WAVE_PORT, SQUARE_WAVE_PIN, gpioModePushPull, 1);
}

GPIO_DriveStrength_TypeDef driveStrength = gpioDriveStrengthStrongAlternateStrong;
uint32_t slewRate = 6;

/**************************************************************************//**
* @brief Unified GPIO Interrupt handler (pushbuttons).
*        PB0 Cycles through slew rate settings.
*        PB1 Cycles through drive strength settings.
*****************************************************************************/
void GPIO_Unified_IRQ(void)
{
// Get and clear all pending GPIO interrupts.
uint32_t interruptMask = GPIO_IntGet();

// Act on interrupts.
if (interruptMask & (1 << BSP_GPIO_PB0_PIN))
{
// BTN0: Slew Rate
slewRate += 1;
if (slewRate > 7)
{
slewRate = 0;
}
}

if (interruptMask & (1 << BSP_GPIO_PB1_PIN))
{
// BTN1: cycle through drive strength settings.
if (driveStrength == gpioDriveStrengthStrongAlternateStrong)
{
driveStrength = gpioDriveStrengthWeakAlternateWeak;
}
else
{
driveStrength = gpioDriveStrengthStrongAlternateStrong;
}
}
}

/**************************************************************************//**
* @brief GPIO Interrupt handler for even pins.
*****************************************************************************/
void GPIO_EVEN_IRQHandler(void)
{
GPIO_Unified_IRQ();
}

/**************************************************************************//**
* @brief GPIO Interrupt handler for odd pins.
*****************************************************************************/
void GPIO_ODD_IRQHandler(void)
{
GPIO_Unified_IRQ();
}

#define OUTPUT_FREQ_Hz (1000000UL)
/**************************************************************************//**
* @brief Timer setup to output a square wave on PA0
*****************************************************************************/
void timerSetup(void)
{
// Set Timer0 to toggle PA0 at 1 MHz
CMU_ClockEnable(cmuClock_TIMER0, true);
uint32_t hfperFreq = CMU_ClockFreqGet(cmuClock_HFPER);
TIMER_TopBufSet(TIMER0, (hfperFreq / (2 * OUTPUT_FREQ_Hz)));
TIMER_Init_TypeDef init = TIMER_INIT_DEFAULT;
TIMER_Init(TIMER0, &init);

TIMER_InitCC_TypeDef initCh = TIMER_INITCC_DEFAULT;
initCh.cofoa = timerOutputActionToggle;
initCh.mode = timerCCModeCompare;
TIMER_InitCC(TIMER0, 0, &initCh);

TIMER0->ROUTEPEN |= TIMER_ROUTEPEN_CC0PEN;
TIMER0->ROUTELOC0 |= SQUARE_WAVE_LOC;
}

/**************************************************************************//**
* @brief  Main function
*
* This example demonstrates the slew rate settings for the GPIO. A 1 MHz
* square wave is generated on a pin. The slew rate setting is changed by
* pressing BTN0. The drive strength setting is changed by pressing BTN1. The
* effects of these settings on the pin's slew rate can be observed by placing
* a 50 pF capacitor on the output pin and observing the change in rise and
* fall times of the 1 MHz square wave.
*
* Output pin is PD1 on SLSTK3701 (EFM32GG11 STK) and SLSTK3301 (EFM32TG11 STK)
* and PA0 on other kits.
*
* To test:
* 1. Place a 50 pF capacitor between the square wave output and GND.
* 2. Upload and run the example.
* 3. While observing the rise and fall times of the waveform on PA0/PD1:
*    a. Press BTN0 to change the slew rate setting
*    b. Press BTN1 to change the drive strength setting
*****************************************************************************/
int main(void)
{
/* Chip errata */
CHIP_Init();

/* Initialize Push Buttons and PA0 */
gpioSetup();

/* Initialize PA0 square-wave output */
timerSetup();

/* Infinite loop */
while (1)
{
/* Update PA0 drive strength and slew rate */
GPIO_DriveStrengthSet(SQUARE_WAVE_PORT, driveStrength);
GPIO_SlewrateSet(SQUARE_WAVE_PORT, slewRate, slewRate);

/* Enter EM1 until a push-button interrupt triggers a wake-up */
EMU_EnterEM1();
}
}

#### FvM

##### Super Moderator
Staff member
Drive strength is changed by calling GPIO_DriveStrengthSet() function. It's setting the respective bits in GPIO_Px_CTRL register. That's what you need to know from the software writer perspective.

From the hardware perspective drive strength is changed by enabling a second driver transistor with higher saturation current respectively lower rdson.

#### yefj

##### Advanced Member level 2
Hello FVM,i am using efr32 mcu with the referance shown bellow. What you said is very intresting.
I am trying to link slew rate to drive strength current.

slew rate is a consept i know from a basic an RC circuit as shown bellow.
it doesnt use current. the output slope comes from exponential expression with constant of RC

Could you please show me a schmatics of how this drive strength is linked to slew rate?
Thanks.

"From the hardware perspective drive strength is changed by enabling a second driver transistor with higher saturation current respectively lower rdson."

#### KlausST

##### Super Moderator
Staff member
Hi,

Did you read the datasheet?

I am trying to link slew rate to drive strength current.

Could you please show me a schmatics of how this drive strength is linked to slew rate?

Why do you want to "link" drive strength to slew rate?
When the given datasheet clearly states that there are independent settings for
* 32.3.1.3 Drive Strength
* 32.3.1.4 Slewrate

I mean it theoretically is possible, with the use of capacitors...

But in your case you can both control independently ... even without the use of capacitors.

****
But you refer to capacitors, but say it does not use the current. But why do you say it does not use the current?
For sure it does. The resistor has direct control to the current, and the current has direct control to the rise rate of a capacitor.

There is Ohm's law (Or what we refer to as it): R = V / I ... or reearranged: I = V / R.
--> Thus: the higher the resistance, the lower the current.

The unit for capacitance is "F" = Farad, and 1F = 1 A * s / V.
The unit of rise rate is: Volts per second, or "V/s"

See the capacitance unit above: F = A * s / V... divide both sides by "A" ... and get F / A = s / V
Re arrange it by swapping the fractions of both sides and get : A / F = V / s
In words: current divided by capacitance = rise rate.

You clearly see that the rise rate is directly linked to current (drive strength) ... if you combine it with a capacitor.
* The higher the current, the higher the rise rate
* The higher the capacitance, the lower the rise rate

Klaus

yefj

### yefj

Points: 2

#### FvM

##### Super Moderator
Staff member
The datasheet and reference manual give no information about the quantitative effect of different slew rate settings. This discussion might help https://community.silabs.com/0D51M00007xeLE1SAM

Generally, slew rate programming is meaningfull only if the output load allows for fast signal transitions. The load capacitance of 50 uf mentioned in the example code is beyond useful limits and might even cause damage of the processor. I suspect a typo, 50 pF would be reasonable.

#### yefj

##### Advanced Member level 2
Hello Klauss, you are correct we do need to connect a capacitor.
my question is understanding the use "drive strength" current .
In VLSI lessons our buffer is basickly a double inverter as shown bellow.
we have C_L*R where R=r_ds_pmos||r_ds_nmos .
our digital square wave signal charge and discharges the load capacitor with RC constant.
How does drive strength current consept fits in here?
how drive strength current is used ?
Thanks.

"Why do you want to "link" drive strength to slew rate?"

--- Updated ---

Update :
So drivestrength current is the ability to charge an discharge the load capacitor.
drive strength current is basicly load current.
the higher drive strength current will result in higher slew rate(if we connect capacitor to the load)

Last edited:

#### yefj

##### Advanced Member level 2
Second update:
suppose i am using port A pins 1 2 3 what is the difference between DRIVESTRENGTH and DRIVESTRENGTHALT .
As i see it every pin have these two settings.
How these two setting play together in desiding what totaldrive strength current we will get?
Thanks.

#### FvM

##### Super Moderator
Staff member
As i see it every pin have these two settings.
No, the setting is per port. See explanation in reference manual:
32.3.1.2 Alternate Port Control
The Alternate Port Control allows for additional flexibilty of port level settings. A user may setup two different port configurations (normal and alternate modes) and select which is applied on a pin by pin bases. For example you may configure half of port A to use the lowdrive strength setting (normal mode) while the other half uses high drive strength (alternate mode).

Alternate port control is enabled when MODEn is set to any of the ALT enumerated modes (ie. PUSHPULLALT). When MODEn is an alternate mode, the pin uses the alternate port control values specified in the DINDISALT, SLEWRATEALT, and DRIVESTRENGTHALT fields in GPIO_Px_CTRL. In all other modes, the port control values are used from the DINDIS,SLEWRATE, and DRIVESTRENGTH fields in GPIO_Px_CTRL.

#### yefj

##### Advanced Member level 2
Hello FVM,looking at the register bellow.
if i define drivestrength=0 (strong) and drive strength_alt=1 then its 10+1=11mA drive strength?correct?
Thanks.

#### FvM

##### Super Moderator
Staff member
I'd expect 10 mA. Unfortuantely there are no output characteristics documented in the reference manual as they are given for other SiLabs processors.
You shouldn't misunderstand the mA value. It doesn't mean current is limited to this value, it's just the current for a nominal output voltage drop. Maximal output current will be higher.

#### yefj

##### Advanced Member level 2
Hello,I am using efr32 GPIO ,how do i know what state of gpio to use?
is there some intuition that i know for example ,for this task i need less drive strength etc then the other task?
Thanks.

reference manual:

Code:
/** GPIO weak 1mA and alternate function weak 1mA. */
gpioDriveStrengthWeakAlternateWeak     = GPIO_P_CTRL_DRIVESTRENGTH_WEAK | GPIO_P_CTRL_DRIVESTRENGTHALT_WEAK,

/** GPIO weak 1mA and alternate function strong 10mA. */
gpioDriveStrengthWeakAlternateStrong   = GPIO_P_CTRL_DRIVESTRENGTH_WEAK | GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG,

/** GPIO strong 10mA and alternate function weak 1mA. */
gpioDriveStrengthStrongAlternateWeak   = GPIO_P_CTRL_DRIVESTRENGTH_STRONG | GPIO_P_CTRL_DRIVESTRENGTHALT_WEAK,

/** GPIO strong 10mA and alternate function strong 10mA. */
gpioDriveStrengthStrongAlternateStrong = GPIO_P_CTRL_DRIVESTRENGTH_STRONG | GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG,
} GPIO_DriveStrength_TypeDef;