SlideShare a Scribd company logo
1 of 221
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
1
Embedded Linux Rapid
Prototyping tutorials
with Raspberry Pi
Naohiko Shimizu
Tokai University, Japan
nshimizu@keyaki.cc.u-tokai.ac.jp
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
2
Agenda
• Introduction
• Prepare the Raspberry Pi for the workshop
– Basic installation
– Tools for cross compilation
• Embedded Linux Programming with C
– Basic Linux API
– Kernel modules
• Rapid prototyping with Python
• Exercise
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
3
Objective of this course
• Browse the development of embedded
systems
• Get the basics of Linux API
• Make kernel modules on Linux
• Rapid prototyping with Python
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
4
Introduction
• Raspberry Pi is a low cost and the one of
the most popular credit-card sized computer
in the world.
http://www.raspberrypi.org
• Rpi foundation is an
educational charity in UK.
• They want to provide affordable,
programmable computers everywhere.
Model B+
Model B
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
5
Raspberry Pi Model B+
• 700MHz ARM1176JZF-S
• VideoCore IV GPU
• 512MB RAM
4 x USB
Ethernet
Audio
Video
HDMImicroUSB
Power
microSD
For OS
GPIO
Broadcom BCM2835 SoC
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
6
• GPIO have multiple
functions as shown
in the block diagram
• Default pad drive
strength is 8mA for output
• Output voltage is 3.3V
• It can pull up/down
• It can make an interrupt
GPIO on BCM2835
BCM2835 ARM Peripherals
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
7
GPIO registers(1)
BCM2835 ARM Peripherals
The address is physical and you
have to map to your virtual space.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
8
GPIO registers(2)
BCM2835 ARM Peripherals
GPIO can be set or clear with
GPIO output set/clear registers.
We can read the whole value with
GPIO level register but cannot set the
values directly.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
9
GPIO registers(3)
BCM2835 ARM Peripherals
GPIO alternate functions
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
10
GPIO in Linux kernel
• ARM Linux is using the Device Tree.
– It defines the I/O subsystem out of the kernel.
/boot/bcm2708-rpi-b-plus.dtb
is the compiled Device Tree for Pi B+
The source code (.dts) is available on the Linux
source tree
arch/arm/boot/dts/bcm2708-rpi-b-plus.dts
arch/arm/boot/dts/bcm2708.dtsi
• We use Pinctrl and GPIO library. See
Documentation/pinctrl.txt
Documentation/gpio/gpio-legacy.txt
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
11
Pinctrl subsystem
http://free-electrons.com/pub/conferences/2013/fosdem/arm-support-kernel/
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
12
GPIO special function on Pi
• DTS defines some
special functions
on GPIOs
gpio: gpio {
compatible = "brcm,bcm2835-gpio";
reg = <0x7e200000 0xb4>;
interrupts = <2 17>, <2 18>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
&gpio {
spi0_pins: spi0_pins {
brcm,pins = <7 8 9 10 11>;
brcm,function = <4>; /* alt0 */
};
i2c0_pins: i2c0 {
brcm,pins = <0 1>;
brcm,function = <4>;
};
i2c1_pins: i2c1 {
brcm,pins = <2 3>;
brcm,function = <4>;
};
i2s_pins: i2s {
brcm,pins = <18 19 20 21>;
brcm,function = <4>; /* alt0 */
};
};
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
13
System Timer
• BCM2835 has a free run 64 bit system
timer which is running at 1 MHz on
RaspberryPi.
BCM2835 ARM Peripherals
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
14
IRQ for timer
http://xinu.mscs.mu.edu/BCM2835_Interrupt_Controller
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
15
The I/O board for this seminar
• We will use LED and SW board.
DIS1 DIS2
S1 S2
LED1 LED2
a
b
c
d
e
f
g
dp
b
c
d
e
f
g
dp
a
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
16
The I/O board for this seminar
• GPIO port number of the I/O boad
Port Func Port Func
2 S1 3 S2
4 LED1 9 LED2
7 DIS1 8 DIS2
14 a 15 b
17 c 18 d
22 e 23 f
24 g 25 dp
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
17
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
18
Software for Raspberry Pi
• OS : Raspberian distribution which is based
on Debian GNU Linux.
• Installer : NOOBS make your life easy.
• ssh : Communicate to RPi
• wiringPi : GPIO library for C
• RPi.GPIO : GPIO library for Python
• Linux kernel related : kernel source, gcc-4.8
etc.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
19
Software version we use
• NOOBS v1.4.0
• Raspbian wheezy
– Firmware 8aca5762
• wiringPi 2.22
• Rpi.GPIO 0.5.11
• LiveCygwin from http://www.ip-arch.jp
• RaspberryPi cross package from
http://www.ip-arch.jp/RaspberryPi.tar.bz2
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
20
Our system with headless
Raspberry Pi
• We use the ethernet connection between
Raspberry Pi and PC.
• Also we use GPIO to connect Raspberry Pi
to the world.
• No keyboard nor display for Raspberry Pi
Ethernet
PC
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
21
Prepare the Raspberry Pi
• Raspberry Pi model B+ or B
• microSD card
> 8GB
• microUSB Power
> 1A
• Ethernet cable
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
22
Basic Installation 1
• Format your microSD card with FAT32.
– You may need a miroSD to SD adapter
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
23
Basic Installation 2
• Copy the contents of NOOBS on the
microSD card.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
24
Basic Installation 3
• Add silentinstall at the last of recovery.cmdline.
• Modify os/Raspbian/flavours.json.
• Delete os/Data_Partition folder
Add
Don’t forget
ENTER at the
end of the line.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
25
Basic Installation 4
• Eject your microSD card from PC, and put it
in the slot of Raspberry Pi
• Plug your Raspberry Pi to the USB Power.
You will see Power LED is on and ACT LED
is blinking.
• It takes long time
we will prepare
other things
during the boot.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
26
Basic Installation 5
• Setup Internet Connection Sharing on your
Windows PC.
– Change the Sharing properties of your WiFi
adapter on the Control Panel -> Network and
Internet -> Network Connections
– Check ‘Allow other network users to connect
through this computer’s Internet connection’ on
the Sharing tab
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
27
Basic Installation 6
• Connect your Raspberry Pi to your PC
– Your PC will provide an IP address to Pi, but
unfortunately there is no way to know it.
– You can use HDMI display for monitoring.
Check the PC’s IP address
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
28
Basic Installation 7
• Search your Raspberry Pi’s IP address :-0
– Open cmd
• [win]+R
• cmd
– Make a bat file
• Notepad
– Save as ck.bat
– Run it
– You will find the Pi’s IP address
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
29
Basic Installation 8
• Connect to your Raspberry Pi with ssh
Login: pi
Password: raspberry
We use LiveCygwin in this seminar
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
30
Tools for cross compilation
• C applications
– Cross tools by ct-ng
• gcc
• Linux library
• Linux headers
– wiringPi static library
• Linux kernel modules
– Linux kernel source
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
31
Cross compilation
• Build your ct-ng tools on Cygwin.
– In cygwin environment, you need some patches
• https://sourceware.org/ml/crossgcc/2012-05/msg00012.html
• http://www.raspberrypi.org/forums/viewtopic.php?f=7&t=4058
• Configure and make your cross tools
• Prepare your Linux kernel (see next slide for detail)
– Or Download x-tools from http://www.ip-arch.jp/
• http://www.ip-arch.jp/RaspberryPi.tar.bz2
• Put the file on the LiveCygwin’s /usr/arch directory, it will be
extracted on the next session of LiveCygwin.
• In the package you also have the Linux kernel source code.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
32
Linux kernel source
• We need the same kernel source and some files
as the kernel running on the Raspberry Pi
– On Raspberry Pi, you can get the version in
/usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz
– Get the git_hash value from
https://raw.githubusercontent.com/raspberrypi/firmware/<firmware-version>/extra/git_hash
– Get the linux source from
https://github.com/raspberrypi/linux/archive/<git_hash-value>.tar.gz
– Get Module.symvers from
https://raw.githubusercontent.com/raspberrypi/firmware/<firmware-version>/extra/Module.symvers
and copy it to the linux directory
– Get .config on Raspberry Pi with
zcat /proc/config.gz > ~/linux/.config
You can skip if you use LiveCygwin
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
33
On NOOBS v1.4.0
• We will show the detailed instructions
to get kernel development environment
with NOOBS v1.4.0 based Rasbian
–If you use LiveCygwin, you can use ready
made package by me.
http://www.ip-arch.jp/RaspberryPi.tar.bz2
Therefore, you can skip to the section
“Embedded Linux Programming with C.”
and go to page 40.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
34
On NOOBS v1.4.0
• Get the firmware version from
/usr/share/doc/raspberrypi-
bootloader/changelog.Debian.gz
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
35
On NOOBS v1.4.0
–Get the git_hash value from
https://raw.githubusercontent.com/raspberrypi/firmware/8aca5762/extra/git
_hash
Firmware version
Git_hash value
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
36
On NOOBS v1.4.0
• Get the linux source from
https://github.com/raspberrypi/linux/archive/0be82f722c097340632a59
b879fbfee9c6148f53.tar.gz
And extract it on your cygwin home directory.
Git_hash value
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
37
On NOOBS v1.4.0
• Get Module.symvers from
https://raw.githubusercontent.com/raspberrypi/firmware/8aca5762/extr
a/Module.symvers
save and copy it to the linux
source directory
as Module.symvers
Firmware version
Module7.symvers for Pi2
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
38
On NOOBS v1.4.0
• Get .config on Raspberry Pi from
/proc/config.gz
put it on your linux source directory
as .config
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
39
On NOOBS v1.4.0
• Install required package for this seminar on your
Raspberry Pi
– Suggested packages are:
• gcc-48 : This package is not mandatory, but useful if you want to
compile kernel modules on your Raspberry Pi.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
40
On NOOBS v1.4.0
• Extract RaspberryPi.tar.bz2 on your
home of LiveCygwin
–In the RaspberryPi directory, type
make pi2
or
make pibp
For RaspberryPi2
For RaspberryPi B+
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
41
On NOOBS v1.4.0
• What is going on the Makefile is:
–Change your directory to linux
• cd linux
–Preparing your kernel to use
• ARCH=arm make oldconfig
• CROSS_COMPILE=~/RaspberryPi/x-tools/arm-unknown-linux-
gnueabi/bin/arm-unknown-linux-gnueabi- ARCH=arm make prepare
modules_prepare
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
42
Embedded Linux Programming with C
• Access memory mapped I/O via mmap
– /dev/mem can be used to access I/O registers
– You need to set the port direction, pull up/down,
etc. for GPIO.
• Interrupt can be handled via device driver
– You need a device driver which handle IRQ
– The driver will make a callback or signal
• Any Linux API can be used for your
applications
• Use real-time task for less jitter.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
43
Program execution
STACK
BSS
DATA
TEXT
HEAP
#include <stdio.h>
int main() {
printf(“hello worldn”);
return 0;
}
compile
Source code
Execution binary
TEXT
DATA
Processor memory
header
Source code is compiled to binary.
Text and Data segments are loaded on memory.
Header has the size of BSS and Stack segments.
Loader also link the unresolved labels to the dynamic link libraries.
load
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
44
Linux process
• User process can use up to 3GB of virtual
memory.
• C language execution format has
four segments to load on memory.
• Process has a priority
– 0-99 real-time task
– 100-139 conventional task
– Real-time tasks are scheduled
on their priority
STACK
BSS
DATA
TEXT
HEAP
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
45
User space
User space
Kernel and User space
• Linux uses virtual address
for their processes.
• 3GB is for user space,
1GB for kernel space.
• User mode program access
only to his user space.
• Kernel space is common to
the all processes.
• User program will switch to
kernel via interrupt or svc.
User space
User space
00000000
C0000000
Kernel space
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
46
Address translation
• Linux uses the paging system of ARM
kernel
kernel
kernel
Virtual space 1
Virtual space 2
Page table 1
Page table 2
Physical memory
This figure only shows the concept of the address translation
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
47
Program execution
Hardware
Linux kernel
Device driver Device driver Device driver
C Library Library B
Library A
User application 1 User application 2 User application3
User space 1 User space 2 User space 3
Shared
memory
Kernel
space
Physical
memory
Multiple
User
spaces
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
48
Untimed program vs. timed world
• The basic C language structure is untimed
where the real world is timed.
– We need methods our programs to be
compatible with real world
Wait with sleep
nanosleep()
Polling the timer
timer
Use callback
set
timer
callback
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
49
Make your C application
• Change directory to ~/RaspberryPi/apps/C
• Make your executable binary as:
make hello.exe
The command make the executable from hello.c
• Copy your binary to Raspberry Pi
– scp hello.exe pi@192.168.137.XX:
where XX depends on your environment. See P.15
• On Raspbery Pi, run the binary.
./hello.exe
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
50
Example “Hello World”
• Cross-compile hello.c
> make hello.exe
• Transfer it to the Raspberry Pi
> scp hello.exe pi@192.168.137.xxx:
• Run it on the Raspberry Pi
> ./hello.exe #include <stdio.h>
int main() {
printf(“hello worldn”);
return 0;
}
Source code
The xxx is the IP address
of your RPi
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
51
Program debug on remote
STACK
BSS
DATA
TEXT
HEAP
#include <stdio.h>
int main() {
printf(“hello worldn”);
return 0;
} control
Source code
TEXT
DATA
Processor memory
header
Execution binary
gdb
gdbserver
Program itself is on the remomte.
The gdbserver provide the interface to host.
Remote system
Host system
#include <stdio.h>
int main() {
printf(“hello worldn”);
return 0;
}
Source code
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
52
Example “Hello World”
• Make sure you have hello.exe
• Run gdbserver on you Raspberry Pi with port yyy
• Run cross-gdb on your host
> make hello.exe.debug
(gdb) target remote 192.168.137.xxx:yyy
(gdb) b main
(gdb) c
(gdb) n
Break pointBreak point
Start debugging
xxx is the ip address of
RPi, yyy is the port you
specified on gdbserver
command line.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
53
Exercise
• Make a C proram that print 1 through 10 on
the screen.
• Cross compile it and run it under the control
of the debugger.
• Run the program step by step.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
54
Refer to functions C/Linux provides
• We will use C library or Linux system calls
– C library is realized over the system calls
• Ex. printf, scanf, fopen, strlen, malloc, free, etc.
– System calls directly executed by your program.
• Ex. open, close, read, write, ioctl, llseek, mmap, etc.
• We can use online manual of Linux
> make printf.man
will show you the manual page of printf.
#include <stdio.h>
int printf(const char *format, ...);
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
55
System calls
• With the service all, the system call will
change your program to privileged state.
Linux kernel
C Library
User application
Function call
Service call Service call
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
56
ARM Linux system calls
• Provided via a software interrupt svc #0.
– Arguments for the call are placed on registers
Function Register
System call number r7
arg1 r0
arg2 r1
arg2 r2
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
57
Linux system call example
• We can also use inline assembler to make
a system call.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <asm/unistd.h>
int main() {
char *buf="Hello Worldn";
register int r0 asm("r0");
register int r1 asm("r1");
register int r2 asm("r2");
register int r7 asm("r7");
r7 = __NR_write;
r0 = STDOUT_FILENO;
r1 = (int)buf;
r2 = strlen(buf);
__asm__ volatile(
"svc #0n":
"=r"(r0):"r"(r7),"r"(r0),"r"(r1),"r"(r2));
printf("nres=%dn", r0);
return 0;
}
RaspberryPi/apps/C/syscall.c
A part of system call definitions
#define __NR3264_lseek 62
#define __NR_read 63
#define __NR_write 64
#define __NR_exit 93
#define __NR_nanosleep 101
#define __NR_getitimer 102
#define __NR_setitimer 103
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
58
Exercise
• Based on the system call example, make a
C program that copy a character from
STDIN_FILENO to STDOUT_FILENO while
the system call result is 1, otherwise, the
program should return from main.
• Cross compile it and run it under the control
of the debugger.
• Run the program step by step.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
59
Linux API we will use
• Time : get the current time
• Sleep : suspend the process
• Timer : notify or measure certain duration
• Signal : notification to the process
• Memory : allocate, share the memory space
• Process : invoke, synchronize processes
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
60
Time
• Linux and/or Unix start their time from 1st
January 1970 when the Unix was
developed at Bell Laboratory in USA.
– It is recommended to use POSIX function
• Use clock_gettime() with CLOCK_REALTIME to get
time.
• To control physical devices, CLOCK_MONOTONIC
will be better. It will not be affected by ntpd.
• The resolution can be get with clock_getres()
• We need to add ‘–lrt’ to compile with these function.
exec
gettime
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
61
API : Time
• We have three time related API
– clockid defines what type of the time
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#include <time.h>
int clock_getres(clockid_t clk_id, struct timespec *res);
int clock_gettime(clockid_t clk_id, struct timespec *tp);
int clock_settime(clockid_t clk_id, const struct timespec *tp);
CLOCK_REALTIME
CLOCK_MONOTONIC
CLOCK_PROCESS_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
62
Example: Time
#include <stdio.h>
#include <time.h>
struct timespec tp;
int main () {
clock_gettime(CLOCK_REALTIME, &tp);
printf("ctime = %sn", ctime(&tp.tv_sec));
clock_getres(CLOCK_REALTIME, &tp);
printf("clock resolution is %dnSn", tp.tv_nsec);
return 0;
}
RaspberryPi/apps/C/API/clock.c
$ cd ~/RaspberryPi/apps/C
$ make API/clock.exe
$ scp API/clock.exe pi@192.168.137.xx:
On the Raspberry Pi
$ ./clock.exe
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
63
Exercise : Time
• On the example hello, get the time with
CLOCK_MONOTONIC before and after the
printf, and show the time of the printf in
nano seconds.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
64
Sleep
• This API suspends the execution of the
process for a certain duration or got a signal.
– We have a few sleep APIs sleep(), nanosleep()
and clock_nanosleep()
– These functions will be interrupted when the
process got a signal. In that case, the remained
time will be reported by the functions.
exec1
exec2
sleep
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
65
API : Sleep
• The API for sleep functions
#include <time.h>
int nanosleep(const struct timespec *req, struct timespec *rem);
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
66
Example : Sleep
#include <stdio.h>
#include <time.h>
struct timespec req, rem, tps, tpe;
int main () {
req.tv_sec = 2;
req.tv_nsec = 500000000;
clock_gettime(CLOCK_REALTIME, &tps);
nanosleep(&req, &rem);
clock_gettime(CLOCK_REALTIME, &tpe);
printf("Start to sleep at %sn", ctime(&tps.tv_sec));
printf("End to sleep at %sn", ctime(&tpe.tv_sec));
printf("Diff = %fn", (double)(tpe.tv_sec+tpe.tv_nsec*1e-9) -
(double)(tps.tv_sec+tps.tv_nsec*1e-9));
return 0;
} $ cd ~/RaspberryPi/apps/C
$ make API/sleep.exe
$ scp API/sleep.exe pi@192.168.137.xx:
RaspberryPi/apps/C/API/sleep.c
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
67
Exercise : sleep
• From 1nS, 10nS, …, to 10S, show the sleep
time with the nanosleep call.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
68
Timer
• POSIX timer is a
useful functionality for
many applications.
– It can be a single shot
or interval timer
– It can generate a signal
at the specified time
– It can call a specified
thread at the specified
time
– Or program only read
the timer
Program
execution
timer
Set timer
notify
timeout
signal
callback
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
69
API : Timer
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#include <signal.h>
#include <time.h>
int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid);
int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value,
struct itimerspec * old_value);
int timer_gettime(timer_t timerid, struct itimerspec *curr_value);
int timer_delete(timer_t timerid);
CLOCK_REALTIME
CLOCK_MONOTONIC
CLOCK_PROCESS_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID
struct itimerspec {
struct timespec it_interval; /* Timer interval */
struct timespec it_value; /* Initial expiration */
};
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
70
API : Timer
union sigval { /* Data passed with notification */
int sival_int; /* Integer value */
void *sival_ptr; /* Pointer value */
};
struct sigevent {
int sigev_notify; /* Notification method */
int sigev_signo; /* Notification signal */
union sigval sigev_value; /* Data passed with notification */
void (*sigev_notify_function) (union sigval);
/* Function used for thread notification (SIGEV_THREAD) */
void *sigev_notify_attributes; /* Attributes for notification thread (SIGEV_THREAD) */
pid_t sigev_notify_thread_id; /* ID of thread to signal (SIGEV_THREAD_ID) */
};
SIGEV_NONE
SIGEV_SIGNAL
SIGEV_THREAD
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
71
Example: Timer
#include <stdio.h>
#include <signal.h>
#include <time.h>
struct sigevent evp;
timer_t tm;
struct itimerspec itim;
void thread_func(union sigval val) {
struct timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
printf("Got timer at %sn", ctime(&tp.tv_sec));
return;
}
$ cd ~/RaspberryPi/apps/C
$ make API/timer.exe
$ scp API/timer.exe pi@192.168.137.xx
int main () {
evp.sigev_notify =SIGEV_THREAD;
evp.sigev_notify_function = thread_func;
timer_create(CLOCK_REALTIME, &evp, &tm);
itim.it_value.tv_sec = 2;
itim.it_value.tv_nsec = 0;
itim.it_interval.tv_sec = 3;
itim.it_interval.tv_nsec = 0;
timer_settime(tm, 0, &itim, NULL);
sleep(30);
return 0;
}
RaspberryPi/apps/C/API/timer.c
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
72
Exercise : timer
• Make each kind of timers for
CLOCK_REALTIME,
CLOCK_MONOTONIC,
CLOCK_PROCESS_CPUTIME_ID,
CLOCK_THREAD_CPUTIME_ID
and compare the value during the intervals
in the previous example.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
73
Signal
• Signal is a notification to processes. We
have two types of signal on Linux
– Conventional signal
– Realtime signal
• It works like an interrupt
Signal
callback
exec
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
74
API : Signal
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
int sigqueue(pid_t pid, int sig, const union sigval value);
int sigwaitinfo(const sigset_t *set, siginfo_t *info);
int sigtimedwait(const sigset_t *set, siginfo_t *info,
const struct timespec *timeout);
int kill(pid_t pid, int sig);
int sigwait(const sigset_t *set, int *sig);
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask; int sa_flags;
void (*sa_restorer)(void);
};
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
75
Example: Signal
#include <stdio.h>
#include <signal.h>
#include <time.h>
struct sigaction sa;
struct timespec tp;
void sig_handler() {
clock_gettime(CLOCK_REALTIME, &tp);
printf("got a signaln");
printf("ctime = %sn", ctime(&tp.tv_sec));
return;
}
$ cd ~/RaspberryPi/apps/C
$ make API/signal.exe
$ scp API/signal.exe pi@xxxx
int main () {
sa.sa_handler = sig_handler;
sigaction(SIGUSR1,&sa,NULL);
while (1) sleep(0);
return 0;
}
RaspberryPi/apps/C/API/signal.c
This program will wait for signals.
Then you can send a signal via kill command.
kill –USR1 pid
Where pid is the process id of this program.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
76
Example: Signal(2)
#include <stdio.h>
#include <signal.h>
#include <time.h>
struct sigevent evp;
timer_t tm;
struct itimerspec itim = {{2,0},{3,0}};
struct sigaction sa;
struct timespec tp;
void sig_handler() {
clock_gettime(CLOCK_REALTIME, &tp);
printf("got a signaln");
printf("ctime = %sn", ctime(&tp.tv_sec));
return;
}
$ cd ~/RaspberryPi/apps/C
$ make API/signal2.exe
$ scp API/signal2.exe pi@xxxx
int main () {
evp.sigev_notify =SIGEV_SIGNAL;
evp.sigev_signo = SIGUSR1;
timer_create(CLOCK_REALTIME, &evp, &tm);
sa.sa_handler = sig_handler;
sigaction(SIGUSR1,&sa,NULL);
timer_settime(tm, 0, &itim, NULL);
while (1) sleep(0);
return 0;
}
RaspberryPi/apps/C/API/signal2.c
This program generates signals
inside itself by an interval timer.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
77
Example: Signal(3)
#include <stdio.h>
#include <signal.h>
struct sigaction sa;
void sig_handler(int sig, siginfo_t *si, void *context) {
printf("got a signal %d(%d)n", sig, si->si_value.sival_int);
return;
}
int main () {
int sig;
sa.sa_handler = sig_handler;
sa.sa_flags = SA_SIGINFO;
for(sig=SIGRTMIN;sig<SIGRTMAX;sig++) sigaction(sig, &sa, NULL);
while (1) sleep(0);
return 0;
}
$ cd ~/RaspberryPi/apps/C
$ make API/signal3.exe
$ scp API/signal3.exe pi@xxxx
RaspberryPi/apps/C/API/signal3.c
This program wait real-time signals
SIGRTMIN 32
SIGRTMAX 64
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
78
Example: Signal(3-2)
#include <stdio.h>
#include <signal.h>
int main(int argc, char *argv[]) {
union sigval sv;
if(argc < 4) {
printf("%s pid sig datn",argv[0]);
return -1;
}
sv.sival_int = atoi(argv[3]);
sigqueue(atoi(argv[1]), atoi(argv[2]), sv);
return 0;
}
$ cd ~/RaspberryPi/apps/C
$ make API/sigqueue.exe
$ scp API/sigqueue.exe pi@xxxx
RaspberryPi/apps/C/API/sigqueue.c
This program will send a signal to a process.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
79
Memory
• The virtual memory
– The mmap vs. malloc
– File map
• Dedicate the physical memory
– mlock
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
80
API : mmap
• mmap() creates a new mapping in the
virtual address space of the calling process.
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);
PROT_EXEC Pages may be executed.
PROT_READ Pages may be read.
PROT_WRITE Pages may be written.
PROT_NONE Pages may not be accessed.
MAP_SHARED Share this mapping.
Updates to the mapping are visible to
other processes that map this file, and
are carried through to the underlying
file. The file may not actually be
updated until msync(2) or munmap()
is called.
MAP_PRIVATE The mapping is private
MAP_ANONYMOUS Not associate
with a file
fd is the file descriptor which we can
to map. And offset is the offset from
the start of the mapped file.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
81
Example : mmap
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#define MAPFILE "mmaptest.txt"
#define BUFSZ 4096
int main(int argc, char *argv[]) {
int i,fd;
char *buf, *bufo;
fd = open(MAPFILE, O_RDWR);
if(fd<0) return 1;
buf=(char*)mmap(NULL, BUFSZ, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
bufo=buf;
for(i=0;i<argc;i++){
sprintf(buf,"%sn",argv[i]);
buf+=strlen(buf);
}
msync(bufo, BUFSZ, MS_SYNC);
return 0;
}
RaspberryPi/apps/C/API/mmap.c
Before running the program on pi,
you shoud make the target file with:
dd if=/dev/zero of=mmaptest.txt bs=1 count=4096
This command make a file which size is 4096 bytes
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
82
Exercise : mmap
• Make a program which has a pointer to int
which designate 0x20000000. Then
read/write some valule on that area.
Observe what will be happened.
int *p = (int*)0x20000000;
*p = 1; or x=*p; where x is a int variable.
• Make a region with mmap at 0x20000000.
Then read/write some value on that region.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
83
Process/thread
• Priority
• Multithread
– invoke
– Mutex
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
84
API : scheduler
• You can set scheduler policy and priority for
a target process or itself (pid=0)
#include <sched.h>
int sched_setscheduler(pid_t pid, int policy,
const struct sched_param *param);
int sched_getscheduler(pid_t pid);
int sched_yield(void);
int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);
struct sched_param {
...
int sched_priority;
...
};
Usual tasks:
SCHED_OTHER
SCHED_BATCH
SCHED_IDLE
------------------------
Realtime tasks:
SCHED_FIFO
SCHED_RR
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
85
Example : sched
#include <sched.h>
#include <stdio.h>
int main (int argc, char *argv[]) {
int count;
if(argc < 2) return -1;
struct sched_param sp = {10};
sched_setscheduler(0, SCHED_RR, &sp);
for(count=0;count<atoi(argv[1]);count++) {
if(!(count%65536)) printf(“c:%dn”,count);
}
return 0;
}
RaspberryPi/apps/C/API/sched.c
Run two copies of the execution file as:
$ sudo ./a.out & sudo ./a.out
Try SCHED_FIFO also
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
86
API : pthread
• The pthread and mutex is the basic method
for multiple thread programming.
#include <pthread.h>
int pthread_create(pthread_t *thread, const
pthread_attr_t *attr, void *(*start_routine) (void
*), void *arg);
int pthread_join(pthread_t thread, void
**retval);
int pthread_mutex_init (pthread_mutex_t
*mutex, pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock (pthread_mutex_t
*mutex);
int pthread_mutex_unlock (pthread_mutex_t
*mutex);
int pthread_mutex_destroy (pthread_mutex_t
*mutex);
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
87
Example : pthread
#include <stdio.h>
#include <pthread.h>
#define LOOP 500000
int comm, t1, t2, mx;
pthread_mutex_t lock;
void *thread(void *arg) {
int i;
for(i=0;i<LOOP;i++) {
if(mx) pthread_mutex_lock(&lock);
comm++;
if(mx) pthread_mutex_unlock(&lock);
t1++;
}
return NULL;
}
RaspberryPi/apps/C/API/pthread.c
int main(int argc, char *argv[]) {
pthread_t t;
int i;
if(argc>1) mx=1;
pthread_mutex_init(&lock, NULL);
if(pthread_create(&t, NULL, thread, &comm)) {
return 1;
}
for(i=0;i<LOOP;i++) {
if(mx) pthread_mutex_lock(&lock);
comm++;
if(mx) pthread_mutex_unlock(&lock);
t2++;
}
pthread_join(t, NULL);
pthread_mutex_destroy(&lock);
printf("comm=%d, t1=%d, t2=%dn", comm,
t1, t2);
return 0;
}
Compare the results when command line argument is or is not.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
88
TCP/IP Network
• We will focus on the datagram socket.
socket
bind
recvfrom
sendto
socket
sendto
recvfrom
clientserver
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
89
Network API
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
struct sockaddr_in {
short sin_family; // e.g. AF_INET, AF_INET6
unsigned short sin_port; // e.g. htons(3490)
struct in_addr sin_addr; // see struct in_addr, below
char sin_zero[8]; // zero this if you want to
};
struct in_addr {
unsigned long s_addr; // load with inet_pton()
};
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
90
Network Example (server) -1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#define PORT 55123
void errExit(char str[]) {
fprintf(stderr,"Error with %sn",str);
exit(-1);
}
int main(int argc, char *argv[]) {
struct sockaddr_in sv, cl;
int soc;
char buf[100];
if((soc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) errExit("socket");
memset(&sv, 0, sizeof(sv));
RaspberryPi/apps/C/API/listen.c
Port number is arbitrary
$ cd ~/RaspberryPi/apps/C
$ make API/listen.exe
$ scp API/listen.exe pi@xxxx
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
91
Network Example (server) -2
sv.sin_family = AF_INET;
sv.sin_addr.s_addr = INADDR_ANY;
sv.sin_port = htons(PORT);
if(bind(soc, (struct sockaddr *)&sv, sizeof(sv)) < 0) errExit("bind");
while (1) {
int i;
socklen_t len = sizeof(struct sockaddr_in);
ssize_t sz;
if((sz = recvfrom(soc, buf, sizeof(buf), 0,
(struct sockaddr *)&cl, &len)) < 0) errExit("recvfrom");
for(i=0;i<sz;i++)
buf[i] = (buf[i]>='a' && buf[i] <='z')? buf[i]-0x20:buf[i]+0x20;
buf[i]=0;
if(sendto(soc, buf, sz, 0, (struct sockaddr*)&cl, len) != sz) errExit("sendto");
}
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
92
Network Example (client) -1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#define PORT 55123
void errExit(char str[]) {
fprintf(stderr,"Error with %sn",str);
exit(-1);
}
int main(int argc, char *argv[]) {
struct sockaddr_in sv, cl;
int soc;
char buf[100];
if(argc < 3) errExit("arg1 ipaddr, arg2 strings");
if((soc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) errExit("socket");
memset(&sv, 0, sizeof(struct sockaddr_in));
RaspberryPi/apps/C/API/sending.c
$ cd ~/RaspberryPi/apps/C
$ gcc sending.c –o sending
$ ./sending 192.168.137.xx “test send”
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
93
Network Example (client) -2
sv.sin_family = AF_INET;
sv.sin_port = htons(PORT);
if(inet_pton(AF_INET, argv[1], &sv.sin_addr)<=0) errExit("inet_pton");
if(sendto(soc, argv[2], strlen(argv[2]),0,(struct socaddr*)&sv,
sizeof(struct sockaddr_in)) != strlen(argv[2])) errExit("sendto");
memset(buf,0,sizeof(buf));
if(recvfrom(soc, buf, sizeof(buf), 0, NULL, NULL)<0) errExit("recvfrom");
printf("Recv:%sn", buf);
exit(EXIT_SUCCESS);
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
94
Physical and virtual address
• I/O devices usually use the physical
address, because they don’t have address
mapping method.
• User programs uses virtual address.
• We can map the physical to virtual with
mmap system call with /dev/mem device
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
95
Raspberry Pi specific
programming
With Linux user API
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
96
GPIO programming
• In the following section we will use raw
GPIO interface via mmap.
User space
GPIO mem
/dev/mem
Shared mem
GPIO
mmap
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
97
Ex1. GPIO programming (1)
• We will start programming with raw GPIO
interface with mmap.
• The physical address of GPIO is defined by
hardware
• We need a little includes
to use some Linux API.
#define BCM2708_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>Example is based on Dom and Gert from
http://elinux.org/RPi_Low-level_peripherals
RaspberryPi/apps/C/RPI/ex1_gpio.c
The address is 0x3f000000 on Pi 2.The address is 0x3f000000 on Pi 2.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
98
Ex1. GPIO programming (2)
• For mmap access, we prepare variables
and a constant.
• Now start the main
• /dev/mem is a device which content is the
memory data itself.
#define BLOCK_SIZE (4*1024)
int mem_fd;
volatile unsigned *gpio;
int main(int argc, char **argv)
{
int rep;
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem n");
exit(-1);
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
99
Ex1. GPIO programming (3)
• Now mmap the gpio address space.
/* mmap GPIO */
gpio = (volatile unsigned *)mmap(
NULL, //Any adddress in our space will do
BLOCK_SIZE, //Map length
PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
MAP_SHARED, //Shared with other processes
mem_fd, //File to map
GPIO_BASE //Offset to GPIO peripheral
);
close(mem_fd); //No need to keep mem_fd open after mmap
if (gpio == MAP_FAILED) {
printf("mmap error %dn", (int)gpio);//errno also set!
exit(-1);
}
Now gpio is a pointer to where the GPIO is mapped on the user space.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
100
Ex1. GPIO programming (4)
• Setup the ports direction with FSEL register.
– Each GPIO port occupy 3bit of FSEL register,
then we use octal number for convenience.
• For the input signal, we set pull up registers.
// Set gpio direction 0 is input, 1 is output.
*gpio = 01110010000; /* GPSEL0 GPIO 9- 0 */
*(gpio+1) = 00110110000; /* GPSEL1 GPIO 19-10 */
*(gpio+2) = 00000111100; /* GPSEL2 GPIO 29-20 */
*(gpio+37)= 2; /* GPPUD enable pull up */
*(gpio+38)= 0x0000000C; /* GPPUDCLK0 set GPIO 2,3 pull up clock */
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
101
Ex1. GPIO programming (5)
• The body of our program is turn on and off
the all LEDs on our board.
for(rep=0;rep<100;rep++) {
*(gpio+7)=0x03C6c390; /* GPSET0 turn on all LEDs */
printf("%08Xn", *(gpio+13)); /* GPLEV0 print the level value */
sleep(1);
*(gpio+10)=0x03C6c390; /* GPCLR0 turn off all LEDs */
printf("%08Xn", *(gpio+13)); /* GPLEV0 print the level value */
sleep(1);
}
return 0;
} // main
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
102
The memory mapped I/O
• We can use them via mmap.
timer
pwm
spi
i2c
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
103
Ex2. Timer programming (1)
• As GPIO, we can use system timer.
– This example will check the accuracy of sleep
time.
#define BCM2708_PERI_BASE 0x20000000
#define TIMER_BASE (BCM2708_PERI_BASE + 0x3000)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#define BLOCK_SIZE (4*1024)
int mem_fd;
volatile unsigned *timer;
RaspberryPi/apps/C/RPI/ex2_timer.c
The address is 0x3f000000 on Pi 2.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
104
Ex2. Timer programming (2)
• The basic structure is just the same
int main(int argc, char **argv)
{
int rep;
int timer_val;
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem n");
exit(-1);
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
105
Ex2. Timer programming (3)
• We use mmap to map system timer
timer = (volatile unsigned *)mmap(
NULL, //Any adddress in our space will do
BLOCK_SIZE, //Map length
PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
MAP_SHARED, //Shared with other processes
mem_fd, //File to map
TIMER_BASE //Offset to GPIO peripheral
);
close(mem_fd); //No need to keep mem_fd open after mmap
if (timer == MAP_FAILED) {
printf("mmap error %dn", (int)timer);//errno also set!
exit(-1);
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
106
Ex2. Timer programming (4)
• See the accuracy of sleep.
for(rep=0;rep<100;rep++) {
timer_val = *(timer+1);
sleep(1);
printf("sleep = %fn", (double)(*(timer+1)-timer_val)/1e6);
timer_val = *(timer+1);
sleep(1);
printf("sleep = %fn", (double)(*(timer+1)-timer_val)/1e6);
}
return 0;
} // main
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
107
Ex2. Timer programming (5)
• Check the accuracy of normal task and
real-time task.
– sudo ./ex2_timer.exe
– sudo chrt 1 ./ex2_timer.exe
Normal Real-time
We can get less jitter on
real-time task.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
108
Embedded Linux Programming with
wiringPi
• The wiringPi is an easy to use library for
RPi.
http://wiringpi.com
– This package provides convenient libraries and
tools to develop C applications on Raspberry
Pi.
– Make libraries on Cygwin
– Make Associated program on Cygwin and put it
on Raspberry Pi
– Make applications on Cygwin and put and run
on Raspberry Pi
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
109
Make your wiringPi application
• Change directory to ~/RaspberryPi/apps/C
• Make libraries and gpio command
– make lib gpio
• Copy your gpio binary to Raspberry Pi
– scp wiringPi/gpio/gpio pi@192.168.137.XX:
where XX depends on your environment.
• On Raspbery Pi, copy the gpio to
/usr/local/bin
– sudo cp gpio /usr/local/bin
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
110
WiringPi core functions
• At first your will have to include
WiringPi/WiringPi.h
– Initialize WiringPi
– Setup gpio
– application
wiringPiSetupGpio()
pinMode()
pullUpDncontrol()
wiringPiISR()
digitalRead()
digitalWrite()
There are many intializer
functions, but we only use
wiringPisetupGpio() functionl
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
111
wiringPiSetupGpio()
• This function must be called once before
any other wiringPi functions are called.
– You can also use virtual pin numbering with
wiringPiSetup(), but we will not discuss it.
int wiringPiSetupGpio(void);
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
112
Example: wpitest.c
#include <wiringPi.h>
#include <stdio.h>
#define LED0 4
#define SW1 3
int main (void)
{
wiringPiSetupGpio () ;
pinMode (LED0, OUTPUT) ;
pinMode (SW1, INPUT) ;
pullUpDnControl(SW1,PUD_UP);
for (;;) {
digitalWrite (LED0, 1-digitalRead(SW1)) ;
}
return 0 ;
}
RaspberryPi/apps/C/WPI/wpitest.c
$ cd ~/RaspberryPi/apps/C
$ make lib gpio
$ make WPI/wpitest.wpi
$ scp wiringPi/gpio/gpio pi@192.168.xxxx
$ scp WPI/wpitest.wpi pi@192.168.xxxx
$ ssh pi@192.168.xxxx
Pi$ sudo cp gpio /usr/local/bin
Pi$ sudo ./wpitest.wpi
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
113
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
114
Dive into the kernel
kernel modules for Raspberry Pi
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
115
Kernel modules and device
• There are many things that only kernel can
do. Therefore, we want to make kernel
modules to do them.
• Kernel modules must be compiled with the
same configuration and/or version of Linux
and its source with the target.
– In this seminar, we already have the Linux
source code that is compatible to the NOOBS
v1.4.0.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
116
Device access
• We will access devices via special file (ex.
/dev/console)
– The special file has two number (major and
minor) and block/character property to
designate a device
• The major number designates a device driver
• The minor number designates the functionality
– With the opened special file, we can use
read/write/ioctl/mmap etc.
• The pointers to the corresponding functions are
provided by a file_operations structure.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
117
file_operations
• Device can provide various file operations. The struct
file_operations is defined in linux/fs.h
The following is a part of the definition that is usable to
most of the device drivers.
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
};
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
118
Special file and device driver
/dev/foo
C, 3,1
1
2
3
255
1
2
3
255
cdevbdev struct file_operations for foo
open
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
119
Service call behavior
• Service call will change the privilege of the
process to kernel mode.
– Kernel mode can access to user space too.
User space kernel space
Service call (svc)
open()
Device driver
File descriptor
Service call (svc)
read() Read_routine()
Io space
User data
copy_to_user()
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
120
The kernel modules
• The kernel module is a mechanism which
extends the functionality of the Linux kernel
– The functions on the kernel module work as a
part of the Linux kernel.
Linux kernel
module
init_module()
cleanup_module()
file_operations
sys_init_module()
sys_delete_module()
read()
write()
ioctl()
mmap() Kernel
functions
variables
/proc/kallsyms
insmod
rmmod
User application
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
121
Module behavior
• System calls are redirected to the module
User space kernel space
Service call (svc)
open()
Device driver
File descriptor
Service call (svc)
read() Read_routine()
Io space
User data
copy_to_user()
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
122
How to make a module
• We need the same source of Linux kernel
on that the kernel module will be installed.
• You will also need Module.symvers, .config
Module
source
Kernel source
Module.symvers
.config
MakefileKbuild
gcc
module
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
123
Example : hello
• Our first module example is hello.c
To make the module, in the modules directory,
type
> make hello.ko
To install the module, copy the file to RPi and type
> sudo insmod hello.ko  on RPi.
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Naohiko Shimizu");
int init_module(void) { printk("Hello, worldn"); return 0; }
void cleanup_module(void) { printk("Goodbye worldn"); }
/home/RaspberryPi/modules/hello.c
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
124
Example : helloinit
• Our second module example is helloinit.c
This module is just like the previous one but
added some features.
#include <linux/module.h>
#include <linux/init.h>
static int dec=0;
static char* name="world";
module_param(dec, int, 0);
module_param(name, charp, 0);
int __init init_hello(void) { printk("Hello, %s(%d)n", name, dec); return 0; }
void __exit cleanup_hello(void) { printk("Goodbye %sn", name); }
module_init(init_hello);
module_exit(cleanup_hello);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Naohiko Shimizu");
/home/RaspberryPi/modules/helloinit.c
sudo insmod helloinit.ko name=someone dec=10
Parameters declaration
specify initialize function names
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
125
GPIO control from kernel
• On Raspberry Pi, GPIO pins are under the
pinctrl module’s control. You need to
request and free the pin for you.
int pinctrl_request_gpio (unsigned gpio)
void pinctrl_free_gpio (unsigned gpio)
int pinctrl_gpio_direction_input (unsigned gpio)
int pinctrl_gpio_direction_output (unsigned gpio)
• We will also use gpiolib functions
gpio_set_value (unsigned gpio, unsigned level)
gio_get_value (unsigned gpio)
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
126
Example : gpio
• This example shows how to use gpio.
> make gpio.ko
/home/RaspberryPi/modules/gpio.c
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/pinctrl/consumer.h>
#define LED 4
#define SW 2
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Naohiko Shimizu");
int ledlevel = 1;
int init_module(void) {
pinctrl_request_gpio(LED);
pinctrl_gpio_direction_output(LED);
gpio_set_value(LED,ledlevel);
pinctrl_request_gpio(SW);
pinctrl_gpio_direction_input(SW);
printk("Hello GPIO Pinctrl SW=%dn",
gpio_get_value(SW));
return 0;
}
void cleanup_module(void) {
pinctrl_free_gpio(LED);
pinctrl_free_gpio(SW);
printk("Goodbye GPIO Pinctrln");
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
127
Interrupt in Linux
• Device drivers will request IRQ and register
the callback function.
• The gpiolib will handle
each gpio’s irq.
kernel
Io device
IRQACK
Interrupt
distributer
Device
driver
callback
request_irqgpio_to_irq: get irq number from pin
request_irq: register interrupt function
free_irq: unregister interrupt
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
128
Example: hgpio
/home/RaspberryPi/modules/hgpio.c
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include “gpio_pud.h”
#define SW 2
#define LED 4
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Naohiko Shimizu");
void setup_gpio(void);
int ledlevel = 1;
static int irq;
long count = 0;
static irqreturn_t irq_sw(int irq,
void *dev_id, struct pt_regs *regs) {
ledlevel = 1 - ledlevel;
gpio_set_value(LED,ledlevel);
count++;
return IRQ_HANDLED;
}
int init_module(void) {
setup_gpio();
irq = gpio_to_irq(SW);
if(request_irq(irq,
(irq_handler_t) irq_sw,
IRQF_SHARED|IRQ_TYPE_EDGE_FALLING,
"GPIO SW INT",
THIS_MODULE->name)<0)
printk("request_irq failed");
return 0;
}
void cleanup_module(void) {
free_irq(irq,THIS_MODULE->name);
pinctrl_free_gpio(LED);
pinctrl_free_gpio(SW);
printk("Goodbye GPIO: IRQ %ld timesn",count);
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
129
Example: hgpio
/home/RaspberryPi/modules/hgpio.c
void setup_gpio(void){
pinctrl_request_gpio(LED);
pinctrl_gpio_direction_output(LED);
gpio_set_value(LED,ledlevel);
pinctrl_request_gpio(SW);
pinctrl_gpio_direction_input(SW);
gpio_pud(SW,PUD_UP);
gpio_pud(7,PUD_DOWN);
gpio_pud(8,PUD_DOWN);
gpio_pud(9,PUD_DOWN);
gpio_pud(4,PUD_DOWN);
}
#include <linux/gpio.h>
#include <linux/delay.h>
#include <asm/io.h>
#define PUD_UP 2
#define PUD_DOWN 1
#define PUD_OFF 0
#define GPIOUD(x) (0x94+(x)*4)
#define GPIOUDCLK(x) (0x98+(x)*4)
void gpio_pud(unsigned pin, int control) {
void __iomem *base;
base = __io_address(GPIO_BASE);
writel(control, base+GPIOUD(0));
udelay(5);
writel(1<<(pin%32), base+GPIOUDCLK(pin/32));
udelay(5);
writel(0, base+GPIOUD(0));
udelay(5);
writel(0<<(pin%32), base+GPIOUDCLK(pin/32));
}
/home/RaspberryPi/modules/gpio_pud.h
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
130
Deferred work
• Interrupt handler must return as fast as
possible not to lose other interrupts for
other handlers.
– The heavy process related to this interrupt must
be delayed with some method
• Tasklet
• Workqueue
• Timer
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
131
Tasklet
• Handlers can queue tasklets.
• Tasklets will be executed at the end of irq
service when each handler is finished.
interrupt
Interrupt
dispatcher
Deferred work
(soft irq)
Handler
A Handler
B
Handler
C
Tasklet
1
Tasklet
2
Tasklet
3
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
132
Example: hgpio_tl
/home/RaspberryPi/modules/hgpio_tl.c
void tasklet_hgpio(unsigned long data) {
int *p=(int*)data;
gpio_set_value(LED,*p);
*p = 1 - *p;
count++;
}
DECLARE_TASKLET( tl_body, tasklet_hgpio, (unsigned long)&ledlevel);
static irqreturn_t irq_sw(int irq, void *dev_id, struct pt_regs *regs) {
tasklet_schedule(&tl_body);
return IRQ_HANDLED;
}
• We will only show the modified lines from hgpio.c.
– The tasklet body function, declaration, invocation from
irq handler.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
133
Workqueue
• Handlers can queue works.
• Workqueues will be executed at a certain invocation timing
or kernel evend daemon for the system’s common queue.
interrupt
Interrupt
dispatcher
Handler
A Handler
B
Handler
C
workqueue
1
workqueue
2
workqueue
3
Some driver
Kernel
eventd
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
134
Example: hgpio_wq
/home/RaspberryPi/modules/hgpio_wq.c
void work_hgpio(struct work_struct *work) {
gpio_set_value(LED, ledlevel);
ledlevel = 1 - ledlevel;
count++;}
DECLARE_WORK(wq_body, work_hgpio);
static irqreturn_t irq_sw(int irq, void *dev_id, struct pt_regs *regs) {
schedule_work(&wq_body);
return IRQ_HANDLED;}
• We will only show the modified lines from hgpio.c.
– The workqueue body function, declaration, invocation
from irq handler and initialize of the data.
This example uses
schedule_work in
which structs are
invoked by kernel
event daemon.
If you need to pass some data
to the work, you need to use
an extended struct which
include struct work_struct.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
135
Timer
• Linux provides timers.
– Conventional timer is based on jiffies variable
– High resolution timer provides precise timing
– Timer block has parameter and callback
function.
Timer 1 Timer 2 Timer 3 Timer 4
Kernel timer interrupt
handler
Timer new
New timer is placed
at appropriate link.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
136
Example : timer
/home/RaspberryPi/modules/timer.c
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/gpio.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Naohiko Shimizu");
#define LED 4
static int advance = 100;
struct timer_list timer_x;
int led = 0;
void timer_timeout(unsigned long arg)
{
led = 1 - led;
gpio_set_value(LED,led);
timer_x.expires = jiffies +
msecs_to_jiffies(advance);
add_timer(&timer_x);
}
int init_module(void) {
printk("Hello timern");
pinctrl_request_gpio(LED);
pinctrl_gpio_direction_output(LED);
init_timer(&timer_x);
timer_x.function = timer_timeout;
timer_x.expires = jiffies +
msecs_to_jiffies(advance);
add_timer(&timer_x);
return 0;
}
void cleanup_module(void) {
pinctrl_free_gpio(LED);
del_timer(&timer_x);
printk("Goodbye timern");
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
137
Example : hrtimer
/home/RaspberryPi/modules/hrtimer.c
#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/gpio.h>
#define LED 4
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Naohiko Shimizu");
static int ledlevel = 1;
struct hrtimer hrt;
ktime_t kt;
int count = 2000;
enum hrtimer_restart
timer_timeout(struct hrtimer *timer)
{
ledlevel = 1 - ledlevel;
gpio_set_value(LED,ledlevel);
if(count) {
count--;
hrtimer_forward_now(timer,kt);
return HRTIMER_RESTART;
}
return HRTIMER_NORESTART;
}
int init_module(void) {
printk("Hello timern");
pinctrl_request_gpio(LED);
pinctrl_gpio_direction_output(LED);
gpio_set_value(LED,ledlevel);
kt=ktime_set(0,100000000UL);
hrtimer_init(&hrt, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
hrt.function = timer_timeout;
hrtimer_start(&hrt,kt,
HRTIMER_MODE_REL);
return 0;
}
void cleanup_module(void) {
pinctrl_free_gpio(LED);
hrtimer_cancel(&hrt);
printk("Goodby timern");
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
138
procfs
• Linux provides a convenient method to
observe the kernel status by user.
– One of them is the procfs which will provide
observation points at /proc/
– The obervation points can be hierarchical.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
139
Example: hgpio_proc
/home/RaspberryPi/modules/hgpio_proc.c
#include <linux/fs.h>
#include <linux/proc_fs.h>
struct proc_dir_entry *p;
static int proc_show_gpio(struct seq_file *m, void *data) {
seq_printf(m, "gpio count=%d n", count);
return 0; }
static int proc_open_gpio(struct inode *id, struct file *file) {
return single_open(file, proc_show_gpio, NULL); }
static const struct file_operations proc_fops = {
.owner = THIS_MODULE,
.open = proc_open_gpio,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
• We will only show the modified lines from hgpio.c
You can see /proc/proc_gpio
entry on your RPi.
cat /proc/proc_gpio
will show the number of
interrupts.
int init_module(void) {
p=proc_create("proc_gpio", S_IRUGO,
NULL, &proc_fops);
void cleanup_module(void) {
remove_proc_entry("proc_gpio", NULL);
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
140
sysctl
• Linux provides a convenient method to
observe or modify the kernel status by user.
– The sysctl will provide observation points at
/proc/sys
– You can use ‘cat’ to show the value, and ‘echo’
to set the value on the variables.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
141
Example: hgpio_sysctl
/home/RaspberryPi/modules/hgpio_sysctl.c
##include <linux/fs.h>
#include <linux/sysctl.h>
static struct ctl_table proctest_table[] = {
{"ledlevel", &ledlevel, sizeof(int),
S_IRUGO|S_IWUSR, NULL, &proc_dointvec, NULL,
NULL},
{"count", &count, sizeof(int), S_IRUGO|S_IWUSR,
NULL, &proc_dointvec, NULL, NULL},
{0}
};
static struct ctl_table sys_table[] = {
{"hgpio_sysctl", NULL, 0, S_IXUGO|S_IRUGO,
proctest_table, NULL, NULL},
{0}
};
struct ctl_table_header *s;
• We will only show the modified lines from hgpio.c
You can see
/proc/sys/hgpio_sysctl entry
on your RPi.
You can get value by cat
comnad, and put value with
echo (super user only)
int init_module(void) {
s=register_sysctl_table(sys_table);
void cleanup_module(void) {
unregister_sysctl_table(s);
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
142
• Register the operations
• Access via a special file
Device access
conventional method
register_chrdev()
struct file_operations {
.read=
.write=
}
User application
open()
read()
write()
close()
special file
Major number
Module functions
Kernel/module
file
descriptor
Make the special file
with ‘mknod’ command
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
143
Example : device
/home/RaspberryPi/modules/device.c
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Naohiko Shimizu");
#define LED 4
static int led = 0;
static ssize_t led_read(struct file *f, char __user
*buf, size_t len, loff_t *off) {
printk("buf = %p",buf);
copy_to_user(buf, (void*)&led, (len>4)?4:len);
return (len>4)?4:len;
}
static ssize_t led_write(struct file *f, const char
__user *buf, size_t len, loff_t *off) {
printk("buf = %p",buf);
copy_from_user((void*)&led, buf,
(len>4)?4:len);
gpio_set_value(LED,led&1);
return (len>4)?4:len;
}
static struct file_operations LED_fops =
{
.owner = THIS_MODULE,
.read = led_read,
.write = led_write
};
static int maj;
int init_module(void) {
printk("Hello devicen");
pinctrl_request_gpio(LED);
pinctrl_gpio_direction_output(LED);
maj = register_chrdev(0, "device", &LED_fops);
if(maj < 0) {printk("Could not get majorn");
return -1;}
printk("major = %dn", maj);
return 0;
}
void cleanup_module(void) {
pinctrl_free_gpio(LED);
if(maj) unregister_chrdev(maj, "device");
printk("Goodbye devicen");
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
144
Example : device usage
/home/RaspberryPi/modules/device_ua.c
#include <stdio.h>
#include <fcntl.h>
int main(int argc, char *argv[]) {
int led, fd, i;
if(argc<3) {
printf("Usage sudo ./device_ua.exe
device_file valuen");
return 1; }
fd=open(argv[1],O_RDWR);
if(fd<0) return 1;
read(fd,&led,4);
printf("current LED=%dn",led);
led=atoi(argv[2]);
for(i=0;i<10;i++) {
write(fd,&led,4);
sleep(1);
led=1-led; }
return 0;
}
On Raspberry Pi,
sudo insmod device.ko
dmesg
sudo mknod device c XXX 0
sudo ./device_ua device 1
Where XXX is the major number of device,
which can be confirmed with ‘dmesg’
command.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
145
• Automatically generate
special file and variable
Device access
sysfs method
alloc_chrdev_region()
class_create()
device_create()
cdev_init()
cdev_add()
device_create_file()
struct file_operations {
.read=
.write=
}
User application
open()
read()
write()
close()
special file
Module functions
Kernel/module
file
descriptor
special variable
/sys/class/foo/foo/var
User operations
cat
echo
DEVICE_ATTR
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
146
Example : device and class
/home/RaspberryPi/modules/class.c
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Naohiko Shimizu");
#define LED 4
static int advance = 100;
struct timer_list timer_x;
int led = 0;
void timer_timeout(unsigned long arg) {
led = 1 - led;
gpio_set_value(LED,led);
timer_x.expires = jiffies + msecs_to_jiffies(advance);
add_timer(&timer_x);}
static ssize_t callback(struct device *dev,struct device_attribute
*attr, const char *buf, size_t count) {
long value;
if(kstrtol(buf,10,&value) < 0) return -EINVAL;
advance = value;
del_timer(&timer_x);
add_timer(&timer_x);
return count;}
DEVICE_ATTR(period,0220,NULL,callback);
static struct class *sClass;
static struct device *sDevice;
static struct cdev c_dev;
static dev_t dev;
static ssize_t led_read(struct file *f, char __user *buf, size_t
len, loff_t *off){
printk("buf = %p",buf);
copy_to_user(buf, (void*)&advance, (len>4)?4:len);
del_timer(&timer_x);
add_timer(&timer_x);
return (len>4)?4:len;}
static ssize_t led_write(struct file *f, const char __user *buf,
size_t len, loff_t *off){
printk("buf = %p",buf);
copy_from_user((void*)&advance, buf, (len>4)?4:len);
del_timer(&timer_x);
add_timer(&timer_x);
return (len>4)?4:len;}
static struct file_operations LED_fops =
{
.owner = THIS_MODULE,
.read = led_read,
.write = led_write
};
To be continued
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
147
Example : device and class
/home/RaspberryPi/modules/class.c
int init_module(void) {
printk("Hello timern");
pinctrl_request_gpio(LED);
pinctrl_gpio_direction_output(LED);
init_timer(&timer_x);
timer_x.function = timer_timeout;
timer_x.expires = jiffies + msecs_to_jiffies(advance);
add_timer(&timer_x);
alloc_chrdev_region(&dev, 0, 1, "LED");
sClass = class_create(THIS_MODULE, "LED");
sDevice = device_create(sClass,NULL,dev,NULL,"LED");
cdev_init(&c_dev, &LED_fops);
cdev_add(&c_dev, dev, 1);
device_create_file(sDevice,&dev_attr_period);
return 0;
}
void cleanup_module(void) {
pinctrl_free_gpio(LED);
del_timer(&timer_x);
cdev_del(&c_dev);
device_remove_file(sDevice,&dev_attr_period);
device_destroy(sClass,dev);
class_destroy(sClass);
unregister_chrdev_region(dev,1);
printk("Goodbye timern");
}
To make our life simple we will be the super user.
$ sudo –s
# insmod class.ko
# echo 2000 > /sys/class/LED/LED/period
# ls –l /dev/LED
crw------- 1 root root 246, 0 Feb 28 06:25 /dev/LED
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
148
Memory mapping
• To avoid the system call overhead, we can
use mmap to map the physical memory to
the user virtual address space.
Device registers on
physcal memory
Device registers mapped
on user virtual memory
Physical space
User virtual
space
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
149
Example : mmap
/home/RaspberryPi/modules/mmap.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Naohiko Shimizu");
void* mmap_area=0;
char* mmap_vm;
void vma_open(struct vm_area_struct *vma) {
printk(KERN_NOTICE "mmap open. virt : %lx,
phys : %lxn ", vma->vm_start
, vma->vm_pgoff << PAGE_SHIFT); }
void vma_close(struct vm_area_struct *vma) {
printk(KERN_NOTICE "mmap close.n"); }
static struct vm_operations_struct remap_vm_ops = {
.open = vma_open,
.close = vma_close,
};
static int remap_mm(struct file *filp, struct vm_area_struct
*vma) {
vma->vm_flags |= VM_IO;
vma->vm_pgoff =
virt_to_phys(mmap_area)>>PAGE_SHIFT;
if(remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
vma->vm_ops = &remap_vm_ops;
vma_open(vma);
return 0;}
static struct file_operations mmap_fops = {
mmap: remap_mm,
};
static dev_t dev;
static struct class *sClass;
static struct device *sDevice;
static struct cdev c_dev;
To be continued
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
150
Example : mmap
/home/RaspberryPi/modules/mmap.c
int init_module(void) {
mmap_area=(void*)__get_free_page(GFP_KERNEL);
*(int*)(mmap_area)=0x12345678;
printk("Hello mmap(%p)n",(void*)mmap_area);
alloc_chrdev_region(&dev,0,1,"mmap_test");
sClass=class_create(THIS_MODULE,"Mmap");
sDevice=device_create(sClass,NULL,dev,NULL,"Mma
p");
cdev_init(&c_dev, &mmap_fops);
cdev_add(&c_dev, dev, 1);
return 0;
}
void cleanup_module(void) {
printk("Goodbye mmapn");
cdev_del(&c_dev);
device_destroy(sClass,dev);
class_destroy(sClass);
unregister_chrdev_region(dev,1);
free_page((unsigned int)mmap_area);
}
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char**argv) {
int fd, i;
int *buffer;
fd=open("/dev/Mmap",O_RDWR);
printf("open fd(%d)n",fd);
if(argc>1) { buffer=(int*)mmap(NULL, 0x1000,
PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
printf("buffer address=%pn",buffer);
for(i=1;i<argc;i++) {
buffer[i-1]=atoi(argv[i]); } }
else
buffer=(int*)mmap(NULL,0x1000,PROT_READ,
MAP_PRIVATE,fd,0);
msync(buffer,0x1000,MS_SYNC);
for(i=0;i<10;i++) { printf("buff[%d]=%08xn", i,
buffer[i]); }
return(0);
}
User routine
mmaptest.c
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
151
Rapid prototyping with Python
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
152
Python basics
• Python was designed by Guido van Rossum in
90’s.
• Easy to use
– Simple syntax
– interpreter
– The variables does not have type but the object has.
– Comprehensive standard library
• Cross platform
• Free
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
153
Python introduction
• Values
• Data types
– int, float, bool, str
– list, tuple, set, dictionary
• Operators
• Controls
• Functions
• Classes
• Modules
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
154
Values
• Integer
– Binary number : 0b1100
– Octal number: 0o71
– Hex decimal number: 0x2f
– Decimal number: 12345678901234567901234
• Float
– 3.14e-1
– 1.435
• Complex number
– 1+3j
• Boolean
– True, False
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
155
Data types
• The int type represents an integer. Unlike C
or Java, Python’s integer does not have
fixed bit size, but can be unlimited digit.
• The float type represents a floating point
number. It is just same as C’s double
precision number
• The bool is a Boolean type.
• The str type is a string of characters.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
156
Example
• Invoke python3 with python3 command
> python3
• Try to print any data with print() command
>>> print(3.14)
3.14
>>> print(123456789012345678901234567890)
123456789012345678901234567890
>>> print(True)
True
>>> print(‘abc def’)
abc def
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
157
Data types - continue
• The list is a sequence of data in brackets
[1,”x”,[1,2,3],True]
• The tuple is also a sequence of data in
parentheses. Unlike lists, it cannot be changed.
(2,”F”,0)
• The dictionary is an association structure in
braces.
{“key1”:”value1”,”key2”:”value2”}
• The set is a set of data in braces.
{‘2’, ‘5’, ‘9’}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
158
Example
• Try to print the values on Python
>>> print([1,”x”,[1,2,3],True])
[1, 'x', [1, 2, 3], True]
>>> print((2,”F”,0))
(2, 'F', 0)
>>> print({“key1”:”value1”,”key2”:”value2”})
{'key2': 'value2', 'key1': 'value1'}
>>> print({‘2’, ‘5’, ‘9’})
{'9', '5', '2'}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
159
Operators(1)
• Numerical/comparison operators
• Boolean operators
+ Addition
- Subtraction
* Multiplication
// Division
% Remainder
/ Division (float)
** To the power
int() Convert to integer
float() Convert to float
< Less than
> Greater than
== Equal
<= Less than or Equal to
>= Greater than or Equal to
!= Not equal to
and
or
not
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
160
Example
• Try to use operators for values
>>> print(10/3)
3.3333333333333335
>>> print(10//3)
3
>>> print(0b11000011 | 0x3c)
255
>>> print(10 or 30)
10
>>> print(5 and 10)
10
>>> print((0+1j)**2)
(-1+0j)
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
161
Operators(2)
• String operators
String[x] Get the xth character
String[x:y] Get substring from xth to yth
String[:y] Get substring to yth
String[x:] Get substring from xth to the end
len(string) Return the length of the string
String+string Join two strings
str(expression) Convert to string
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
162
Example
>>> 'abcdefg'[1]
'b'
>>> 'abcdefg'[1:4]
'bcd'
>>> 'abcdefg'[:3]
'abc'
>>> 'abcdefg'[5:]
'fg'
>>> len('abcdefg')
7
>>> 'abc'+'hij'
'abchij'
>>> str(3+2j)
'(3+2j)'
>>> str((3+2j)**2)
'(5+12j)'
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
163
Operators and methods(3)
• List
List[i] return the ith elements of the list
len(list) Return the number of the element inside
+ Return the merged list
*num Repeat the list num times
item in List Return whether item is in the List or not
List.appned(item) Add item to the end of the list
List.extend(list2) Join the list2 to the end of the list
List.pop(x) Return and remove the xth item
List.insert(x,item) Insert item at the xth position
List.sort() Sort the list
List.index(item) Return the position of the first occurrence of item
List.count(item) Count how many items are in list
List.remove(item) Remove the first occurrence of item
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
164
Example
>>> [1,2,3,4][2]
3
>>> len([1,2,3,4])
4
>>> [1,2,3,4]+[5,6]
[1, 2, 3, 4, 5, 6]
>>> [1,2]*3
[1, 2, 1, 2, 1, 2]
>>> 2 in [1,2,3,4]
True
>>> 5 in [1,2,3,4]
False
>>> [1,2,3,4].pop(3)
4
>>> [1,2,3,4].count(3)
1
>>> [1,2,3,4].index(3)
2
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
165
Operators and methods(4)
• Dictionary
• Set
Dict[key] Return the value of the dictionary item with key
key in Dict Return whether key is in Dict or not
Dict.keys() Get the view of the Dict
del Dict[key] Remove the data associated with key in Dict
Set1 & Set2 Return the intersection of sets
Set1 | Set2 Return the union of sets
Set1 – Set2 Return the difference of sets
Set1 ^ Set2 Return the symmetric difference
x in Set Return whethere x is in Set or not
Set1 <= Set2 Return whether Set1 is the subset of Set2 or not
Set1 >= Set2 Return whether Set1 is the superset of Set2 or not
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
166
Example
>>> {'abc':1, 'def':2, 'hij':3}['hij']
3
>>> 'def' in {'abc':1, 'def':2, 'hij':3}
True
>>> {'abc':1, 'def':2, 'hij':3}.keys()
dict_keys(['hij', 'abc', 'def'])
>>> {1,2,3} & {2,3,4}
{2, 3}
>>> {1,2,3} | {2,3,4}
{1, 2, 3, 4}
>>> {1,2,3} - {2,3,4}
{1}
>>> {1,2,3} ^ {2,3,4}
{1, 4}
>>> 3 in {1,2,3}
True
>>> {1,2,3} <= {1,5,4,3,2}
True
>>> {1,2,3} >= {1,2}
True
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
167
Controls
• while condition: loop while condition is
true
• for i in range(1,10): loop i for the set of
items. Item can be list, set, etc.
• if condition: selective execution
elif condtion2:
else:
• try: Catching exceptions
except type_of_error:
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
168
Type of Errors on Python
• There are many exceptions which will be
raised on Python
– See the python document for detail:
https://docs.python.org/3/library/exceptions.htm
l
– Commonly used exceptions:
SystemExit, KeyboardInterrupt ,
ArithmeticError, OverflowError,
ZeroDivisionError, EOFError, LookupError,
FileExistsError, FileNotFoundError,
PermissionError, TypeError , ValueError
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
169
Example
>>> i=0
>>> while i<10:
... print(i)
... i=i+1
...
0
1
2
3
4
5
6
7
8
9
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
170
Example
>>> for i in [1,5,6]:
... print(i)
...
1
5
6
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
171
Example
>>> if 2 in [1,5,6]:
... print(True)
... elif 5 in [1,5,6]:
... print("ELIF")
... else:
... print(False)
...
ELIF
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
172
Example
>>> try:
... 1/0
... except ZeroDivisionError:
... print("Zero Division Error")
...
Zero Division Error
>>> try:
... 1/1
... except ZeroDivisionError:
... print("Zero Division Error")
...
1.0
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
173
Functions
• def func_name(parameters): defines
function. Parameters can have default
values.
– Any new variables in functions are treated as
local. If you want to access to global variables,
you need designate ‘global’ explicitly.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
174
Example
>>> def foo(a):
... return(a+1)
...
>>> foo(3)
4
>>> def foo2(x=1):
... return(x**2)
...
>>> foo2()
1
>>> foo2(4)
16
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
175
Classis
• class class_name():
def __init__(self, parameters):
self.parameters = parameters;
def own_method(self):
self.parameters = self.parameters +1
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
176
Example
>>> class cfoo():
... def __init__ (self, p1):
... self.p1 = p1
... def myfunc(self):
... self.p1 = self.p1**2
... def myget(self):
... return(self.p1)
...
>>> a=cfoo(10)
>>> a.myget()
10
>>> a.myfunc()
>>> a.myget()
100
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
177
Modules
• You can make a file ‘foo.py’ which contains
any definitions of functions or classes or
variables. You can import the file with
import command.
import foo
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
178
Example
• Make a file which name is foo.py and make
the content as
print("foo imported")
• Invoke python3 and type “import foo”
>>> import foo
foo imported
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
179
Time on Python
• The time module provides the method for time.
– time.monotonic(): Return the value (in fractional seconds) of a
monotonic clock, i.e. a clock that cannot go backwards. The clock
is not affected by system clock updates. The reference point of the
returned value is undefined, so that only the difference between
the results of consecutive calls is valid.
– time.sleep(secs): Suspend execution of the calling thread for the
given number of seconds. The argument may be a floating point
number to indicate a more precise sleep time. The actual
suspension time may be less than that requested because any
caught signal will terminate the sleep() following execution of that
signal’s catching routine. Also, the suspension time may be longer
than requested by an arbitrary amount because of the scheduling
of other activity in the system.
– time.ctime([secs]): Convert a time expressed in seconds since the
epoch to a string representing local time. If secs is not provided or
None, the current time as returned by time() is used. ctime(secs) is
equivalent to asctime(localtime(secs)). Locale information is not
used by ctime().
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
180
Threading on Python
• The threading module will provide to control
multiple threading. You can start and join
threads.
import threading as t
import time
def thr(Name, value):
print(Name+":"+str(value)+" "+time.ctime())
time.sleep(value)
print(Name+" end sleep "+time.ctime())
quit()
t1=t.Thread(target=thr,args=("1st",10))
t2=t.Thread(target=thr,args=("2nd",5))
t1.start()
t2.start()
t1.join()
t2.join()
Thread.py
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
181
Timer on Python
• We will use the timer funciton in threading
package.
– threading.Timer can designate an activation
time in seconds and a call back thread
import threading
def cb():
print(“called”)
quit()
t=threading.Timer(10,cb)
t.start()
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
182
Interval timer module making
• The threading module does not provide
interval timer functionality. So I wrote my
module which provides one by myself.
• Extract and install it
– Send PyTimer-0.1.tar.bz2 to Raspberry Pi
– Then type following commands on Pi
> tar xjvf PyTimer-0.1.tar.bz2
> cd PyTimer-0.1
> python3 setup.py install
– You will get PyTimer module on Pi
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
183
PyTimer methods
• There are four method on PyTimer
– Create : Create an interval timer and designate
the callback function
– Delete : Delete the timer
– Gettime : Get the remaining time of the timer
and the interval
– Settime : Set the timer value and start it
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
184
PyTimer module methods(create)
• Create a new timer
• PyTimer.create(clockid, [callback]) : timerid
– Clockid can be PyTimer.CLOCK_REALTIME,
PyTimer.CLOCK_MONOTONIC, etc.
• Cygwin only support CLOCK_REALTIME
– Callback designate to the method for callback.
It is optional parameter
– The method returns the timerid created
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
185
PyTimer module methods(delete)
• Delete an existing timer
• PyTimer.delete(timerid)
– The timerid must be one that PyTimer.create()
returned.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
186
PyTimer module methods(gettime)
• Get the timer value of an existing timer
• PyTimer.gettime(timerid) : (remain, interval)
– The timerid must be one that PyTimer.create()
returned.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
187
PyTimer module methods(settime)
• Set the timer value and start timer
• PyTimer.settime(timerid,start,[period],[flag])
– The timerid must be one that PyTimer.create()
returned.
– The start designate the start value of the timer
– The period designate the interval of the timer.
Optional
– The flag designate where the start time is the
absolute (wall clock) time or not. Set
TIMER_ABSTIME for wall clock.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
188
Try the PyTimer on LiveCygwin
• Try followings.
 python3
>>> import PyTimer
>>> t=PyTimer.create(PyTimer.CLOCK_REALTIME)
>>> PyTimer.settime(t,1000)
>>> print(PyTimer.gettime(t))
>>> print(PyTimer.gettime(t))
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
189
Excersize
• Make a python program which print time
and date every 15 seconds. It must be
terminated safely with keyboard interrupt
(Control-C).
• Make a python program for keyboard typing
training and evaluate the user skill with
WPS(Words Per Seconds)
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
190
Writing Python module with C
• If your project needs more functionality on
Python, you can make a extension module
with C
– Make a simple Python module with C
– Compile and use with Python
– Test the module with PyUnit (unittest)
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
191
Make a simple Python module with
C
• How Python can find your module(pyfoo)?
– Prepare PyModuleDef and/or PyMethodDef
struct
– Special initialize function with the module name
will be called with above struct.
• Python3: PyInit_pyfoo
• Python2. X:Initpyfoo
– Write your own methods
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
192
Method writing (1)
#include "Python.h“
// python function foo(arg, oparg)
static PyObject *py_foo(PyObject *self, PyObject *args, PyObject *kwargs)
{
double arg, oparg=-1;
static char *kwlist[] = {"arg", "oparg", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d|d", kwlist, &arg, &oparg))
return NULL;
return Py_BuildValue("(dd)", arg, oparg);
}
RaspberryPi/apps/Python/pyfoo/pyfoo.c
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
193
Method writing (2)
// python function goo(arg)
static PyObject *py_goo(PyObject *self, PyObject *args)
{
int arg;
if (!PyArg_ParseTuple(args, "i", &arg))
return NULL;
switch(arg)
{
case 0: return Py_BuildValue("s", "arg=0");
case 1: PyErr_SetString(PyExc_RuntimeError, "arg==1");
return NULL;
case 2: PyErr_SetString(PyExc_ValueError, "arg==2");
return NULL;
case 3: PyErr_SetString(PyExc_BaseException, "arg==3");
return NULL;
case 4: PyErr_SetString(PyExc_StandardError, "arg==4");
return NULL;
case 5: PyErr_SetString(PyExc_OSError, "arg==5");
return NULL;
default: break;
}
Py_RETURN_NONE;
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
194
Module definition example
static const char moduledocstring[] = "pyfoo functions";
static PyMethodDef pyfoo_methods[] = {
{"foo", (PyCFunction)py_foo, METH_VARARGS | METH_KEYWORDS,
"foo - function1narg - argumentn
[oparg] - optional argumentn"},
{"goo", (PyCFunction)py_goo, METH_VARARGS,
"goo - function2narg - argument
"},
{NULL, NULL, 0, NULL}
};
#if PY_MAJOR_VERSION > 2
static struct PyModuleDef pyfoomodule = {
PyModuleDef_HEAD_INIT,
"pyfoo", // name of module
moduledocstring, // module documentation, may be NULL
-1, // size of per-interpreter state of the module, or -1 if the module keeps s
tate in global variables.
pyfoo_methods
};
#endif
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
195
Module initialize
#if PY_MAJOR_VERSION > 2
PyMODINIT_FUNC PyInit_pyfoo(void)
#else
PyMODINIT_FUNC initpyfoo(void)
#endif
{
PyObject *module = NULL;
#if PY_MAJOR_VERSION > 2
if ((module = PyModule_Create(&pyfoomodule)) == NULL)
return NULL;
#else
if ((module = Py_InitModule("pyfoo", pyfoo_methods)) == NULL)
return;
#endif
if (!PyEval_ThreadsInitialized())
PyEval_InitThreads();
#if PY_MAJOR_VERSION > 2
return module;
#else
return;
#endif
}
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
196
Compile module
• On cygwin, target module must be DLL
On RaspberryPi/apps/Python/pyfoo directory,
gcc --shared -I/usr/include/python2.7 pyfoo.c -
lpython2.7 -o pyfoo.dll
Or
gcc --shared -I/usr/include/python3.4m pyfoo.c -
lpython3.4m -o pyfoo.dll
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
197
Import the module and run
• Run python
>>> import pyfoo
>>> pyfoo.foo(3,oparg=5)
(3.0, 5.0)
>>> pyfoo.foo(oparg=5,arg=3)
(3.0, 5.0)
>>> pyfoo.foo(2,3)
(2.0, 3.0)
>>> pyfoo.goo(0)
'arg=0'
>>> pyfoo.goo(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: arg==1
>>> pyfoo.goo(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: arg==2
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
198
Test your module with PyUnit(1)
• Make your test script with PyUnit as test.py
import unittest
import pyfoo
class TestFoo(unittest.TestCase):
def test_foo1(self):
"""Test foo with 1 argument"""
self.assertEqual(pyfoo.foo(400), (400.0,-1.0))
def test_foo2(self):
"""Test foo with 2 argument"""
self.assertEqual(pyfoo.foo(3,5), (3.0,5.0))
def test_fook1(self):
"""Test foo with 1 keyword argument"""
self.assertEqual(pyfoo.foo(arg=3), (3.0,-1.0))
def test_fook2(self):
"""Test foo with 2 keyword argument"""
self.assertEqual(pyfoo.foo(oparg=10, arg=3), (3.0,10.0))
def test_goo0(self):
"""Test goo(0)"""
self.assertEqual(pyfoo.goo(0), 'arg=0')
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
199
Test your module with PyUnit(2)
def test_over_goo1(self):
"""Test goo(1)"""
with self.assertRaises(RuntimeError):
pyfoo.goo(1)
def test_over_goo2(self):
"""Test goo(2)"""
with self.assertRaises(ValueError):
pyfoo.goo(2)
def test_over_goo3(self):
"""Test goo(3)"""
with self.assertRaises(BaseException):
pyfoo.goo(3)
def test_over_goo4(self):
"""Test goo(4)"""
with self.assertRaises(StandardError):
pyfoo.goo(4)
def test_over_goo5(self):
"""Test goo(5)"""
with self.assertRaises(OSError):
pyfoo.goo(5)
def test_over_goo6(self):
"""Test goo(6)"""
self.assertIsNone(pyfoo.goo(6))
if __name__ == '__main__':
unittest.main()
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
200
Test your module with PyUnit(3)
• Run the test
$ python -m unittest test
...........
----------------------------------------------------------------------
Ran 11 tests in 0.001s
OK
$
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
201
Exercise
• Read PyTimer source code and discuss
how it works.
• Make a python module with C and test it
which provides
– Fibonacci function
– Dynamic display on 7 segments LEDs
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
202
Python for RaspberryPi
• We will use Rpi GPIO package to control
RaspberryPi with Python
– GPIO
– PWM
– Interrupts
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
203
RPi.GPIO Objects
• Port voltage level
– HIGH: high level
– LOW: low level
• Port direction
– OUT: output
– IN: input
• Pin number scheme
– BOARD: --
– BCM: ARM chip pin number
• GPIO pull up/down control
– PUD_OFF: pull up/down off
– PUD_UP: pull up
– PUD_DOWN: pull down
• GPIO edge detect
– RISING: GPIO risign edge
– FALLING: GPIO falling edge
– BOTH: GPIO both edge
• Pin function
– HARD_PWM: hardware PWM
– SERIAL: uart
– I2C: I2C
– SPI: SPI
– UNKNOWN: unknown function
• VERSION
• RPI_REVISION
• RPI_INFO
• PWM: PWM control objects
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
204
RPi.GPIO Method
• GPIO method
– setup
– cleanup
– output
– input
– setmode
– getmode
– add_event_detect
– remove_event_detect
– event_detected
– add_event_callback
– wait_for_edge
– gpio_function
– setwarnings
• PWM method
– Start
– ChangeDutyCycle
– ChangeFrequency
– stop
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
205
RPi.GPIO Method: setup
• Set up a GPIO channel or list of channels
with a direction and (optional) pull/up down
control channel - either board pin number or
BCM number depending on which mode is
set.
– direction - IN or OUT
– [pull_up_down] - PUD_OFF (default), PUD_UP
or PUD_DOWN
– [initial] - Initial value for an output channel
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
206
RPi.GPIO Method: cleanup
• Clean up by resetting all GPIO channels
that have been used by this program to
INPUT with no pullup/pulldown and no
event detection
– [channel] - individual channel or list/tuple of
channels to clean up. Default - clean every
channel that has been used.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
207
RPi.GPIO Method: output
• Output to a GPIO channel or list of
channels
– channel - either board pin number or BCM
number depending on which mode is set.
– value - 0/1 or False/True or LOW/HIGH
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
208
RPi.GPIO Method: input
• Input from a GPIO channel.
Returns HIGH=1=True or LOW=0=False
– channel - either board pin number or BCM
number depending on which mode is set.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
209
RPi.GPIO Method: setmode
• Set up numbering mode to use for
channels.
– BOARD - Use Raspberry Pi board numbers
– BCM - Use Broadcom GPIO 00..nn numbers
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
210
RPi.GPIO Method: getmode
• Get numbering mode used for channel
numbers.
– Returns
BOARD, BCM or UNKNOWN
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
211
RPi.GPIO Method:
add_event_detect
• Enable edge detection events for a
particular GPIO channel.
– channel - either board pin number or BCM
number depending on which mode is set.
– edge - RISING, FALLING or BOTH
– [callback] - A callback function for the event
(optional)
– [bouncetime] - Switch bounce timeout in ms for
callback
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
212
RPi.GPIO Method:
remove_event_detect
• Remove edge detection for a particular
GPIO channel
– channel - either board pin number or BCM
number depending on which mode is set.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
213
RPi.GPIO Method: event_detected
• Returns True if an edge has occured on a
given GPIO. You need to enable edge
detection using add_event_detect() first.
– channel - either board pin number or BCM
number depending on which mode is set.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
214
RPi.GPIO Method:
add_event_callback
• Add a callback for an event already defined
using add_event_detect()
– channel - either board pin number or BCM
number depending on which mode is set.
– callback - a callback function
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
215
RPi.GPIO Method: wait_for_edge
• Wait for an edge.
– channel - either board pin number or BCM
number depending on which mode is set.
– edge - RISING, FALLING or BOTH
– [bouncetime] - time allowed between calls to
allow for switch bounce
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
216
RPi.GPIO Method: gpio_function
• Return the current GPIO function (IN, OUT,
PWM, SERIAL, I2C, SPI)
– channel - either board pin number or BCM
number depending on which mode is set.
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
217
RPi.GPIO Method: setwarnings
• Enable or disable warning messages
– value - 0/1 or False/True or LOW/HIGH
Copyright (c) 2015 Naohiko Shimizu, All rights reserved
218
PWM Method
• start : Start software PWM
– dutycycle - the duty cycle (0.0 to 100.0)
• ChangeDutyCycle: Change the duty cycle
– dutycycle - between 0.0 and 100.0
• ChangeFrequency: Change the frequency
– frequency - frequency in Hz (freq > 1.0)
• stop: Stop software PWM
Raspberry Pi Embedded Linux and Python Prototyping Workshop
Raspberry Pi Embedded Linux and Python Prototyping Workshop
Raspberry Pi Embedded Linux and Python Prototyping Workshop

More Related Content

What's hot

PiFlash: Linux utility to flash SD cards for Raspberry Pi computers
PiFlash: Linux utility to flash SD cards for Raspberry Pi computersPiFlash: Linux utility to flash SD cards for Raspberry Pi computers
PiFlash: Linux utility to flash SD cards for Raspberry Pi computersIan Kluft
 
都立大「ユビキタスロボティクス特論」5月12日
都立大「ユビキタスロボティクス特論」5月12日都立大「ユビキタスロボティクス特論」5月12日
都立大「ユビキタスロボティクス特論」5月12日NoriakiAndo
 
Yocto Project introduction
Yocto Project introductionYocto Project introduction
Yocto Project introductionYi-Hsiu Hsu
 
200519 TMU Ubiquitous Robot
200519 TMU Ubiquitous Robot200519 TMU Ubiquitous Robot
200519 TMU Ubiquitous RobotNoriakiAndo
 
Introduction to Raspberry Pi and GPIO
Introduction to Raspberry Pi and GPIOIntroduction to Raspberry Pi and GPIO
Introduction to Raspberry Pi and GPIOKris Findlay
 
Creating new Tizen profiles using the Yocto Project
Creating new Tizen profiles  using the Yocto ProjectCreating new Tizen profiles  using the Yocto Project
Creating new Tizen profiles using the Yocto ProjectLeon Anavi
 
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...Marco Cavallini
 
Dragon board 410c workshop - slideshow
Dragon board 410c workshop - slideshowDragon board 410c workshop - slideshow
Dragon board 410c workshop - slideshow96Boards
 
HKG18-411 - Introduction to OpenAMP which is an open source solution for hete...
HKG18-411 - Introduction to OpenAMP which is an open source solution for hete...HKG18-411 - Introduction to OpenAMP which is an open source solution for hete...
HKG18-411 - Introduction to OpenAMP which is an open source solution for hete...Linaro
 
Hack.lu 09 ip-morph
Hack.lu 09 ip-morphHack.lu 09 ip-morph
Hack.lu 09 ip-morphSteph Cliche
 
Japanese input environment on Tizen 2.0 Alpha
Japanese input environment on Tizen 2.0 AlphaJapanese input environment on Tizen 2.0 Alpha
Japanese input environment on Tizen 2.0 AlphaNaruto TAKAHASHI
 
Raspberry Pi Using Python
Raspberry Pi Using PythonRaspberry Pi Using Python
Raspberry Pi Using PythonSeggy Segaran
 
Java Device I/O at Raspberry PI to Build a Candy Vending Machine
Java Device I/O at Raspberry PI to Build a Candy Vending MachineJava Device I/O at Raspberry PI to Build a Candy Vending Machine
Java Device I/O at Raspberry PI to Build a Candy Vending MachineJeff Prestes
 
[Forward4 Webinar 2016] Building IoT Prototypes w/ Raspberry Pi
[Forward4 Webinar 2016] Building IoT Prototypes w/ Raspberry Pi [Forward4 Webinar 2016] Building IoT Prototypes w/ Raspberry Pi
[Forward4 Webinar 2016] Building IoT Prototypes w/ Raspberry Pi Tomomi Imura
 
Raspberry Pi (Introduction)
Raspberry Pi (Introduction)Raspberry Pi (Introduction)
Raspberry Pi (Introduction)Mandeesh Singh
 
A timeline for embedded Linux
A timeline for embedded LinuxA timeline for embedded Linux
A timeline for embedded LinuxChris Simmonds
 
IPMI is dead, Long live Redfish
IPMI is dead, Long live RedfishIPMI is dead, Long live Redfish
IPMI is dead, Long live RedfishBruno Cornec
 
Redfish and python-redfish for Software Defined Infrastructure
Redfish and python-redfish for Software Defined InfrastructureRedfish and python-redfish for Software Defined Infrastructure
Redfish and python-redfish for Software Defined InfrastructureBruno Cornec
 

What's hot (20)

PiFlash: Linux utility to flash SD cards for Raspberry Pi computers
PiFlash: Linux utility to flash SD cards for Raspberry Pi computersPiFlash: Linux utility to flash SD cards for Raspberry Pi computers
PiFlash: Linux utility to flash SD cards for Raspberry Pi computers
 
都立大「ユビキタスロボティクス特論」5月12日
都立大「ユビキタスロボティクス特論」5月12日都立大「ユビキタスロボティクス特論」5月12日
都立大「ユビキタスロボティクス特論」5月12日
 
Yocto Project introduction
Yocto Project introductionYocto Project introduction
Yocto Project introduction
 
200519 TMU Ubiquitous Robot
200519 TMU Ubiquitous Robot200519 TMU Ubiquitous Robot
200519 TMU Ubiquitous Robot
 
Introduction to Raspberry Pi and GPIO
Introduction to Raspberry Pi and GPIOIntroduction to Raspberry Pi and GPIO
Introduction to Raspberry Pi and GPIO
 
Creating new Tizen profiles using the Yocto Project
Creating new Tizen profiles  using the Yocto ProjectCreating new Tizen profiles  using the Yocto Project
Creating new Tizen profiles using the Yocto Project
 
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
Marco Cavallini @ LinuxLab 2018 : Workshop Yocto Project, an automatic genera...
 
Dragon board 410c workshop - slideshow
Dragon board 410c workshop - slideshowDragon board 410c workshop - slideshow
Dragon board 410c workshop - slideshow
 
HKG18-411 - Introduction to OpenAMP which is an open source solution for hete...
HKG18-411 - Introduction to OpenAMP which is an open source solution for hete...HKG18-411 - Introduction to OpenAMP which is an open source solution for hete...
HKG18-411 - Introduction to OpenAMP which is an open source solution for hete...
 
Hack.lu 09 ip-morph
Hack.lu 09 ip-morphHack.lu 09 ip-morph
Hack.lu 09 ip-morph
 
Japanese input environment on Tizen 2.0 Alpha
Japanese input environment on Tizen 2.0 AlphaJapanese input environment on Tizen 2.0 Alpha
Japanese input environment on Tizen 2.0 Alpha
 
Raspberry Pi Using Python
Raspberry Pi Using PythonRaspberry Pi Using Python
Raspberry Pi Using Python
 
Java Device I/O at Raspberry PI to Build a Candy Vending Machine
Java Device I/O at Raspberry PI to Build a Candy Vending MachineJava Device I/O at Raspberry PI to Build a Candy Vending Machine
Java Device I/O at Raspberry PI to Build a Candy Vending Machine
 
Pi Is For Python
Pi Is For PythonPi Is For Python
Pi Is For Python
 
[Forward4 Webinar 2016] Building IoT Prototypes w/ Raspberry Pi
[Forward4 Webinar 2016] Building IoT Prototypes w/ Raspberry Pi [Forward4 Webinar 2016] Building IoT Prototypes w/ Raspberry Pi
[Forward4 Webinar 2016] Building IoT Prototypes w/ Raspberry Pi
 
Using Qt under LGPLv3
Using Qt under LGPLv3Using Qt under LGPLv3
Using Qt under LGPLv3
 
Raspberry Pi (Introduction)
Raspberry Pi (Introduction)Raspberry Pi (Introduction)
Raspberry Pi (Introduction)
 
A timeline for embedded Linux
A timeline for embedded LinuxA timeline for embedded Linux
A timeline for embedded Linux
 
IPMI is dead, Long live Redfish
IPMI is dead, Long live RedfishIPMI is dead, Long live Redfish
IPMI is dead, Long live Redfish
 
Redfish and python-redfish for Software Defined Infrastructure
Redfish and python-redfish for Software Defined InfrastructureRedfish and python-redfish for Software Defined Infrastructure
Redfish and python-redfish for Software Defined Infrastructure
 

Similar to Raspberry Pi Embedded Linux and Python Prototyping Workshop

My presentation raspberry pi
My presentation raspberry piMy presentation raspberry pi
My presentation raspberry piHusainBhaldar21
 
Advanced View of Projects Raspberry Pi List - Raspberry PI Projects.pdf
Advanced View of Projects Raspberry Pi List - Raspberry PI Projects.pdfAdvanced View of Projects Raspberry Pi List - Raspberry PI Projects.pdf
Advanced View of Projects Raspberry Pi List - Raspberry PI Projects.pdfWiseNaeem
 
PyCon2022 - Building Python Extensions
PyCon2022 - Building Python ExtensionsPyCon2022 - Building Python Extensions
PyCon2022 - Building Python ExtensionsHenry Schreiner
 
Raspberry Pi 3 Tutorial | Raspberry Pi 3 Projects | IoT Projects | IoT Tutori...
Raspberry Pi 3 Tutorial | Raspberry Pi 3 Projects | IoT Projects | IoT Tutori...Raspberry Pi 3 Tutorial | Raspberry Pi 3 Projects | IoT Projects | IoT Tutori...
Raspberry Pi 3 Tutorial | Raspberry Pi 3 Projects | IoT Projects | IoT Tutori...Edureka!
 
Raspberry pi overview
Raspberry pi overview Raspberry pi overview
Raspberry pi overview Matthew Karas
 
IoT Prototyping using BBB and Debian
IoT Prototyping using BBB and DebianIoT Prototyping using BBB and Debian
IoT Prototyping using BBB and DebianMender.io
 
Raspberry pi pico projects raspberry pi projects
Raspberry pi pico projects raspberry pi projectsRaspberry pi pico projects raspberry pi projects
Raspberry pi pico projects raspberry pi projectsIsmailkhan77481
 
02-Introduction-to-RPi.pdf
02-Introduction-to-RPi.pdf02-Introduction-to-RPi.pdf
02-Introduction-to-RPi.pdfGrego M.
 
Embedded Systems: Lecture 8: The Raspberry Pi as a Linux Box
Embedded Systems: Lecture 8: The Raspberry Pi as a Linux BoxEmbedded Systems: Lecture 8: The Raspberry Pi as a Linux Box
Embedded Systems: Lecture 8: The Raspberry Pi as a Linux BoxAhmed El-Arabawy
 
Raspberry Pi Session - 22_11_2014
Raspberry Pi Session - 22_11_2014Raspberry Pi Session - 22_11_2014
Raspberry Pi Session - 22_11_2014Mandeesh Singh
 
Raspberry Pi Free Session - 20_09_2014
Raspberry Pi Free Session - 20_09_2014Raspberry Pi Free Session - 20_09_2014
Raspberry Pi Free Session - 20_09_2014Mandeesh Singh
 
Running Android on the Raspberry Pi: Android Pie meets Raspberry Pi
Running Android on the Raspberry Pi: Android Pie meets Raspberry PiRunning Android on the Raspberry Pi: Android Pie meets Raspberry Pi
Running Android on the Raspberry Pi: Android Pie meets Raspberry PiChris Simmonds
 
ch4-Software is Everywhere
ch4-Software is Everywherech4-Software is Everywhere
ch4-Software is Everywheressuser06ea42
 
5 IOT MODULE 5 RaspberryPi Programming using Python.pdf
5 IOT MODULE 5 RaspberryPi Programming using Python.pdf5 IOT MODULE 5 RaspberryPi Programming using Python.pdf
5 IOT MODULE 5 RaspberryPi Programming using Python.pdfJayanthi Kannan MK
 

Similar to Raspberry Pi Embedded Linux and Python Prototyping Workshop (20)

Bringing Tizen to a Raspberry Pi 2 Near You
Bringing Tizen to a Raspberry Pi 2 Near YouBringing Tizen to a Raspberry Pi 2 Near You
Bringing Tizen to a Raspberry Pi 2 Near You
 
My presentation raspberry pi
My presentation raspberry piMy presentation raspberry pi
My presentation raspberry pi
 
Raspberry pi
Raspberry piRaspberry pi
Raspberry pi
 
Advanced View of Projects Raspberry Pi List - Raspberry PI Projects.pdf
Advanced View of Projects Raspberry Pi List - Raspberry PI Projects.pdfAdvanced View of Projects Raspberry Pi List - Raspberry PI Projects.pdf
Advanced View of Projects Raspberry Pi List - Raspberry PI Projects.pdf
 
Raspberry pi
Raspberry piRaspberry pi
Raspberry pi
 
Raspberry PI
Raspberry PIRaspberry PI
Raspberry PI
 
PyCon2022 - Building Python Extensions
PyCon2022 - Building Python ExtensionsPyCon2022 - Building Python Extensions
PyCon2022 - Building Python Extensions
 
Raspberry Pi 3 Tutorial | Raspberry Pi 3 Projects | IoT Projects | IoT Tutori...
Raspberry Pi 3 Tutorial | Raspberry Pi 3 Projects | IoT Projects | IoT Tutori...Raspberry Pi 3 Tutorial | Raspberry Pi 3 Projects | IoT Projects | IoT Tutori...
Raspberry Pi 3 Tutorial | Raspberry Pi 3 Projects | IoT Projects | IoT Tutori...
 
IoT: LoRa and Java on the PI
IoT: LoRa and Java on the PIIoT: LoRa and Java on the PI
IoT: LoRa and Java on the PI
 
Raspberry pi overview
Raspberry pi overview Raspberry pi overview
Raspberry pi overview
 
Unit 3 Complete.pptx
Unit 3 Complete.pptxUnit 3 Complete.pptx
Unit 3 Complete.pptx
 
IoT Prototyping using BBB and Debian
IoT Prototyping using BBB and DebianIoT Prototyping using BBB and Debian
IoT Prototyping using BBB and Debian
 
Raspberry pi pico projects raspberry pi projects
Raspberry pi pico projects raspberry pi projectsRaspberry pi pico projects raspberry pi projects
Raspberry pi pico projects raspberry pi projects
 
02-Introduction-to-RPi.pdf
02-Introduction-to-RPi.pdf02-Introduction-to-RPi.pdf
02-Introduction-to-RPi.pdf
 
Embedded Systems: Lecture 8: The Raspberry Pi as a Linux Box
Embedded Systems: Lecture 8: The Raspberry Pi as a Linux BoxEmbedded Systems: Lecture 8: The Raspberry Pi as a Linux Box
Embedded Systems: Lecture 8: The Raspberry Pi as a Linux Box
 
Raspberry Pi Session - 22_11_2014
Raspberry Pi Session - 22_11_2014Raspberry Pi Session - 22_11_2014
Raspberry Pi Session - 22_11_2014
 
Raspberry Pi Free Session - 20_09_2014
Raspberry Pi Free Session - 20_09_2014Raspberry Pi Free Session - 20_09_2014
Raspberry Pi Free Session - 20_09_2014
 
Running Android on the Raspberry Pi: Android Pie meets Raspberry Pi
Running Android on the Raspberry Pi: Android Pie meets Raspberry PiRunning Android on the Raspberry Pi: Android Pie meets Raspberry Pi
Running Android on the Raspberry Pi: Android Pie meets Raspberry Pi
 
ch4-Software is Everywhere
ch4-Software is Everywherech4-Software is Everywhere
ch4-Software is Everywhere
 
5 IOT MODULE 5 RaspberryPi Programming using Python.pdf
5 IOT MODULE 5 RaspberryPi Programming using Python.pdf5 IOT MODULE 5 RaspberryPi Programming using Python.pdf
5 IOT MODULE 5 RaspberryPi Programming using Python.pdf
 

Recently uploaded

Introduction to Machine Learning Unit-3 for II MECH
Introduction to Machine Learning Unit-3 for II MECHIntroduction to Machine Learning Unit-3 for II MECH
Introduction to Machine Learning Unit-3 for II MECHC Sai Kiran
 
Heart Disease Prediction using machine learning.pptx
Heart Disease Prediction using machine learning.pptxHeart Disease Prediction using machine learning.pptx
Heart Disease Prediction using machine learning.pptxPoojaBan
 
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort serviceGurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort servicejennyeacort
 
Call Girls Delhi {Jodhpur} 9711199012 high profile service
Call Girls Delhi {Jodhpur} 9711199012 high profile serviceCall Girls Delhi {Jodhpur} 9711199012 high profile service
Call Girls Delhi {Jodhpur} 9711199012 high profile servicerehmti665
 
Sachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
Sachpazis Costas: Geotechnical Engineering: A student's Perspective IntroductionSachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
Sachpazis Costas: Geotechnical Engineering: A student's Perspective IntroductionDr.Costas Sachpazis
 
DATA ANALYTICS PPT definition usage example
DATA ANALYTICS PPT definition usage exampleDATA ANALYTICS PPT definition usage example
DATA ANALYTICS PPT definition usage examplePragyanshuParadkar1
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptSAURABHKUMAR892774
 
What are the advantages and disadvantages of membrane structures.pptx
What are the advantages and disadvantages of membrane structures.pptxWhat are the advantages and disadvantages of membrane structures.pptx
What are the advantages and disadvantages of membrane structures.pptxwendy cai
 
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)Dr SOUNDIRARAJ N
 
Call Girls Narol 7397865700 Independent Call Girls
Call Girls Narol 7397865700 Independent Call GirlsCall Girls Narol 7397865700 Independent Call Girls
Call Girls Narol 7397865700 Independent Call Girlsssuser7cb4ff
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024hassan khalil
 
Concrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptxConcrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptxKartikeyaDwivedi3
 
Internship report on mechanical engineering
Internship report on mechanical engineeringInternship report on mechanical engineering
Internship report on mechanical engineeringmalavadedarshan25
 
pipeline in computer architecture design
pipeline in computer architecture  designpipeline in computer architecture  design
pipeline in computer architecture designssuser87fa0c1
 
main PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfidmain PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfidNikhilNagaraju
 
Risk Assessment For Installation of Drainage Pipes.pdf
Risk Assessment For Installation of Drainage Pipes.pdfRisk Assessment For Installation of Drainage Pipes.pdf
Risk Assessment For Installation of Drainage Pipes.pdfROCENODodongVILLACER
 
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube ExchangerStudy on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube ExchangerAnamika Sarkar
 
Electronically Controlled suspensions system .pdf
Electronically Controlled suspensions system .pdfElectronically Controlled suspensions system .pdf
Electronically Controlled suspensions system .pdfme23b1001
 

Recently uploaded (20)

Introduction to Machine Learning Unit-3 for II MECH
Introduction to Machine Learning Unit-3 for II MECHIntroduction to Machine Learning Unit-3 for II MECH
Introduction to Machine Learning Unit-3 for II MECH
 
Heart Disease Prediction using machine learning.pptx
Heart Disease Prediction using machine learning.pptxHeart Disease Prediction using machine learning.pptx
Heart Disease Prediction using machine learning.pptx
 
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort serviceGurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
 
Call Girls Delhi {Jodhpur} 9711199012 high profile service
Call Girls Delhi {Jodhpur} 9711199012 high profile serviceCall Girls Delhi {Jodhpur} 9711199012 high profile service
Call Girls Delhi {Jodhpur} 9711199012 high profile service
 
Sachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
Sachpazis Costas: Geotechnical Engineering: A student's Perspective IntroductionSachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
Sachpazis Costas: Geotechnical Engineering: A student's Perspective Introduction
 
DATA ANALYTICS PPT definition usage example
DATA ANALYTICS PPT definition usage exampleDATA ANALYTICS PPT definition usage example
DATA ANALYTICS PPT definition usage example
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.ppt
 
What are the advantages and disadvantages of membrane structures.pptx
What are the advantages and disadvantages of membrane structures.pptxWhat are the advantages and disadvantages of membrane structures.pptx
What are the advantages and disadvantages of membrane structures.pptx
 
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
9953056974 Call Girls In South Ex, Escorts (Delhi) NCR.pdf
 
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
UNIT III ANALOG ELECTRONICS (BASIC ELECTRONICS)
 
Call Girls Narol 7397865700 Independent Call Girls
Call Girls Narol 7397865700 Independent Call GirlsCall Girls Narol 7397865700 Independent Call Girls
Call Girls Narol 7397865700 Independent Call Girls
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024
 
POWER SYSTEMS-1 Complete notes examples
POWER SYSTEMS-1 Complete notes  examplesPOWER SYSTEMS-1 Complete notes  examples
POWER SYSTEMS-1 Complete notes examples
 
Concrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptxConcrete Mix Design - IS 10262-2019 - .pptx
Concrete Mix Design - IS 10262-2019 - .pptx
 
Internship report on mechanical engineering
Internship report on mechanical engineeringInternship report on mechanical engineering
Internship report on mechanical engineering
 
pipeline in computer architecture design
pipeline in computer architecture  designpipeline in computer architecture  design
pipeline in computer architecture design
 
main PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfidmain PPT.pptx of girls hostel security using rfid
main PPT.pptx of girls hostel security using rfid
 
Risk Assessment For Installation of Drainage Pipes.pdf
Risk Assessment For Installation of Drainage Pipes.pdfRisk Assessment For Installation of Drainage Pipes.pdf
Risk Assessment For Installation of Drainage Pipes.pdf
 
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube ExchangerStudy on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
Study on Air-Water & Water-Water Heat Exchange in a Finned Tube Exchanger
 
Electronically Controlled suspensions system .pdf
Electronically Controlled suspensions system .pdfElectronically Controlled suspensions system .pdf
Electronically Controlled suspensions system .pdf
 

Raspberry Pi Embedded Linux and Python Prototyping Workshop

  • 1. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 1 Embedded Linux Rapid Prototyping tutorials with Raspberry Pi Naohiko Shimizu Tokai University, Japan nshimizu@keyaki.cc.u-tokai.ac.jp
  • 2. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 2 Agenda • Introduction • Prepare the Raspberry Pi for the workshop – Basic installation – Tools for cross compilation • Embedded Linux Programming with C – Basic Linux API – Kernel modules • Rapid prototyping with Python • Exercise
  • 3. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 3 Objective of this course • Browse the development of embedded systems • Get the basics of Linux API • Make kernel modules on Linux • Rapid prototyping with Python
  • 4. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 4 Introduction • Raspberry Pi is a low cost and the one of the most popular credit-card sized computer in the world. http://www.raspberrypi.org • Rpi foundation is an educational charity in UK. • They want to provide affordable, programmable computers everywhere. Model B+ Model B
  • 5. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 5 Raspberry Pi Model B+ • 700MHz ARM1176JZF-S • VideoCore IV GPU • 512MB RAM 4 x USB Ethernet Audio Video HDMImicroUSB Power microSD For OS GPIO Broadcom BCM2835 SoC
  • 6. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 6 • GPIO have multiple functions as shown in the block diagram • Default pad drive strength is 8mA for output • Output voltage is 3.3V • It can pull up/down • It can make an interrupt GPIO on BCM2835 BCM2835 ARM Peripherals
  • 7. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 7 GPIO registers(1) BCM2835 ARM Peripherals The address is physical and you have to map to your virtual space.
  • 8. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 8 GPIO registers(2) BCM2835 ARM Peripherals GPIO can be set or clear with GPIO output set/clear registers. We can read the whole value with GPIO level register but cannot set the values directly.
  • 9. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 9 GPIO registers(3) BCM2835 ARM Peripherals GPIO alternate functions
  • 10. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 10 GPIO in Linux kernel • ARM Linux is using the Device Tree. – It defines the I/O subsystem out of the kernel. /boot/bcm2708-rpi-b-plus.dtb is the compiled Device Tree for Pi B+ The source code (.dts) is available on the Linux source tree arch/arm/boot/dts/bcm2708-rpi-b-plus.dts arch/arm/boot/dts/bcm2708.dtsi • We use Pinctrl and GPIO library. See Documentation/pinctrl.txt Documentation/gpio/gpio-legacy.txt
  • 11. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 11 Pinctrl subsystem http://free-electrons.com/pub/conferences/2013/fosdem/arm-support-kernel/
  • 12. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 12 GPIO special function on Pi • DTS defines some special functions on GPIOs gpio: gpio { compatible = "brcm,bcm2835-gpio"; reg = <0x7e200000 0xb4>; interrupts = <2 17>, <2 18>; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; }; &gpio { spi0_pins: spi0_pins { brcm,pins = <7 8 9 10 11>; brcm,function = <4>; /* alt0 */ }; i2c0_pins: i2c0 { brcm,pins = <0 1>; brcm,function = <4>; }; i2c1_pins: i2c1 { brcm,pins = <2 3>; brcm,function = <4>; }; i2s_pins: i2s { brcm,pins = <18 19 20 21>; brcm,function = <4>; /* alt0 */ }; };
  • 13. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 13 System Timer • BCM2835 has a free run 64 bit system timer which is running at 1 MHz on RaspberryPi. BCM2835 ARM Peripherals
  • 14. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 14 IRQ for timer http://xinu.mscs.mu.edu/BCM2835_Interrupt_Controller
  • 15. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 15 The I/O board for this seminar • We will use LED and SW board. DIS1 DIS2 S1 S2 LED1 LED2 a b c d e f g dp b c d e f g dp a
  • 16. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 16 The I/O board for this seminar • GPIO port number of the I/O boad Port Func Port Func 2 S1 3 S2 4 LED1 9 LED2 7 DIS1 8 DIS2 14 a 15 b 17 c 18 d 22 e 23 f 24 g 25 dp
  • 17. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 17
  • 18. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 18 Software for Raspberry Pi • OS : Raspberian distribution which is based on Debian GNU Linux. • Installer : NOOBS make your life easy. • ssh : Communicate to RPi • wiringPi : GPIO library for C • RPi.GPIO : GPIO library for Python • Linux kernel related : kernel source, gcc-4.8 etc.
  • 19. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 19 Software version we use • NOOBS v1.4.0 • Raspbian wheezy – Firmware 8aca5762 • wiringPi 2.22 • Rpi.GPIO 0.5.11 • LiveCygwin from http://www.ip-arch.jp • RaspberryPi cross package from http://www.ip-arch.jp/RaspberryPi.tar.bz2
  • 20. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 20 Our system with headless Raspberry Pi • We use the ethernet connection between Raspberry Pi and PC. • Also we use GPIO to connect Raspberry Pi to the world. • No keyboard nor display for Raspberry Pi Ethernet PC
  • 21. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 21 Prepare the Raspberry Pi • Raspberry Pi model B+ or B • microSD card > 8GB • microUSB Power > 1A • Ethernet cable
  • 22. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 22 Basic Installation 1 • Format your microSD card with FAT32. – You may need a miroSD to SD adapter
  • 23. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 23 Basic Installation 2 • Copy the contents of NOOBS on the microSD card.
  • 24. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 24 Basic Installation 3 • Add silentinstall at the last of recovery.cmdline. • Modify os/Raspbian/flavours.json. • Delete os/Data_Partition folder Add Don’t forget ENTER at the end of the line.
  • 25. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 25 Basic Installation 4 • Eject your microSD card from PC, and put it in the slot of Raspberry Pi • Plug your Raspberry Pi to the USB Power. You will see Power LED is on and ACT LED is blinking. • It takes long time we will prepare other things during the boot.
  • 26. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 26 Basic Installation 5 • Setup Internet Connection Sharing on your Windows PC. – Change the Sharing properties of your WiFi adapter on the Control Panel -> Network and Internet -> Network Connections – Check ‘Allow other network users to connect through this computer’s Internet connection’ on the Sharing tab
  • 27. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 27 Basic Installation 6 • Connect your Raspberry Pi to your PC – Your PC will provide an IP address to Pi, but unfortunately there is no way to know it. – You can use HDMI display for monitoring. Check the PC’s IP address
  • 28. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 28 Basic Installation 7 • Search your Raspberry Pi’s IP address :-0 – Open cmd • [win]+R • cmd – Make a bat file • Notepad – Save as ck.bat – Run it – You will find the Pi’s IP address
  • 29. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 29 Basic Installation 8 • Connect to your Raspberry Pi with ssh Login: pi Password: raspberry We use LiveCygwin in this seminar
  • 30. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 30 Tools for cross compilation • C applications – Cross tools by ct-ng • gcc • Linux library • Linux headers – wiringPi static library • Linux kernel modules – Linux kernel source
  • 31. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 31 Cross compilation • Build your ct-ng tools on Cygwin. – In cygwin environment, you need some patches • https://sourceware.org/ml/crossgcc/2012-05/msg00012.html • http://www.raspberrypi.org/forums/viewtopic.php?f=7&t=4058 • Configure and make your cross tools • Prepare your Linux kernel (see next slide for detail) – Or Download x-tools from http://www.ip-arch.jp/ • http://www.ip-arch.jp/RaspberryPi.tar.bz2 • Put the file on the LiveCygwin’s /usr/arch directory, it will be extracted on the next session of LiveCygwin. • In the package you also have the Linux kernel source code.
  • 32. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 32 Linux kernel source • We need the same kernel source and some files as the kernel running on the Raspberry Pi – On Raspberry Pi, you can get the version in /usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz – Get the git_hash value from https://raw.githubusercontent.com/raspberrypi/firmware/<firmware-version>/extra/git_hash – Get the linux source from https://github.com/raspberrypi/linux/archive/<git_hash-value>.tar.gz – Get Module.symvers from https://raw.githubusercontent.com/raspberrypi/firmware/<firmware-version>/extra/Module.symvers and copy it to the linux directory – Get .config on Raspberry Pi with zcat /proc/config.gz > ~/linux/.config You can skip if you use LiveCygwin
  • 33. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 33 On NOOBS v1.4.0 • We will show the detailed instructions to get kernel development environment with NOOBS v1.4.0 based Rasbian –If you use LiveCygwin, you can use ready made package by me. http://www.ip-arch.jp/RaspberryPi.tar.bz2 Therefore, you can skip to the section “Embedded Linux Programming with C.” and go to page 40.
  • 34. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 34 On NOOBS v1.4.0 • Get the firmware version from /usr/share/doc/raspberrypi- bootloader/changelog.Debian.gz
  • 35. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 35 On NOOBS v1.4.0 –Get the git_hash value from https://raw.githubusercontent.com/raspberrypi/firmware/8aca5762/extra/git _hash Firmware version Git_hash value
  • 36. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 36 On NOOBS v1.4.0 • Get the linux source from https://github.com/raspberrypi/linux/archive/0be82f722c097340632a59 b879fbfee9c6148f53.tar.gz And extract it on your cygwin home directory. Git_hash value
  • 37. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 37 On NOOBS v1.4.0 • Get Module.symvers from https://raw.githubusercontent.com/raspberrypi/firmware/8aca5762/extr a/Module.symvers save and copy it to the linux source directory as Module.symvers Firmware version Module7.symvers for Pi2
  • 38. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 38 On NOOBS v1.4.0 • Get .config on Raspberry Pi from /proc/config.gz put it on your linux source directory as .config
  • 39. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 39 On NOOBS v1.4.0 • Install required package for this seminar on your Raspberry Pi – Suggested packages are: • gcc-48 : This package is not mandatory, but useful if you want to compile kernel modules on your Raspberry Pi.
  • 40. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 40 On NOOBS v1.4.0 • Extract RaspberryPi.tar.bz2 on your home of LiveCygwin –In the RaspberryPi directory, type make pi2 or make pibp For RaspberryPi2 For RaspberryPi B+
  • 41. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 41 On NOOBS v1.4.0 • What is going on the Makefile is: –Change your directory to linux • cd linux –Preparing your kernel to use • ARCH=arm make oldconfig • CROSS_COMPILE=~/RaspberryPi/x-tools/arm-unknown-linux- gnueabi/bin/arm-unknown-linux-gnueabi- ARCH=arm make prepare modules_prepare
  • 42. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 42 Embedded Linux Programming with C • Access memory mapped I/O via mmap – /dev/mem can be used to access I/O registers – You need to set the port direction, pull up/down, etc. for GPIO. • Interrupt can be handled via device driver – You need a device driver which handle IRQ – The driver will make a callback or signal • Any Linux API can be used for your applications • Use real-time task for less jitter.
  • 43. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 43 Program execution STACK BSS DATA TEXT HEAP #include <stdio.h> int main() { printf(“hello worldn”); return 0; } compile Source code Execution binary TEXT DATA Processor memory header Source code is compiled to binary. Text and Data segments are loaded on memory. Header has the size of BSS and Stack segments. Loader also link the unresolved labels to the dynamic link libraries. load
  • 44. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 44 Linux process • User process can use up to 3GB of virtual memory. • C language execution format has four segments to load on memory. • Process has a priority – 0-99 real-time task – 100-139 conventional task – Real-time tasks are scheduled on their priority STACK BSS DATA TEXT HEAP
  • 45. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 45 User space User space Kernel and User space • Linux uses virtual address for their processes. • 3GB is for user space, 1GB for kernel space. • User mode program access only to his user space. • Kernel space is common to the all processes. • User program will switch to kernel via interrupt or svc. User space User space 00000000 C0000000 Kernel space
  • 46. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 46 Address translation • Linux uses the paging system of ARM kernel kernel kernel Virtual space 1 Virtual space 2 Page table 1 Page table 2 Physical memory This figure only shows the concept of the address translation
  • 47. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 47 Program execution Hardware Linux kernel Device driver Device driver Device driver C Library Library B Library A User application 1 User application 2 User application3 User space 1 User space 2 User space 3 Shared memory Kernel space Physical memory Multiple User spaces
  • 48. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 48 Untimed program vs. timed world • The basic C language structure is untimed where the real world is timed. – We need methods our programs to be compatible with real world Wait with sleep nanosleep() Polling the timer timer Use callback set timer callback
  • 49. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 49 Make your C application • Change directory to ~/RaspberryPi/apps/C • Make your executable binary as: make hello.exe The command make the executable from hello.c • Copy your binary to Raspberry Pi – scp hello.exe pi@192.168.137.XX: where XX depends on your environment. See P.15 • On Raspbery Pi, run the binary. ./hello.exe
  • 50. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 50 Example “Hello World” • Cross-compile hello.c > make hello.exe • Transfer it to the Raspberry Pi > scp hello.exe pi@192.168.137.xxx: • Run it on the Raspberry Pi > ./hello.exe #include <stdio.h> int main() { printf(“hello worldn”); return 0; } Source code The xxx is the IP address of your RPi
  • 51. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 51 Program debug on remote STACK BSS DATA TEXT HEAP #include <stdio.h> int main() { printf(“hello worldn”); return 0; } control Source code TEXT DATA Processor memory header Execution binary gdb gdbserver Program itself is on the remomte. The gdbserver provide the interface to host. Remote system Host system #include <stdio.h> int main() { printf(“hello worldn”); return 0; } Source code
  • 52. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 52 Example “Hello World” • Make sure you have hello.exe • Run gdbserver on you Raspberry Pi with port yyy • Run cross-gdb on your host > make hello.exe.debug (gdb) target remote 192.168.137.xxx:yyy (gdb) b main (gdb) c (gdb) n Break pointBreak point Start debugging xxx is the ip address of RPi, yyy is the port you specified on gdbserver command line.
  • 53. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 53 Exercise • Make a C proram that print 1 through 10 on the screen. • Cross compile it and run it under the control of the debugger. • Run the program step by step.
  • 54. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 54 Refer to functions C/Linux provides • We will use C library or Linux system calls – C library is realized over the system calls • Ex. printf, scanf, fopen, strlen, malloc, free, etc. – System calls directly executed by your program. • Ex. open, close, read, write, ioctl, llseek, mmap, etc. • We can use online manual of Linux > make printf.man will show you the manual page of printf. #include <stdio.h> int printf(const char *format, ...);
  • 55. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 55 System calls • With the service all, the system call will change your program to privileged state. Linux kernel C Library User application Function call Service call Service call #include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);
  • 56. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 56 ARM Linux system calls • Provided via a software interrupt svc #0. – Arguments for the call are placed on registers Function Register System call number r7 arg1 r0 arg2 r1 arg2 r2
  • 57. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 57 Linux system call example • We can also use inline assembler to make a system call. #include <stdio.h> #include <unistd.h> #include <string.h> #include <asm/unistd.h> int main() { char *buf="Hello Worldn"; register int r0 asm("r0"); register int r1 asm("r1"); register int r2 asm("r2"); register int r7 asm("r7"); r7 = __NR_write; r0 = STDOUT_FILENO; r1 = (int)buf; r2 = strlen(buf); __asm__ volatile( "svc #0n": "=r"(r0):"r"(r7),"r"(r0),"r"(r1),"r"(r2)); printf("nres=%dn", r0); return 0; } RaspberryPi/apps/C/syscall.c A part of system call definitions #define __NR3264_lseek 62 #define __NR_read 63 #define __NR_write 64 #define __NR_exit 93 #define __NR_nanosleep 101 #define __NR_getitimer 102 #define __NR_setitimer 103
  • 58. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 58 Exercise • Based on the system call example, make a C program that copy a character from STDIN_FILENO to STDOUT_FILENO while the system call result is 1, otherwise, the program should return from main. • Cross compile it and run it under the control of the debugger. • Run the program step by step.
  • 59. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 59 Linux API we will use • Time : get the current time • Sleep : suspend the process • Timer : notify or measure certain duration • Signal : notification to the process • Memory : allocate, share the memory space • Process : invoke, synchronize processes
  • 60. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 60 Time • Linux and/or Unix start their time from 1st January 1970 when the Unix was developed at Bell Laboratory in USA. – It is recommended to use POSIX function • Use clock_gettime() with CLOCK_REALTIME to get time. • To control physical devices, CLOCK_MONOTONIC will be better. It will not be affected by ntpd. • The resolution can be get with clock_getres() • We need to add ‘–lrt’ to compile with these function. exec gettime
  • 61. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 61 API : Time • We have three time related API – clockid defines what type of the time struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; #include <time.h> int clock_getres(clockid_t clk_id, struct timespec *res); int clock_gettime(clockid_t clk_id, struct timespec *tp); int clock_settime(clockid_t clk_id, const struct timespec *tp); CLOCK_REALTIME CLOCK_MONOTONIC CLOCK_PROCESS_CPUTIME_ID CLOCK_THREAD_CPUTIME_ID
  • 62. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 62 Example: Time #include <stdio.h> #include <time.h> struct timespec tp; int main () { clock_gettime(CLOCK_REALTIME, &tp); printf("ctime = %sn", ctime(&tp.tv_sec)); clock_getres(CLOCK_REALTIME, &tp); printf("clock resolution is %dnSn", tp.tv_nsec); return 0; } RaspberryPi/apps/C/API/clock.c $ cd ~/RaspberryPi/apps/C $ make API/clock.exe $ scp API/clock.exe pi@192.168.137.xx: On the Raspberry Pi $ ./clock.exe
  • 63. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 63 Exercise : Time • On the example hello, get the time with CLOCK_MONOTONIC before and after the printf, and show the time of the printf in nano seconds.
  • 64. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 64 Sleep • This API suspends the execution of the process for a certain duration or got a signal. – We have a few sleep APIs sleep(), nanosleep() and clock_nanosleep() – These functions will be interrupted when the process got a signal. In that case, the remained time will be reported by the functions. exec1 exec2 sleep
  • 65. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 65 API : Sleep • The API for sleep functions #include <time.h> int nanosleep(const struct timespec *req, struct timespec *rem); #include <unistd.h> unsigned int sleep(unsigned int seconds); struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ };
  • 66. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 66 Example : Sleep #include <stdio.h> #include <time.h> struct timespec req, rem, tps, tpe; int main () { req.tv_sec = 2; req.tv_nsec = 500000000; clock_gettime(CLOCK_REALTIME, &tps); nanosleep(&req, &rem); clock_gettime(CLOCK_REALTIME, &tpe); printf("Start to sleep at %sn", ctime(&tps.tv_sec)); printf("End to sleep at %sn", ctime(&tpe.tv_sec)); printf("Diff = %fn", (double)(tpe.tv_sec+tpe.tv_nsec*1e-9) - (double)(tps.tv_sec+tps.tv_nsec*1e-9)); return 0; } $ cd ~/RaspberryPi/apps/C $ make API/sleep.exe $ scp API/sleep.exe pi@192.168.137.xx: RaspberryPi/apps/C/API/sleep.c
  • 67. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 67 Exercise : sleep • From 1nS, 10nS, …, to 10S, show the sleep time with the nanosleep call.
  • 68. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 68 Timer • POSIX timer is a useful functionality for many applications. – It can be a single shot or interval timer – It can generate a signal at the specified time – It can call a specified thread at the specified time – Or program only read the timer Program execution timer Set timer notify timeout signal callback
  • 69. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 69 API : Timer struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; #include <signal.h> #include <time.h> int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid); int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec * old_value); int timer_gettime(timer_t timerid, struct itimerspec *curr_value); int timer_delete(timer_t timerid); CLOCK_REALTIME CLOCK_MONOTONIC CLOCK_PROCESS_CPUTIME_ID CLOCK_THREAD_CPUTIME_ID struct itimerspec { struct timespec it_interval; /* Timer interval */ struct timespec it_value; /* Initial expiration */ };
  • 70. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 70 API : Timer union sigval { /* Data passed with notification */ int sival_int; /* Integer value */ void *sival_ptr; /* Pointer value */ }; struct sigevent { int sigev_notify; /* Notification method */ int sigev_signo; /* Notification signal */ union sigval sigev_value; /* Data passed with notification */ void (*sigev_notify_function) (union sigval); /* Function used for thread notification (SIGEV_THREAD) */ void *sigev_notify_attributes; /* Attributes for notification thread (SIGEV_THREAD) */ pid_t sigev_notify_thread_id; /* ID of thread to signal (SIGEV_THREAD_ID) */ }; SIGEV_NONE SIGEV_SIGNAL SIGEV_THREAD
  • 71. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 71 Example: Timer #include <stdio.h> #include <signal.h> #include <time.h> struct sigevent evp; timer_t tm; struct itimerspec itim; void thread_func(union sigval val) { struct timespec tp; clock_gettime(CLOCK_REALTIME, &tp); printf("Got timer at %sn", ctime(&tp.tv_sec)); return; } $ cd ~/RaspberryPi/apps/C $ make API/timer.exe $ scp API/timer.exe pi@192.168.137.xx int main () { evp.sigev_notify =SIGEV_THREAD; evp.sigev_notify_function = thread_func; timer_create(CLOCK_REALTIME, &evp, &tm); itim.it_value.tv_sec = 2; itim.it_value.tv_nsec = 0; itim.it_interval.tv_sec = 3; itim.it_interval.tv_nsec = 0; timer_settime(tm, 0, &itim, NULL); sleep(30); return 0; } RaspberryPi/apps/C/API/timer.c
  • 72. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 72 Exercise : timer • Make each kind of timers for CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID and compare the value during the intervals in the previous example.
  • 73. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 73 Signal • Signal is a notification to processes. We have two types of signal on Linux – Conventional signal – Realtime signal • It works like an interrupt Signal callback exec
  • 74. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 74 API : Signal #include <signal.h> int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); int sigqueue(pid_t pid, int sig, const union sigval value); int sigwaitinfo(const sigset_t *set, siginfo_t *info); int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout); int kill(pid_t pid, int sig); int sigwait(const sigset_t *set, int *sig); struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };
  • 75. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 75 Example: Signal #include <stdio.h> #include <signal.h> #include <time.h> struct sigaction sa; struct timespec tp; void sig_handler() { clock_gettime(CLOCK_REALTIME, &tp); printf("got a signaln"); printf("ctime = %sn", ctime(&tp.tv_sec)); return; } $ cd ~/RaspberryPi/apps/C $ make API/signal.exe $ scp API/signal.exe pi@xxxx int main () { sa.sa_handler = sig_handler; sigaction(SIGUSR1,&sa,NULL); while (1) sleep(0); return 0; } RaspberryPi/apps/C/API/signal.c This program will wait for signals. Then you can send a signal via kill command. kill –USR1 pid Where pid is the process id of this program.
  • 76. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 76 Example: Signal(2) #include <stdio.h> #include <signal.h> #include <time.h> struct sigevent evp; timer_t tm; struct itimerspec itim = {{2,0},{3,0}}; struct sigaction sa; struct timespec tp; void sig_handler() { clock_gettime(CLOCK_REALTIME, &tp); printf("got a signaln"); printf("ctime = %sn", ctime(&tp.tv_sec)); return; } $ cd ~/RaspberryPi/apps/C $ make API/signal2.exe $ scp API/signal2.exe pi@xxxx int main () { evp.sigev_notify =SIGEV_SIGNAL; evp.sigev_signo = SIGUSR1; timer_create(CLOCK_REALTIME, &evp, &tm); sa.sa_handler = sig_handler; sigaction(SIGUSR1,&sa,NULL); timer_settime(tm, 0, &itim, NULL); while (1) sleep(0); return 0; } RaspberryPi/apps/C/API/signal2.c This program generates signals inside itself by an interval timer.
  • 77. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 77 Example: Signal(3) #include <stdio.h> #include <signal.h> struct sigaction sa; void sig_handler(int sig, siginfo_t *si, void *context) { printf("got a signal %d(%d)n", sig, si->si_value.sival_int); return; } int main () { int sig; sa.sa_handler = sig_handler; sa.sa_flags = SA_SIGINFO; for(sig=SIGRTMIN;sig<SIGRTMAX;sig++) sigaction(sig, &sa, NULL); while (1) sleep(0); return 0; } $ cd ~/RaspberryPi/apps/C $ make API/signal3.exe $ scp API/signal3.exe pi@xxxx RaspberryPi/apps/C/API/signal3.c This program wait real-time signals SIGRTMIN 32 SIGRTMAX 64
  • 78. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 78 Example: Signal(3-2) #include <stdio.h> #include <signal.h> int main(int argc, char *argv[]) { union sigval sv; if(argc < 4) { printf("%s pid sig datn",argv[0]); return -1; } sv.sival_int = atoi(argv[3]); sigqueue(atoi(argv[1]), atoi(argv[2]), sv); return 0; } $ cd ~/RaspberryPi/apps/C $ make API/sigqueue.exe $ scp API/sigqueue.exe pi@xxxx RaspberryPi/apps/C/API/sigqueue.c This program will send a signal to a process.
  • 79. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 79 Memory • The virtual memory – The mmap vs. malloc – File map • Dedicate the physical memory – mlock
  • 80. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 80 API : mmap • mmap() creates a new mapping in the virtual address space of the calling process. #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length); PROT_EXEC Pages may be executed. PROT_READ Pages may be read. PROT_WRITE Pages may be written. PROT_NONE Pages may not be accessed. MAP_SHARED Share this mapping. Updates to the mapping are visible to other processes that map this file, and are carried through to the underlying file. The file may not actually be updated until msync(2) or munmap() is called. MAP_PRIVATE The mapping is private MAP_ANONYMOUS Not associate with a file fd is the file descriptor which we can to map. And offset is the offset from the start of the mapped file.
  • 81. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 81 Example : mmap #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/mman.h> #define MAPFILE "mmaptest.txt" #define BUFSZ 4096 int main(int argc, char *argv[]) { int i,fd; char *buf, *bufo; fd = open(MAPFILE, O_RDWR); if(fd<0) return 1; buf=(char*)mmap(NULL, BUFSZ, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); bufo=buf; for(i=0;i<argc;i++){ sprintf(buf,"%sn",argv[i]); buf+=strlen(buf); } msync(bufo, BUFSZ, MS_SYNC); return 0; } RaspberryPi/apps/C/API/mmap.c Before running the program on pi, you shoud make the target file with: dd if=/dev/zero of=mmaptest.txt bs=1 count=4096 This command make a file which size is 4096 bytes
  • 82. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 82 Exercise : mmap • Make a program which has a pointer to int which designate 0x20000000. Then read/write some valule on that area. Observe what will be happened. int *p = (int*)0x20000000; *p = 1; or x=*p; where x is a int variable. • Make a region with mmap at 0x20000000. Then read/write some value on that region.
  • 83. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 83 Process/thread • Priority • Multithread – invoke – Mutex
  • 84. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 84 API : scheduler • You can set scheduler policy and priority for a target process or itself (pid=0) #include <sched.h> int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param); int sched_getscheduler(pid_t pid); int sched_yield(void); int sched_get_priority_max(int policy); int sched_get_priority_min(int policy); struct sched_param { ... int sched_priority; ... }; Usual tasks: SCHED_OTHER SCHED_BATCH SCHED_IDLE ------------------------ Realtime tasks: SCHED_FIFO SCHED_RR
  • 85. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 85 Example : sched #include <sched.h> #include <stdio.h> int main (int argc, char *argv[]) { int count; if(argc < 2) return -1; struct sched_param sp = {10}; sched_setscheduler(0, SCHED_RR, &sp); for(count=0;count<atoi(argv[1]);count++) { if(!(count%65536)) printf(“c:%dn”,count); } return 0; } RaspberryPi/apps/C/API/sched.c Run two copies of the execution file as: $ sudo ./a.out & sudo ./a.out Try SCHED_FIFO also
  • 86. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 86 API : pthread • The pthread and mutex is the basic method for multiple thread programming. #include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); int pthread_join(pthread_t thread, void **retval); int pthread_mutex_init (pthread_mutex_t *mutex, pthread_mutexattr_t *mutexattr); int pthread_mutex_lock (pthread_mutex_t *mutex); int pthread_mutex_unlock (pthread_mutex_t *mutex); int pthread_mutex_destroy (pthread_mutex_t *mutex);
  • 87. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 87 Example : pthread #include <stdio.h> #include <pthread.h> #define LOOP 500000 int comm, t1, t2, mx; pthread_mutex_t lock; void *thread(void *arg) { int i; for(i=0;i<LOOP;i++) { if(mx) pthread_mutex_lock(&lock); comm++; if(mx) pthread_mutex_unlock(&lock); t1++; } return NULL; } RaspberryPi/apps/C/API/pthread.c int main(int argc, char *argv[]) { pthread_t t; int i; if(argc>1) mx=1; pthread_mutex_init(&lock, NULL); if(pthread_create(&t, NULL, thread, &comm)) { return 1; } for(i=0;i<LOOP;i++) { if(mx) pthread_mutex_lock(&lock); comm++; if(mx) pthread_mutex_unlock(&lock); t2++; } pthread_join(t, NULL); pthread_mutex_destroy(&lock); printf("comm=%d, t1=%d, t2=%dn", comm, t1, t2); return 0; } Compare the results when command line argument is or is not.
  • 88. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 88 TCP/IP Network • We will focus on the datagram socket. socket bind recvfrom sendto socket sendto recvfrom clientserver
  • 89. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 89 Network API #include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol); int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); struct sockaddr_in { short sin_family; // e.g. AF_INET, AF_INET6 unsigned short sin_port; // e.g. htons(3490) struct in_addr sin_addr; // see struct in_addr, below char sin_zero[8]; // zero this if you want to }; struct in_addr { unsigned long s_addr; // load with inet_pton() };
  • 90. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 90 Network Example (server) -1 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #define PORT 55123 void errExit(char str[]) { fprintf(stderr,"Error with %sn",str); exit(-1); } int main(int argc, char *argv[]) { struct sockaddr_in sv, cl; int soc; char buf[100]; if((soc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) errExit("socket"); memset(&sv, 0, sizeof(sv)); RaspberryPi/apps/C/API/listen.c Port number is arbitrary $ cd ~/RaspberryPi/apps/C $ make API/listen.exe $ scp API/listen.exe pi@xxxx
  • 91. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 91 Network Example (server) -2 sv.sin_family = AF_INET; sv.sin_addr.s_addr = INADDR_ANY; sv.sin_port = htons(PORT); if(bind(soc, (struct sockaddr *)&sv, sizeof(sv)) < 0) errExit("bind"); while (1) { int i; socklen_t len = sizeof(struct sockaddr_in); ssize_t sz; if((sz = recvfrom(soc, buf, sizeof(buf), 0, (struct sockaddr *)&cl, &len)) < 0) errExit("recvfrom"); for(i=0;i<sz;i++) buf[i] = (buf[i]>='a' && buf[i] <='z')? buf[i]-0x20:buf[i]+0x20; buf[i]=0; if(sendto(soc, buf, sz, 0, (struct sockaddr*)&cl, len) != sz) errExit("sendto"); } }
  • 92. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 92 Network Example (client) -1 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #define PORT 55123 void errExit(char str[]) { fprintf(stderr,"Error with %sn",str); exit(-1); } int main(int argc, char *argv[]) { struct sockaddr_in sv, cl; int soc; char buf[100]; if(argc < 3) errExit("arg1 ipaddr, arg2 strings"); if((soc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) errExit("socket"); memset(&sv, 0, sizeof(struct sockaddr_in)); RaspberryPi/apps/C/API/sending.c $ cd ~/RaspberryPi/apps/C $ gcc sending.c –o sending $ ./sending 192.168.137.xx “test send”
  • 93. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 93 Network Example (client) -2 sv.sin_family = AF_INET; sv.sin_port = htons(PORT); if(inet_pton(AF_INET, argv[1], &sv.sin_addr)<=0) errExit("inet_pton"); if(sendto(soc, argv[2], strlen(argv[2]),0,(struct socaddr*)&sv, sizeof(struct sockaddr_in)) != strlen(argv[2])) errExit("sendto"); memset(buf,0,sizeof(buf)); if(recvfrom(soc, buf, sizeof(buf), 0, NULL, NULL)<0) errExit("recvfrom"); printf("Recv:%sn", buf); exit(EXIT_SUCCESS); }
  • 94. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 94 Physical and virtual address • I/O devices usually use the physical address, because they don’t have address mapping method. • User programs uses virtual address. • We can map the physical to virtual with mmap system call with /dev/mem device
  • 95. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 95 Raspberry Pi specific programming With Linux user API
  • 96. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 96 GPIO programming • In the following section we will use raw GPIO interface via mmap. User space GPIO mem /dev/mem Shared mem GPIO mmap
  • 97. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 97 Ex1. GPIO programming (1) • We will start programming with raw GPIO interface with mmap. • The physical address of GPIO is defined by hardware • We need a little includes to use some Linux API. #define BCM2708_PERI_BASE 0x20000000 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h>Example is based on Dom and Gert from http://elinux.org/RPi_Low-level_peripherals RaspberryPi/apps/C/RPI/ex1_gpio.c The address is 0x3f000000 on Pi 2.The address is 0x3f000000 on Pi 2.
  • 98. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 98 Ex1. GPIO programming (2) • For mmap access, we prepare variables and a constant. • Now start the main • /dev/mem is a device which content is the memory data itself. #define BLOCK_SIZE (4*1024) int mem_fd; volatile unsigned *gpio; int main(int argc, char **argv) { int rep; /* open /dev/mem */ if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { printf("can't open /dev/mem n"); exit(-1); }
  • 99. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 99 Ex1. GPIO programming (3) • Now mmap the gpio address space. /* mmap GPIO */ gpio = (volatile unsigned *)mmap( NULL, //Any adddress in our space will do BLOCK_SIZE, //Map length PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory MAP_SHARED, //Shared with other processes mem_fd, //File to map GPIO_BASE //Offset to GPIO peripheral ); close(mem_fd); //No need to keep mem_fd open after mmap if (gpio == MAP_FAILED) { printf("mmap error %dn", (int)gpio);//errno also set! exit(-1); } Now gpio is a pointer to where the GPIO is mapped on the user space.
  • 100. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 100 Ex1. GPIO programming (4) • Setup the ports direction with FSEL register. – Each GPIO port occupy 3bit of FSEL register, then we use octal number for convenience. • For the input signal, we set pull up registers. // Set gpio direction 0 is input, 1 is output. *gpio = 01110010000; /* GPSEL0 GPIO 9- 0 */ *(gpio+1) = 00110110000; /* GPSEL1 GPIO 19-10 */ *(gpio+2) = 00000111100; /* GPSEL2 GPIO 29-20 */ *(gpio+37)= 2; /* GPPUD enable pull up */ *(gpio+38)= 0x0000000C; /* GPPUDCLK0 set GPIO 2,3 pull up clock */
  • 101. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 101 Ex1. GPIO programming (5) • The body of our program is turn on and off the all LEDs on our board. for(rep=0;rep<100;rep++) { *(gpio+7)=0x03C6c390; /* GPSET0 turn on all LEDs */ printf("%08Xn", *(gpio+13)); /* GPLEV0 print the level value */ sleep(1); *(gpio+10)=0x03C6c390; /* GPCLR0 turn off all LEDs */ printf("%08Xn", *(gpio+13)); /* GPLEV0 print the level value */ sleep(1); } return 0; } // main
  • 102. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 102 The memory mapped I/O • We can use them via mmap. timer pwm spi i2c
  • 103. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 103 Ex2. Timer programming (1) • As GPIO, we can use system timer. – This example will check the accuracy of sleep time. #define BCM2708_PERI_BASE 0x20000000 #define TIMER_BASE (BCM2708_PERI_BASE + 0x3000) #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #define BLOCK_SIZE (4*1024) int mem_fd; volatile unsigned *timer; RaspberryPi/apps/C/RPI/ex2_timer.c The address is 0x3f000000 on Pi 2.
  • 104. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 104 Ex2. Timer programming (2) • The basic structure is just the same int main(int argc, char **argv) { int rep; int timer_val; /* open /dev/mem */ if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { printf("can't open /dev/mem n"); exit(-1); }
  • 105. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 105 Ex2. Timer programming (3) • We use mmap to map system timer timer = (volatile unsigned *)mmap( NULL, //Any adddress in our space will do BLOCK_SIZE, //Map length PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory MAP_SHARED, //Shared with other processes mem_fd, //File to map TIMER_BASE //Offset to GPIO peripheral ); close(mem_fd); //No need to keep mem_fd open after mmap if (timer == MAP_FAILED) { printf("mmap error %dn", (int)timer);//errno also set! exit(-1); }
  • 106. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 106 Ex2. Timer programming (4) • See the accuracy of sleep. for(rep=0;rep<100;rep++) { timer_val = *(timer+1); sleep(1); printf("sleep = %fn", (double)(*(timer+1)-timer_val)/1e6); timer_val = *(timer+1); sleep(1); printf("sleep = %fn", (double)(*(timer+1)-timer_val)/1e6); } return 0; } // main
  • 107. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 107 Ex2. Timer programming (5) • Check the accuracy of normal task and real-time task. – sudo ./ex2_timer.exe – sudo chrt 1 ./ex2_timer.exe Normal Real-time We can get less jitter on real-time task.
  • 108. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 108 Embedded Linux Programming with wiringPi • The wiringPi is an easy to use library for RPi. http://wiringpi.com – This package provides convenient libraries and tools to develop C applications on Raspberry Pi. – Make libraries on Cygwin – Make Associated program on Cygwin and put it on Raspberry Pi – Make applications on Cygwin and put and run on Raspberry Pi
  • 109. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 109 Make your wiringPi application • Change directory to ~/RaspberryPi/apps/C • Make libraries and gpio command – make lib gpio • Copy your gpio binary to Raspberry Pi – scp wiringPi/gpio/gpio pi@192.168.137.XX: where XX depends on your environment. • On Raspbery Pi, copy the gpio to /usr/local/bin – sudo cp gpio /usr/local/bin
  • 110. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 110 WiringPi core functions • At first your will have to include WiringPi/WiringPi.h – Initialize WiringPi – Setup gpio – application wiringPiSetupGpio() pinMode() pullUpDncontrol() wiringPiISR() digitalRead() digitalWrite() There are many intializer functions, but we only use wiringPisetupGpio() functionl
  • 111. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 111 wiringPiSetupGpio() • This function must be called once before any other wiringPi functions are called. – You can also use virtual pin numbering with wiringPiSetup(), but we will not discuss it. int wiringPiSetupGpio(void);
  • 112. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 112 Example: wpitest.c #include <wiringPi.h> #include <stdio.h> #define LED0 4 #define SW1 3 int main (void) { wiringPiSetupGpio () ; pinMode (LED0, OUTPUT) ; pinMode (SW1, INPUT) ; pullUpDnControl(SW1,PUD_UP); for (;;) { digitalWrite (LED0, 1-digitalRead(SW1)) ; } return 0 ; } RaspberryPi/apps/C/WPI/wpitest.c $ cd ~/RaspberryPi/apps/C $ make lib gpio $ make WPI/wpitest.wpi $ scp wiringPi/gpio/gpio pi@192.168.xxxx $ scp WPI/wpitest.wpi pi@192.168.xxxx $ ssh pi@192.168.xxxx Pi$ sudo cp gpio /usr/local/bin Pi$ sudo ./wpitest.wpi
  • 113. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 113
  • 114. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 114 Dive into the kernel kernel modules for Raspberry Pi
  • 115. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 115 Kernel modules and device • There are many things that only kernel can do. Therefore, we want to make kernel modules to do them. • Kernel modules must be compiled with the same configuration and/or version of Linux and its source with the target. – In this seminar, we already have the Linux source code that is compatible to the NOOBS v1.4.0.
  • 116. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 116 Device access • We will access devices via special file (ex. /dev/console) – The special file has two number (major and minor) and block/character property to designate a device • The major number designates a device driver • The minor number designates the functionality – With the opened special file, we can use read/write/ioctl/mmap etc. • The pointers to the corresponding functions are provided by a file_operations structure.
  • 117. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 117 file_operations • Device can provide various file operations. The struct file_operations is defined in linux/fs.h The following is a part of the definition that is usable to most of the device drivers. struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); };
  • 118. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 118 Special file and device driver /dev/foo C, 3,1 1 2 3 255 1 2 3 255 cdevbdev struct file_operations for foo open
  • 119. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 119 Service call behavior • Service call will change the privilege of the process to kernel mode. – Kernel mode can access to user space too. User space kernel space Service call (svc) open() Device driver File descriptor Service call (svc) read() Read_routine() Io space User data copy_to_user()
  • 120. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 120 The kernel modules • The kernel module is a mechanism which extends the functionality of the Linux kernel – The functions on the kernel module work as a part of the Linux kernel. Linux kernel module init_module() cleanup_module() file_operations sys_init_module() sys_delete_module() read() write() ioctl() mmap() Kernel functions variables /proc/kallsyms insmod rmmod User application
  • 121. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 121 Module behavior • System calls are redirected to the module User space kernel space Service call (svc) open() Device driver File descriptor Service call (svc) read() Read_routine() Io space User data copy_to_user()
  • 122. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 122 How to make a module • We need the same source of Linux kernel on that the kernel module will be installed. • You will also need Module.symvers, .config Module source Kernel source Module.symvers .config MakefileKbuild gcc module
  • 123. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 123 Example : hello • Our first module example is hello.c To make the module, in the modules directory, type > make hello.ko To install the module, copy the file to RPi and type > sudo insmod hello.ko  on RPi. #include <linux/module.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Naohiko Shimizu"); int init_module(void) { printk("Hello, worldn"); return 0; } void cleanup_module(void) { printk("Goodbye worldn"); } /home/RaspberryPi/modules/hello.c
  • 124. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 124 Example : helloinit • Our second module example is helloinit.c This module is just like the previous one but added some features. #include <linux/module.h> #include <linux/init.h> static int dec=0; static char* name="world"; module_param(dec, int, 0); module_param(name, charp, 0); int __init init_hello(void) { printk("Hello, %s(%d)n", name, dec); return 0; } void __exit cleanup_hello(void) { printk("Goodbye %sn", name); } module_init(init_hello); module_exit(cleanup_hello); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Naohiko Shimizu"); /home/RaspberryPi/modules/helloinit.c sudo insmod helloinit.ko name=someone dec=10 Parameters declaration specify initialize function names
  • 125. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 125 GPIO control from kernel • On Raspberry Pi, GPIO pins are under the pinctrl module’s control. You need to request and free the pin for you. int pinctrl_request_gpio (unsigned gpio) void pinctrl_free_gpio (unsigned gpio) int pinctrl_gpio_direction_input (unsigned gpio) int pinctrl_gpio_direction_output (unsigned gpio) • We will also use gpiolib functions gpio_set_value (unsigned gpio, unsigned level) gio_get_value (unsigned gpio)
  • 126. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 126 Example : gpio • This example shows how to use gpio. > make gpio.ko /home/RaspberryPi/modules/gpio.c #include <linux/module.h> #include <linux/gpio.h> #include <linux/pinctrl/consumer.h> #define LED 4 #define SW 2 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Naohiko Shimizu"); int ledlevel = 1; int init_module(void) { pinctrl_request_gpio(LED); pinctrl_gpio_direction_output(LED); gpio_set_value(LED,ledlevel); pinctrl_request_gpio(SW); pinctrl_gpio_direction_input(SW); printk("Hello GPIO Pinctrl SW=%dn", gpio_get_value(SW)); return 0; } void cleanup_module(void) { pinctrl_free_gpio(LED); pinctrl_free_gpio(SW); printk("Goodbye GPIO Pinctrln"); }
  • 127. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 127 Interrupt in Linux • Device drivers will request IRQ and register the callback function. • The gpiolib will handle each gpio’s irq. kernel Io device IRQACK Interrupt distributer Device driver callback request_irqgpio_to_irq: get irq number from pin request_irq: register interrupt function free_irq: unregister interrupt
  • 128. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 128 Example: hgpio /home/RaspberryPi/modules/hgpio.c #include <linux/module.h> #include <linux/gpio.h> #include <linux/pinctrl/consumer.h> #include <linux/interrupt.h> #include <asm/io.h> #include “gpio_pud.h” #define SW 2 #define LED 4 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Naohiko Shimizu"); void setup_gpio(void); int ledlevel = 1; static int irq; long count = 0; static irqreturn_t irq_sw(int irq, void *dev_id, struct pt_regs *regs) { ledlevel = 1 - ledlevel; gpio_set_value(LED,ledlevel); count++; return IRQ_HANDLED; } int init_module(void) { setup_gpio(); irq = gpio_to_irq(SW); if(request_irq(irq, (irq_handler_t) irq_sw, IRQF_SHARED|IRQ_TYPE_EDGE_FALLING, "GPIO SW INT", THIS_MODULE->name)<0) printk("request_irq failed"); return 0; } void cleanup_module(void) { free_irq(irq,THIS_MODULE->name); pinctrl_free_gpio(LED); pinctrl_free_gpio(SW); printk("Goodbye GPIO: IRQ %ld timesn",count); }
  • 129. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 129 Example: hgpio /home/RaspberryPi/modules/hgpio.c void setup_gpio(void){ pinctrl_request_gpio(LED); pinctrl_gpio_direction_output(LED); gpio_set_value(LED,ledlevel); pinctrl_request_gpio(SW); pinctrl_gpio_direction_input(SW); gpio_pud(SW,PUD_UP); gpio_pud(7,PUD_DOWN); gpio_pud(8,PUD_DOWN); gpio_pud(9,PUD_DOWN); gpio_pud(4,PUD_DOWN); } #include <linux/gpio.h> #include <linux/delay.h> #include <asm/io.h> #define PUD_UP 2 #define PUD_DOWN 1 #define PUD_OFF 0 #define GPIOUD(x) (0x94+(x)*4) #define GPIOUDCLK(x) (0x98+(x)*4) void gpio_pud(unsigned pin, int control) { void __iomem *base; base = __io_address(GPIO_BASE); writel(control, base+GPIOUD(0)); udelay(5); writel(1<<(pin%32), base+GPIOUDCLK(pin/32)); udelay(5); writel(0, base+GPIOUD(0)); udelay(5); writel(0<<(pin%32), base+GPIOUDCLK(pin/32)); } /home/RaspberryPi/modules/gpio_pud.h
  • 130. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 130 Deferred work • Interrupt handler must return as fast as possible not to lose other interrupts for other handlers. – The heavy process related to this interrupt must be delayed with some method • Tasklet • Workqueue • Timer
  • 131. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 131 Tasklet • Handlers can queue tasklets. • Tasklets will be executed at the end of irq service when each handler is finished. interrupt Interrupt dispatcher Deferred work (soft irq) Handler A Handler B Handler C Tasklet 1 Tasklet 2 Tasklet 3
  • 132. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 132 Example: hgpio_tl /home/RaspberryPi/modules/hgpio_tl.c void tasklet_hgpio(unsigned long data) { int *p=(int*)data; gpio_set_value(LED,*p); *p = 1 - *p; count++; } DECLARE_TASKLET( tl_body, tasklet_hgpio, (unsigned long)&ledlevel); static irqreturn_t irq_sw(int irq, void *dev_id, struct pt_regs *regs) { tasklet_schedule(&tl_body); return IRQ_HANDLED; } • We will only show the modified lines from hgpio.c. – The tasklet body function, declaration, invocation from irq handler.
  • 133. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 133 Workqueue • Handlers can queue works. • Workqueues will be executed at a certain invocation timing or kernel evend daemon for the system’s common queue. interrupt Interrupt dispatcher Handler A Handler B Handler C workqueue 1 workqueue 2 workqueue 3 Some driver Kernel eventd
  • 134. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 134 Example: hgpio_wq /home/RaspberryPi/modules/hgpio_wq.c void work_hgpio(struct work_struct *work) { gpio_set_value(LED, ledlevel); ledlevel = 1 - ledlevel; count++;} DECLARE_WORK(wq_body, work_hgpio); static irqreturn_t irq_sw(int irq, void *dev_id, struct pt_regs *regs) { schedule_work(&wq_body); return IRQ_HANDLED;} • We will only show the modified lines from hgpio.c. – The workqueue body function, declaration, invocation from irq handler and initialize of the data. This example uses schedule_work in which structs are invoked by kernel event daemon. If you need to pass some data to the work, you need to use an extended struct which include struct work_struct.
  • 135. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 135 Timer • Linux provides timers. – Conventional timer is based on jiffies variable – High resolution timer provides precise timing – Timer block has parameter and callback function. Timer 1 Timer 2 Timer 3 Timer 4 Kernel timer interrupt handler Timer new New timer is placed at appropriate link.
  • 136. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 136 Example : timer /home/RaspberryPi/modules/timer.c #include <linux/module.h> #include <linux/pinctrl/consumer.h> #include <linux/gpio.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Naohiko Shimizu"); #define LED 4 static int advance = 100; struct timer_list timer_x; int led = 0; void timer_timeout(unsigned long arg) { led = 1 - led; gpio_set_value(LED,led); timer_x.expires = jiffies + msecs_to_jiffies(advance); add_timer(&timer_x); } int init_module(void) { printk("Hello timern"); pinctrl_request_gpio(LED); pinctrl_gpio_direction_output(LED); init_timer(&timer_x); timer_x.function = timer_timeout; timer_x.expires = jiffies + msecs_to_jiffies(advance); add_timer(&timer_x); return 0; } void cleanup_module(void) { pinctrl_free_gpio(LED); del_timer(&timer_x); printk("Goodbye timern"); }
  • 137. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 137 Example : hrtimer /home/RaspberryPi/modules/hrtimer.c #include <linux/module.h> #include <linux/hrtimer.h> #include <linux/pinctrl/consumer.h> #include <linux/gpio.h> #define LED 4 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Naohiko Shimizu"); static int ledlevel = 1; struct hrtimer hrt; ktime_t kt; int count = 2000; enum hrtimer_restart timer_timeout(struct hrtimer *timer) { ledlevel = 1 - ledlevel; gpio_set_value(LED,ledlevel); if(count) { count--; hrtimer_forward_now(timer,kt); return HRTIMER_RESTART; } return HRTIMER_NORESTART; } int init_module(void) { printk("Hello timern"); pinctrl_request_gpio(LED); pinctrl_gpio_direction_output(LED); gpio_set_value(LED,ledlevel); kt=ktime_set(0,100000000UL); hrtimer_init(&hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrt.function = timer_timeout; hrtimer_start(&hrt,kt, HRTIMER_MODE_REL); return 0; } void cleanup_module(void) { pinctrl_free_gpio(LED); hrtimer_cancel(&hrt); printk("Goodby timern"); }
  • 138. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 138 procfs • Linux provides a convenient method to observe the kernel status by user. – One of them is the procfs which will provide observation points at /proc/ – The obervation points can be hierarchical.
  • 139. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 139 Example: hgpio_proc /home/RaspberryPi/modules/hgpio_proc.c #include <linux/fs.h> #include <linux/proc_fs.h> struct proc_dir_entry *p; static int proc_show_gpio(struct seq_file *m, void *data) { seq_printf(m, "gpio count=%d n", count); return 0; } static int proc_open_gpio(struct inode *id, struct file *file) { return single_open(file, proc_show_gpio, NULL); } static const struct file_operations proc_fops = { .owner = THIS_MODULE, .open = proc_open_gpio, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; • We will only show the modified lines from hgpio.c You can see /proc/proc_gpio entry on your RPi. cat /proc/proc_gpio will show the number of interrupts. int init_module(void) { p=proc_create("proc_gpio", S_IRUGO, NULL, &proc_fops); void cleanup_module(void) { remove_proc_entry("proc_gpio", NULL);
  • 140. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 140 sysctl • Linux provides a convenient method to observe or modify the kernel status by user. – The sysctl will provide observation points at /proc/sys – You can use ‘cat’ to show the value, and ‘echo’ to set the value on the variables.
  • 141. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 141 Example: hgpio_sysctl /home/RaspberryPi/modules/hgpio_sysctl.c ##include <linux/fs.h> #include <linux/sysctl.h> static struct ctl_table proctest_table[] = { {"ledlevel", &ledlevel, sizeof(int), S_IRUGO|S_IWUSR, NULL, &proc_dointvec, NULL, NULL}, {"count", &count, sizeof(int), S_IRUGO|S_IWUSR, NULL, &proc_dointvec, NULL, NULL}, {0} }; static struct ctl_table sys_table[] = { {"hgpio_sysctl", NULL, 0, S_IXUGO|S_IRUGO, proctest_table, NULL, NULL}, {0} }; struct ctl_table_header *s; • We will only show the modified lines from hgpio.c You can see /proc/sys/hgpio_sysctl entry on your RPi. You can get value by cat comnad, and put value with echo (super user only) int init_module(void) { s=register_sysctl_table(sys_table); void cleanup_module(void) { unregister_sysctl_table(s);
  • 142. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 142 • Register the operations • Access via a special file Device access conventional method register_chrdev() struct file_operations { .read= .write= } User application open() read() write() close() special file Major number Module functions Kernel/module file descriptor Make the special file with ‘mknod’ command
  • 143. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 143 Example : device /home/RaspberryPi/modules/device.c #include <linux/module.h> #include <linux/gpio.h> #include <linux/pinctrl/consumer.h> #include <linux/fs.h> #include <asm/uaccess.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Naohiko Shimizu"); #define LED 4 static int led = 0; static ssize_t led_read(struct file *f, char __user *buf, size_t len, loff_t *off) { printk("buf = %p",buf); copy_to_user(buf, (void*)&led, (len>4)?4:len); return (len>4)?4:len; } static ssize_t led_write(struct file *f, const char __user *buf, size_t len, loff_t *off) { printk("buf = %p",buf); copy_from_user((void*)&led, buf, (len>4)?4:len); gpio_set_value(LED,led&1); return (len>4)?4:len; } static struct file_operations LED_fops = { .owner = THIS_MODULE, .read = led_read, .write = led_write }; static int maj; int init_module(void) { printk("Hello devicen"); pinctrl_request_gpio(LED); pinctrl_gpio_direction_output(LED); maj = register_chrdev(0, "device", &LED_fops); if(maj < 0) {printk("Could not get majorn"); return -1;} printk("major = %dn", maj); return 0; } void cleanup_module(void) { pinctrl_free_gpio(LED); if(maj) unregister_chrdev(maj, "device"); printk("Goodbye devicen"); }
  • 144. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 144 Example : device usage /home/RaspberryPi/modules/device_ua.c #include <stdio.h> #include <fcntl.h> int main(int argc, char *argv[]) { int led, fd, i; if(argc<3) { printf("Usage sudo ./device_ua.exe device_file valuen"); return 1; } fd=open(argv[1],O_RDWR); if(fd<0) return 1; read(fd,&led,4); printf("current LED=%dn",led); led=atoi(argv[2]); for(i=0;i<10;i++) { write(fd,&led,4); sleep(1); led=1-led; } return 0; } On Raspberry Pi, sudo insmod device.ko dmesg sudo mknod device c XXX 0 sudo ./device_ua device 1 Where XXX is the major number of device, which can be confirmed with ‘dmesg’ command.
  • 145. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 145 • Automatically generate special file and variable Device access sysfs method alloc_chrdev_region() class_create() device_create() cdev_init() cdev_add() device_create_file() struct file_operations { .read= .write= } User application open() read() write() close() special file Module functions Kernel/module file descriptor special variable /sys/class/foo/foo/var User operations cat echo DEVICE_ATTR
  • 146. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 146 Example : device and class /home/RaspberryPi/modules/class.c #include <linux/module.h> #include <linux/timer.h> #include <linux/gpio.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/cdev.h> #include <linux/fs.h> #include <asm/uaccess.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Naohiko Shimizu"); #define LED 4 static int advance = 100; struct timer_list timer_x; int led = 0; void timer_timeout(unsigned long arg) { led = 1 - led; gpio_set_value(LED,led); timer_x.expires = jiffies + msecs_to_jiffies(advance); add_timer(&timer_x);} static ssize_t callback(struct device *dev,struct device_attribute *attr, const char *buf, size_t count) { long value; if(kstrtol(buf,10,&value) < 0) return -EINVAL; advance = value; del_timer(&timer_x); add_timer(&timer_x); return count;} DEVICE_ATTR(period,0220,NULL,callback); static struct class *sClass; static struct device *sDevice; static struct cdev c_dev; static dev_t dev; static ssize_t led_read(struct file *f, char __user *buf, size_t len, loff_t *off){ printk("buf = %p",buf); copy_to_user(buf, (void*)&advance, (len>4)?4:len); del_timer(&timer_x); add_timer(&timer_x); return (len>4)?4:len;} static ssize_t led_write(struct file *f, const char __user *buf, size_t len, loff_t *off){ printk("buf = %p",buf); copy_from_user((void*)&advance, buf, (len>4)?4:len); del_timer(&timer_x); add_timer(&timer_x); return (len>4)?4:len;} static struct file_operations LED_fops = { .owner = THIS_MODULE, .read = led_read, .write = led_write }; To be continued
  • 147. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 147 Example : device and class /home/RaspberryPi/modules/class.c int init_module(void) { printk("Hello timern"); pinctrl_request_gpio(LED); pinctrl_gpio_direction_output(LED); init_timer(&timer_x); timer_x.function = timer_timeout; timer_x.expires = jiffies + msecs_to_jiffies(advance); add_timer(&timer_x); alloc_chrdev_region(&dev, 0, 1, "LED"); sClass = class_create(THIS_MODULE, "LED"); sDevice = device_create(sClass,NULL,dev,NULL,"LED"); cdev_init(&c_dev, &LED_fops); cdev_add(&c_dev, dev, 1); device_create_file(sDevice,&dev_attr_period); return 0; } void cleanup_module(void) { pinctrl_free_gpio(LED); del_timer(&timer_x); cdev_del(&c_dev); device_remove_file(sDevice,&dev_attr_period); device_destroy(sClass,dev); class_destroy(sClass); unregister_chrdev_region(dev,1); printk("Goodbye timern"); } To make our life simple we will be the super user. $ sudo –s # insmod class.ko # echo 2000 > /sys/class/LED/LED/period # ls –l /dev/LED crw------- 1 root root 246, 0 Feb 28 06:25 /dev/LED
  • 148. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 148 Memory mapping • To avoid the system call overhead, we can use mmap to map the physical memory to the user virtual address space. Device registers on physcal memory Device registers mapped on user virtual memory Physical space User virtual space
  • 149. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 149 Example : mmap /home/RaspberryPi/modules/mmap.c #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/highmem.h> #include <linux/device.h> #include <linux/cdev.h> #include <asm/io.h> #include <asm/uaccess.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Naohiko Shimizu"); void* mmap_area=0; char* mmap_vm; void vma_open(struct vm_area_struct *vma) { printk(KERN_NOTICE "mmap open. virt : %lx, phys : %lxn ", vma->vm_start , vma->vm_pgoff << PAGE_SHIFT); } void vma_close(struct vm_area_struct *vma) { printk(KERN_NOTICE "mmap close.n"); } static struct vm_operations_struct remap_vm_ops = { .open = vma_open, .close = vma_close, }; static int remap_mm(struct file *filp, struct vm_area_struct *vma) { vma->vm_flags |= VM_IO; vma->vm_pgoff = virt_to_phys(mmap_area)>>PAGE_SHIFT; if(remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; vma->vm_ops = &remap_vm_ops; vma_open(vma); return 0;} static struct file_operations mmap_fops = { mmap: remap_mm, }; static dev_t dev; static struct class *sClass; static struct device *sDevice; static struct cdev c_dev; To be continued
  • 150. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 150 Example : mmap /home/RaspberryPi/modules/mmap.c int init_module(void) { mmap_area=(void*)__get_free_page(GFP_KERNEL); *(int*)(mmap_area)=0x12345678; printk("Hello mmap(%p)n",(void*)mmap_area); alloc_chrdev_region(&dev,0,1,"mmap_test"); sClass=class_create(THIS_MODULE,"Mmap"); sDevice=device_create(sClass,NULL,dev,NULL,"Mma p"); cdev_init(&c_dev, &mmap_fops); cdev_add(&c_dev, dev, 1); return 0; } void cleanup_module(void) { printk("Goodbye mmapn"); cdev_del(&c_dev); device_destroy(sClass,dev); class_destroy(sClass); unregister_chrdev_region(dev,1); free_page((unsigned int)mmap_area); } #include <stdio.h> #include <sys/mman.h> #include <string.h> #include <fcntl.h> int main(int argc, char**argv) { int fd, i; int *buffer; fd=open("/dev/Mmap",O_RDWR); printf("open fd(%d)n",fd); if(argc>1) { buffer=(int*)mmap(NULL, 0x1000, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0); printf("buffer address=%pn",buffer); for(i=1;i<argc;i++) { buffer[i-1]=atoi(argv[i]); } } else buffer=(int*)mmap(NULL,0x1000,PROT_READ, MAP_PRIVATE,fd,0); msync(buffer,0x1000,MS_SYNC); for(i=0;i<10;i++) { printf("buff[%d]=%08xn", i, buffer[i]); } return(0); } User routine mmaptest.c
  • 151. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 151 Rapid prototyping with Python
  • 152. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 152 Python basics • Python was designed by Guido van Rossum in 90’s. • Easy to use – Simple syntax – interpreter – The variables does not have type but the object has. – Comprehensive standard library • Cross platform • Free
  • 153. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 153 Python introduction • Values • Data types – int, float, bool, str – list, tuple, set, dictionary • Operators • Controls • Functions • Classes • Modules
  • 154. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 154 Values • Integer – Binary number : 0b1100 – Octal number: 0o71 – Hex decimal number: 0x2f – Decimal number: 12345678901234567901234 • Float – 3.14e-1 – 1.435 • Complex number – 1+3j • Boolean – True, False
  • 155. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 155 Data types • The int type represents an integer. Unlike C or Java, Python’s integer does not have fixed bit size, but can be unlimited digit. • The float type represents a floating point number. It is just same as C’s double precision number • The bool is a Boolean type. • The str type is a string of characters.
  • 156. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 156 Example • Invoke python3 with python3 command > python3 • Try to print any data with print() command >>> print(3.14) 3.14 >>> print(123456789012345678901234567890) 123456789012345678901234567890 >>> print(True) True >>> print(‘abc def’) abc def
  • 157. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 157 Data types - continue • The list is a sequence of data in brackets [1,”x”,[1,2,3],True] • The tuple is also a sequence of data in parentheses. Unlike lists, it cannot be changed. (2,”F”,0) • The dictionary is an association structure in braces. {“key1”:”value1”,”key2”:”value2”} • The set is a set of data in braces. {‘2’, ‘5’, ‘9’}
  • 158. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 158 Example • Try to print the values on Python >>> print([1,”x”,[1,2,3],True]) [1, 'x', [1, 2, 3], True] >>> print((2,”F”,0)) (2, 'F', 0) >>> print({“key1”:”value1”,”key2”:”value2”}) {'key2': 'value2', 'key1': 'value1'} >>> print({‘2’, ‘5’, ‘9’}) {'9', '5', '2'}
  • 159. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 159 Operators(1) • Numerical/comparison operators • Boolean operators + Addition - Subtraction * Multiplication // Division % Remainder / Division (float) ** To the power int() Convert to integer float() Convert to float < Less than > Greater than == Equal <= Less than or Equal to >= Greater than or Equal to != Not equal to and or not
  • 160. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 160 Example • Try to use operators for values >>> print(10/3) 3.3333333333333335 >>> print(10//3) 3 >>> print(0b11000011 | 0x3c) 255 >>> print(10 or 30) 10 >>> print(5 and 10) 10 >>> print((0+1j)**2) (-1+0j)
  • 161. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 161 Operators(2) • String operators String[x] Get the xth character String[x:y] Get substring from xth to yth String[:y] Get substring to yth String[x:] Get substring from xth to the end len(string) Return the length of the string String+string Join two strings str(expression) Convert to string
  • 162. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 162 Example >>> 'abcdefg'[1] 'b' >>> 'abcdefg'[1:4] 'bcd' >>> 'abcdefg'[:3] 'abc' >>> 'abcdefg'[5:] 'fg' >>> len('abcdefg') 7 >>> 'abc'+'hij' 'abchij' >>> str(3+2j) '(3+2j)' >>> str((3+2j)**2) '(5+12j)'
  • 163. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 163 Operators and methods(3) • List List[i] return the ith elements of the list len(list) Return the number of the element inside + Return the merged list *num Repeat the list num times item in List Return whether item is in the List or not List.appned(item) Add item to the end of the list List.extend(list2) Join the list2 to the end of the list List.pop(x) Return and remove the xth item List.insert(x,item) Insert item at the xth position List.sort() Sort the list List.index(item) Return the position of the first occurrence of item List.count(item) Count how many items are in list List.remove(item) Remove the first occurrence of item
  • 164. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 164 Example >>> [1,2,3,4][2] 3 >>> len([1,2,3,4]) 4 >>> [1,2,3,4]+[5,6] [1, 2, 3, 4, 5, 6] >>> [1,2]*3 [1, 2, 1, 2, 1, 2] >>> 2 in [1,2,3,4] True >>> 5 in [1,2,3,4] False >>> [1,2,3,4].pop(3) 4 >>> [1,2,3,4].count(3) 1 >>> [1,2,3,4].index(3) 2
  • 165. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 165 Operators and methods(4) • Dictionary • Set Dict[key] Return the value of the dictionary item with key key in Dict Return whether key is in Dict or not Dict.keys() Get the view of the Dict del Dict[key] Remove the data associated with key in Dict Set1 & Set2 Return the intersection of sets Set1 | Set2 Return the union of sets Set1 – Set2 Return the difference of sets Set1 ^ Set2 Return the symmetric difference x in Set Return whethere x is in Set or not Set1 <= Set2 Return whether Set1 is the subset of Set2 or not Set1 >= Set2 Return whether Set1 is the superset of Set2 or not
  • 166. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 166 Example >>> {'abc':1, 'def':2, 'hij':3}['hij'] 3 >>> 'def' in {'abc':1, 'def':2, 'hij':3} True >>> {'abc':1, 'def':2, 'hij':3}.keys() dict_keys(['hij', 'abc', 'def']) >>> {1,2,3} & {2,3,4} {2, 3} >>> {1,2,3} | {2,3,4} {1, 2, 3, 4} >>> {1,2,3} - {2,3,4} {1} >>> {1,2,3} ^ {2,3,4} {1, 4} >>> 3 in {1,2,3} True >>> {1,2,3} <= {1,5,4,3,2} True >>> {1,2,3} >= {1,2} True
  • 167. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 167 Controls • while condition: loop while condition is true • for i in range(1,10): loop i for the set of items. Item can be list, set, etc. • if condition: selective execution elif condtion2: else: • try: Catching exceptions except type_of_error:
  • 168. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 168 Type of Errors on Python • There are many exceptions which will be raised on Python – See the python document for detail: https://docs.python.org/3/library/exceptions.htm l – Commonly used exceptions: SystemExit, KeyboardInterrupt , ArithmeticError, OverflowError, ZeroDivisionError, EOFError, LookupError, FileExistsError, FileNotFoundError, PermissionError, TypeError , ValueError
  • 169. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 169 Example >>> i=0 >>> while i<10: ... print(i) ... i=i+1 ... 0 1 2 3 4 5 6 7 8 9
  • 170. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 170 Example >>> for i in [1,5,6]: ... print(i) ... 1 5 6
  • 171. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 171 Example >>> if 2 in [1,5,6]: ... print(True) ... elif 5 in [1,5,6]: ... print("ELIF") ... else: ... print(False) ... ELIF
  • 172. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 172 Example >>> try: ... 1/0 ... except ZeroDivisionError: ... print("Zero Division Error") ... Zero Division Error >>> try: ... 1/1 ... except ZeroDivisionError: ... print("Zero Division Error") ... 1.0
  • 173. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 173 Functions • def func_name(parameters): defines function. Parameters can have default values. – Any new variables in functions are treated as local. If you want to access to global variables, you need designate ‘global’ explicitly.
  • 174. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 174 Example >>> def foo(a): ... return(a+1) ... >>> foo(3) 4 >>> def foo2(x=1): ... return(x**2) ... >>> foo2() 1 >>> foo2(4) 16
  • 175. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 175 Classis • class class_name(): def __init__(self, parameters): self.parameters = parameters; def own_method(self): self.parameters = self.parameters +1
  • 176. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 176 Example >>> class cfoo(): ... def __init__ (self, p1): ... self.p1 = p1 ... def myfunc(self): ... self.p1 = self.p1**2 ... def myget(self): ... return(self.p1) ... >>> a=cfoo(10) >>> a.myget() 10 >>> a.myfunc() >>> a.myget() 100
  • 177. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 177 Modules • You can make a file ‘foo.py’ which contains any definitions of functions or classes or variables. You can import the file with import command. import foo
  • 178. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 178 Example • Make a file which name is foo.py and make the content as print("foo imported") • Invoke python3 and type “import foo” >>> import foo foo imported
  • 179. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 179 Time on Python • The time module provides the method for time. – time.monotonic(): Return the value (in fractional seconds) of a monotonic clock, i.e. a clock that cannot go backwards. The clock is not affected by system clock updates. The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid. – time.sleep(secs): Suspend execution of the calling thread for the given number of seconds. The argument may be a floating point number to indicate a more precise sleep time. The actual suspension time may be less than that requested because any caught signal will terminate the sleep() following execution of that signal’s catching routine. Also, the suspension time may be longer than requested by an arbitrary amount because of the scheduling of other activity in the system. – time.ctime([secs]): Convert a time expressed in seconds since the epoch to a string representing local time. If secs is not provided or None, the current time as returned by time() is used. ctime(secs) is equivalent to asctime(localtime(secs)). Locale information is not used by ctime().
  • 180. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 180 Threading on Python • The threading module will provide to control multiple threading. You can start and join threads. import threading as t import time def thr(Name, value): print(Name+":"+str(value)+" "+time.ctime()) time.sleep(value) print(Name+" end sleep "+time.ctime()) quit() t1=t.Thread(target=thr,args=("1st",10)) t2=t.Thread(target=thr,args=("2nd",5)) t1.start() t2.start() t1.join() t2.join() Thread.py
  • 181. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 181 Timer on Python • We will use the timer funciton in threading package. – threading.Timer can designate an activation time in seconds and a call back thread import threading def cb(): print(“called”) quit() t=threading.Timer(10,cb) t.start()
  • 182. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 182 Interval timer module making • The threading module does not provide interval timer functionality. So I wrote my module which provides one by myself. • Extract and install it – Send PyTimer-0.1.tar.bz2 to Raspberry Pi – Then type following commands on Pi > tar xjvf PyTimer-0.1.tar.bz2 > cd PyTimer-0.1 > python3 setup.py install – You will get PyTimer module on Pi
  • 183. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 183 PyTimer methods • There are four method on PyTimer – Create : Create an interval timer and designate the callback function – Delete : Delete the timer – Gettime : Get the remaining time of the timer and the interval – Settime : Set the timer value and start it
  • 184. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 184 PyTimer module methods(create) • Create a new timer • PyTimer.create(clockid, [callback]) : timerid – Clockid can be PyTimer.CLOCK_REALTIME, PyTimer.CLOCK_MONOTONIC, etc. • Cygwin only support CLOCK_REALTIME – Callback designate to the method for callback. It is optional parameter – The method returns the timerid created
  • 185. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 185 PyTimer module methods(delete) • Delete an existing timer • PyTimer.delete(timerid) – The timerid must be one that PyTimer.create() returned.
  • 186. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 186 PyTimer module methods(gettime) • Get the timer value of an existing timer • PyTimer.gettime(timerid) : (remain, interval) – The timerid must be one that PyTimer.create() returned.
  • 187. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 187 PyTimer module methods(settime) • Set the timer value and start timer • PyTimer.settime(timerid,start,[period],[flag]) – The timerid must be one that PyTimer.create() returned. – The start designate the start value of the timer – The period designate the interval of the timer. Optional – The flag designate where the start time is the absolute (wall clock) time or not. Set TIMER_ABSTIME for wall clock.
  • 188. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 188 Try the PyTimer on LiveCygwin • Try followings.  python3 >>> import PyTimer >>> t=PyTimer.create(PyTimer.CLOCK_REALTIME) >>> PyTimer.settime(t,1000) >>> print(PyTimer.gettime(t)) >>> print(PyTimer.gettime(t))
  • 189. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 189 Excersize • Make a python program which print time and date every 15 seconds. It must be terminated safely with keyboard interrupt (Control-C). • Make a python program for keyboard typing training and evaluate the user skill with WPS(Words Per Seconds)
  • 190. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 190 Writing Python module with C • If your project needs more functionality on Python, you can make a extension module with C – Make a simple Python module with C – Compile and use with Python – Test the module with PyUnit (unittest)
  • 191. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 191 Make a simple Python module with C • How Python can find your module(pyfoo)? – Prepare PyModuleDef and/or PyMethodDef struct – Special initialize function with the module name will be called with above struct. • Python3: PyInit_pyfoo • Python2. X:Initpyfoo – Write your own methods
  • 192. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 192 Method writing (1) #include "Python.h“ // python function foo(arg, oparg) static PyObject *py_foo(PyObject *self, PyObject *args, PyObject *kwargs) { double arg, oparg=-1; static char *kwlist[] = {"arg", "oparg", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d|d", kwlist, &arg, &oparg)) return NULL; return Py_BuildValue("(dd)", arg, oparg); } RaspberryPi/apps/Python/pyfoo/pyfoo.c
  • 193. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 193 Method writing (2) // python function goo(arg) static PyObject *py_goo(PyObject *self, PyObject *args) { int arg; if (!PyArg_ParseTuple(args, "i", &arg)) return NULL; switch(arg) { case 0: return Py_BuildValue("s", "arg=0"); case 1: PyErr_SetString(PyExc_RuntimeError, "arg==1"); return NULL; case 2: PyErr_SetString(PyExc_ValueError, "arg==2"); return NULL; case 3: PyErr_SetString(PyExc_BaseException, "arg==3"); return NULL; case 4: PyErr_SetString(PyExc_StandardError, "arg==4"); return NULL; case 5: PyErr_SetString(PyExc_OSError, "arg==5"); return NULL; default: break; } Py_RETURN_NONE; }
  • 194. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 194 Module definition example static const char moduledocstring[] = "pyfoo functions"; static PyMethodDef pyfoo_methods[] = { {"foo", (PyCFunction)py_foo, METH_VARARGS | METH_KEYWORDS, "foo - function1narg - argumentn [oparg] - optional argumentn"}, {"goo", (PyCFunction)py_goo, METH_VARARGS, "goo - function2narg - argument "}, {NULL, NULL, 0, NULL} }; #if PY_MAJOR_VERSION > 2 static struct PyModuleDef pyfoomodule = { PyModuleDef_HEAD_INIT, "pyfoo", // name of module moduledocstring, // module documentation, may be NULL -1, // size of per-interpreter state of the module, or -1 if the module keeps s tate in global variables. pyfoo_methods }; #endif
  • 195. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 195 Module initialize #if PY_MAJOR_VERSION > 2 PyMODINIT_FUNC PyInit_pyfoo(void) #else PyMODINIT_FUNC initpyfoo(void) #endif { PyObject *module = NULL; #if PY_MAJOR_VERSION > 2 if ((module = PyModule_Create(&pyfoomodule)) == NULL) return NULL; #else if ((module = Py_InitModule("pyfoo", pyfoo_methods)) == NULL) return; #endif if (!PyEval_ThreadsInitialized()) PyEval_InitThreads(); #if PY_MAJOR_VERSION > 2 return module; #else return; #endif }
  • 196. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 196 Compile module • On cygwin, target module must be DLL On RaspberryPi/apps/Python/pyfoo directory, gcc --shared -I/usr/include/python2.7 pyfoo.c - lpython2.7 -o pyfoo.dll Or gcc --shared -I/usr/include/python3.4m pyfoo.c - lpython3.4m -o pyfoo.dll
  • 197. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 197 Import the module and run • Run python >>> import pyfoo >>> pyfoo.foo(3,oparg=5) (3.0, 5.0) >>> pyfoo.foo(oparg=5,arg=3) (3.0, 5.0) >>> pyfoo.foo(2,3) (2.0, 3.0) >>> pyfoo.goo(0) 'arg=0' >>> pyfoo.goo(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: arg==1 >>> pyfoo.goo(2) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: arg==2
  • 198. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 198 Test your module with PyUnit(1) • Make your test script with PyUnit as test.py import unittest import pyfoo class TestFoo(unittest.TestCase): def test_foo1(self): """Test foo with 1 argument""" self.assertEqual(pyfoo.foo(400), (400.0,-1.0)) def test_foo2(self): """Test foo with 2 argument""" self.assertEqual(pyfoo.foo(3,5), (3.0,5.0)) def test_fook1(self): """Test foo with 1 keyword argument""" self.assertEqual(pyfoo.foo(arg=3), (3.0,-1.0)) def test_fook2(self): """Test foo with 2 keyword argument""" self.assertEqual(pyfoo.foo(oparg=10, arg=3), (3.0,10.0)) def test_goo0(self): """Test goo(0)""" self.assertEqual(pyfoo.goo(0), 'arg=0')
  • 199. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 199 Test your module with PyUnit(2) def test_over_goo1(self): """Test goo(1)""" with self.assertRaises(RuntimeError): pyfoo.goo(1) def test_over_goo2(self): """Test goo(2)""" with self.assertRaises(ValueError): pyfoo.goo(2) def test_over_goo3(self): """Test goo(3)""" with self.assertRaises(BaseException): pyfoo.goo(3) def test_over_goo4(self): """Test goo(4)""" with self.assertRaises(StandardError): pyfoo.goo(4) def test_over_goo5(self): """Test goo(5)""" with self.assertRaises(OSError): pyfoo.goo(5) def test_over_goo6(self): """Test goo(6)""" self.assertIsNone(pyfoo.goo(6)) if __name__ == '__main__': unittest.main()
  • 200. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 200 Test your module with PyUnit(3) • Run the test $ python -m unittest test ........... ---------------------------------------------------------------------- Ran 11 tests in 0.001s OK $
  • 201. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 201 Exercise • Read PyTimer source code and discuss how it works. • Make a python module with C and test it which provides – Fibonacci function – Dynamic display on 7 segments LEDs
  • 202. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 202 Python for RaspberryPi • We will use Rpi GPIO package to control RaspberryPi with Python – GPIO – PWM – Interrupts
  • 203. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 203 RPi.GPIO Objects • Port voltage level – HIGH: high level – LOW: low level • Port direction – OUT: output – IN: input • Pin number scheme – BOARD: -- – BCM: ARM chip pin number • GPIO pull up/down control – PUD_OFF: pull up/down off – PUD_UP: pull up – PUD_DOWN: pull down • GPIO edge detect – RISING: GPIO risign edge – FALLING: GPIO falling edge – BOTH: GPIO both edge • Pin function – HARD_PWM: hardware PWM – SERIAL: uart – I2C: I2C – SPI: SPI – UNKNOWN: unknown function • VERSION • RPI_REVISION • RPI_INFO • PWM: PWM control objects
  • 204. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 204 RPi.GPIO Method • GPIO method – setup – cleanup – output – input – setmode – getmode – add_event_detect – remove_event_detect – event_detected – add_event_callback – wait_for_edge – gpio_function – setwarnings • PWM method – Start – ChangeDutyCycle – ChangeFrequency – stop
  • 205. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 205 RPi.GPIO Method: setup • Set up a GPIO channel or list of channels with a direction and (optional) pull/up down control channel - either board pin number or BCM number depending on which mode is set. – direction - IN or OUT – [pull_up_down] - PUD_OFF (default), PUD_UP or PUD_DOWN – [initial] - Initial value for an output channel
  • 206. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 206 RPi.GPIO Method: cleanup • Clean up by resetting all GPIO channels that have been used by this program to INPUT with no pullup/pulldown and no event detection – [channel] - individual channel or list/tuple of channels to clean up. Default - clean every channel that has been used.
  • 207. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 207 RPi.GPIO Method: output • Output to a GPIO channel or list of channels – channel - either board pin number or BCM number depending on which mode is set. – value - 0/1 or False/True or LOW/HIGH
  • 208. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 208 RPi.GPIO Method: input • Input from a GPIO channel. Returns HIGH=1=True or LOW=0=False – channel - either board pin number or BCM number depending on which mode is set.
  • 209. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 209 RPi.GPIO Method: setmode • Set up numbering mode to use for channels. – BOARD - Use Raspberry Pi board numbers – BCM - Use Broadcom GPIO 00..nn numbers
  • 210. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 210 RPi.GPIO Method: getmode • Get numbering mode used for channel numbers. – Returns BOARD, BCM or UNKNOWN
  • 211. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 211 RPi.GPIO Method: add_event_detect • Enable edge detection events for a particular GPIO channel. – channel - either board pin number or BCM number depending on which mode is set. – edge - RISING, FALLING or BOTH – [callback] - A callback function for the event (optional) – [bouncetime] - Switch bounce timeout in ms for callback
  • 212. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 212 RPi.GPIO Method: remove_event_detect • Remove edge detection for a particular GPIO channel – channel - either board pin number or BCM number depending on which mode is set.
  • 213. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 213 RPi.GPIO Method: event_detected • Returns True if an edge has occured on a given GPIO. You need to enable edge detection using add_event_detect() first. – channel - either board pin number or BCM number depending on which mode is set.
  • 214. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 214 RPi.GPIO Method: add_event_callback • Add a callback for an event already defined using add_event_detect() – channel - either board pin number or BCM number depending on which mode is set. – callback - a callback function
  • 215. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 215 RPi.GPIO Method: wait_for_edge • Wait for an edge. – channel - either board pin number or BCM number depending on which mode is set. – edge - RISING, FALLING or BOTH – [bouncetime] - time allowed between calls to allow for switch bounce
  • 216. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 216 RPi.GPIO Method: gpio_function • Return the current GPIO function (IN, OUT, PWM, SERIAL, I2C, SPI) – channel - either board pin number or BCM number depending on which mode is set.
  • 217. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 217 RPi.GPIO Method: setwarnings • Enable or disable warning messages – value - 0/1 or False/True or LOW/HIGH
  • 218. Copyright (c) 2015 Naohiko Shimizu, All rights reserved 218 PWM Method • start : Start software PWM – dutycycle - the duty cycle (0.0 to 100.0) • ChangeDutyCycle: Change the duty cycle – dutycycle - between 0.0 and 100.0 • ChangeFrequency: Change the frequency – frequency - frequency in Hz (freq > 1.0) • stop: Stop software PWM