Advertisement

Introduction to the rapid prototyping with python and linux for embedded systems

Profeseur invite at LIP6 UPMC
Sep. 14, 2015
Advertisement

More Related Content

Advertisement

Introduction to the rapid prototyping with python and linux for embedded systems

  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
Advertisement