Tag Archives: arty

ARTY – SPI, I2C and PMODS

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Pretty much every embedded system / FPGA design has to interface to the real world through sensors or external interfaces. Some systems require large volumes of data to be moved around very quickly, in which case high-speed communications interfaces like PCI-X, Giga Bit Ethernet, USB, Fire/ SpaceWire, or those featuring multi-gigabit transceivers may be employed.

However, many embedded systems also need to interface to slower interfaces for sensors, memories and other peripherals these systems can employ one or more of the simpler communications protocols. The four simplest, and therefore most commonly used, protocols are as follows.

  • UART (Universal Asynchronous Receiver Transmitter): This comprises a number of standards defined by the Electronic Industry Association (EIA), the most popular being the RS-232, RS-422, and RS-485 interfaces. These standards are often used for inter-module communication (that is, the transfer of data and supervisory control between different modules forming the system) as opposed to between the FPGA and peripherals on the same board, although I am sure there are plenty of applications that do this also. These standards defined are a mixture of point-to-point and multi-drop buses.
  • SPI (Serial Peripheral Interface): This is a full-duplex, serial, four-wire interface that was originally developed by Motorola, but which has developed into a de facto standard. This standard is commonly used for intra-module communication (that is, transferring data between peripherals and the FPGA within the same system module). Often used for memory devices, analog-to-digital converters (ADCs), CODECs, and MultiMediaCard (MMC) and Secure Digital (SD) memory cards, the system architecture of this interface consists of a single master device and multiple slave devices.
  • I2C (Inter-Integrated Circuit): This is a multi-master, two-wire serial bus that was developed by Phillips in the early 1980s with a similar purpose as SPI. Due to the two-wire nature of this interface, communications are only possible in half-duplex mode.
  • Parallel: Perhaps the simplest method of transferring data between an FPGA and an on-board peripheral, this supports half-duplex communications between the master and the slave. Depending upon the width of data to be transferred, coupled with the addressable range, a parallel interface may be small and simple or large and complex.

The arty board provides four PMOD outputs (JA through JD) along with the Arduino / ChipKit shield connector through which we can interface with peripherals using these interfaces. Over the next few weeks I am going to interface the PModDA4 (SPI) and the PModAD2 (I2C) to the MicroBlaze System that we have created.

The first step is to generate the hardware build within Vivado such that we can interface to the PMODs. We can add in a AXI SPI controller from the IP library and configure it to be a standard SPI driver and not a dual or quad (more on those in future blogs). We can also add in the AXI IIC (remember to search for iic not i2c) controller module and connect it up to the AXI bus, do not forget to add both interrupts to the interrupt controller.

 

1

Once both controllers are within the design the next step is to customise for application at hand, with these complete we can assign the i2c and SPI pins to the correct external ports for the PMOD desired.

All that remains then is to build the hardware and write the software, it sounds so easy when we say it quickly.

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Arty – In Chip Logic Analyser

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Sometimes despite the simulation we have performed upon our design we still have issues with the design on the hardware. One way we can debug in the hardware is to use a ILA within our hardware design, this gives us the ability to monitor either a number of AXI interfaces or discrete inputs.

Adding in an AXI monitor on the AXI interface to the XADC we are currently using in our example we enable us to monitor the transactions. In this case just such that we can examine them however in other instances it may be necessary due to design or integration issues.

We can add in the ILA into our design from the Integration library in our block diagram.

1

Insertion of the ILA into the Design

By default, the ILA is configured to monitor a AXI interface however, we can change its settings by double clicking on the ILA block and customising as required. We can add in trigger ports, capture control and comparators to trigger on specific patterns in the data stream. For this example, I am going to keep it fairly simple to show the flow and then we can look at more advanced aspects once this is understood.

2

 

Customising the ILA

With the ILA inserted into the design the next stage is to reset the generated outputs and then re generate these such that we can implement the design. Once the design is implemented we can then programme the device using the hardware manager, it is via the hardware manager that we can also examine the contents of the interfaces we wished to examine.

Using the hardware manager, we should connect to our Arty target, the next step is to programme the FPGA and initialise the logic analyser. To achieve this we need both the bit file and the definition of the debug nets we wanted to examine in the Vivado block diagram, you will see this as the ltx file within the projects runs / implementation directory beside the bit file.

3

Identifying the ltx file

4

Configuring the device and debug profile.

Once these files have been configured we will see the screen below open up in the hardware manager which provides the interface we can use to configure the triggering, capture mode and arm the ILA core.

Once we have configured the core as we wish, we can examine the waveform in the waveform viewer below.

5

 

