How to use GPIO ports?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to use GPIO ports?

Jump to solution
11,770 Views
giova841
Contributor II

Hi everybody, I have developed a function on the TWR-K65 development Platform and now I need to measure its processing time. I think that the best way to do this is to set up a GPIO signal before the function to start and turn off the signal once the function has been completed. Monitoring this signal with an oscilloscope I will get the processing time I am looking for. Is there any tutorial I can follow about switching on/off a GPIO singal on the TWR-K65 Platform? Cheers, Giulio

0 Kudos
1 Solution
6,780 Views
sebastianhutten
Contributor II

Have you tried using the online tools (pins and clocks) and are you calling BOARD_InitPins()? 

https://mcuxpresso.nxp.com/en/welcome

The pins tool will give you the pin_mux.c & .h files. The BOARD_InitPins() will ensure pin routing is to your configuration and the required GPIO port clocks are enabled. Then the GPIO_* API (e.g. SDK v2.x) can be used (set direction, read, write, etc.)

Using the GPIO API is nice in that you don't need to understand/use the MCU registers.The GPIO source code is there (fsl_gpio.c) if later you want/need to go to the lower level.

Following is a typical main init when using the config tools & SDK v2.x

int main(void)
{

/* Init board hardware. */
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();

// **** now GPIO_*() and PRINTF() should work

hope this is helpful

View solution in original post

0 Kudos
16 Replies
6,781 Views
sebastianhutten
Contributor II

Have you tried using the online tools (pins and clocks) and are you calling BOARD_InitPins()? 

https://mcuxpresso.nxp.com/en/welcome

The pins tool will give you the pin_mux.c & .h files. The BOARD_InitPins() will ensure pin routing is to your configuration and the required GPIO port clocks are enabled. Then the GPIO_* API (e.g. SDK v2.x) can be used (set direction, read, write, etc.)

Using the GPIO API is nice in that you don't need to understand/use the MCU registers.The GPIO source code is there (fsl_gpio.c) if later you want/need to go to the lower level.

Following is a typical main init when using the config tools & SDK v2.x

int main(void)
{

/* Init board hardware. */
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();

// **** now GPIO_*() and PRINTF() should work

hope this is helpful

0 Kudos
6,780 Views
giova841
Contributor II

Yes the problem was just right that, the pins were not correctly

initialized, so I took the gpio_led example available in the KSDK and

barely copied the led init code into my program and now I have a led

blinking as my program runs so I can easily measure its exec time.

Il giorno ven 10 feb 2017 alle 01:31 sebastianhutten <

admin@community.nxp.com> ha scritto:

NXP Community

<https://community.freescale.com/resources/statics/1000/35400-NXP-Community-Email-banner-600x75.jpg>

Re: How to use GPIO ports?

reply from Sebastian Hutten

<https://community.nxp.com/people/sebastianhutten?et=watches.email.thread>

in Kinetis Microcontrollers - View the full discussion

<https://community.nxp.com/message/875763?commentID=875763&et=watches.email.thread#comment-875763>

0 Kudos
6,780 Views
egoodii
Senior Contributor III

I do this ALL the time.

In this particular example, I have PortB, bit 10, as this 'spare output' on a TP I can monitor, set up 'somewhere early' as output:

//Debug output pin
    GPIOB_PCOR = 1<<10;
    GPIOB_PDDR |= 1<<10;          //   B10 for output
    PORTB_PCR10 = PORT_PCR_MUX(1); //I/O

At the start of the time-window:

  GPIOB_PSOR = 1<<10;       //Debug timing strobe in

followed at the end by:

  GPIOB_PCOR = 1<<10;       //Debug timing strobe out

This just has to load the constant for the address of  GPIOB_PxOR (one PC-relative load, two cycles), then the constant (another clock for this simple constant), and assuming write-buffering one clock to do the actual store.

6,780 Views
giova841
Contributor II

Thank you Earl,

probably there is something missing in my code since I cannot use the GPIO...

Let me explain better, I would like to use the port GPIOC pin 15configured as an output and I have written the following code which gives no error but the pin is still dead :-(. Looking at these functions (provided by the KSDK 2.1) it seems that they do just the same instructions you suggested me.

Is there any initialization I have to do?

gpio_pin_config_t conifg = {

   kGPIO_DigitalOutput,

   0,

}

GPIO_PinInit(GPIOC,15U,&config);

delay(500U);

GPIO_WritePinOutput(GPIOC,15U,1);

delay(500U);

GPIO_WritePinOutput(GPIOC,15U,0);

0 Kudos
6,780 Views
egoodii
Senior Contributor III

Sorry, I don't know what ANY of those procedures do, in particular.  I stick to 'bare metal' (such as the direct register writes above) whenever I need to be sure I know what is going on.  And in ANY case I would NOT use 'procedure calls' as part of any actual timestamping-operations, as both the call-overhead AND the register-use-requirements thru a call will appreciably affect the code sequence you would like to measure.

0 Kudos
6,780 Views
giova841
Contributor II

Hi Earl,

I completly agree with you but it is the first time I am coding on MCU and I felt more comfortable using SDK functions.

If you can support me I would try with the direct register access as you suggested.

Assuming GPIOC is the address of my port, how con configure and manage pin 15?

0 Kudos
6,780 Views
egoodii
Senior Contributor III

Just put 'C' and '15' where I have 'B' and '10':

//Debug output pin
    GPIOC_PCOR = 1<<15;
    GPIOC_PDDR |= 1<<15;          //   C15 for output
    PORTC_PCR15 = PORT_PCR_MUX(1); //I/O

 

At the start of the time-window:

  GPIOC_PSOR = 1<<15;       //Debug timing strobe in

followed at the end by:

  GPIOC_PCOR = 1<<15;       //Debug timing strobe out

0 Kudos
6,780 Views
giova841
Contributor II

Ok but how are GPIOC_PCOR/PSOR/PDDR defined? Are they memory registers? If so which is the right initialization for these variables? This code does not compile in my project... probabely there are some inclusion missing...

Sorry but this is the first time I am dealing with GPIO ports... :smileycry:

0 Kudos
6,780 Views
egoodii
Senior Contributor III

These should be the names defined in the header-file you are including for your processor (MKxxxxxxx.h).  The defines therein will give the compiler absolute addresses to link-in.  I haven't used the compiler configuration of the SDK, so I don't know how it links to a process-header.

Alternatively, you can go ahead and just fix your usage of the 'macros' you demonstrated earlier, just putting in 1<<15 to get to your bit (rather than 14U) for all the pin-access macros.  The PIN-mux macro may be '15' or '1<<15', I don't know.

0 Kudos
6,779 Views
giova841
Contributor II

I think that these functions are very close toyou approah, have a look to theri implementation:

/** GPIO - Register Layout Typedef */
typedef struct {
  __IO uint32_t PDOR;                              /**< Port Data Output Register, offset: 0x0 */
  __O  uint32_t PSOR;                              /**< Port Set Output Register, offset: 0x4 */
  __O  uint32_t PCOR;                              /**< Port Clear Output Register, offset: 0x8 */
  __O  uint32_t PTOR;                              /**< Port Toggle Output Register, offset: 0xC */
  __I  uint32_t PDIR;                              /**< Port Data Input Register, offset: 0x10 */
  __IO uint32_t PDDR;                              /**< Port Data Direction Register, offset: 0x14 */
} GPIO_Type;

void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
{
    assert(config);

    if (config->pinDirection == kGPIO_DigitalInput)
    {
        base->PDDR &= ~(1U << pin);
    }
    else
    {
        GPIO_WritePinOutput(base, pin, config->outputLogic);
        base->PDDR |= (1U << pin);
    }
}

/*!
 * @brief Sets the output level of the multiple GPIO pins to the logic 1.
 *
 * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
 * @param mask GPIO pin number macro
 */

static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask)
{
    base->PSOR = mask;
}

/*!
 * @brief Sets the output level of the multiple GPIO pins to the logic 0.
 *
 * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
 * @param mask GPIO pin number macro
 */
static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask)
{
    base->PCOR = mask;
}

Just to be sure I will take a pre-defined example about LED blinking provided with the KSDK and I will try some work-around,s.. I will update yoy if any progress occurs.

Thank you,

Giulio

0 Kudos
6,780 Views
egoodii
Senior Contributor III

Those look like items that will get the job done.  I don't see a Pin-mux-setting macro here though...

6,780 Views
mjbcswitzerland
Specialist V

Giulio

Have you enabled locks to the Port C peripheral (in SIM_SCGC5)?

Regards

Mark

0 Kudos
6,780 Views
giova841
Contributor II

Hi Mark,

I have added the following lines to the BOOT_InitPins() procedure:

CLOCK_EnableClock(kCLOCK_PortC); 

PORT_SetPinMux(PORTC,14, kPORT_MuxAsGpio);

GPIO_PinInit(GPIOC,14U,&config);

Then in the main() I have written:

GPIO_SetPinsOutput(GPIOC,14U);

delay(1000);

GPIO_ClearPinsOutput(GPIOC,14U);

Nonetheless nothing is moving on pin 15... :smileysad:

0 Kudos
6,780 Views
mjbcswitzerland
Specialist V

Hi

Are you sure that your code (or the initialisation part) is really being called?
Connect the board to the debugger, open up the register view and simply write the expected commands to make the output(s) move. Once you know which they are, step the program to see what it is doing differently - it may be obvious then.

Eg.
GPIO_SetPinsOutput(GPIOC,14U); is this GPIO14 or GPIO 15? Is it an enum or should it be a bit field?
Same question for
PORT_SetPinMux(PORTC,14, kPORT_MuxAsGpio);


I do it like this on the TWR-K65 board:

_CONFIG_PORT_OUTPUT(C, PORTC_BIT15, (PORT_SRE_FAST | PORT_DSE_HIGH));
_TOGGLE_PORT(C, PORTC_BIT15);
// delay to measure
_TOGGLE_PORT(C, PORTC_BIT15);

Nothing can go wrong here.

Compare with: http://www.utasker.com/kinetis/TWR-K65F180M.html
where it is fully simulated - again nothing can go wrong and no project delays.

Regards

Mark

P.S. I looked in SDK and it looks like you are incorrectly using the calls. Here is an example:

GPIO_ClearPinsOutput(BOARD_LED_RED3_GPIO, 1U << BOARD_LED_RED3_GPIO_PIN) /*!< Turn on target LED_RED3 */

so you would need

GPIO_ClearPinsOutput(GPIOC, 1U << 15) ;

This is inline code and thus efficient, even if a bit over-complicated.

6,780 Views
giova841
Contributor II

Mark,

can you show me your macros definitions? I cannot find them in my project (which is a standalone project created with Kinetis Project Genertor by cloning an example provided with KSDK).

_CONFIG_PORT_OUTPUT(C, PORTC_BIT15, (PORT_SRE_FAST | PORT_DSE_HIGH));
_TOGGLE_PORT(C, PORTC_BIT15);
// delay to measure
_TOGGLE_PORT(C, PORTC_BIT15);

0 Kudos
6,780 Views
mjbcswitzerland
Specialist V

Giulio

The macros are available in the uTasker project, which is available as open source at

http://www.utasker.com/forum/index.php?topic=1721.0

Regards

Mark

0 Kudos