Wyjaśnimy Ci co to jest system heterogoniczny, jak wygląda Linuxowy sterownik do "misc. character device" oraz w jaki sposób Linux może dogadać się z FreeRTOSem.
3. Plan
● Podział systemów wieloprocesorowych
● Przykład systemu heterogenicznego
● Linuxowy misc/char device driver
○ ogólnie
○ na przykładzie cm3
● O czym pamiętać podczas komunikacji IPC
○ rozmieszczenie struktur w pamięci
○ optymalizacje kompilatora i procesora
○ bariery
○ typy pamięci w arm
5. Plan
● Podział systemów wieloprocesorowych
● Przykład systemu heterogonicznego
● Linuxowy misc/char device driver
○ ogólnie
○ na przykładzie cm3
● O czym pamiętać podczas komunikacji IPC
○ rozmieszczenie struktur w pamięci
○ optymalizacje kompilatora i procesora
○ bariery
○ typy pamięci w arm
7. CM3 jako część SoC’a
- koszt (zajmowany krzem)
- cm3 jako peryferium
- ściśle określone zadania
- zgłasza przerwania
- wymiana danych
- koprocesor ogólnego przeznaczenia
- lepiej niż SW, gorzej niż HW
- małe opóźnienia obsługi przerwań
- mniejszy niż FPGA
- programowa realizacja peryferium
- wielofunkcyjność (w zależności od
potrzeb)
ARMv7
UART
Kontroler
SATA
Kontroler
PCI
P4
CM3
CPU
1
CPU
2
L1 L1
L2
...
10. Plan
● Podział systemów wieloprocesorowych
● Przykład systemu heterogonicznego
● Linuxowy misc/char device driver
○ ogólnie
○ na przykładzie cm3
● O czym pamiętać podczas komunikacji IPC
○ rozmieszczenie struktur w pamięci
○ optymalizacje kompilatora i procesora
○ bariery
○ typy pamięci w arm
11. Char/misc device driver
- Urządzenie jako plik
- powszechnie używane - np /dev/mem
(dostęp do pamięci fizycznej + devmem tool)
- open, close, read, write itd.
- major/minor number
crw-r----- 1 root kmem 1, 1 Jun 4 02:25 mem
crw-r----- 1 root kmem 1, 2 Jun 4 02:25 kmem
crw--w---- 1 root tty 4, 0 Jun 4 02:25 tty0
crw-rw---- 1 root tty 4, 1 Jun 4 02:25 tty1
Aplication
Char
Dev File
Character driver
Device
User Space
Kernel Space
Kernel Space
Hardware Space
12. cm3 misc driver
- Urządzenie jako plik
- powszechnie używane - np /dev/mem
(dostęp do pamięci fizycznej)
- open, close, read, write itd.
- major/minor number
cm3_tool
/dev/cm3
driver/misc/cm3
cm3
mem
User Space
Kernel Space
Kernel Space
Hardware Space
cm3
control
13. cm3 misc driver - write
- Urządzenie jako plik
- powszechnie używane - np /dev/mem
(dostęp do pamięci fizycznej)
- open, close, read, write itd.
- major/minor number
cm3_tool
/dev/cm3
driver/misc/cm3
cm3
mem
User Space
Kernel Space
Kernel Space
Hardware Space
cm3
control
14. cm3 misc driver - read
- Urządzenie jako plik
- powszechnie używane - np /dev/mem
(dostęp do pamięci fizycznej)
- open, close, read, write itd.
- major/minor number
cm3_tool
/dev/cm3
driver/misc/cm3
cm3
mem
User Space
Kernel Space
Kernel Space
Hardware Space
cm3
control
15. cm3 misc driver - ioctl (control device)
- Urządzenie jako plik
- powszechnie używane - np /dev/mem
(dostęp do pamięci fizycznej)
- open, close, read, write itd.
- major/minor number
cm3_tool
/dev/cm3
driver/misc/cm3
cm3
mem
User Space
Kernel Space
Kernel Space
Hardware Space
cm3
control
16. cm3 misc driver - (kernel)
static const struct file_operations cm3_fops = {
.llseek = cm3_lseek,
.read = cm3_read,
.write = cm3_write,
.unlocked_ioctl = cm3_ioctl,
.mmap = cm3_mmap,
.open = cm3_open,
.release = cm3_release
};
static int cm3_probe(struct platform_device *pdev) {
…
info->proc_sram_base =
devm_ioremap(&pdev->dev, res->start, info->proc_mem_size);
...
info->miscdev.minor = MISC_DYNAMIC_MINOR;
info->miscdev.name = drv_name; //np. “cm3”
info->miscdev.fops = &cm3_fops;
ret = misc_register(&info->miscdev);
...
}
cm3_tool
/dev/cm3
driver/misc/cm3
cm3
mem
User Space
Kernel Space
Kernel Space
Hardware Space
cm3
control
17. cm3 misc driver - (kernel)
static ssize_t cm3_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
struct cm3_info *info = filp->private_data;
…
dst_ptr = info->proc_mem_base + *f_pos;
...
if (*f_pos + count > mem_size) {
dev_err(dev, "Not enough space in %s for writing %d", drv_name, count);
return -ENOMEM;
}
...
for (i = 0; i < count; i = i + _4B_ALIGN)
if (copy_from_user(dst_ptr + i, buf + i, _4B_ALIGN)) {
dev_err(dev, "%s: copy_from_user failed.n", __func__);
return -EFAULT;
}
…
*f_pos += i;
return i;
}
cm3_tool
/dev/cm3
driver/misc/cm3
cm3
mem
User Space
Kernel Space
Kernel Space
Hardware Space
cm3
control
18. Czy wskaźnik do buf może być bezpośrednio wyłuskany w
kodzie kernela? Dlaczego musimy używać funkcji
copy_from_user a nie operować bezpośrednio na wskaźniku
‘buf’ używajac np. memcpy?
static ssize_t cm3_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
...
for (i = 0; i < count; i = i + _4B_ALIGN)
if (copy_from_user(dst_ptr + i, buf + i, _4B_ALIGN)) {
dev_err(dev, "%s: copy_from_user failed.n", __func__);
return -EFAULT;
}
...
}
19. cm3 misc driver - (kernel)
static long cm3_do_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
...
if (_IOC_TYPE(cmd) != CM3_IOC_MAGIC)
return -ENOTTY;
switch (cmd) {
case CM3_IOC_STATE:
if (copy_from_user(&reset, (uint32_t *)arg, sizeof(uint32_t))) {
dev_err(dev, "copy_from_user failedn");
return -EFAULT;
}
ret = unreset_cm3(reset, info);
if (ret)
return ret;
break;
case CM3_IOC_YYY:
...
}
…
}
cm3_tool
/dev/cm3
driver/misc/cm3
cm3
mem
User Space
Kernel Space
Kernel Space
Hardware Space
cm3
control
20. cm3 misc - userspace
int fd_cm3;
...
fd_cm3 = open(name, O_RDWR); //np. “/dev/cm3”
..
if (lseek(fd_cm3, atoi(off), SEEK_SET) < 0)
goto fail1;
....
nw = write(fd_cm3, buf, count);
….
rc = ioctl(fd_cm3, CM3_IOC_STATE, &state);
...
close(fd_cm3);
cm3_tool
/dev/cm3
driver/misc/cm3
cm3
mem
User Space
Kernel Space
Kernel Space
Hardware Space
cm3
control
21. Jakie syscall’e wywołają się, gdy zrobimy
cp file /dev/cm3 ?
Jakiego narzędzia można użyć żeby to sprawdzić?
23. Plan
● Podział systemów wieloprocesorowych
● Przykład systemu heterogonicznego
● Linuxowy misc/char device driver
○ ogólnie
○ na przykładzie cm3
● O czym pamiętać podczas komunikacji IPC
○ rozmieszczenie struktur w pamięci
○ optymalizacje kompilatora i procesora
○ bariery
○ typy pamięci w arm
25. Rozmieszczenie struktur w pamięci
struct info {
unsigned int a;
bool is_enabled;
bool y;
unsigned int b;
...
}
Linux (include/linux/types.h):
typedef _Bool bool;
FreeRTOS:
typedef int bool;
najlepiej używać standardowych typów z stdint.h/types.h
(int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t i
uint64_t)
26. Optymalizacje kompilatora
optymalizacje kompilatora (volatile):
kod źródłowy:
1) zapis do pamieci SRAM
2) zapis do rejestru (wygenerowanie przerwania)
kod wynikowy
str r2, [r0] ;wygenerowanie przerwania
add r1, r4, #4
str r3, [r1] ;zapis do SRAM
Linux (w kodzie sterowników):
writel/writel_relaxed oraz readl/readl_relaxed
#define writel_relaxed(b, addr) __raw_writel(b, addr)
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
asm volatile("str %1, %0"
: : "Qo" (*(volatile u32 __force *)addr), "r" (val));
}
27. Optymalizacje procesora i systemu pamięci
add r0, r0, #4
mul r2, r2, r3
str r2, [r0]
ldr r4, [r1]
sub r1, r4, r2 bx lr
out-of-order:
0 add r0, r0, #4
1 mul r2, r2, r3
2 ldr r4, [r1]
3 str r2, [r0]
4 sub r1, r4, r2
5 bx lr
in-order:
0 add r0, r0, #4
1 mul r2, r2, r3
2 *stall*
3 str r2, [r0]
4 ldr r4, [r1]
5 *stall*
6 sub r1, r4, r2
7 bx lr
out-of-order dmb:
add r0, r0, #4
mul r2, r2, r3
str r2, [r0]
dmb
ldr r4, [r1]
sub r1, r4, r2 bx lr
28. Bariery ARMv7
DMB Data memory barrier
DSB Data synchronization barrier.
ISB Instruction synchronization barrier
29. Typy pamięci w ARM
Normal memory: cached, write buffer (instruction and most program data)
Device memory: memory access size, number and order preserved; (peripherals
+ adressses with side-effects)
Strongly-ordered: like device but write buffers not permitted
31. Bariery a Linux
#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
#define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); })
DRAM
IO
CPU P
32. Inne przykłady systemów heterogenicznych
- Texas Instruments OMAP5432 (2 x Cortex-A15 + 2 x Cortex-M4)
- Xilinx UltraScale MPSoC (4 x Cortex-A53 + 2 x Cortex-R5).
- Freescale’s i.MX7 Solo (Cortex-A7 + Cortex-M4)
- ARM’s “Juno” development platform contains 2 x Cortex-A57 + 4 x Cortex-
A53 cores, plus a Cortex-M3 System Control Processor for power control.
33. Referencje
- LINUX DEVICE DRIVERS, Jonathan Corbet, Alessandro Rubini, and Greg
Kroah-Hartman
- http://www.embedded.com/design/programming-languages-and-
tools/4437925/1/Dealing-with-memory-access-ordering-in-complex-
embedded-designs-