Using gpio on k22f

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

Using gpio on k22f

4,418 Views
jverive
Contributor III

Hi all. I have had success controlling the on-board multi-color LED using kGpioLED1, kGpioLED2, and kGpioLED3, but I have a project that requires the use of several (16) GPIO pins. I've tried to follow the information in the API reference manual at C:\Freescale\KSDK_1.0.0\doc\Kinetis SDK API Reference Manual, but I'm not really understanding all that is necessary to handle GPIO pins.

 

What is needed to assign names to GPIO pins and set them up as general inputs or outputs? I'd like to use  GPIO_DRV_SetPinDir(pinName, value) and GPIO_DRV_WritePinOutput(pinName, value) to set input/output mode and to read/write pin values, but I'm open to using other functions/methods if need be.

 

Thanks,

Jeff

Labels (1)
Tags (3)
9 Replies

1,822 Views
aminiman
Contributor I

hi jeff,

why appear error " undefined reference to 'hardware_init' when i build it? whats wrong?

0 Kudos

1,822 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Jeff,

Firstly , define GPIO pins as you need , use  "GIPO_MAKE_PIN()" function .

for example :

// Feel free to change the pin names as what you want

enum _gpio_pins

{

kGpioLED1 = GPIO_MAKE_PIN(HW_PORTC, 0x0),

kGpioLED2 = GPIO_MAKE_PIN(HW_PORTC, 0x1),

kGpioLED3 = GPIO_MAKE_PIN(HW_PORTC, 0x2),

kGpioLED4 = GPIO_MAKE_PIN(HW_PORTC, 0x3),

};

Then configure pin direction ,use            " GPIO_DRV_SetPinDir(kGpioLED1, kGpioDigitalOutput); "

Then write the  value of GPIO ,  use "GPIO_DRV_WritePinOutput(kGpioLED1, value);" 


If have any question for this , plase feel free to contact me .


Best Regards,

Alice

0 Kudos

1,822 Views
jverive
Contributor III

Alice,

Thnaks for your advice. Do I need to do something special to use this code with Processor Expert in KDS using KSDK? I think I implemented the code as you suggested, but nothing is happening (see code below). This code is meant to flash LEDs connected to Port E pins 0 and 1 (alternatively) at 1/2 second intervals, but nothing is happening. Am I missing an #include or some other code?

Thanks,

Jeff

code follows "---------":

---------------------------------------------------

/* ###################################################################

**     Filename    : main.c

**     Project     : RGB_Flasher_with_PE

**     Processor   : MK22FN512VLH12

**     Version     : Driver 01.01

**     Compiler    : GNU C Compiler

**     Date/Time   : 2014-10-17, 09:09, # CodeGen: 0

**     Abstract    :

**         Main module.

**         This module contains user's application code.

**     Settings    :

**     Contents    :

**         No public methods

**

** ###################################################################*/

/*!

** @file main.c

** @version 01.01

** @brief

**         Main module.

**         This module contains user's application code.

*/        

/*!

**  @addtogroup main_module main module documentation

**  @{

*/        

/* MODULE main */

/* Including needed modules to compile this module/procedure */

#include "Cpu.h"

#include "Events.h"

#include "pin_mux.h"

#include "gpio_pins.h"

#include "WAIT1.h"

#if CPU_INIT_CONFIG

  #include "Init_Config.h"

#endif

/* User includes (#include below this line is not maintained by Processor Expert) */

#include "fsl_device_registers.h"

#include "board.h"

  enum _gpio_pins

  {

   CLOCK_LED_1 = GPIO_MAKE_PIN(HW_PORTE, 0x1),

   CLOCK_LED_COMMON = GPIO_MAKE_PIN(HW_PORTE, 0x0)

  };

/*lint -save  -e970 Disable MISRA rule (6.3) checking. */

int main(void)

/*lint -restore Enable MISRA rule (6.3) checking. */

