User Tools

Site Tools


lab_2_simplified_programming_stack

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

lab_2_simplified_programming_stack [2019/05/15 15:38]
hutch created
lab_2_simplified_programming_stack [2019/05/15 15:39] (current)
hutch
Line 5: Line 5:
 {{ ::​embeddedprogramstack.png?​800 |}} {{ ::​embeddedprogramstack.png?​800 |}}
  
-=== Background === 
- 
-== GPIO == 
- 
-As shown in the schematic, these buttons and slide switches are attached to pins on the ZYNQ chip that can be found in the center of the ZYBO board. OK, so far, so good, but how do we access them? The logic values at the pins of the ZYBO chip can be read using a piece of hardware (IP) that I programmed into the bit-stream that you will use in the class. This IP is called General-Purpose Input/​Output (GPIO). The GPIO IP is described in the   ​{{:​ds744_axi_gpio.pdf|GPIO documentation}} that is provided by Xilinx. 
- 
-I have reproduced the schematic on Page 3 of the GPIO document below. This shows one bit's worth of the GPIO connection. There is a separate GPIO block for the push-buttons and a separate GPIO block for the slide switches (the diagram below shows only one block). Both GPIO blocks are 4-bits wide because there are 4 push-buttons and 4 slide-switches. I have annotated the schematic to show the path that the button or slide-switch logic value will take through the GPIO IP. Also, note that each pin of the GPIO block can function as either an input or output. **You want all of the GPIO pins to function as an input so you can read the switch values.** When a pin is functioning as input, the tri-state driver must be turned off; when functioning as an output, the tri-state driver is turned on. You turn the tri-state driver off or on by writing the correct value to the GPIO_TRI register (see Page 9 of the GPIO documentation). ​ 
- 
-Each GPIO block provides 4 inputs/​outputs so both the GPIO_TRI and GPIO_DATA register are each 4 bits wide. When reading the GPIO_DATA register, bit 0 corresponds to BTN_0, bit 1 corresponds to BTN_1, etc. When writing the GPIO_TRI register to configure the GPIO so that it provides inputs, bit 0 corresponds to BTN_0, bit 1 corresponds to BTN_1, etc. You will write the GPIO_TRI register in the _init functions so that the GPIO block is setup as having only inputs. See Page 9 of the GPIO documentation for programming details for the GPIO_TRI register. 
- 
-For example, if I read the GPI_DATA register and receive the hexadecimal value F (1111), this means that all push-buttons are depressed. If I read the GPIO_DATA and receive the hexadecimal value A (1010), this means that push-buttons BTN_3 and BTN_1 are depressed. 
- 
-**Pro Tip:** One way to check to see if hardware is present is to write a write-able register with a value and then read it back to see if the value still exists. If you cannot not successfully write the selected register, the proper hardware may not be present. It would be good to print out an error message in this case to notify the application programmer or user about a catastrophic problem. For example, in the buttons_init() function (for example), you could write the value to the GPIO_TRI register to setup the GPIO hardware to serve as inputs and then //read// the value back and check to see that it is the correct value. 
- 
-{{::​gpioschematicannotated.jpg?​600|}} 
- 
-OK, the hardware seems straightforward enough but how do you access the GPIO hardware from software? As you can see in the schematic shown above, three registers are shown (GPIO_TRI, GPIO_DATA, and READ_REG_IN). However, there are only two actual registers that you can access: GPIO_TRI and GPIO_DATA. GPIO_DATA does double duty; when you write it, the value appears at the output (this would be useful for turning on an LED). When you read it, you are reading the value of the switch or button. The Xilinx schematic is a little confusing in this regard. For purposes of this lab, you will only read the GPIO_DATA register. A larger picture that shows how the ARM core, the GPIO block, and the switches are organized is shown below. 
- 
-{{::​zynqgpiobuttonblockdiagram.jpg?​800|}} 
- 
-{{::​gpioregisteroffsets.jpg?​800|}} 
- 
-You can read and write the GPIO registers via the address that was assigned when I generated the bit-stream. You find the base address for the GPIO IP block by looking it up in the xparameters.h file. This xparameters.h file can be found as follows (see the screenshot from the SDK below). You can't see the "​xparameters.h"​ filename in the screenshot but it is contained in the "​include"​ directory under the "​HW3_bsp"​ (board-support package). You will need to scroll to the bottom of this directory in the SDK to see it.  
- 
-{{::​sdk_xparameters.h.jpg?​500|}} 
- 
-I have included an excerpt from the xparameters.h file that contains the necessary #define statements that tell us what the base addresses for the GPIO blocks are. 
- 
-<code C> 
-/* Definitions for peripheral GPIO_PUSH_BUTTONS */ 
-#define XPAR_PUSH_BUTTONS_BASEADDR 0x41240000 
-#define XPAR_PUSH_BUTTONS_HIGHADDR 0x4124FFFF 
-#define XPAR_PUSH_BUTTONS_DEVICE_ID 3 
-#define XPAR_PUSH_BUTTONS_INTERRUPT_PRESENT 1 
-#define XPAR_PUSH_BUTTONS_IS_DUAL 0 
- 
- 
-/* Definitions for peripheral GPIO_SLIDE_SWITCHES */ 
-#define XPAR_SLIDE_SWITCHES_BASEADDR 0x41280000 
-#define XPAR_SLIDE_SWITCHES_HIGHADDR 0x4128FFFF 
-#define XPAR_SLIDE_SWITCHES_DEVICE_ID 4 
-#define XPAR_SLIDE_SWITCHES_INTERRUPT_PRESENT 1 
-#define XPAR_SLIDE_SWITCHES_IS_DUAL 0 
-</​code>​ 
- 
-For this lab, you only need to know the base address for the push buttons (XPAR_PUSH_BUTTONS_BASEADDR) and the slide switches (XPAR_SLIDE_SWITCHES_BASEADDR). You can ignore all of the other lines with #​define. ​ 
- 
-**Note: Do not use the numbers from xparameters.h in your software. Use the symbolic constant!** 
- 
-Armed with a knowledge of the base addresses for the two GPIO blocks, how do you access GPIO registers via '​C'?​ Xilinx makes it very simple. ​ 
- 
-<code C> 
-// Note that I have defined my own BUTTONS_GPIO_DEVICE_BASE_ADDRESS 
-#define BUTTONS_GPIO_DEVICE_BASE_ADDRESS XPAR_PUSH_BUTTONS_BASEADDR 
- 
-// Helper function to read GPIO registers. 
-#include "​xil_io.h"​ 
-int32_t buttons_readGpioRegister(int32_t offset) { 
-//   Just use the low-level Xilinx call. 
-   ​return Xil_In32(BUTTONS_GPIO_DEVICE_BASE_ADDRESS + offset); 
-} 
-</​code>​ 
- 
-When you use the above function to read the logic levels of the push buttons, it will return a 32-bit value. The upper 28 bits should be ignored. The lower 4 bits (bit3 - bit0) will represent the logic values of the push buttons. For example, if all 4 push-buttons are pressed when this function is called, the function will return the ''​1111''​ in those last 4 bits. If btn3 and btn0 are pressed when the function is called, the function will return ''​1001''​ and so forth. 
- 
-As previously mentioned, you must access two registers in the GPIO block. These are described in the GPIO reference that was previously discussed. I have included a screen-capture from Page 8 of the GPIO reference that lists the two registers that you must access. You can use the function provided above to access both of these registers. The first (GPIO_DATA) has an offset of 0, so you use an offset of 0 for that one. The second register has an offset of 4, so that is the offset that you provide the readGpioRegister() function when you call it. More details on the registers are described on Pages 8, 9 of the GPIO document so read those pages so you will know what value to write the GPIO_TRI register so that you can configure the pins of the GPIO block so that they function as inputs. 
- 
-{{::​gpioregisteroffsets.jpg?​800|}} 
- 
-Note that you will also have to write a function that writes GPIO registers so that you can write the correct value to the GPIO_TRI register. I'll leave that to you :-D 
- 
-For the switches, try using two low-level Xilinx IO functions for accessing the registers contained in the GPIO IP. These functions are available if you add ''#​include "​xil_io.h"''​ at the top of your program. These functions are found in the Board Support Package (BSP) in your project. You can find this and the corresponding ''​xil_io.c''​ file as shown below (note that these files are located near the bottom of the listing and are not shown in the picture - you will need to scroll down to see them). 
- 
-{{::​bspfiles.jpg?​200|}} 
- 
-I have extracted the '​C'​ code for the relevant functions here for your convenience. Note that this is only for viewing purposes; **DO NOT ADD THE CODE BELOW TO YOUR PROJECT**, just add the ''#​include xil_io.h''​ at the top of your program and you will have access to these functions (and many others). ​ 
- 
-<code C> 
-/​*****************************************************************************/​ 
-/** 
-* 
-* Performs an output operation for a 32-bit memory location by writing the 
-* specified Value to the the specified address. 
-* 
-* @param OutAddress contains the address to perform the output operation 
-* at. 
-* @param Value contains the Value to be output at the specified address. 
-* 
-* @return None. 
-* 
-* @note None. 
-* 
-******************************************************************************/​ 
-void Xil_Out32(u32 OutAddress, u32 Value) 
-{ 
- *(volatile u32 *) OutAddress = Value; 
-} 
- 
-/​*****************************************************************************/​ 
-/** 
-* 
-* Performs an input operation for a 32-bit memory location by reading from the 
-* specified address and returning the Value read from that address. 
-* 
-* @param Addr contains the address to perform the input operation 
-* at. 
-* 
-* @return The Value read from the specified input address. 
-* 
-* @note None. 
-* 
-******************************************************************************/​ 
-u32 Xil_In32(u32 Addr) 
-{ 
- return *(volatile u32 *) Addr; 
-} 
  
lab_2_simplified_programming_stack.txt ยท Last modified: 2019/05/15 15:39 by hutch