ILA Configuration and control scheme in Hardware Manager

 

6

Captured Waveform

With the simple flow explained we can, in the next blog look at how we can use more advanced features of the ILA.

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Arty – FreeRTOS & XADC

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Happy New Year! For the first blog of the year I thought we would combine the FreeRTOS and the XADC examples we had bbeen looking at previously.

This will enable me to show how we can do the following

  1. Configure the XADC
  2. Create a task to read from the XADC
  3. Create a second task to take action on the results from the first task

The intended functionality is the one task, once a second reads the XADC internal parameters and stores them within a array. This array is then communicated via a queue to the recieivng task which processes the results, for this example it just outputs them over the UART. If we wanted to this task could perform more detailed analysis or calcualtion on the results being provided to it.

We can easily modify the hello world example to perform this. If we wish to make it more complex and introduce more tasks which share resources, we must ensure they are properly managed and do not become deadlocked.

The first thing we need to do is include the proper header files such that we can use the API for the XADC we do this by including the “XSYSMON.H”.

Within the main function we are going to configure and initialise the XADC before we start the two tasks.

As we are going to be using the printf function and we are going to transfering data we need to ensure the stack size is correctly allocated. To prevent problems I decided to increase this to ensure there was sufficent for that requred for both tasks, when we create the tasks in the main() we are required to define the stack allocated to each task. For both tasks I decided to allocate 1000 bytes, I left the task pirorites as the receiving task being a higher priortiy than the transmitting task ensuring the data is transmitted as soon as it is received.

1

The next step was to create the queue, as I mentioned above due to the priorities of the RX and TX tasks there will only be one element in the queue, which will be the size of the size element XADC_Buf.

The final element is to start the scheduler and let the tasks run for ever well once we have written them.

We write each task as a we would any function in C, being careful to ensure we include the 1 second dealy within the transmitt task.

When I ran the code (which is available here) I got the following results.

2

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Arty – RTOS Overview

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Over the last few blogs we have written software which runs on the MicroBlaze and reads the XADC, to do this we have not used an operating system instead using a bare metal approach. However as we wish to develop more complex systems, we need to introduce an operating system, so over the next few blogs we will be looking at how we can do just that.

1

However first I think it is a good idea to talk a little about operating systems and real time operating systems in particular. What differentiates an RTOS from a generic operating system? An RTOS is deterministic, that means the response of the system will meet a defined deadline.

But does the system have to always meet these deadlines to be classed a real-time system?

Actually, no it does not.

There are three RTOS categories that address deadlines differently:

Hard RTOS – Missing a deadline is classified as a system failure.

Firm RTOS – Occasionally missing a deadline is acceptable and is not classified as a failure.

Soft RTOS – Missing a deadline simply reduces the usefulness of the results.

An RTOS operates around the concept of running tasks (sometimes called processes). Each of these tasks performs a required system function. For example, a task might read data from an interface or perform a calculation. A very simple real-time system may use just one task, but it is more likely that multiple tasks will be running on the processor at any one time. Switching between these tasks is referred to as “context switching” and requires that the RTOS saves the processor state for each task before the context switch starts the next task. The RTOS saves this processor state on a task stack.

Determining which task to run next is controlled by the RTOS kernel and this decision can be complicated—especially if we want to avoid deadlock where tasks lock each other out—but the two basic decision methods are:

Time sharing – Each task gets a dedicated time slot on the processor. Tasks with higher priority can have multiple time slots. Time slicing is controlled via a regular interrupt or timer. This method is often called Round Robin scheduling.

Event Driven – Tasks are only switched when a task finishes or when a higher priority task must be run. This method is often called pre-emptive scheduling

When two or more tasks want to share a resource— the XADC for example—it is possible that the tasks might request the resource at the same time. Resource access needs to be controlled to prevent contention and this is one of the operating system’s most important duties. Without the correct resource management, deadlock or starvation might occur.

Here are the definitions we’ll use for deadlock and starvation:

Deadlock – Occurs when a task holds a resource, cannot release it until the task completes, and is currently unable to complete because it requires another resource currently held by another task. If that second task requires a resource held by the first task, the system will never exit this deadlocked state. Deadlock is a bad situation for an RTOS to find itself in.

Starvation – Occurs when a task cannot run because the resources it needs are always allocated to another task. The task starves because of a lack of resources.