{

  /* Write your local variable definition here */

  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/

  PE_low_level_init();

  /*** End of Processor Expert internal initialization.                    ***/

  GPIO_DRV_SetPinDir(CLOCK_LED_1, kGpioDigitalOutput);

  GPIO_DRV_SetPinDir(CLOCK_LED_COMMON, kGpioDigitalOutput);

     while (1)

          {

            GPIO_DRV_WritePinOutput(CLOCK_LED_1, 1);

            GPIO_DRV_WritePinOutput(CLOCK_LED_COMMON, 0);

            WAIT1_Waitms(500);

            GPIO_DRV_WritePinOutput(CLOCK_LED_1, 0);

            GPIO_DRV_WritePinOutput(CLOCK_LED_COMMON, 1);

            WAIT1_Waitms(500);

          }

     return 0;

  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/

  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/

  #ifdef PEX_RTOS_START

    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */

  #endif

  /*** End of RTOS startup code.  ***/

  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/

  for(;;){}

  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/

} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

/* END main */

/*!

** @}

*/

/*

** ###################################################################

**

**     This file was created by Processor Expert 10.4 [05.10]

**     for the Freescale Kinetis series of microcontrollers.

**

** ###################################################################

*/

0 Kudos

1,822 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hi Jeff,

You missing the " hardware_init()" function , this function in " hardware_init.c "file , this function enable clock for PORTS.

Hope it helps

Alice

0 Kudos

1,822 Views
chris_brown
NXP Employee
NXP Employee

Hi Jeff,

It looks like you are missing a part of the step.  Firstly, I recommend simply adding the pins you need to in gpio_pins.h.  This file should look like this:

k22f_gpio_pins_h.PNG.png

Now, we have defined multiple config structures in the SDK because we are currently using one set of board files to support multiple demo applicaitons.  So for your case, it may make life a little easier and simpler if you just define one input config and one output config.

The next piece of the puzzle, is to make sure that your input/output configs are defined.  Here is an example (from gpio_pins.c):

k22f_led_pins_struct.PNG.png

Now, you need to make sure that the pins you just created are in a structure like this (best place to put that is in gpio_pins.c).

