Embedded systems 5/7
G. Goavec-M´ erou, J.-M Friedt FEMTO-ST/time & frequency department
jmfriedt@femto-st.fr slides at jmfriedt.free.fr
October 22, 2021
1 / 12
Device
A device only defines the resources needed by a peripheral but will not create the communication entries (taken care of by the driver)
s t a t i c s t r u c t r e s o u r c e j m f r e s o u r c e s 1 [ ] ={ {. s t a r t = 0 x 4 1 2 0 0 0 0 0 ,
. end = 0 x 4 1 2 0 0 0 f f ,
. f l a g s = IORESOURCE MEM , // c o u l d be IORESOURCE IO : s e e i n c l u d e / l i n u x / i o p o r t . h . name =" io - l e d 1 " // x 8 6=P o r t I O ; ARM=MMIO ( Memory Mapped IO ) },
{. s t a r t = 0 x 4 1 2 1 0 0 0 0 , . end = 0 x 4 1 2 1 0 0 f f , . f l a g s = IORESOURCE MEM , . name =" io - l e d 2 "
}, };
s t a t i c s t r u c t p l a t f o r m d e v i c e ∗pdev1 ,∗p d e v 2 ; s t a t i c i n t i n i t g p i o s i m p l e i n i t (v o i d)
{p d e v 1= p l a t f o r m d e v i c e r e g i s t e r s i m p l e (" jmf ", 0 , j m f r e s o u r c e s 1 , ARRAY SIZE ( j m f r e s o u r c e s 1 ) ) ; p d e v 2= p l a t f o r m d e v i c e r e g i s t e r s i m p l e (" jmf ", 1 , j m f r e s o u r c e s 1 , ARRAY SIZE ( j m f r e s o u r c e s 1 ) ) ; r e t u r n 0 ;
}
s t a t i c v o i d e x i t g p i o s i m p l e e x i t (v o i d) {p l a t f o r m d e v i c e u n r e g i s t e r ( p d e v 1 ) ;
p l a t f o r m d e v i c e u n r e g i s t e r ( p d e v 2 ) ; }
m o d u l e i n i t ( g p i o s i m p l e i n i t ) m o d u l e e x i t ( g p i o s i m p l e e x i t ) MODULE LICENSE (" GPL ") ;
2 / 12
Device
[ . . . ]
s t a t i c s t r u c t p l a t f o r m d e v i c e ∗pdev1 ,∗p d e v 2 ; s t a t i c i n t i n i t g p i o s i m p l e i n i t (v o i d)
{p d e v 1= p l a t f o r m d e v i c e r e g i s t e r s i m p l e (" jmf ", 0 , j m f r e s o u r c e s 1 , ARRAY SIZE ( j m f r e s o u r c e s 1 ) ) ; p d e v 2= p l a t f o r m d e v i c e r e g i s t e r s i m p l e (" jmf ", 1 , j m f r e s o u r c e s 1 , ARRAY SIZE ( j m f r e s o u r c e s 1 ) ) ; r e t u r n 0 ;
}
s t a t i c v o i d e x i t g p i o s i m p l e e x i t (v o i d) {p l a t f o r m d e v i c e u n r e g i s t e r ( p d e v 1 ) ;
p l a t f o r m d e v i c e u n r e g i s t e r ( p d e v 2 ) ; }
m o d u l e i n i t ( g p i o s i m p l e i n i t ) m o d u l e e x i t ( g p i o s i m p l e e x i t ) MODULE LICENSE (" GPL ") ;
redpitaya> insmod dr_comm.ko redpitaya> insmod pl_resource2.ko jmf hello 0
jmf hello 1
redpitaya> ls /sys/bus/platform/devices/jmf.*
/sys/bus/platform/devices/jmf.0:
driver modalias subsystem valuer
driver_override power uevent valuew
/sys/bus/platform/devices/jmf.1:
driver modalias subsystem valuer
driver_override power uevent valuew
3 / 12
Driver
s t r u c t j m f s t r u c t {v o i d∗mem base ;};
s t a t i c s s i z e t g p i o s i m p l e s t o r e (s t r u c t d e v i c e ∗dev , s t r u c t d e v i c e a t t r i b u t e ∗a t t r , c o n s t c h a r ∗b u f , s i z e t c o u n t ) {s t r u c t j m f s t r u c t∗ m a s t r u c t=d e v g e t d r v d a t a ( d e v ) ;
l o n g i n t r e s ;
i f ( ! k s t r t o l ( b u f , 1 0 , & r e s ) ) p r i n t k (" % s = % d ", b u f , r e s ) ; r e t u r n( c o u n t ) ;
}
s t a t i c DEVICE ATTR ( v a l u e w , 0 2 2 0 , NULL , g p i o s i m p l e s t o r e ) ; s t a t i c i n t g p i o s i m p l e r e m o v e (s t r u c t p l a t f o r m d e v i c e ∗p d e v ) {d e v i c e r e m o v e f i l e (& pdev−>dev , &d e v a t t r v a l u e w ) ;
p r i n t k ( KERN ALERT" jmf bye % d \ n ", pdev−>i d ) ;r e t u r n 0 ; }
s t a t i c i n t g p i o s i m p l e p r o b e (s t r u c t p l a t f o r m d e v i c e∗p d e v ) {s t r u c t r e s o u r c e ∗r ;
v o i d∗m;
d e v i c e c r e a t e f i l e (& pdev−>dev , &d e v a t t r v a l u e w ) ; r= p l a t f o r m g e t r e s o u r c e ( pdev , IORESOURCE MEM , pdev−>i d ) ;
p r i n t k ( KERN ALERT" jmf h e l l o % d :% x - -% x \ n ", pdev−>i d , (i n t) r−>s t a r t , (i n t) r−>end ) ; m=i o r e m a p ( r−>s t a r t , r e s o u r c e s i z e ( r ) ) ; // on r e c u p e r e end−s t a r t
w r i t e l ( 0 x0 ,m+0x 0 4 ) ; // a l l a s o u t p u t ( 0 = o u t p u t ! ) w r i t e l ( 0 x05 ,m) ; // a l l a s o u t p u t
r e t u r n 0 ; }
s t a t i c s t r u c t p l a t f o r m d r i v e r g p i o s i m p l e d r i v e r ={ . p r o b e = g p i o s i m p l e p r o b e , . r e m o v e = g p i o s i m p l e r e m o v e , . d r i v e r ={. name =" jmf ",}, };
m o d u l e p l a t f o r m d r i v e r ( g p i o s i m p l e d r i v e r ) ; MODULE LICENSE (" GPL ") ;
4 / 12
FPGA
Xilinx Vivado to configure the FPGA (WebPack: 37 GB, including SDK)
DDR FIXED_IO Vaux0
Vaux1 Vaux8 Vaux9 Vp_Vn adc_clk_n_i adc_clk_p_i
adc_csn_o
adc_dat_a_i[13:0]
adc_dat_b_i[13:0]
adc_enc_n_o adc_enc_p_o
axi_gpio_0
AXI GPIO S_AXI
GPIO s_axi_aclk s_axi_aresetn
dac_clk_o dac_dat_o[13:0]
dac_pwm_o[3:0]
dac_rst_o dac_sel_o dac_wrt_o exp_n_tri_io[7:0]
exp_p_tri_io[7:0]
led_o processing_system7_0
ZYNQ7 Processing System MDIO_ETHERNET_0
DDR FIXED_IO SPI_0 USBIND_0 S_AXI_HP0_FIFO_CTRL
M_AXI_GP0 S_AXI_HP0
TTC0_WAVE0_OUT TTC0_WAVE1_OUT TTC0_WAVE2_OUT M_AXI_GP0_ACLK
S_AXI_HP0_ACLK
FCLK_CLK0 FCLK_RESET0_N
processing_system7_0_axi_periph
AXI Interconnect S00_AXI
M00_AXI ACLK
ARESETN S00_ACLK S00_ARESETN M00_ACLK M00_ARESETN rst_processing_system7_0_125M
Processor System Reset slowest_sync_clk ext_reset_in aux_reset_in mb_debug_sys_rst dcm_locked
mb_reset bus_struct_reset[0:0]
peripheral_reset[0:0]
interconnect_aresetn[0:0]
peripheral_aresetn[0:0]
PS (Zynq)+bus AXI+GPIO for accessing EMIO
(25 min sythesis first time, 5 min afterwards)Vivado provides mandatory address ranges for each peripheral on the AXI bus
5 / 12
FPGA: EMIO
EMIO: GPIO connected to the PL (6= MIO connected to the PS) Functions of the registers provided by the GPIO block: 1 :
1
https://www.xilinx.com/support/documentation/ip_documentation/axi_gpio/v2_0/pg144-axi-gpio.pdf
6 / 12
FPGA: EMIO pin assignment
File: ports.xdc
[ . . . ]
### LED
s e t p r o p e r t y IOSTANDARD LVCMOS33 [ g e t p o r t s {l e d o t r i i o [∗]}]
s e t p r o p e r t y SLEW SLOW [ g e t p o r t s{l e d o t r i i o [∗]}]
s e t p r o p e r t y DRIVE 8 [ g e t p o r t s {l e d o t r i i o [∗]}]
s e t p r o p e r t y PACKAGE PIN F16 [ g e t p o r t s {l e d o t r i i o [ 0 ]}]
s e t p r o p e r t y PACKAGE PIN F17 [ g e t p o r t s {l e d o t r i i o [ 1 ]}]
s e t p r o p e r t y PACKAGE PIN G15 [ g e t p o r t s {l e d o t r i i o [ 2 ]}]
s e t p r o p e r t y PACKAGE PIN H15 [ g e t p o r t s {l e d o t r i i o [ 3 ]}]
s e t p r o p e r t y PACKAGE PIN K14 [ g e t p o r t s {l e d o t r i i o [ 4 ]}]
s e t p r o p e r t y PACKAGE PIN G14 [ g e t p o r t s {l e d o t r i i o [ 5 ]}]
s e t p r o p e r t y PACKAGE PIN J15 [ g e t p o r t s {l e d o t r i i o [ 6 ]}]
s e t p r o p e r t y PACKAGE PIN J14 [ g e t p o r t s {l e d o t r i i o [ 7 ]}]
Red_Pitaya_Schematics_STEM_125-10_V1.0.pdf
7 / 12Configuring the FPGA from GNU/Linux: fpga manager
Unified, vendor independent access to the PL part of the SoC:
I convert the .bit synthesized by Vivado to a bit.bin: provide a configuration file .bif
all: {bitstream_name.bit}
I bit → bit.bin: $VIVADO_SDK/bin/bootgen -image file.bif -arch zynq -process_bitstream bin
I configure the FPGA using fpga manager
(mkdir /lib/firmwareif needed)cp system_wrapper.bit.bin /lib/firmware/system_wrapper.bit.bin
echo "system_wrapper.bit.bin" > /sys/class/fpga_manager/fpga0/firmware
I Use the functionalities provided by the new FPGA bitstream
devmem 0x41200004 8 0x0 devmem 0x41200000 8 0xf
I WARNING: accessing the FPGA not configured by a bitstream will yield a crash of Linux (AXI transaction not acknowledged)
8 / 12
fpga manager
Demonstration of a driver for controlling the 8 LEDs from the probe method
#i n c l u d e<l i n u x / m o d u l e . h>
#i n c l u d e<l i n u x / p l a t f o r m d e v i c e . h>
#i n c l u d e<l i n u x / i o . h> // i o r e m a p s t a t i c s t r u c t p l a t f o r m d r i v e r g p i o s i m p l e d r i v e r ={
. p r o b e = g p i o s i m p l e p r o b e , . r e m o v e = g p i o s i m p l e r e m o v e , . d r i v e r ={. name =" jmf ",}, };
s t a t i c i n t g p i o s i m p l e r e m o v e (s t r u c t p l a t f o r m d e v i c e ∗p d e v ) {p r i n t k ( KERN ALERT" jmf bye % d \ n ", pdev−>i d ) ;r e t u r n 0;}
s t a t i c i n t g p i o s i m p l e p r o b e (s t r u c t p l a t f o r m d e v i c e∗p d e v ) {s t r u c t r e s o u r c e ∗r ;
s t a t i c v o i d i o m e m∗j m f g p i o ; // i n t j m f g p i o ;
r= p l a t f o r m g e t r e s o u r c e ( pdev , IORESOURCE MEM , pdev−>i d ) ; // MEM e t non IO p r i n t k ( KERN ALERT" jmf h e l l o % d :% x - -% x \ n ", pdev−>i d , (i n t) r−>s t a r t , (i n t) r−>end ) ; j m f g p i o =(v o i d ∗) i o r e m a p ( r−>s t a r t , 0 x 0 4 ) ;
w r i t e l ( 0 x0 , j m f g p i o +0x 0 4 ) ; // a l l a s o u t p u t w r i t e l ( 0 x05 , j m f g p i o ) ; // a l l a s o u t p u t r e t u r n 0 ;
}
m o d u l e p l a t f o r m d r i v e r ( g p i o s i m p l e d r i v e r ) ; MODULE LICENSE (" GPL ") ;
9 / 12
Controlling the LEDs from a writable file
Private structure 2 dupplicating the resources used by the driver 3
s t r u c t j m f s t r u c t {v o i d∗mem base ;};
s t a t i c s s i z e t g p i o s i m p l e s t o r e (s t r u c t d e v i c e ∗dev , s t r u c t d e v i c e a t t r i b u t e ∗a t t r , c o n s t c h a r ∗b u f , s i z e t c o u n t ) {s t r u c t j m f s t r u c t∗ m a s t r u c t=d e v g e t d r v d a t a ( d e v ) ; // LOCAL c o p y
l o n g i n t r e s ;
i f ( ! k s t r t o l ( b u f , 1 0 , & r e s ) ) w r i t e l ( r e s , m a s t r u c t−>mem base ) ; // a l l a s o u t p u t p r i n t k (" % s = % ld ", b u f , r e s ) ;
r e t u r n( c o u n t ) ; }
s t a t i c DEVICE ATTR ( v a l u e w , 0 2 2 0 , NULL , g p i o s i m p l e s t o r e ) ; s t a t i c i n t g p i o s i m p l e r e m o v e (s t r u c t p l a t f o r m d e v i c e ∗p d e v ) {s t r u c t j m f s t r u c t∗ m a s t r u c t=p l a t f o r m g e t d r v d a t a ( p d e v ) ;
k f r e e ( m a s t r u c t ) ;
d e v i c e r e m o v e f i l e (& pdev−>dev , &d e v a t t r v a l u e w ) ; p r i n t k ( KERN ALERT" jmf bye % d \ n ", pdev−>i d ) ;r e t u r n 0 ; }
s t a t i c i n t g p i o s i m p l e p r o b e (s t r u c t p l a t f o r m d e v i c e∗p d e v ) {s t r u c t r e s o u r c e ∗r ;
s t r u c t j m f s t r u c t ∗m a s t r u c t ;
m a s t r u c t =(s t r u c t j m f s t r u c t ∗) k z a l l o c (s i z e o f(s t r u c t j m f s t r u c t ) , GFP KERNEL ) ; // z=z e r o d e v i c e c r e a t e f i l e (& pdev−>dev , &d e v a t t r v a l u e w ) ;
r= p l a t f o r m g e t r e s o u r c e ( pdev , IORESOURCE MEM , pdev−>i d ) ;
m a s t r u c t−>mem base=i o r e m a p ( r−>s t a r t , r e s o u r c e s i z e ( r ) ) ; // on r e c u p e r e end−s t a r t p l a t f o r m s e t d r v d a t a ( pdev , m a s t r u c t ) ;
r e t u r n 0 ; }
2
see for example data dma direct core in https://github.com/oscimp/linux_driver/
3
DO NOT create a global variable which would be overwritten by the latest copy of the driver being loaded.
10 / 12
Demonstration using multiple copies of the driver
Application justifying the two resource configurations:
I split the single 8-bit GPIO latch in two 4-bit subsets I autoroute
I constraint file after re-naming gpio rtl to ledo 2
EMIO pins connected
to LEDs Type and wiring of the pins
Separating the GPIO bus into two 4 bit latches
Address space provided by Vivado
Exercise: update the driver to fetch the two possible configurations, depending whether led0 or led1 is being controlled
Demonstrate passing parameters (pattern on the LEDs) through /sys
11 / 12Exercise
1. add the XADC block to the Vivado design already including the GPIO
2. synthesize and configure the FPGA using this bitstream: what pins are associated with the analog inputs ? what is the voltage range ?
3. find the documentation of the XADC block and identify the registers relevant for using the analog to digital converters
4. write a driver able to read an ADC value (what is the base-address of the registers ?) 5. demontrate periodic acquisition of the XADC samples by a driver
12 / 12