- Timestamp:
-
03/11/15 00:07:57 (9 years ago)
- Author:
-
Chris Johns
- Comment:
-
Fix formatting.
Legend:
- Unmodified
- Added
- Removed
- Modified
-
v95
|
v96
|
|
14 | 14 | such device can be easily connected to systems with different CPU architectures (x86, PowerPC, ARM, etc.). |
15 | 15 | We decided to focus on SJA1000 chip, because it is widespread standalone controller variant. As for the |
16 | | concrete card, we have selected Kvaser PCI because we (mentors from [http://www.cvut.cz/ Czech Technical University] [http://dce.fel.cvut.cz/en/department/organizational-structure/industrial-informatics-group IIG group]) use more these cards in |
| 16 | concrete card, we have selected Kvaser PCI because we (mentors from |
| 17 | [http://www.cvut.cz/ Czech Technical University] [http://dce.fel.cvut.cz/en/department/organizational-structure/industrial-informatics-group IIG group]) |
| 18 | use more these cards in |
17 | 19 | our projects and can compare emulated HW behavior with real hardware. We selected interfacing |
18 | 20 | to SocketCAN (Linux kernel standard CAN API/drivers) on QEMU host side to connect emulated controller |
19 | 21 | CAN bus to the virtual CAN network, host side monitoring tools or to the real CAN bus wired network. |
| 22 | |
20 | 23 | = CAN QEMU Sources and Testing = |
21 | 24 | |
… |
… |
|
27 | 30 | When QEMU with CAN PCI support is compiled then next two CAN boards can be selected |
28 | 31 | |
29 | | * simple PCI memory space mapped SJA1000 which maps the chip registers directly into the first BAR of emulated device. QEMU startup options |
30 | | |
31 | | -device pci_can,chardev=canbus0,model=SJA1000 |
32 | | |
33 | | * CAN bus Kvaser PCI CAN-S (single SJA1000 channel mapped into IO space) board. QEMU startup options |
34 | | |
35 | | -device kvaser_pci,canbus=canbus0,host=vcan0 |
| 32 | * simple PCI memory space mapped SJA1000 which maps the chip registers directly into the first BAR of emulated device. QEMU startup options '-device pci_can,chardev=canbus0,model=SJA1000' |
| 33 | * CAN bus Kvaser PCI CAN-S (single SJA1000 channel mapped into IO space) board. QEMU startup options '-device kvaser_pci,canbus=canbus0,host=vcan0' |
36 | 34 | |
37 | 35 | The ''kvaser_pci'' board/device model is compatible with and has been tested with ''kvaser_pci'' driver included |
… |
… |
|
40 | 38 | |
41 | 39 | Next parameters has been used for qemu-system-x86_64 |
42 | | |
43 | | qemu-system-x86_64 -enable-kvm -kernel /boot/vmlinuz-3.12.4-1-amd64 \ |
| 40 | {{{ |
| 41 | qemu-system-x86_64 -enable-kvm -kernel /boot/vmlinuz-3.12.4-1-amd64 \ |
44 | 42 | -initrd ramdisk.cpio \ |
45 | 43 | -virtfs local,path=shareddir,security_model=none,mount_tag=shareddir \ |
… |
… |
|
47 | 45 | -device kvaser_pci,canbus=canbus0,host=can0 \ |
48 | 46 | -nographic -append "console=ttyS0" |
| 47 | }}} |
49 | 48 | |
50 | 49 | The list of parameters for qemu-system-arm |
51 | | |
52 | | qemu-system-arm -cpu arm1176 -m 256 -M versatilepb \ |
| 50 | {{{ |
| 51 | qemu-system-arm -cpu arm1176 -m 256 -M versatilepb \ |
53 | 52 | -kernel kernel-qemu-arm1176-versatilepb \ |
54 | 53 | -hda rpi-wheezy-overlay \ |
… |
… |
|
56 | 55 | -nographic \ |
57 | 56 | -virtfs local,path=shareddir,security_model=none,mount_tag=shareddir \ |
58 | | -device kvaser_pci,canbus=canbus0,host=can0 \ |
| 57 | -device kvaser_pci,canbus=canbus0,host=can0 |
| 58 | }}} |
| 59 | |
59 | 60 | = The previous CAN for QEMU versions = |
60 | 61 | |
61 | 62 | The Jin Yang initial effort has targeted stable version QEMU-1.4.2 and Linux with mainline provided SocketCAN |
62 | 63 | has been used on host side. |
63 | | * Host: The host was Ubuntu-13.04 including the basic building tools and some other software. |
64 | | * Guest: This is also a Linux environment which we build from scratch. The Linux kernel is [https://www.kernel.org/pub/linux/kernel/v3.0/linux-3.4.48.tar.bz2 Linux-3.4.48], the commands are statically compiled using [http://www.busybox.net/downloads/busybox-1.21.0.tar.bz2 Busybox-1.21.0] and also some other files including configure files, start scripts, etc. |
65 | | * Others: [http://wiki.qemu-project.org/download/qemu-1.4.2.tar.bz2 Qemu-1.4.2] |
| 64 | * Host: The host was Ubuntu-13.04 including the basic building tools and some other software. |
| 65 | * Guest: This is also a Linux environment which we build from scratch. The Linux kernel is [https://www.kernel.org/pub/linux/kernel/v3.0/linux-3.4.48.tar.bz2 Linux-3.4.48], the commands are statically compiled using [http://www.busybox.net/downloads/busybox-1.21.0.tar.bz2 Busybox-1.21.0] and also some other files including configure files, start scripts, etc. |
| 66 | * Others: [http://wiki.qemu-project.org/download/qemu-1.4.2.tar.bz2 Qemu-1.4.2] |
66 | 67 | |
67 | 68 | The best option is to implement that as simple device |
| 69 | {{{ |
68 | 70 | -chardev can,id=sja1000,port=vcan0 |
69 | 71 | -device pci-can,chardev=sja1000,model=SJA1000 |
| 72 | }}} |
70 | 73 | and use Linux mainlined SocketCAN API to connect virtual device to real CAN hardware (SocketCAN allows multiple applications access) or to SocketCAN Virtual CAN (vcan - TCP/IP lo equivalent). |
71 | 74 | This is straightforward and would result in minimal overhead and latency. |
72 | 75 | |
73 | 76 | The above options connect the ''can'' back end to the PCI-CAN device. Just explain the options briefly. |
74 | | * '''-chardev can,id=sja1000,port=vcan0''' specify which back end should we open, here can. ''id'' used for the -device option; ''port'' which interface should we open, we use virtual socketcan device here. |
75 | | * '''-device pci-can,chardev=sja1000,model=SJA1000''' we use pci-can device. ''chardev'' the value '''MUST''' equal to the id specified in chardev option; ''model'' is an optional parameter, default value is SJA1000 and we only support SJA1000 now. |
| 77 | -chardev can,id=sja1000,port=vcan0:: |
| 78 | specify which back end should we open, here can. ''id'' used for the -device option; ''port'' which interface should we open, we use virtual socketcan device here. |
| 79 | -device pci-can,chardev=sja1000,model=SJA1000:: |
| 80 | we use pci-can device. ''chardev'' the value '''MUST''' equal to the id specified in chardev option; ''model'' is an optional parameter, default value is SJA1000 and we only support SJA1000 now. |
76 | 81 | |
77 | 82 | The QEMU CAN infrastructure has been rewritten and SJA1000 code updated to QEMU 2.0 version |
78 | 83 | |
79 | | * Updated version patches at qemu-devel list archive [http://lists.nongnu.org/archive/html/qemu-devel/2014-05/msg01861.html] |
| 84 | * Updated version patches at qemu-devel list archive [http://lists.nongnu.org/archive/html/qemu-devel/2014-05/msg01861.html] |
| 85 | |
80 | 86 | = Installing Qemu = |
81 | 87 | |
… |
… |
|
84 | 90 | |
85 | 91 | You can download the qemu-can project from https://github.com/Jin-Yang/QEMU-1.4.2 or get a copy using the following command(Linux). |
| 92 | {{{ |
86 | 93 | git clone https://github.com/Jin-Yang/QEMU-1.4.2.git . |
87 | | |
| 94 | }}} |
88 | 95 | '''NOTE:''' before you compile QEMU, "libglib2-dev" should be installed, or you will get the error "ERROR: glib-2.12 required to compile QEMU". |
89 | 96 | In Ubuntu, to do that we use command ''sudo apt-get install libglib2-dev'' |
… |
… |
|
95 | 102 | |
96 | 103 | '''NOTE:''' For simplicity of coding, we select the hard-coded --prefix=/opt/qemu so we can write scripts assuming that's where our installed qemu is. |
97 | | |
98 | | ./configure --prefix=/opt/qemu --target-list="i386-softmmu" --enable-sdl && make && sudo make install |
99 | | |
100 | | * --prefix: specify the location where you want to install. |
101 | | * --target-list: the platform you want to simulation, here we only need the i386-softmmu. |
102 | | * --enable-sdl: we also need the sdl (Simple DirectMedia Layer) support. |
| 104 | {{{ |
| 105 | ./configure --prefix=/opt/qemu --target-list="i386-softmmu" --enable-sdl && make && sudo make install |
| 106 | }}} |
| 107 | |
| 108 | --prefix:: |
| 109 | specify the location where you want to install. |
| 110 | --target-list:: |
| 111 | the platform you want to simulation, here we only need the i386-softmmu. |
| 112 | --enable-sdl:: |
| 113 | we also need the sdl (Simple DirectMedia Layer) support. |
103 | 114 | |
104 | 115 | To call the just installed qemu you can add ''/opt/qemu/bin'' to the PATH environment variable or just use ''/opt/qemu/bin/qemu-system-i386'' to start QEMU. |
105 | 116 | Here, we just write a simple shell script and you can start the qemu just use command ''sudo ./qemu.sh'' |
| 117 | |
106 | 118 | = Building Linux Environment = |
| 119 | |
107 | 120 | == Building the Kernel == |
108 | 121 | |
… |
… |
|
112 | 125 | |
113 | 126 | The simplest way to compile a effective kernel is to generate a default one by typing ''make i386_defconfig; make bzImage''. However, this will waste a lot of time on compiling and running something which we do not need yet. So, we will build a minimal kernel through the following commands. |
114 | | cd linux-3.4.48 # change to the linux kernel directory |
115 | | make mrproper # clean up the source code |
116 | | make allnoconfig # disable all configure options |
117 | | make menuconfig # '''NOTE:''' Detailed instructions below |
118 | | make bzImage # compile the kernel image |
119 | | make modules # compile the linux modules |
120 | | make modules_install INSTALL_MOD_PATH=temp # install the linux modules to a temperary directory |
121 | | find -name bzImage # find the kernel image |
122 | | cp ./arch/i386/boot/bzImage ~qemu/. # copy it to the working directory |
| 127 | {{{ |
| 128 | cd linux-3.4.48 # change to the linux kernel directory |
| 129 | make mrproper # clean up the source code |
| 130 | make allnoconfig # disable all configure options |
| 131 | make menuconfig # '''NOTE:''' Detailed instructions below |
| 132 | make bzImage # compile the kernel image |
| 133 | make modules # compile the linux modules |
| 134 | make modules_install INSTALL_MOD_PATH=temp # install the linux modules to a temperary directory |
| 135 | find -name bzImage # find the kernel image |
| 136 | cp ./arch/i386/boot/bzImage ~qemu/. # copy it to the working directory |
| 137 | }}} |
123 | 138 | |
124 | 139 | Then, the modules has installed to ''temp'' directory, so you can copy them to the necessary directory if need. |
125 | 140 | |
126 | 141 | In the 'make menuconfig' step we will chose the following options |
127 | | |
| 142 | {{{ |
128 | 143 | - General setup # for convenience |
129 | 144 | - (-QEMU) Local version - append to kernel release |
… |
… |
|
196 | 211 | - NFS client support for NFS version 4 |
197 | 212 | - Root file system on NFS |
| 213 | }}} |
| 214 | |
198 | 215 | == Build a root file system in ~/qemu/rootfs == |
199 | 216 | |
200 | 217 | Build the basic commands through busybox |
201 | | tar -xf busybox-1.20.0.tar.bz2 |
202 | | cd busybox-1.20.0 |
203 | | make defconfig |
204 | | make menuconfig # '''NOTE:''' ''Busybox Settings -> Build options -> Build Busybox as a static binary'' |
205 | | make |
206 | | make install CONFIG_PREFIX=~/qemu/rootfs # choose this hard coded value for simplicity when writing scripts |
| 218 | {{{ |
| 219 | tar -xf busybox-1.20.0.tar.bz2 |
| 220 | cd busybox-1.20.0 |
| 221 | make defconfig |
| 222 | make menuconfig # '''NOTE:''' ''Busybox Settings -> Build options -> Build Busybox as a static binary'' |
| 223 | make |
| 224 | make install CONFIG_PREFIX=~/qemu/rootfs # choose this hard coded value for simplicity when writing scripts |
| 225 | }}} |
207 | 226 | |
208 | 227 | We also need some necessary directories and some files to build the root file system. However, it's not the main part of the project, you can get more help from google. You can just get the from a public repository https://github.com/Jin-Yang/LINUX-QEMU.git |
… |
… |
|
213 | 232 | |
214 | 233 | '''NOTE:''' this need the root privilege. |
215 | | |
216 | | #!/bin/sh |
217 | | # TUN/TAP to connect host with qemu |
218 | | ifconfig $1 192.168.9.33 |
| 234 | {{{ |
| 235 | #!/bin/sh |
| 236 | # TUN/TAP to connect host with qemu |
| 237 | ifconfig $1 192.168.9.33 |
| 238 | }}} |
| 239 | |
219 | 240 | == Starting Custom Qemu == |
220 | 241 | |
… |
… |
|
222 | 243 | |
223 | 244 | '''TODO:''' ran into an error like: ''~/qemu/ifup-qemu: could not launch network script qemu-system-i386: -net tap,vlan=0,ifname=tap0,script=~/qemu/ifup-qemu: Device 'tap' could not be initialized.'' Need to add instructions for permitting the TAP device to work... |
224 | | |
225 | | /opt/qemu/bin/qemu-system-i386 -s -m 128 -kernel bzImage \ |
| 245 | {{{ |
| 246 | /opt/qemu/bin/qemu-system-i386 -s -m 128 -kernel bzImage \ |
226 | 247 | -append "notsc clocksource=acpi_pm root=/dev/nfs \ |
227 | 248 | nfsroot=192.168.9.33:~/qemu/rootfs rw \ |
… |
… |
|
230 | 251 | -net nic,model=e1000,vlan=0,macaddr=00:cd:ef:00:02:01 \ |
231 | 252 | -net tap,vlan=0,ifname=tap0,script=~/qemu/ifup-qemu |
| 253 | }}} |
232 | 254 | |
233 | 255 | If you have got a copy from https://github.com/Jin-Yang/LINUX-QEMU.git, then you can start the qemu just by command ''sudo ./qemu.sh'' |
… |
… |
|
236 | 258 | |
237 | 259 | We have built a minimal linux environment now. Before we built the PCI-CAN device in QEMU, we will introduce the Linux driver SocketCAN and CAN device SJA1000 at first. |
| 260 | |
238 | 261 | = SocketCAN = |
239 | 262 | |
… |
… |
|
241 | 264 | |
242 | 265 | Simplely, we only need to insert the vcan module and use virtual socketcan device to test the socketcan. Following is what we need to do. |
243 | | $ sudo insmod /lib/modules/`uname -r`/kernel/drivers/net/can/vcan.ko |
244 | | $ sudo ip link add type vcan |
245 | | $ sudo ip link set vcan0 up |
| 266 | {{{ |
| 267 | $ sudo insmod /lib/modules/`uname -r`/kernel/drivers/net/can/vcan.ko |
| 268 | $ sudo ip link add type vcan |
| 269 | $ sudo ip link set vcan0 up |
| 270 | }}} |
246 | 271 | |
247 | 272 | Then you can check the CAN interface using command ''ifconfig vcan0'' . You can test the can networking using can-utils, that you can get from https://gitorious.org/linux-can/can-utils . |
248 | | ./candump vcan0 # Observe vcan0 |
249 | | ./cangen vcan0 # Generate CAN message |
| 273 | {{{ |
| 274 | ./candump vcan0 # Observe vcan0 |
| 275 | ./cangen vcan0 # Generate CAN message |
| 276 | }}} |
| 277 | |
250 | 278 | = SJA1000 = |
251 | 279 | |
… |
… |
|
254 | 282 | SJA1000 is intended to replace the PCA82C200 because it is hardware and software compatible. It has two modes including BasicCAN mode and PeliCAN mode, the details you can get from the above two documents. |
255 | 283 | |
256 | | |
257 | 284 | = Step 3: Build a Basic PCI-CAN device in qemu = |
258 | 285 | |
259 | 286 | We use QEMU Object Model(QOM, formerly Qdev) to simulate the SJA1000 hardware. You can get some useful information from [http://wiki.qemu.org/Features/QOM QEMU Object Model] which intruduce the QOM. |
260 | 287 | |
261 | | |
262 | 288 | There are some files that need to be modified to make a basic PCI-CAN device: default-configs/pci.mak, hw/Makefile.objs, qemu-char.c, hw/can-pci.c. |
263 | | * default-configs/pci.mak add default compiling options |
264 | | * config-all-devices.mak add all compiling options |
265 | | * hw/Makefile.objs needs to be modified to add the object to the qemu build |
266 | | * qemu-char.c is the file that is used for the can-char driver |
267 | | * hw/can-pci.c is the can-pci device |
268 | | |
| 289 | * default-configs/pci.mak add default compiling options |
| 290 | * config-all-devices.mak add all compiling options |
| 291 | * hw/Makefile.objs needs to be modified to add the object to the qemu build |
| 292 | * qemu-char.c is the file that is used for the can-char driver |
| 293 | * hw/can-pci.c is the can-pci device |
269 | 294 | |
270 | 295 | The specification of the pci-can device lists in following. |
| 296 | {{{ |
271 | 297 | Name : pci-can |
272 | 298 | PCI ID : 1b36:beef |
273 | 299 | PCI Region 0: |
274 | 300 | MEM bar, 128 bytes long, you can get the details about the memory map from SJA1000 Data Sheet. |
| 301 | }}} |
| 302 | |
275 | 303 | You can get the device information using command **info pci** in monitor console. Those arguments are initialized in function can_pci_class_initfn() and can_pci_init(). |
| 304 | |
276 | 305 | = Add the Default Compiling Files = |
277 | 306 | |
… |
… |
|
279 | 308 | |
280 | 309 | We want to compile the PCI-CAN device as default. To achieve this goal, we add the following code. |
281 | | # hw/Makefile.objs |
282 | | common-obj-$(CONFIG_CAN_PCI) += can-pci.o |
283 | | # default-configs/pci.mak |
284 | | CONFIG_CAN_PCI=y |
285 | | # config-all-devices.mak |
286 | | CONFIG_CAN_PCI=y |
| 310 | {{{ |
| 311 | # hw/Makefile.objs |
| 312 | common-obj-$(CONFIG_CAN_PCI) += can-pci.o |
| 313 | # default-configs/pci.mak |
| 314 | CONFIG_CAN_PCI=y |
| 315 | # config-all-devices.mak |
| 316 | CONFIG_CAN_PCI=y |
| 317 | }}} |
| 318 | |
287 | 319 | = Add the PCI-CAN structure = |
288 | 320 | |
289 | 321 | We can add a basic PCI-CAN device through the following code, the function can_pci_class_initfn() is used to initialize the device. There is a [https://github.com/qemu/qemu/blob/master/hw/misc/pci-testdev.c PCI TestDev] in QEMU as a reference. |
290 | | |
291 | | static const TypeInfo can_pci_info = { |
| 322 | {{{ |
| 323 | static const TypeInfo can_pci_info = { |
292 | 324 | .name = "pci-can", |
293 | 325 | .parent = TYPE_PCI_DEVICE, |
294 | 326 | .instance_size = sizeof(PCICanState), |
295 | 327 | .class_init = can_pci_class_initfn, |
296 | | }; |
297 | | static void can_pci_register_types(void) |
298 | | { |
| 328 | }; |
| 329 | static void can_pci_register_types(void) |
| 330 | { |
299 | 331 | type_register_static(&can_pci_info); |
300 | | } |
301 | | type_init(can_pci_register_types) |
| 332 | } |
| 333 | type_init(can_pci_register_types) |
| 334 | }}} |
| 335 | |
302 | 336 | = Add Start Options = |
303 | 337 | |
… |
… |
|
308 | 342 | DEFINE_PROP_STRING("model", PCICanState, model), |
309 | 343 | DEFINE_PROP_END_OF_LIST(), |
310 | | };}}} |
| 344 | }; |
| 345 | }}} |
311 | 346 | When start QEMU, we could change the PCI-CAN's properties through **chardev=xxx,model=xxxx**. The argument model is optinal, we use SJA1000 as default and only SJA1000 support now. |
| 347 | |
312 | 348 | = Add CAN back-end = |
313 | 349 | |
314 | 350 | Before add the function for SJA1000, we would introduce how to add the back-end in QEMU at first. To add the CAN back-end we should modefy the qemu-char.c file, this will be introduced step by step. |
| 351 | |
315 | 352 | == Change backend_table[] == |
316 | 353 | |
317 | 354 | We should add a variable to backend_table[] to support a new backend just like following. |
| 355 | {{{ |
318 | 356 | { .name = "CAN", .open = qemu_chr_open_can }, |
| 357 | }}} |
319 | 358 | The qemu_char_open_can() function is used to initialize the backend including analyzing the start options, allocating some memory, opening the SocketCAN device, setting the CAN filter etc. |
| 359 | |
320 | 360 | == Add the start options == |
321 | 361 | |
322 | 362 | We should start the backend like "-chrdev can,id=sja1000,port=vcan0". The valid options for backend list in qemu_chardev_opts variable. The argument 'port' is part of them, so we can use it directly or you should add the option you want to the qemu_chardev_opts variable. When qemu started, you can get the value using qemu_opt_get() function. |
| 363 | |
323 | 364 | == Add writing routine == |
324 | 365 | |
… |
… |
|
326 | 367 | |
327 | 368 | The source code is just like the following, details in qemu-char.c file. |
| 369 | {{{ |
328 | 370 | static int can_chr_write(CharDriverState *chr, const uint8_t *buf, int len) |
329 | 371 | { |
… |
… |
|
337 | 379 | ...... |
338 | 380 | } |
| 381 | }}} |
339 | 382 | This is same with the ioctl funciton. |
| 383 | |
340 | 384 | == Add reading routine == |
341 | 385 | |
… |
… |
|
345 | 389 | |
346 | 390 | So what we should do is like following |
347 | | * figure out if we need to read from the real device. |
348 | | * wait for reading from the device. |
349 | | * read from the device and call the corresponding function. |
| 391 | * figure out if we need to read from the real device. |
| 392 | * wait for reading from the device. |
| 393 | * read from the device and call the corresponding function. |
350 | 394 | |
351 | 395 | QEMU apply this like following |
352 | | * initializing, qemu_set_fd_handler2()-iohandler.c and qemu_chr_add_handlers()-qemu-char.c should be called seperately in can backend and pci-can device. |
353 | | * qemu_iohandler_fill()-iohandler.c is called to test if the pci-can device need to read. |
354 | | * system call select is called to wait for CAN message. |
355 | | * qemu_iohandler_poll()-iohandler.c is called to write the data to pci-can device. |
356 | | |
| 396 | * initializing, qemu_set_fd_handler2()-iohandler.c and qemu_chr_add_handlers()-qemu-char.c should be called seperately in can backend and pci-can device. |
| 397 | * qemu_iohandler_fill()-iohandler.c is called to test if the pci-can device need to read. |
| 398 | * system call select is called to wait for CAN message. |
| 399 | * qemu_iohandler_poll()-iohandler.c is called to write the data to pci-can device. |
| 400 | {{{ |
357 | 401 | static void can_chr_update_read_handler(CharDriverState *chr) |
358 | 402 | { |
… |
… |
|
367 | 411 | ...... |
368 | 412 | } |
369 | | |
| 413 | }}} |
370 | 414 | In can_chr_update_read_handler(), we would call qemu_set_fd_handler2() function to register the reading routine function. The 2nd argument is called to figure out if we need to read from the real device, if need the reture value should bigger than 0 or equal to 0. The 3rd argument is called when we should to read the data. |
371 | 415 | |
372 | | |
373 | 416 | So in can_chr_read_poll() function we will figure out if we need to get some data from the device and in can_chr_read() function we will wirte the data to the pci-can device. |
| 417 | |
374 | 418 | = Step 4: Write Linux driver = |
375 | 419 | |
… |
… |
|
377 | 421 | |
378 | 422 | Unlike the SocketCAN driver which use the socket, we developed a new char device driver. Only receiving and sending routines support now. This means if you want to test the CAN filter you should change the source of Linux driver. Since the SJA1000 has two kinds of mode BasicCAN and PeliCAN, so we build two linux driver to support them. |
| 423 | |
379 | 424 | = Step 5: Test = |
380 | 425 | |
381 | 426 | You can get the test environment form site ''https://github.com/Jin-Yang/LINUX-QEMU.git''. There is a simple intruduce in README about what the files or directories for. |
| 427 | |
382 | 428 | = Add SocketCAN device = |
383 | 429 | |
384 | 430 | The following commands should be executed in host. |
| 431 | {{{ |
385 | 432 | $ sudo insmod /lib/modules/`uname -r`/kernel/drivers/net/can/vcan.ko |
386 | 433 | $ sudo ip link add type vcan |
387 | 434 | $ sudo link set vcan0 up |
| 435 | }}} |
| 436 | |
388 | 437 | = Start qemu = |
389 | 438 | |
390 | 439 | I write a simple start script for it, you can just type the following command to start it. |
391 | | sudo ./qemu.sh |
| 440 | {{{ |
| 441 | sudo ./qemu.sh |
| 442 | }}} |
| 443 | |
392 | 444 | = Linux driver = |
393 | 445 | |
394 | | Under source/ directory, there is a sub-directory linux_driver/ that contains the source code for linux driver. At first, some environment variables should be changed, details in README file. Then you can compile and copy it to the root file system through |
395 | | make |
396 | | sudo ./copy.sh |
| 446 | Under source/ directory, there is a sub-directory linux_driver/ that contains the source code for linux driver. At first, some environment variables should be changed, details in README file. Then you can compile and copy it to the root file system through: |
| 447 | {{{ |
| 448 | make |
| 449 | sudo ./copy.sh |
| 450 | }}} |
397 | 451 | In qemu, change directory to /home/can_pci/basic/ and insert the linux driver by ''./load'', remove by ''./unload''. |
398 | 452 | |
… |
… |
|
402 | 456 | |
403 | 457 | Monitor the vcan0 interface. |
404 | | ~/can-utils$ ./candump vcan0 |
| 458 | {{{ |
| 459 | ~/can-utils$ ./candump vcan0 |
| 460 | open 0 'vcan0' |
| 461 | using interface name 'vcan0' |
| 462 | new index 0 (vcan0) |
| 463 | }}} |
| 464 | then send a CAN message in QEMU |
| 465 | {{{ |
| 466 | root:/home/can_pci/basic# ./send |
| 467 | }}} |
| 468 | finaly, get the message in host |
| 469 | {{{ |
| 470 | ~/can-utils$ ./candump vcan0 |
405 | 471 | open 0 'vcan0' |
406 | | using interface name 'vcan0' |
407 | | new index 0 (vcan0) |
408 | | then send a CAN message in QEMU |
409 | | root:/home/can_pci/basic# ./send |
410 | | finaly, get the message in host |
411 | | ~/can-utils$ ./candump vcan0 |
412 | | open 0 'vcan0' |
413 | | using interface name 'vcan0' |
414 | | new index 0 (vcan0) |
415 | | vcan0 123 [3] 12 34 56 # this is the message we send. |
| 472 | using interface name 'vcan0' |
| 473 | new index 0 (vcan0) |
| 474 | vcan0 123 [3] 12 34 56 # this is the message we send. |
| 475 | }}} |
| 476 | |
416 | 477 | = Receive routine = |
417 | 478 | |
… |
… |
|
419 | 480 | |
420 | 481 | Start receiving routine in QEMU |
421 | | root:/home/can_pci/basic#./receive |
| 482 | {{{ |
| 483 | root:/home/can_pci/basic#./receive |
| 484 | }}} |
422 | 485 | send message in host |
423 | | ~/can-utils$ ./cangen vcan0 -g 1000 # send a CAN message per second. |
| 486 | {{{ |
| 487 | ~/can-utils$ ./cangen vcan0 -g 1000 # send a CAN message per second. |
| 488 | }}} |
424 | 489 | then you will receive the CAN message in QEMU like |
425 | | root:/home/can_pci/basic#./receive |
426 | | 761 [8] -SFF DAT- 4E 9C F1 05 72 8C FB 7E |
427 | | 058 [4] -SFF DAT- 80 D6 B0 25 |
428 | | 2D4 [1] -SFF DAT- 55 |
429 | | |
430 | | |
431 | | |
432 | | |
433 | | |
434 | | |
435 | | |
436 | | |
437 | | |
| 490 | {{{ |
| 491 | root:/home/can_pci/basic#./receive |
| 492 | 761 [8] -SFF DAT- 4E 9C F1 05 72 8C FB 7E |
| 493 | 058 [4] -SFF DAT- 80 D6 B0 25 |
| 494 | 2D4 [1] -SFF DAT- 55 |
| 495 | }}} |
438 | 496 | |
439 | 497 | = QEMU PCI-CAN device = |
440 | 498 | |
441 | 499 | I have maitained a blog at [http://jin-yang.github.io/2013/07/25/add-pcidevice-to-qemu.html Add pci-can]. There are a lots of temperay information, so I will update this at the end of the project. Then only useful message will be updated here. |
| 500 | |
442 | 501 | = RTEMS environment = |
443 | 502 | |
444 | | You can get a basic simulation environment from https://github.com/Jin-Yang/RTEMS-QEMU. This is a simple environment. However before run the RTEMS, environment variables 'PATH' and 'RTEMS_MAKEFILE_PATH' should be added to ~/.bashrc, such as |
445 | | export PATH=/opt/rtems-4.10/bin:${PATH} |
446 | | export RTEMS_MAKEFILE_PATH=/opt/rtems-4.10/i386-rtems4.10/pc386 |
| 503 | You can get a basic simulation environment from https://github.com/Jin-Yang/RTEMS-QEMU. This is a simple environment. However before run the RTEMS, environment variables 'PATH' and 'RTEMS_MAKEFILE_PATH' should be added to ~/.bashrc, such as: |
| 504 | {{{ |
| 505 | export PATH=/opt/rtems-4.10/bin:${PATH} |
| 506 | export RTEMS_MAKEFILE_PATH=/opt/rtems-4.10/i386-rtems4.10/pc386 |
| 507 | }}} |
| 508 | |
447 | 509 | Then, you can run it just using |
448 | | ./qemu |
| 510 | {{{ |
| 511 | ./qemu |
| 512 | }}} |
449 | 513 | |
450 | 514 | Source file located at examples-v2/ and before runing, rtems-grub.cfg should be edited too. |
| 515 | |
451 | 516 | = Adding Qemu to the RTEMS Source Builder = |
452 | 517 | |
… |
… |
|
458 | 523 | |
459 | 524 | '''MinGW''' |
460 | | # http://wiki.qemu.org/Hosts/W32#Native_builds |
461 | | # http://www.mingw.org/wiki/Bootstrapping_GLIB_with_MinGW |
| 525 | 1. http://wiki.qemu.org/Hosts/W32#Native_builds |
| 526 | 1. http://www.mingw.org/wiki/Bootstrapping_GLIB_with_MinGW |
462 | 527 | |
463 | 528 | '''Cygwin''' |
464 | | # http://cygwin.com/packages/ |
| 529 | 1. http://cygwin.com/packages/ |
465 | 530 | |
466 | 531 | Some resources for building on Mac are: |
467 | | # http://www.rubenerd.com/qemu-1-macosx/ |
| 532 | |
| 533 | 1. http://www.rubenerd.com/qemu-1-macosx/ |
| 534 | |
468 | 535 | = References = |
469 | 536 | |
470 | | # https://lists.gnu.org/archive/html/qemu-devel/2013-05/threads.html |
471 | | # http://www.linux-kvm.org/wiki/images/f/f6/2012-forum-QOM_CPU.pdf |
| 537 | 1. https://lists.gnu.org/archive/html/qemu-devel/2013-05/threads.html |
| 538 | 1. http://www.linux-kvm.org/wiki/images/f/f6/2012-forum-QOM_CPU.pdf |