Tag Archives: software

A Recipe for Embedded Systems

Facebooktwittergoogle_plusredditpinterestlinkedinmail

sw3

One thing that is always important for engineers, is the need for us to deliver our projects on quality, schedule and budget. When it comes to developing embedded systems there are a number of lessons, learnt by embedded system developers over the years which can be used to ensure your embedded system achieves these. Let us explore some of the most important lessons learned in developing these.

Link – Page34

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 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 – Interrupts Part One

Facebooktwittergoogle_plusredditpinterestlinkedinmail

When we built the MicroBlaze system we included the ability to handle interrupts by the inclusion of an AXI Interrupt controller. This is connected to the interrupt input on the MicroBlaze controller each AXI interrupt controller is capable of supporting up to 32 interrupts. However, we can cascade the interrupt controllers to support up to 96 interrupts for each MicroBlaze instantiation.

Within the system we created in our first blog  , we had two interrupts one from the AXI UART lite and a second from the AXI Timer.

1

The interrupt signal from both the timer and UART are concatenated into a bus using the concatenate block as can be seen above. The intr input on the AXI interrupt shown above as intr[1:0] will scale automatically depending upon the size of the buss connected to it. To use all 32 interrupts use a 32 input bit concatenate block, when you next click on validate you will see the intr input width on the AXI Interrupt block update automatically to the correct width.

The AXI controller is very simple then containing a number of 32 bit registers such as interrupt status, pending, enable and clear registers along with interrupt vector addresses to manage the 32 interrupts.

Within the AXI interrupt block we can customise its behaviour, most importantly we can select if we want the interrupts to be level triggered and active high or low.

2

Once we have configured the hardware as we desire we can build the hardware and export the hardware to SDK if we have not already done this previously.

Within SDK we can create a simple programme which enable us to configure and initialise the AXI interrupt controller and simulate a timer interrupt occurring. Taking this approach allows us to verify in stages our use of interrupts, this stage allows us to demonstrate that we have correctly configured the interrupt controller. Satisfied that this is working OK we can then configure the timer to function and generate interrupts later on.

The first thing we need to do within our software application is include the correct libraries for this example we will need the following

3

  • stdio.h – Contains the standard input and output functions
  • platform.h – Defines the initialisation and tidy up routines for the MicroBlaze
  • xparameters.h – Contains the address and configurations of need for the system
  • xstatus.h – Contains the status definitions used
  • xintc.h – Contains the API for using the AI interrupt controller
  • xil_exception.h – Contains the API for MicroBlaze exceptions

With the correct libraries included the next stage is to write three functions

  1. Interrupt Example – This one is called from the main() function and controls the demonstration
  2. Interrupt set up – A standalone function which configures the AXI interrupt controller and the microblaze exceptions
  3. Interrupt Service Routine (ISR) – This is the function called when the interrupt occurs

As this is a simulated interrupt the ISR simply terminates the programme after printing a message out over the UART when I ran this I got the following output on my terminal.

4

I have added the software application I wrote to my GIT Hub   repository for download if you want it. The next blog on the ARTY will look at the using the AXI timer and the determining the interrupt latency.

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Arty – SDK Hello World

Facebooktwittergoogle_plusredditpinterestlinkedinmail

When we left the hardware build we had just exported the HDF and bit file to SDK, initially this will have exported the required information to a directory local to the Vivado project.

With the project exported we can close down Vivado and open SDK, if this is the first time you have opened SDK you will be asked for the workspace you wish to use. The workspace is the area where your projects and associated software projects like Board Support Packages (BSP) and copies of the hardware definition will be stored.

Within SDK to get this up and running we need to do the following

  • Create a hardware definition project
  • Create a Board Support Package for the hardware definition
  • Create our application – in this case a simple hello world
  • Build the application – this is the simple part
  • Define the debug environment such that we can run the application on the Arty board over the JTAG link.

