• Aucun résultat trouvé

Embedded systems 7/7

N/A
N/A
Protected

Academic year: 2022

Partager "Embedded systems 7/7"

Copied!
17
0
0

Texte intégral

(1)

Embedded systems 7/7

J.-M Friedt

FEMTO-ST/time & frequency department [email protected]

slides at jmfriedt.free.fr

October 25, 2021

1 / 17

(2)

Linux kernel: a toolbox

I standard interface to access peripherals from userspace (timer, gpio) I access to scheduler to add tasks (tasklet)

I consistent access to resources: semaphore and mutex

Handling events (e.g. interrupts) and propagate a signal to userspace applications

2 / 17

(3)

Kernel API

Core functions provided by the kernel to handle userspace applications: scheduler, timer, communication with userspace

I tasks (tasklet): software interrupts

1

char my_tasklet_data[]="my_tasklet_function was called";

void my_tasklet_function( unsigned long data ) { printk( "%s\n", (char *)data ); return; } DECLARE_TASKLET( my_tasklet, my_tasklet_function,

(unsigned long) &my_tasklet_data );

int init_module( void )

{ tasklet_schedule( &my_tasklet ); return 0; } void cleanup_module( void )

{ tasklet_kill( &my_tasklet ); return; }

→ ISR must be short and create a tasklet scheduled when time allows

1https://developer.ibm.com/technologies/linux/tutorials/l-tasklets/

3 / 17

(4)

Hardware access

Solution 1: ioremap to identify virtual address and set registers

Solution 2: use existing drivers provided by the kernel (make linux-menuconfig in Buildroot)

CONFIG_GPIO_XILINX:

Say yes here to support the Xilinx FPGA GPIO device Symbol: GPIO_XILINX [=m]

Type : tristate

Prompt: Xilinx GPIO support Location:

-> Device Drivers

-> GPIO Support (GPIOLIB [=y]) -> Memory mapped GPIO drivers Defined at drivers/gpio/Kconfig:573

Depends on: GPIOLIB [=y] && HAS_IOMEM [=y] && OF_GPIO [=y]

or for other platforms:

CONFIG_GPIO_SUNXI:

This option enables support for GPIOs on the Allwinner SOCs (sun4i/sun5i/sun7i). The GPIOs must be defined in [gpio_para]

section of sysconfig.fex file (gpio_used/gpio_num/gpio_pin_x variables) Symbol: GPIO_SUNXI [=y]

Type : tristate

Prompt: GPIO Support for sunxi platform

Depends on: GPIOLIB [=y] && (ARCH_SUN4I [=n] || ARCH_SUN5I [=y] || ARCH_SUN7I [=n]) Location:

-> Device Drivers

-> GPIO Support (GPIOLIB [=y])

WARNING: using kernel features requires a GPL license MODULE_LICENSE("GPL");

4 / 17

(5)

Hardware access

Solution 1: ioremap to identify virtual address and set registers

Solution 2: use existing drivers provided by the kernel (make linux-menuconfig in Buildroot) Using GPIO: define pins in devicetree

2

gpio-leds {

compatible = "gpio-leds";

led-8-yellow { label = "led8";

gpios = <&gpio0 0 0>;

default-state = "off";

linux,default-trigger = "mmc0";

};

led-9-red { label = "led9";

gpios = <&gpio0 7 0>;

default-state = "off";

linux,default-trigger = "heartbeat";

};

};

or (pin)+906

2redpitaya/board/redpitaya/zynq-red pitaya.dtsin the BR2 EXTERNAL since the Redpitaya is not officially supported by Buildroot

5 / 17

(6)

Kernel module: using gpiolib & interrupt handling

Test if GPIO is available (22 = EINVAL, 16 = EBUSY)

3

static irqreturn_t irq_handler(int irq, void *dev_id) {...

return IRQ_HANDLED;

}

gpio =906+10; // MIO10 err=gpio_is_valid(gpio);

err=gpio_request_one(gpio, GPIOF_IN, "jmf_irq");

if (err!=-22)

{irq = gpio_to_irq(gpio);

irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);