As you can imagine, much has been written on the subjects of deadlock and starvation over the years and there are many proposed solutions. For example, there’s Dekker’s algorithm, which was the first known correct solution to mutual exclusion. It is a shared-memory mechanism that does not require a special “test and set” instruction (but is therefore limited to managing two competing tasks) and is attributed to the Dutch mathematician Theodorus Dekker. The most commonly used method to handle deadlock is the use of semaphores, which commonly come into two types: binary semaphores and counting semaphores. A binary semaphore controls access to one resource—for example a hardware resource. Counting semaphores control access to a pool of identical, interchangeable resources such as memory buffers.

Typically each resource has a binary semaphore allocated to it. A requesting task will wait for the resource to become available before executing and once the task completes, it releases the resource.  Binary semaphores commonly use WAIT and SIGNAL operations. A task will WAIT on a semaphore. When the resource is free, which could be immediately (or not), the operating system will give control of the resource to the task. When the task completes, it will SIGNAL completion and free the resource. However, if the resource is occupied when the task WAITs on the semaphore, the operating system suspends that task until the resource is free. The WAITing task might have to wait until the the currently executing task is finished with the resource or the WAIT might take longer if it is pre-empted by a higher priority task.

Introducing the concept of task priority also brings up the problem of priority inversion.  There is a more flexible class of binary semaphores called mutex’s (the word “mutex” is an abbreviation for “mutual exclusion”) and these are often used by modern operating systems to prevent priority inversion.

Counting semaphores work in the same way as binary semaphores however they are used when more than one resource is available—data stores for instance. As each of the resources is allocated to requesting tasks, the count is reduced to show the number of free resources remaining. When the semaphore count reaches zero, there are no more resources available and any processes requesting one or more of these resources after the count reaches zero will be suspended until the requisite number of resources is released.

Tasks often need to communicate with each other and there are a number of methods to accomplish this. The simplest method is to use a data store managed with semaphores as described above. More complex communication methods include message queues.

When using message queues, a task that wishes to send information to another task POSTs a message to the queue. When a task wishes to receive a message from a queue, it PENDs on the queue. Message queues therefore work like FIFOs

Over the next few blogs we will look at using FreeRTOS and Micrium uc/OSiii

This is the last Arty blog of 2015 , so have a Merry Christmas and and a Happy New Year.

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Arty – XADC Alarms & References

Facebooktwittergoogle_plusredditpinterestlinkedinmail

One of the most common uses of the XADC is for health monitoring of the FPGA and the wider system to that mind the XADC has a number of useful features which can be used.

  1. Trigger and Reset Threshold Alarm registers for the Internal voltages and temperature parameters
  2. Over Temp Monitoring – Maximum junction operating temperature allowable for the device – Auto shut down is possible.
  3. Maximum and Minimum values – Registers which contain the lowest and highest sampled values for each of the voltages and device temperature.

These three elements make for a very useful health monitoring system, of course the alarms and the over temperature must be correctly configured and enabled first. This can be achieved in one of two ways, either via the XADC wizard within Vivado or via our software application.

1

There are seven possible alarms we can configure on the XADC, however we cannot use all of them on the Artix Silicon as some alarms as dedicated to the Zynq (Alarm 6 Vccddro, Alarm 5 Vccpaux and Alarm 4 Vccpint). There is also an eighth alarm bit which is the logical OR of the seven alarm bits and acts as an overall alarm.

We can see if an alarm has occurred via either the Alarm Status Output Register or configure an interrupt to occur should an alarm condition occur such that it can be immediately dealt with.

2

These trigger and reset values allow us to define values which align with our worst case analysis of supply voltages and junction temperature, ensuring we can protect the system properly.

Each alarm also has an associated output which can be used in the wider system either to indicate via a LED a issue has occurred or to take further action e.g. graceful system degradation.

The over temperature alarm is slightly different in that it can be configured to trigger an automatic shutdown of the device. To set automatic shut down the four LSB’s of the over temperature register must be set high. Doing this means that 10 ms after the trigger level is reached a shut down occurs. This prevents re -configuration of the device until the reset level is reached.

It is intended that the temperature alarm is used to act as a pre-warning that the temperature has exceed what the design has calculated as its maximum. This way the system can take action to prevent the shut down e.g. turning on fans, reducing processing etc.

3

While the maximum and minimum registers provide the system with a simple methodology of quickly and easily checking the worst case values as currently observed by the system during its period of operation. These registers can also be of good use in system commissioning to record supply voltages and temperatures  across worst case environmental conditions for example.

There is also one last issue which must be addressed when using the XADC on the Arty board and that is we need to correctly set up the board to use the internal VRefp. Failure to do this results in a inaccurate conversions.  The Arty board is configured such that you can use either the internal or external reference.

4

 

5

