Arty – XADC SW


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.


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


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_SetAlarmEnables(xadc_inst_ptr, 0x00000000);




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);


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.


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.