err = request_irq(irq, irq_handler, IRQF_SHARED, "GPIO jmf", &dummy);

dummy=0;

}

3/usr/include/asm-generic/errno-base.h

6 / 17

(7)

Signals: event handler in userspace

Userspace equivalent to software interrupt: signals

#include <signal.h>

void my_handler (int sig) {

printf ("I got SIGINT, number %d\n", sig);}

int main ( void ) {

signal (SIGINT, my_handler);

while (1) {}

}

leads to, every time CTRL-C is hit (kill with kill -9 PID)

jmfriedt@(none):~$ ./sigint I got SIGINT, number 2 I got SIGINT, number 2

7 / 17

(8)

Interrupt signal distribution

Sharing interrupt information through signals

1. a unique hardware interrupt handling module (kernel) 2. multiple userspace programs might react to an interrupt 3. each program registers with the module

4. the module reacts quickly to the interrupt signal ...

5. ... and informs the programs identified through their PID when time allows.

8 / 17

(9)

Interrupt signal distribution

Alternate solution (thread)

1. a program wants to be notified of an interrupt as it is running

2. creates a thread blocked when reading a communication interface with the kernel in /sys/class or /dev

3. when the interrupt is triggered, the module unblocks the read syscall handling function ...

4 5

4. ... and the thread notifies the program of the event.

4http://www.makelinux.net/ldd3/chp-6-sect-2

5http://www.makelinux.net/ldd3/chp-5-sect-3for kernel semaphores

9 / 17

(10)

Shared data protection

Multiple tasks use the same data ⇒ consistency issues Three methods to protect shared data handling:

I semaphore (counter)

I mutex (binary with the task removed from the scheduler) I spin-lock (binary with active testing of the lock)

Producer-consumer:

1. one task produces data 2. a user requests these data

3. reading is blocked as long as the data have not been produced I Requesting a semaphore blocks the execution if already null I Raising the semaphore unblocks the waiting process/task I The counter can rise multiple time to unblock multiple processes

#include <linux/semaphore.h>

struct semaphore mysem;

sema_init(&mysem, 0); // init the semaphore as empty down (&mysem); // blocks consumer

...

up (&mysem); // producer unblocks 10 / 17

(11)

Shared data protection: mutex

Blocks-unblocks parts of the software using a common resource:

only one part of a software using a mutex can be executed at any given time

#include <linux/mutex.h>

struct mutex mymutex;

mutex_init(&mymutex);

mutex_lock(&mymutex); // blocks ...

mutex_unlock(&mymutex); // unblocks

As many mutex as shared resources

11 / 17

(12)

Shared data protection: spinlock

A mutex removes the task from the scheduler ⇒ slow

For fast operations (interrupts), actively probe the lock: spinlock

#include <linux/spinlock.h>

static DEFINE_SPINLOCK(myspin);

spin_lock_init(&myspin);

spin_lock(&myspin);

...

spin_unlock(&myspin);

MODULE_LICENSE("GPL");

deadlock issue: two processes calling simultaneously blocking conditions (e.g. SMP architecture with two cores locking mutex depending on each other).

12 / 17

(13)

Demonstration with GPIO

I The two GPIO available are connected to LEDs ⇒ output only

I Other MIO are set for communication (I2C, SPI in ps7 init.c)⇒ reconfigure as GPIO I MIO10 is pin 3 of E2 connector

I 3 bits L0 SEL, L1 SEL and L2 SEL select the GPIO function

> devmem 0xF800012C # GPIO clock active 0x00500444

> devmem 0xF8000728 # A = SPI 0x000016A0

> devmem 0xF8000728 32 0x00001600

13 / 17

(14)

Accessing the GPIO using gpiolib: interrupt handling

#i n c l u d e<l i n u x / m o d u l e . h> /∗Needed by a l l m o d u l e s ∗/

#i n c l u d e<l i n u x / k e r n e l . h> /∗Needed f o r KERN INFO∗/

#i n c l u d e<l i n u x / i n i t . h> /∗Needed f o r t h e m a c r o s ∗/

#i n c l u d e<l i n u x / i n t e r r u p t . h>

#i n c l u d e<l i n u x / i r q . h>