We can ensure the internal reference is used by grounding the XADCVREF input, as such the internal reference will be used. This can be confirmed by reading the flag register which also helpfully contains information on any alarms as well

6

With the XADC configured to correctly monitor the internal signals with suitable alarm levels we can look at how we can use the XADC to receive analogue signals from the real world

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Arty – XADC SW

Facebooktwittergoogle_plusredditpinterestlinkedinmail

With the hardware all built and the MicroBlaze system configured to support the XADC at the hardware level we need to be able to drive it at the software level.

2

The first thing you will notice is that having built the hardware in Vivado we need to open the implementation and export the design and the bit file to SDK. The next time we open SDK we will see a dialog box which states the Hardware platform we are using has changed and would we like to update import that to SDK and update the BSP, the answer of course is YES.

This will result in the hardware platform being updated and most importantly the BSP being updated to pull in the correct drivers for the XADC. We can see this if we open the BSP MSS file and click on customise the BSP button, this will open a dialog box upon which the drivers tab we can see the XADC and the driver used to control it in this case XSYSSMON.H. Looking around the BSP directory under the includes/libsrc/sysmon folder will show you the source code to drive the XADC.

Within our application SW how we initialise and set up a peripheral is very similar for all devices

  1. Define the peripheral of interest from the xparameters.h file in this case

#define xadc XPAR_SYSMON_0_DEVICE_ID

  1. Define the instance of the peripheral type we are going to be controlling

XSysMon xadc_inst;

  1. Declare a instance pointer to the peripheral type pointing to the address of the previous instance

XSysMon *xadc_inst_ptr =&xadc_inst;

  1. Declare a configuration pointer of the type of peripheral to be initialised in this case it is XSysMon_Config *xadc_config;
  2. Initialise the configuration pointer with the parameters for the peripheral in use in using the function

Xadc_config = XSysMon_LookupConfig(xadc);

  1. Initialise the peripheral using the function

XSysMon_CfgInitialize(xadc_inst_ptr,xadc_config,xadc_config->BaseAddress);

With the initialization complete we can then proceed to configure the XADC as needed for our application To do this we use the drivers within the XSysMon.h these allow us to configure all of the ADC inputs, its sequencing and if it is interrupt driven or polled.

For this simple example I am going to configure the XADC to sample its internal parameters namely its temperature, VCCInt, VCCAux, VRefP, VRefN, VBram  as would be expected on a normal health monitoring system. This is simple to do using the functions below, this also disables all the alarms in the XADC.

XSysMon_SetSequencerMode(xadc_inst_ptr,XSM_SEQ_MODE_SAFE);

                 XSysMon_SetAlarmEnables(xadc_inst_ptr, 0x00000000);

XSysMon_SetSeqChEnables(xadc_inst_ptr, XSM_CH_TEMP|XSM_CH_VCCINT|XSM_CH_VCCAUX|XSM_CH_VREFP|XSM_CH_VREFN|XSM_CH_VBRAM);

                 XSysMon_SetSequencerMode(xadc_inst_ptr,XSM_SEQ_MODE_SAFE);

 

As I Mentioned in the last blog as we need to use the XADC to provide temperature information to the MIG we will also be enabling the temperature cycle update and defining the time duration this is updated at

XSysMon_SetTempWaitCycles(xadc_inst_ptr, 0x00000340);

                 XSysMon_EnableTempUpdate(xadc_inst_ptr);

The 0x340 relates to system clock cycles which are 83.25MHz to the refresh rate is 9.9939 us which is within the maximum refresh period of 10 microseconds.

Reading the XADC for this example is very simple I used a polled approach which checks for then of end of sequence bit before it asks for the XADC value.

                for(Index =0; Index <RX_BUFFER_SIZE; Index++){

                while ((XSysMon_GetStatus(xadc_inst_ptr) & XSM_SR_EOS_MASK) !=XSM_SR_EOS_MASK);

                                XADC_Buf[Index] = XSysMon_GetAdcData(xadc_inst_ptr, sample[Index]);

                }

The final stage of the programme is to output the results into the table format as can be seen below over the RS232 link. IT is worth recording here that XADC returns a 16 bit result therefore to give the 12 bit accurate result the output result is shifted left by 4 places.

1

You can get the complete code here on the git hub

Over the next few blogs we will look at the XADC Interrupts and Alarms now we have a verified working platform.

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Arty – XADC Hardware Build

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Like all Seven series device the Artix on the Arty board contains a 1 MSPS 12 bit XADC which is capable of monitoring not only its internal voltages and die temperature but also up to 16 external inputs. This makes the XADC a very useful device within a embedded system, as it allows you to monitor your system health and perform low speed signal processing without the need for a separate ADC.