Processor Expert may be doing some of this for you but here are some more things to check (I will double check this as well.  Check that the clock gate to the port that you're pins are on is being enabled and that the GPIO driver init function is being called somewhere in your application.  It should look like this:

CLOCK_SYS_EnablePortClock( <Port number X> );

/* Then configure the port mux to the pin.  For example */

/* PORTB_PCR0 */

PORT_HAL_SetMuxMode(g_portBaseAddr[1],0u,kPortMuxAsGpio);

/* Initialize the pins used for switches and LEDs only */

    GPIO_DRV_Init(switchPins, ledPins);

The parameters I pass to the driver are one input pins config structure (switchpins), and one output pins config structure (ledPins).

I know this may seem like a lot of steps but it will go a long way to making an application more portable and (once everything is setup correctly) easy to write.

Hope this helps.  Please let me know if you need more information about anything that I have written here.

~Chris

1,822 Views
jverive
Contributor III

Chris,

Thanks for the pointers, though I still have a few questions.

What header file(s) or other project imports do I need to use the "CLOCK_SYS_EnablePortClock() function/method? When I placed it in my program, I received an "undefined reference to CLOCK_SYS_EnablePortClock" error.

Can you tell me what "<Port number X>" should be in the command you gave?

CLOCK_SYS_EnablePortClock( <Port number X>);

I'm trying to assign GPIO Port B pins, so I expect the value to be 1, but I'd like to be sure. The API guide only lists "instance", and gives no examples.

Then for the PORT_HAL_SetMuxMode() function, what do I use for "g_port_BaseAddr[1]"?

Additionally, what do I use for the "switchPins" and "ledPins" in the GPIO_DRV_Init command? Is this command something I use after the "hardware_init()" command?

Sorry for all the questions, but I'm still getting used to the KDS environment, KSDK. I'm really trying to understand this stuff from the API reference, but the information there is still too cryptic for me.

Jeff

0 Kudos

1,822 Views
chris_brown
NXP Employee
NXP Employee

Hi Jeff,

To try to clear up some of the confusion from your previous post, the activity on PTA4 and PTA5 probably wasn't happening because the MUX selection for those pins probably wasn't correct.  That can be corrected in pin_mux.c.  There should be a statement in one of the functions like so:

/* PORTA_PCR1 */

PORT_HAL_SetMuxMode(g_portBaseAddr[0],1u,kPortMuxAsGpio);

This configures PTA1 as a GPIO.  That should be changed (in your case) to

/* PORTA_PCR4 */

PORT_HAL_SetMuxMode(g_portBaseAddr[0],4u,kPortMuxAsGpio);

This then configures PTA4 as a GPIO. Next, you want to be sure that this function gets called.  As Alice mentions below, this can be done by calling hardware_init(). 

Now to answer the questions in your most recent post, for <Port Number X> you should use one of the following:

#define HW_PORTA (0U) /*!< Instance number for PORTA. */

#define HW_PORTB (1U) /*!< Instance number for PORTB. */

#define HW_PORTC (2U) /*!< Instance number for PORTC. */

#define HW_PORTD (3U) /*!< Instance number for PORTD. */

#define HW_PORTE (4U) /*!< Instance number for PORTE. */

These are defined in the MK22F51212_port.h header file. 

As for the g_port_BaseAddr[] argument, you should still be able to use that array.  Just remember that the subscript you use should be the Port instance.  So in your case (since you are using Port A), it would be HW_PORTA (see the list above). 

Does this clear things up?

~Chris

0 Kudos

1,822 Views
jverive
Contributor III

Chris,

Thanks! Things are becoming clearer a little at a time.

Jeff

0 Kudos

1,822 Views
jverive
Contributor III

Chris,

I'm trying to follow your suggestions, but I'm getting confused. Maybe taking a step back will help (also, I am using the K22F):

The built-in gpio_pins.h contains the following:

enum _gpio_pins

{

    kGpioLED1       = GPIO_MAKE_PIN(HW_GPIOA, 1),  /* Red LED */

    kGpioLED2       = GPIO_MAKE_PIN(HW_GPIOA, 2),  /* Green LED */

    kGpioLED3       = GPIO_MAKE_PIN(HW_GPIOD, 5),  /* FRDM-K64F120M LED3 (Blue LED)*/

    kGpioSW1        = GPIO_MAKE_PIN(HW_GPIOC, 1),  /* FRDM-K22F120M SW2 */

    kGpioSW2        = GPIO_MAKE_PIN(HW_GPIOB, 17), /* FRDM-K22F120M SW3 */

    kGpioAccelINT1  = GPIO_MAKE_PIN(HW_GPIOD, 0),  /* FRDM-K22F120M MMA8451Q/FXOS87000CB INT1 */

    kGpioAccelINT2  = GPIO_MAKE_PIN(HW_GPIOD, 1),  /* FRDM-K22F120M MMA8451Q/FXOS87000CB INT2 */

    kGpioUsbFLGA    = GPIO_MAKE_PIN(HW_GPIOC, 0),  /* FRDM-K22F120M USB FLGA */

    kGpioUartDemoTX = GPIO_MAKE_PIN(HW_GPIOE, 0),  /* FRDM-K22F120M UART 1 TX pin (OpenSDA port) */

    kGpioUartDemoRX = GPIO_MAKE_PIN(HW_GPIOE, 1),  /* FRDM-K22F120M UART 1 RX pin (OpenSDA port) */

    kGpioI2Caddr1   = GPIO_MAKE_PIN(HW_GPIOC, 3),  /* FRDM-K22F120M I2C address pin */

    kGpioI2Caddr2   = GPIO_MAKE_PIN(HW_GPIOC, 6),  /* FRDM-K22F120M I2C address pin */

    kGpioSpi0Cs0    = GPIO_MAKE_PIN(HW_GPIOD, 0),  /* FRDM-K22F120M SPI0 CS0 pin */

    kGpioSpi0Cs1    = GPIO_MAKE_PIN(HW_GPIOD, 4),  /* FRDM-K22F120M SPI0 CS1 pin */

    kGpioSofOut     = GPIO_MAKE_PIN(HW_GPIOC, 7),  /* FRDM-K22F120M USB SOF OUT pin */

    kGpioRFCE       = GPIO_MAKE_PIN(HW_GPIOC, 11), /* FRDM-K22F120M RF CE pin */

    kGpioRFIRQ      = GPIO_MAKE_PIN(HW_GPIOD, 0)   /* FRDM-K22F120M RF IRQ pin */

};

extern gpio_input_pin_user_config_t switchPins[];

extern gpio_input_pin_user_config_t accelIntPins[];

extern gpio_input_pin_user_config_t i2cAddressPins[];

extern gpio_output_pin_user_config_t gpioUartDemoTxPin[];

extern gpio_input_pin_user_config_t gpioUartDemoRxPin[];

extern gpio_output_pin_user_config_t ledPins[];

extern gpio_output_pin_user_config_t spiCsPin[];

extern gpio_output_pin_user_config_t rfCEPin[];

extern gpio_input_pin_user_config_t rfIRQPin[];

and the gpio_pin.c has these (for the LEDs on-board):

/* Declare Output GPIO pins */

gpio_output_pin_user_config_t ledPins[] = {

    {

        .pinName = kGpioLED1,

        .config.outputLogic = 1,

        .config.slewRate = kPortSlowSlewRate,

        .config.driveStrength = kPortLowDriveStrength,

    },

    {

        .pinName = kGpioLED2,

        .config.outputLogic = 1,

        .config.slewRate = kPortSlowSlewRate,

        .config.driveStrength = kPortLowDriveStrength,

    },

    {

        .pinName = kGpioLED3,

        .config.outputLogic = 1,

        .config.slewRate = kPortSlowSlewRate,

        .config.driveStrength = kPortLowDriveStrength,

    },

    {

        .pinName = GPIO_PINS_OUT_OF_RANGE,

    }

};

As such, my program (shown below) sequences through red, green and blue LEDs, and I can hook up external LEDs to the

corresponding header pins and see matching activity. So far, so good. However, if I change the gpio_pins.h first two enum's to

    kGpioLED1       = GPIO_MAKE_PIN(HW_GPIOA, 4),

    kGpioLED2       = GPIO_MAKE_PIN(HW_GPIOA, 5),

All this does (in my mind) is change the port pins from 1&2 to 4&5. But when I rebuild the project and flash it onto the board, I see no

activity on the corresponding header pins when kGpioLED1 and kGpioLED2 are switched on and off. The blue LED (kGpioLED3)

is still blinking when turned on and off, so the program is still running.

I'm missing a key part of the puzzle here, and snooping around is getting me nowhere. Why shouldn't changing port A pins from 1&2 to 4&5

transfer activity that was present on 1&2 to pins 4&5? Am I missing a configuration or initialization step for these different pins?


I feel like I'm so close to being able to use the GPIO pins at my whim, but it's getting extremely frustrating at this point.

I'd appreciate any help you can give!

Program listing follows (Processor Expert not used):

#include "fsl_device_registers.h"

#include "board.h"

static int i = 0;

static int delay = 0x08FFFF;

// LEDs are common-anode, with cathodes connected to port pins.

// Therefore, logic high (1) turns them off, and logic low

// (0) turns them on.

short OFF = 1;

short ON = 0;

int main(void)

{

     hardware_init();

     GPIO_DRV_SetPinDir(kGpioLED1, kGpioDigitalOutput); //Green LED

     GPIO_DRV_SetPinDir(kGpioLED2, kGpioDigitalOutput); //Red LED

     GPIO_DRV_SetPinDir(kGpioLED3, kGpioDigitalOutput); //Blue LED

     GPIO_DRV_WritePinOutput(kGpioLED1, OFF); //Green LED initially off

     GPIO_DRV_WritePinOutput(kGpioLED2, OFF); //Red LED initially off

     GPIO_DRV_WritePinOutput(kGpioLED3, OFF); //Blue LED initially off

     while (1)

          {

          for (i = 0; i<delay; i++)

          {

          }

          GPIO_DRV_WritePinOutput(kGpioLED1, ON); //Green LED on

          for (i = 0; i<delay; i++)

          {

          }

          GPIO_DRV_WritePinOutput(kGpioLED1, OFF); //Green LED off

          for (i = 0; i<delay; i++)

          {

          }

          GPIO_DRV_WritePinOutput(kGpioLED2, ON); //Red LED on

          for (i = 0; i<delay; i++)

          {

          }

          GPIO_DRV_WritePinOutput(kGpioLED2, OFF); //Red LED off

          for (i = 0; i<delay; i++)

          {

          };

          GPIO_DRV_WritePinOutput(kGpioLED3, ON); //Blue LED on

          for (i = 0; i<delay; i++)

          {

          }

          GPIO_DRV_WritePinOutput(kGpioLED3, OFF); //Blue LED off

          }

     return 0;

}

0 Kudos