The first step is to import the hardware definition we just exported from Vivado to do this select file->new-> other from the SDK menu this will open a dialog box, beneath the Xilinx folder as shown below select new Hardware Platform Specification

21On the next dialog box enter your project name, I always prefer to call it project_HW to be clear what it is and browse to the directory within your Vivado project which contains the HDF file. Note this is within the .sdk folder under your Vivado project.

22

This will create the hardware specification which, will appear under the project explorer on the left side of SDK, as shown below (this does show all three of the elements we need to create a project)

23

We are now in a position that we can create a BSP for the hardware platform, this contains the drivers necessary for the hardware. We can create the BSP by selecting file->new->board support package this will open a dialog box like below

24

Enter a project name, notice how it has picked up the hardware platform we just created, for this example we will use the standalone operating system.

This will a settings pop up for the BSP there are no changes we need to make here but this is where we can add in additional options if needed e.g. light weight IP stack etc

25

We can also on the standalone page select the stdin and stdout for the compiler make sure this is set to uart lite as below.

26

With this verified you can close the BSP settings and you will see a progress box appear while the software generates the BSP files for your system.

At this point we can then create our application, for this example I am going to use the simple hello world template. We can create the application project by selecting file->new->application project this will open a dialog box where we can select the BSP we previously created the hardware definition and the processor we are targeting (in this case there is only one)

27

 

29

This will create a simple application which will output hello world over the USB-UART, selecting build all will then enable us to build the BSP and the application project such that we get an ELF file which can be downloaded and run on the hardware.  The project is built using the project->build all settings and you will see the ELF file appear under your application project as below

210

The next stage is to run it on the Arty board, this requires that we remove the jumper on J1 on the arty board such that we do not load the design example already loaded within the QSPI flash.

To run the example we need to do the following

  • Programme the FPGA
  • Download the ELF

Before we can download the ELF we need to create a debug environment such that when we click on it we can download the elf. To do this right click on your application project and select Debug As -> Debug Configurations as below

211

This will open a dialog box where we can create a new debug environment, we wish to create a new GBD debug application

212

One you have selected new you will see the dialog box below, you should only need to change the information on page one (most should be auto populated)

213

Provide a name and If not selected select the Rest Processor from the drop down menu close to the bottom, we also need to click on the Debugger applications tab and uncheck the option ”stop at main() when debugging” this ensures the application will run automatically on download finally then click on apply not debug and then close.

214

With this completed it is time to connect the arty board to the USB of your PC, this will auto detect and install any software required when it is completed we can progress and test our application. Note it should only ever need to install once.

The first thing to do is programme the FPGA we do this under the Xilinx Tools -> Programme FPGA which will open the following dialog box (you should not need to change anything)

216

Click on program and you will see the FPGA is programmed, you can confirm this on your Arty board as the done LED will illuminate green.

We are now ready to download our ELF file, click on the bug icon on the top menu and this will use the debug configuration we just created to download the application

217

Once downloaded you will notice the software runs and the message “hello world” will appear in your chosen terminal programme.

You can find part one here

Facebooktwittergoogle_plusredditpinterestlinkedinmail

A Double-Barreled Way to Get the Most from Your Zynq SoC

Facebooktwittergoogle_plusredditpinterestlinkedinmail

xilinx90

One of the many benefits
of the Xilinx® Zynq®-7000
All Programmable SoC is
that it is has two ARM®
Cortex™-A9 processors
onboard. However, many
bare-metal applications and simpler operating
systems use only one of the two
ARM cores in the Zynq SoC’s processing
system (PS), a design choice that can potentially
limit system performance.
Depending upon the application in development,
there could, however, be a need
to have both processors running bare-metal
applications, or to run different operating
systems on each of the processors. For
instance, one side could be performing
critical calculations and hence running a
bare-metal/RTOS application while the second
processor is providing HMI and communications
using Linux.

Link here

Facebooktwittergoogle_plusredditpinterestlinkedinmail