55. #define BCM2708_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000)
int setup(void)
{
int mem_fd;
uint8_t *gpio_mem;
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0)
{
return SETUP_DEVMEM_FAIL;
}
if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
return SETUP_MALLOC_FAIL;
….
gpio_map = (uint32_t *)mmap( (caddr_t)gpio_mem, BLOCK_SIZE,
PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, GPIO_BASE);
}
WebIOPi-0.7.1¥python¥native¥gpio.c
ソースコードの確認(初期化処理-1)
55
←0x2000 00000x7E00 0000→
※ Raspberry Pi3で利用されているBCM2836/2837では、周辺機器用のPhysical Address上のアドレ
スは、0x2000 0000から0x3F000000に変更になっており、WibIOPiのパッチで、Raspberry Pi3の場
合は周辺機器用のベースアドレスが変更されていることに注意
←0x0000 0000
←0x2020 0000(GPIO用)0x7E20 0000→
https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
Bus Address Field Name Description Size
0x 7E20 0000 GPFSEL0 GPIO Function Select 0
Function Select 0-9
32
… … … …
6. General Purpose I/O (GPIO)
なるほど・・・
56. ソースコードの確認-初期化処理-2
56
#define FSEL_OFFSET 0 // 0x0000
#define IN 0
#define OUT 1
void set_function(int gpio, int function, int pud)
{
if (function == PWM) {
function = OUT;
enablePWM(gpio);
}
...
int offset = FSEL_OFFSET + (gpio/10);
int shift = (gpio%10)*3;
set_pullupdn(gpio, pud);
*(gpio_map+offset) = (*(gpio_map+offset) &
~(7<<shift)) | (function<<shift);
}
WebIOPi-0.7.1¥python¥native¥gpio.c
Bus Address Field Name Description Size
0x 7E20 0000 GPFSEL0 GPIO Function Select 0
Function Select 0-9
32
0x 7E20 0004 GPFSEL1 GPIO Function Select 1
Function Select 10-19
32
0x 7E20 0008 GPFSEL2 GPIO Function Select 2
Function Select 20-29
32
Bit(s) Field Name Description
... ... ...
17-15 FSEL25 FSEL25 - Function Select 25
000 = GPIO Pin 25 is an input
001 = GPIO Pin 25 is an output
100 = GPIO Pin 25 takes alternate
function 0
...
Register Assignment
GPIO Alternate function select register 2
なるほど・・・
57. ソースコードの確認-モーター回転処理
57
Bit(s) Field Name Description
31-0 SETn(n=0..31) 0 = No effect
1 = Set GPIO pin n
Bus Address Field Name Description Size
0x 7E20 001C GPSET0 GPIO Pin Output Set 0 32
0x 7E20 0020 GPSET1 GPIO Pin Output Set 1 32
Register Assignment
GPIO Output Set Register 0
void pulseTS(int gpio, struct timespec *up, struct timespec *down) {
if ((up->tv_sec > 0) || (up->tv_nsec > 0)) {
output(gpio, 1);
nanosleep(up, NULL);
}
if ((down->tv_sec > 0) || (down->tv_nsec > 0)) {
output(gpio, 0);
nanosleep(down, NULL);
}
}
#define SET_OFFSET 7 // 0x001c / 4
void output(int gpio, int value)
{
int offset, shift;
if (value) // value == HIGH
offset = SET_OFFSET + (gpio/32);
else // value == LOW
offset = CLR_OFFSET + (gpio/32);
shift = (gpio%32);
*(gpio_map+offset) = 1 << shift;
} WebIOPi-0.7.1¥python¥native¥gpio.c
Bit(s) Field Name Description
31-0 SETn(n=32..53) 0 = No effect
1 = Set GPIO pin n
GPIO Output Set Register 1
なるほど・・・
58. /dev/memの権限の確認
• 公開され、root権限でread/write可能
• webiopiモジュールは、root権限で実行されている
• kernelのbuild設定で、CONFIG_DEVMEMが有効になっている
58
pi@raspberrypi:~ $ ps axu|grep webiopi
root 570 2.1 1.4 77340 13328 ? Sl 05:01 4:17 /usr/bin/python3 -m webiopi -l /var/log/webiopi -
c /etc/webiopi/config
pi@raspberrypi:~/linux $ KERNEL=kernel7
pi@raspberrypi:~/linux $ make bcm2709_defconfig
pi@raspberrypi:~/linux $ grep “DEVMEM” .config
CONFIG_DEVMEM=y
# CONFIG_DEVKMEM is not set
https://github.com/raspberrypi/linux
pi@raspberrypi:~ $ ls -lZ /dev/|grep mem
crw-r----- 1 root kmem ? 1, 1 1月 20 18:39 mem
なるほど・・・
59. /dev/gpiomemの権限の確認
• /dev/gpiomemは、gpioグループの権限でread/write可能
• RPi.GPIOは、/dev/gpiomemをopenしている
59
pi@raspberrypi:~ $ ls -lZ /dev/|grep mem
crw-rw---- 1 root gpio ? 244, 0 1月 20 18:39 gpiomem
pi@raspberrypi:~ $ id
uid=1000(pi) gid=1000(pi)
groups=1000(pi),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(g
ames),100(users),101(input),108(netdev),997(gpio),998(i2c),999(spi)
int setup(void)
{
// try /dev/gpiomem first - this does not require root privs
if ((mem_fd = open("/dev/gpiomem", O_RDWR|O_SYNC)) > 0)
{
gpio_map = (uint32_t *)mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0);
}
RPi.GPIO-0.6.3¥source¥c_gpio.c
なるほど・・・
60. 比較:/dev/memの権限
• /dev/memは存在しない
• kernelのbuild設定で、CONFIG_DEVMEMが有効になっていない
• CTSでチェックしている(Android 2.3以降)
60
bullhead:/ $ ls -al /dev/mem
ls: /dev/mem: No such file or directory
# CONFIG_DEVMEM is not set
https://android.googlesource.com/kernel/msm/+/android-msm-bullhead-3.10-marshmallow-mr2/arch/arm64/configs/bullhead_defconfig
https://android.googlesource.com/platform/cts/+/master/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
Android
public void testDevMemSane() throws Exception {
File f = new File("/dev/mem");
assertFalse(f.exists());
}