#i n c l u d e<l i n u x / g p i o . h>

s t a t i c i n t dummy , i r q , d e v i d , j m f g p i o =906+10;

s t a t i c i r q r e t u r n t i r q h a n d l e r (i n t i r q , v o i d ∗d e v i d ) {dummy++; p r i n t k ( KERN INFO " p l i p % d ", dummy ) ;

r e t u r n IRQ HANDLED ; }

i n t h e l l o s t a r t ( ) {i n t e r r ;

e r r= g p i o i s v a l i d ( j m f g p i o ) ;

e r r=g p i o r e q u e s t o n e ( j m f g p i o , GPIOF IN , " j m f _ i r q ") ; i f ( e r r !=−22)

{i r q = g p i o t o i r q ( j m f g p i o ) ;

i r q s e t i r q t y p e ( i r q , IRQ TYPE EDGE BOTH ) ;

e r r = r e q u e s t i r q ( i r q , i r q h a n d l e r , IRQF SHARED , " G P I O jmf ", &d e v i d ) ; dummy=0;

} r e t u r n 0 ; }

v o i d h e l l o e n d ( ) {f r e e i r q ( i r q ,& d e v i d ) ;

g p i o f r e e ( j m f g p i o ) ; }

m o d u l e i n i t ( h e l l o s t a r t ) ; m o d u l e e x i t ( h e l l o e n d ) ;

MODULE LICENSE (" GPL ") ; // n e e d e d t o u s e L i n u x k e r n e l f u n c t i o n s

14 / 17

(15)

Accessing the GPIO using gpiolib: sending a signal

#i n c l u d e<l i n u x / s c h e d / s i g n a l . h> // k i l l p i d

#i f d e f ARMEL // on R e d p i t a y a

#i n c l u d e<l i n u x / g p i o . h>

s t a t i c i r q r e t u r n t i r q h a n d l e r (i n t i r q , v o i d ∗d e v i d )

#e l s e // on PC

s t r u c t t i m e r l i s t e x p t i m e r ;

s t a t i c v o i d i r q h a n d l e r (s t r u c t t i m e r l i s t ∗t )

#e n d i f

{s t r u c t p i d ∗mypid ; i f ( p i d != 0)

{mypid= f i n d v p i d ( p i d ) ; i f ( mypid == NULL )

p r i n f o (" C a n n o t f i n d PID f r o m u s e r p r o g r a m \ r \ n ") ;

e l s e // d o s e n d s i g i n f o ( SIGUSR1 , SEND SIG FORCED , t a s k , PIDTYPE MAX ) ; k i l l p i d ( mypid , SIGUSR1 , 1 ) ;

}

#i f d e f ARMEL

r e t u r n IRQ HANDLED ;

#e l s e

m o d t i m e r ( t , j i f f i e s + HZ) ;

#e n d i f }

s t a t i c s s i z e t d e v w r i t e (s t r u c t f i l e ∗f i l ,c o n s t c h a r ∗b u f f , s i z e t l e n , l o f f t ∗o f f ) {i n t m y l e n ;

c h a r b u f [ 1 5 ] ;

i f ( l e n>14) m y l e n =14; e l s e m y l e n=l e n ;

i f ( c o p y f r o m u s e r ( b u f , b u f f , m y l e n ) == 0 ) s s c a n f ( b u f , " % d ", &p i d ) ; p r i n t k (" PID % d r e g i s t e r e d ", p i d ) ;

r e t u r n l e n ; }

15 / 17

(16)

Accessing the GPIO using gpiolib: creating a task to handle the interrupt

s t a t i c s t r u c t w o r k s t r u c t i r q w o r k ;

s t a t i c i r q r e t u r n t i r q h a n d l e r (i n t i r q , v o i d d e v i d )

{s c h e d u l e w o r k (& i r q w o r k ) ; // l o n g t a s k h a n d l e d when t i m e a l l o w s r e t u r n IRQ HANDLED ;

}

v o i d d o s o m e t h i n g (s t r u c t w o r k s t r u c t ∗d a t a ) {s t r u c t p i d ∗mypid ;

i f ( p i d != 0)

{mypid= f i n d v p i d ( p i d ) ; i f ( mypid == NULL )

p r i n f o (" C a n n o t f i n d PID f r o m u s e r p r o g r a m \ r \ n ") ;

e l s e // d o s e n d s i g i n f o ( SIGUSR1 , SEND SIG FORCED , t a s k , PIDTYPE MAX ) ; k i l l p i d ( mypid , SIGUSR1 , 1 ) ;

}

#i f d e f ARMEL

r e t u r n IRQ HANDLED ;

#e l s e

m o d t i m e r ( t , j i f f i e s + HZ) ;

#e n d i f }

i n t h e l l o s t a r t ( ) // i n i t m o d u l e ( v o i d ) {. . .

INIT WORK(& i r q w o r k , d o s o m e t h i n g ) ; . . .

e r r = r e q u e s t i r q ( i r q , i r q h a n d l e r , IRQF SHARED , " G P I O jmf ", & i r q i d ) ; }

v o i d h e l l o e n d ( ) // c l e a n u p m o d u l e ( v o i d ) {. . .

f r e e i r q ( i r q ,& i r q i d ) ; }