1

To show the ease with which we can implement and use a XADC we will add one in to the MicroBlaze system we have been using previously. This will provide the fastest way to configure and report output of the XADC. In fact as we have been using the Memory Interface Generator we already been using the XADC without knowledge as it is used within the MIG to compensate for temperature effects to ensure the DQS is kept centred.
As such if we were to add in another XADC to our block diagram in Vivado we will fail implementation as there would be two XADC instantiations called up when there is only one within the device.
Therefore before we can place the XADC and use it as we wish within our design to monitor the Arty temperature and voltage supplies we need to adjust the configuration on the MIG to not call up the XADC as shown in the image below.

2

Instead this will create a new port at the top level of the MIG which is supplied the temperature from the XADC we wish to instantiate.
With this complete we can now open the IP library and place and connect the XADC to the AXI bus, we can make the VP/VN signals connected to the external ports (J5 on the Arty board) by right clicking on the VPVN port on the XADC and selecting make external.
With the XADC connected into the system we need to configure it to provide the temperature output bus needed by the MIG such that it can provide temperature compensation.
To do this we need to tick the Temp Bus option within the basic tab of the XADC wizard, there are a few software switches we need to set when we write the software.

3

This should result in a block diagram which looks like below when the XADC and the MIG are connected together as required.

7

We can drive the XADC in either a polled or interrupt fashion depending upon our application needs, to ensure interrupt support we need to make some connections in the Vivado block diagram.
The first thing we need to do is add a third input to the concatenation block which creates the interrupt vector, we need to increase this from two to three inputs. With this completed we can connect the ip2intc_irpt output signal from the XADC to the new input on the concatenation block.
I also decided the block diagram was getting congested and hard to read so I group up a number of blocks and created a hierarchy. This is easy to do select the blocks you wish to group together, right click and select create hierarchy, enter the block name and a new block will be created with that name. other blocks within your design can then be dragged into that hierarchy block if you wish to add them to it or removed by expanding the block (+ sign in top left) and dragged out. This enables us to create very net looking diagrams. Do not forget to click the re draw option once you have implemented your blocks.

8

Next time we will look at how we can drive the XADC using C in SDK.

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Arty – Interrupts Part Two – AXI Timer

Facebooktwittergoogle_plusredditpinterestlinkedinmail

In the last blog we had successfully instantiated the interrupt controller and demonstrated it functioning as intended by simulating the timer interrupt.

The next step is to configure the timer and demonstrate that the interrupts can be handled properly from the timer in reality.

What I want to be able to do using the AXI Timer is measure the interrupt latency of the MicroBlaze. Interrupt latency—the time between the interrupt being raised and the interrupt being serviced—plays a large role in performance. A number of issues impact interrupt latency, two of these issues are the presence of an operating system and the complexity of the ISR (Interrupt Service Routine).

However the underlying hardware and processor architecture will also have an impact on the interrupt latency time. We can use the AXI Timer to help us measure this time however, first we need to get the AXI Timer up and running.

The AXI Timer contains two 32 bit timer which can be configured in the following modes

  • Generate – The counter counts up or down as selected from a reset value, once the terminal count is reached the generate output is pulsed and the interrupt if enabled is generated. This mode is used to generate a signal or interrupt at a predefined time interval
  • Capture – The assertion of the external trigger signal stores the value of the counter when the signal is asserted. This can be used to measure the duration of external events.
  • PWM – Uses both timers to create a PWM signal – timer 0 defines the overall period and timer 1 defines the high time of the period.

As you can see the AXI timer is a very useful component to our embedded system, what is important for measuring the interrupt latency is the ability to assert the freeze input which stops the counter.

1

The timer can be configured to operate as either an up or down counter and in our application is clocked from the UI_CLK output from the MIG. This clock frequency is 83.25MHz or ¼ of the DDR Controller rate.
For this example and the interrupt latency we will use the timer in the generate mode such that it generates at a predefined period, we will be using the counter in its default count up mode.

The periodic time is defined by loading in a predefined value

Period = ( 2^32-1 – Reset Value + 2) * Clk Period

We will use a Reset Value of 0xF0000000 with an 83.25 MHz clock results in a period of 3.22 seconds between interrupts.

The interrupt service routine will be configured to print out that the interrupt has occurred and restart the counter. I have added the code example code to the Github repository when I ran the code on my Arty board I got the result below.

2

In the next blog we will look at how we can use the timer in more detail to determine the interrupt latency and the potential methods we can use to do this.

Facebooktwittergoogle_plusredditpinterestlinkedinmail