Jump to content
  • 0

PS GPIO - baremetal


engrpetero

Question

I'm trying to access the buttons 4 and 5 and the LED 4 on the Zybo-10 PS.  I searched these fora and found one seemingly relevant post but it has to do with petalinux and I'm just doing baremetal.  I also downloaded the polled and interrupt examples (which I usually find really useful) but alas, not so for accessing these buttons and LED.

One snip from the XGPIOPS polled example includes these two items (Input_Pin and Output_Pin).  I can't figure out what they reference though (I assume some exposed pin on the GPIO MIO though I don't find pins 10 or 14 on the Zynq block (second pic)).  I also included a snip from the schematic but still can't make sense out of the 10 and 14 in the code snip (maybe the MIO pins?).  Any chance there is a pointer to access these two buttons and LED somewhere? 

FWIW, I have done the PMOD example project on the website when I was learning and found it very useful.

image.png.d21a13da7f24f92bf237e60faf96354a.png

image.thumb.png.a135930fe40589ca766ae8987482d0e8.png

image.png.5d6e3ac28bc598624d9deabe63430c49.png

Link to comment
Share on other sites

12 answers to this question

Recommended Posts

  • 0

I spoke just a little too soon!  As a somewhat relevant post @artvvb provided a response to a similar question related to the Arty board here.

Interaction with the LED4 is straightforward.  However, I'm still off on the GpioPs interrupts, particularly the BTN4 and BTN5 interrupts.  I've looked at the functions in the xgpiops_intr.c file and there are (as expected) lots of functions that aren't used in the example.  However, many of them require the 'Bank' as an argument.

From the schematic content above, it seems the LED (MIO7), and the JF pins 1,2,3,4,7,8,9,10 (MIO shown in the schematic) on Bank 500 use XGPIOPS_BANK0 (from the xgpiops.h file) and that bank has 16 addressable MIO pins.  The BTN4 and BTN5 items - MIO50 and 51 respectively - are shown in the schematic on Bank 501 - Is this XGPIOPS_BANK1 from a driver perspective?

And if so, there seem to be more than 32 pins on that bank (MIO53-MIO16 = 38 pins) but the XGpioPs_IntrEnable function requires a U32 Mask that obviously can satisfy a 38 pin bank.  So how is/are the bank(s) arranged?  Setting interrupts on the 16 pins on bank 0 (where the JF PMOD is) should be straightforward (I think) as it is easy to mask those 16 pins with a U32 Mask.

void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType,
			  u32 IntrPolarity, u32 IntrOnAny)

void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask)

image.png.6a1703ae530d9b03a7a4264f8b71f466.png

Link to comment
Share on other sites

  • 0

In the xgpiops drivers, I'd also refer to lines 154:159 of xgpiops.h:

Quote

#define XGPIOPS_DEVICE_MAX_PIN_NUM    (u32)118 /**< Max pins in the Zynq GPIO device
                          * 0 - 31,  Bank 0
                          * 32 - 53, Bank 1
                          *    54 - 85, Bank 2
                          *    86 - 117, Bank 3
                          */

And to the XGpioPs_GetBankPin implementation in xgpiops.c, relevant part around line 763. The function is able to return which pin index within which bank a given MIO# is connected to.

Thanks,

Arthur

Link to comment
Share on other sites

  • 0
14 hours ago, artvvb said:

In the xgpiops drivers, I'd also refer to lines 154:159 of xgpiops.h:

And to the XGpioPs_GetBankPin implementation in xgpiops.c, relevant part around line 763. The function is able to return which pin index within which bank a given MIO# is connected to.

Thanks,

Arthur

I saw that handy function GetBankPin yesterday as well.  :-)  Still can't get the interrupt example to work.  But also still trying.  Vitis IDE seems to do weird things sometimes while debugging.

Link to comment
Share on other sites

  • 0

The plot thickens a bit (well, at least to me). 

I've been playing with the Vitis GpioPs polled and interrupt examples.  Recall on the Zybo-10 (see first pic below), the GPIO MIO has 8 pins.  Only the pin 7 direction is set as output in the Vivado Zynq subsystem - the other pins are set as inout.  Also recall that on the Zybo-10, LED4 is connected to MIO pin 7 and BTN4, BTN5 are connected to MIO pins 50, 51 respectively.

The Vitis polled example has an 'Output' and an 'Input' test section.  In the Output section, a for loop writes a 1 to the defined output pin, reads the pin value back, delays a bit, writes a 0 to the output pin followed by a read again of the output pin.  The loop continues 10 times which would allow for turning an LED on and off 10 times for visual indication something was happening.