16 / 17

(17)

Accessing the GPIO using gpiolib: userspace

#i n c l u d e<s t d i o . h>

#i n c l u d e<s t d l i b . h>

#i n c l u d e<s i g n a l . h>

#i n c l u d e<s t r i n g . h>

#i n c l u d e<s y s / t y p e s . h>

#i n c l u d e<s y s / s t a t . h>

#i n c l u d e<u n i s t d . h>

#i n c l u d e<f c n t l . h>

v o i d s i g n a l h a n d l e r (i n t s i g n u m ) {p r i n t f (" S i g n a l r e c e i v e d \ r \ n ") ;}

i n t main ( ) {FILE∗f ;

s i g n a l ( SIGUSR1 , s i g n a l h a n d l e r ) ; p r i n t f (" My PID is % d .\ n ", g e t p i d ( ) ) ;

f=f o p e n (" / dev / jmf "," w ") ; // t u n e t o c o m m u n i c a t i o n i n t e r f a c e w i t h m o d u l e f p r i n t f ( f ," % d \ n ", g e t p i d ( ) ) ; f f l u s h ( f ) ;

f c l o s e ( f ) ; w h i l e ( 1 ) {};

r e t u r n 0 ; }

Demonstrate read() blocking from a separate thread, unblocked by interrupt trigger

#i n c l u d e<p t h r e a d . h> // c o m p i l e w i t h−l p t h r e a d

v o i d ∗f u n c t i o n (v o i d ∗dummy ) {[ . . . ]} // b l o c k i n g r e a d and r e a c t t o i n t e r r u p t i n t main ( )

{p t h r e a d t m y t h r e a d ;

p t h r e a d c r e a t e (& m y t h r e a d , NULL , f u n c t i o n , NULL ) ; // l a s t NULL = dummy param p t h r e a d j o i n ( m y t h r e a d , NULL ) ;

}

17 / 17

Références

Documents relatifs

Iteration of rational functions was studied extensively by Fatou [3] and Julia [5] and the analogous theory for tran- scendental entire functions more briefly by Fatou

Data 1/0 has become the world's largest supplier of microcircuit programming equipment by working closely with you and the people who design and manufacture the

ON THE UNSYMMETRICAL TOP... On the Unsymmetrical

When ν ≡ 1 , the partition funtion ounts the number of dimer ongurations of the graph G , or equivalently the number of tilings of the graph G ∗ , and the Boltzmann measure is

Le diagramme d’états comprend deux pseudo-états supplémentaires : – l’état initial du diagramme d’états correspond à la création d’une instance ; – l’état final

How accurate are physicians’ clinical predictions of survival and the available prognostic tools in estimating survival times in terminally ill cancer patients.. A

• E.g., when the maximum number of concurrent accesses is reached, subsequent access requests are queued in FIFO order. – Adding characteristic attributes using tags (e.g.,

This leads to trial-and-error development, always adding tools to the programming environment. Robert Collins, display products manager for Digital Equipment Corp., stated