In the example app, if the output pin is set to pin 7, the Zybo LED does indeed turn on and off.  BUT... the read back of the pin after setting it is always 0.  It never changes regardless of the written value.  If the output pin is set to any of the other seven GPIO pins - the ones set in the Zynq subsystem with direction 'inout' - then the read back of the pin always matches the write.  I don't have an LED+resistor to connect to those pins to see that they actually turn on but I imagine they do.  Any idea why this read is always 0? I do notice that the write and read registers are different (offset by 60) - I'm not sure why (code snippet of the registers from the ReadPin and WritePin items shown below the pic).

For what it's worth, in the Vitis polled example Input section, the read of MIO pin 50 or 51 always returns 1, regardless of whether the button is pressed.  I'm assuming the two issues are related - just not sure how right now.

image.thumb.png.9d8bd15c891b8f53007c5519ed3a3da5.png

	u8 Bank, PinNumber;
	u32 ValueRead , ShiftAndValueRead, ReadOffset, baseAddr;
	u32 OnOffValue, WriteDataVar, WriteValue, WriteOffset, WriteRegOffset;

	// Get Bank and PinNumber for the Output_Pin (pin 7)
	XGpioPs_GetBankPin((u8)Output_Pin, &Bank, &PinNumber);
	baseAddr = Gpio.GpioConfig.BaseAddr;

	// Get the offset to the U32 register being read
	ReadOffset =  ((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) + XGPIOPS_DATA_RO_OFFSET;

	// Get the offset to the U32 register for writing
	if (PinNumber > 15U) {
		/* There are only 16 data bits in bit maskable register. */
		PinNumber -= (u8)16;
		WriteRegOffset = XGPIOPS_DATA_MSW_OFFSET;
	} else {
		WriteRegOffset = XGPIOPS_DATA_LSW_OFFSET;
	}
	WriteOffset =  ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) + WriteRegOffset;

 

Link to comment
Share on other sites

  • 0

Duh... Notice in the pic above I have the pullups on MIO50 and MIO51 enabled.  That's why the input reads for the BTN4 and BTN5 were always 1.  When I disabled those pull-ups, the buttons work as expected (high when pressed in polled mode, low when not pressed) - and that caused the interrupts to continually fire because they were always high.

Link to comment
Share on other sites

  • 0

That may constitute a bug in the board files' Zynq preset. Will look into getting it fixed. Thank you for writing out your debugging process as you went, reproducing and fixing it should be pretty straightforward, given the information you've presented.

-Arthur

Link to comment
Share on other sites

  • 0

BTW - for anyone reading this post in the future, if you decide to use interrupts for processing GpioPs (or likely any GPIO), I *think* in the button press ISR you'd want to disable the interrupt for the IO you want to do something with, and then only enable it again after you've done something.  Otherwise, the ISR keeps being hit which doesn't allow the processor to do anything else.  

For example, if using interrupts for the two MIO buttons about which this post was written, and you hold down one button, you get the same effect as with the pull-up present.  The ISR is just hit repeatedly so no other processing happens.

Link to comment
Share on other sites

  • 0

Sounds like the interrupts are triggering on active-high level sensitive. You should be able to change the interrupt type to edge sensitive:

/****************************************************************************/
/**
*
* This function is used for setting the Interrupt Type, Interrupt Polarity and
* Interrupt On Any for the specified GPIO Bank pins.
*
* @param	InstancePtr is a pointer to an XGpioPs instance.
* @param	Bank is the bank number of the GPIO to operate on.
*		Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param	IntrType is the 32 bit mask of the interrupt type.
*		0 means Level Sensitive and 1 means Edge Sensitive.
* @param	IntrPolarity is the 32 bit mask of the interrupt polarity.
*		0 means Active Low or Falling Edge and 1 means Active High or
*		Rising Edge.
* @param	IntrOnAny is the 32 bit mask of the interrupt trigger for
*		edge triggered interrupts. 0 means trigger on single edge using
*		the configured interrupt polarity and 1 means  trigger on both
*		edges.
*
* @return	None.
*
* @note		This function is used for setting the interrupt related
*		properties of all the pins in the specified bank. The previous
*		state of the pins is not maintained.
*		To change the Interrupt properties of a single GPIO pin, use the
*		function XGpioPs_SetPinIntrType().
*
*****************************************************************************/
void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType,
			  u32 IntrPolarity, u32 IntrOnAny)

Cheers,

Arthur

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...