├── .gitignore ├── LICENSE ├── README.md ├── doc_and_examples ├── 1_example.sh ├── README.md ├── beaglebone_headers.png └── pinmux.pdf ├── install.sh ├── run.sh └── src ├── driver ├── Makefile ├── README.md └── pru_speak.c ├── dts ├── BB-PRUSPEAK-00A0.dts ├── Makefile ├── README.md └── am335x-boneblack.dts ├── pru-firmware ├── AM3359_PRU.cmd ├── Makefile ├── README.md ├── pru0_firmware.c ├── pru0_firmware.h ├── pru0_syscall.asm ├── pru1_firmware.c ├── pru1_firmware.h └── pru_firmware.h └── userspace_lib ├── Makefile ├── README.md ├── bs_fifo.py ├── bs_shell.py ├── bs_tcp_client.py ├── bs_tcp_server.py ├── example_code.py ├── legacy_code ├── bs_client.py ├── bs_server.py ├── client.py ├── compiler.py ├── fifo_server.py └── pru_speak.py ├── nokia5110_lcd_demo.py ├── pru_speak ├── __init__.py ├── bs_lex.py ├── bs_parse.py ├── kernel_lib.py ├── node.py └── pruspeak.py ├── setup.py └── test_funcs.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Libraries 8 | *.lib 9 | *.a 10 | 11 | # Shared objects (inc. Windows DLLs) 12 | *.dll 13 | *.so 14 | *.so.* 15 | *.dylib 16 | 17 | # Executables 18 | *.exe 19 | *.out 20 | *.app 21 | *.i*86 22 | *.x86_64 23 | *.hex 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Deepak Karki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PRU Speak 2 | ======== 3 | 4 | ## What is it 5 | 6 | PRU Speak is an implementation of the BotSpeak language for the PRU. 7 | This project enables dynamic control of the Beaglebone black's PRU (Programmable Realtime Unit) from the Linux userspace on ARM. For more information have a look at the [official PRU page](http://beagleboard.org/pru) on beagleboard.org 8 | 9 | **BotSpeak** is a robotics programming language designed to bridge the gap between small embedded systems such as the Raspberry Pi, BeagleBone, and Arduino. 10 | [See http://botspeak.org/ and https://sites.google.com/site/botspeak/ for more information] 11 | 12 | **PRU** is a dual core micro-controller system present on the AM335x SoC (TI's ARM A8 based chip) which powers the [Beagle Bone black] [1]. 13 | 14 | The [PRU] [2] is meant to be used for high speed jitter free IO control. Being independent from the linux scheduler and having direct access to the IO pins of the BeagleBone Black, PRU is ideal for offloading IO intensive tasks. 15 | 16 | **NOTE** : PRU Speak will be refactored to use the new remote proc driver for ARM <-> PRU communication, the PRU Bridge. 17 | 18 | ## How to use 19 | 20 | ``` 21 | Installing 22 | ========== 23 | 24 | Install ply (python lex and yacc), make sure pip is installed 25 | #pip install ply 26 | 27 | run (to copy firmwares to reqd folder) 28 | #bash install.sh 29 | 30 | Environment setup 31 | ================= 32 | 33 | To load the kernel module, device tree overlay, firmware and TCP server 34 | #bash run.sh 35 | 36 | Running 37 | ======= 38 | 39 | Three possible interfaces : 40 | 41 | 1. PS shell - 42 | This is a simple terminal interface (written in python) where you can type commands and scripts and interact with the PRU. 43 | All the standard command's return values are recieved and printed. 44 | 45 | 2. Bash interface - 46 | This is a bash interface. PRU Speak shows up as a file entry at "/dev/pruspeak". 47 | All commands can be echoed to the file, eg : root@beaglebone:/dev# echo SET DIO[0], 1 > pruspeak 48 | 49 | 3. TCP interface - 50 | A TCP interface at localhost:6060 for the Pru Speak interpreter. Write to the socket for command/script, read for return value. 51 | 52 | To try a simple blink example (blink P9_31): 53 | #bash blink.sh 54 | 55 | [**NOTE** use only any one interface at a given point of time. PRU Speak is refreshed everytime a interface is initialized. You may lose existing session] 56 | 57 | ``` 58 | 59 | ## How it works 60 | 61 | The project consists of three main components 62 | * The user space libraries 63 | * The remote proc device driver 64 | * The PRU firmware (PRU implementation of the BotSpeak interpreter) 65 | 66 | The system architecture of the project is well illustrated in this flow chart. 67 | 68 | ![The PRU Speak Architecture](https://goo.gl/J2uwTx) 69 | 70 | **The basic workflow is as follows** 71 | 72 | 1. The user space component consists mainly of python code, and is responsible for interacting with the user. The user has 3 main ways to use PRUSpeak - through an open TCP port, through a FIFO or through an interactive shell. If you're a developer, you can use the direct `pruspeak` python api. 73 | See examples [here](https://github.com/deepakkarki/pruspeak/blob/master/src/userspace_lib/example_code.py) 74 | 75 | 2. Create the botspeak script you want to execute, and send it through any of the interfaces. The client side logic will process the commands, compile it to a custom byte code and dump it in a shared memory location. (shared between the userspace process and the PRU0) 76 | 77 | 3. Once the bytecode is placed, the client side code will signal the same to the PRU0 via sysfs interface. The sysfs interfaces are created by the pruspeak kernel driver, which accepts the system calls made to it by the user space libs and forwards it to the PRUs. 78 | 79 | 4. he PRU0 has a small VM running on it which can read the bytecode. Once PRU0 gets the control instructions, it will read the bytecode from the shared memory and begin execution. 80 | 81 | A simple but more detailed explanation can be found [here](https://goo.gl/09xJfa) 82 | 83 | A more detailed description of the design and implementation can be found [here](https://goo.gl/vonpEB) 84 | 85 | See some example code [here](https://github.com/deepakkarki/pruspeak/blob/master/src/userspace_lib/test_funcs.py) and [here](https://github.com/deepakkarki/pruspeak/blob/master/src/userspace_lib/example_code.py) 86 | 87 | ## Build from source 88 | 89 | Run ```bash install.sh``` 90 | 91 | ## future work 92 | 93 | - [ ] Language bindings to Python and Node.js 94 | - [ ] Cleaner interfaces (for TCP and FIFO --to both r/w) 95 | - [ ] Fill in wiki and encoding scheme 96 | - [ ] Explain working in detail 97 | - [ ] Add streams between PRU and ARM 98 | - [ ] Add ability to dynamically set frequency for PWM 99 | - [ ] More commands for qep, uart, hard-pwm etc 100 | - [ ] Integrate PRU bridge for transportation layer 101 | 102 | 103 | [1]: http://beagleboard.org/black 104 | [2]: http://elinux.org/BeagleBone_PRU_Notes 105 | -------------------------------------------------------------------------------- /doc_and_examples/1_example.sh: -------------------------------------------------------------------------------- 1 | echo SCRIPT > /dev/pruspeak 2 | echo SET DIO[0], 1 > /dev/pruspeak 3 | echo WAIT 1000 > /dev/pruspeak 4 | echo SET DIO[0], 0 > /dev/pruspeak 5 | echo WAIT 1000 > /dev/pruspeak 6 | echo GOTO 0 > /dev/pruspeak 7 | echo ENDSCRIPT > /dev/pruspeak 8 | echo RUN > /dev/pruspeak 9 | 10 | -------------------------------------------------------------------------------- /doc_and_examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples and documentations 2 | 3 | ## Pin mappings 4 | DIO[0] to DIO[8] => pru0_r30_0 to pru0_r30_8 5 | pinmux.pdf contains the pru0_r30_x (pru format) GPIOy_z (GPIO format) mappings. 6 | beaglebone_headers.png has the pin number in GPIO format to header pin mapping. 7 | 8 | eg. searching for 'pru0_pru_r30_0' [ i.e. DIO[0] ] in pinmux.pdf gives us a corresponding 'gpio3_14' 9 | looking up 'gpio3_14' in beaglebone_headers.png gives us header pin 'P9.31'. 10 | Hence DIO[0] corresponds to 'P9.31' 11 | 12 | -------------------------------------------------------------------------------- /doc_and_examples/beaglebone_headers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepakkarki/pruspeak/acb24a4f9e91ab8f147154750aec409ab9d3dca0/doc_and_examples/beaglebone_headers.png -------------------------------------------------------------------------------- /doc_and_examples/pinmux.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepakkarki/pruspeak/acb24a4f9e91ab8f147154750aec409ab9d3dca0/doc_and_examples/pinmux.pdf -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #make driver 3 | cd src/driver 4 | make 5 | make install 6 | cd ../.. 7 | 8 | #make pru_firmware 9 | cd src/pru-firmware 10 | make 11 | make install 12 | cd ../.. 13 | 14 | #make dts 15 | cd src/dts 16 | make 17 | make install 18 | cd ../.. 19 | 20 | #make userspace 21 | cd src/userspace_lib 22 | make 23 | make install 24 | cd ../.. 25 | 26 | 27 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | modprobe pru_speak 3 | config-pin overlay BB-PRUSPEAK 4 | bs_tcp_server.py > /var/log/pruspeak.log & 5 | -------------------------------------------------------------------------------- /src/driver/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += pru_speak.o 2 | KDIR := /lib/modules/$(shell uname -r)/build 3 | 4 | all: 5 | if [ ! -d "$(KDIR)" ]; then apt-get install linux-headers-$(shell uname -r); fi 6 | make -C $(KDIR) M=$(PWD) modules 7 | 8 | load: pru_speak.ko unload 9 | insmod ./pru_speak.ko 10 | 11 | unload: 12 | rmmod ./pru_speak.ko || true 13 | 14 | install: 15 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules_install 16 | 17 | clean: 18 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 19 | 20 | -------------------------------------------------------------------------------- /src/driver/README.md: -------------------------------------------------------------------------------- 1 | PRU Speak Driver 2 | ================= 3 | 4 | This is the remote proc driver for the PRU Speak firmware. 5 | 6 | This driver is responsible for : 7 | * Loading the PRU Speak firmware on the PRU. 8 | * Exposing a sysfs interface for exchanging BotSpeak instructions. 9 | * Providing mmap functionality for fast IO between the client process and PRU. 10 | * Forwarding interrupts to the userspace. 11 | -------------------------------------------------------------------------------- /src/dts/BB-PRUSPEAK-00A0.dts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Pantelis Antoniou 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation. 7 | */ 8 | /dts-v1/; 9 | /plugin/; 10 | 11 | / { 12 | compatible = "ti,beaglebone", "ti,beaglebone-black"; 13 | 14 | /* identification */ 15 | part-number = "BB-PRUSPEAK"; 16 | version = "00A0"; 17 | 18 | /* state the resources this cape uses */ 19 | exclusive-use = 20 | /* the pin header uses */ 21 | "P9.27", /* pru0: pr1_pru0_pru_r30_5 */ 22 | 23 | "P8.11", /* pru0: pr1_pru0_pru_r30_15 */ 24 | "P8.12", /* pru0: pr1_pru0_pru_r30_14 */ 25 | "P9.25", /* pru0: pr1_pru0_pru_r30_7 */ 26 | "P9.41", /* pru0: pr1_pru0_pru_r30_6 */ 27 | "P9.42", /* pru0: pr1_pru0_pru_r30_4 */ 28 | "P9.28", /* pru0: pr1_pru0_pru_r30_3 */ 29 | "P9.30", /* pru0: pr1_pru0_pru_r30_2 */ 30 | "P9.29", /* pru0: pr1_pru0_pru_r30_1 */ 31 | "P9.31", /* pru0: pr1_pru0_pru_r30_0 */ 32 | /* pru0: pr1_pru0_pru_r30_13 is on MMC0_CMD */ 33 | /* pru0: pr1_pru0_pru_r30_12 is on MMC0_CLK */ 34 | /* pru0: pr1_pru0_pru_r30_11 is on MMC0_DAT0 */ 35 | /* pru0: pr1_pru0_pru_r30_10 is on MMC0_DAT1 */ 36 | /* pru0: pr1_pru0_pru_r30_9 is on MMC0_DAT2 */ 37 | /* pru0: pr1_pru0_pru_r30_8 is on MMC0_DAT3 */ 38 | "P8.15", /* pru0: pr1_pru0_pru_r31_15 */ 39 | "P8.14", /* pru0: pr1_pru0_pru_r31_14 */ 40 | 41 | //"P8.20", /* pru1: pr1_pru1_pru_r30_13 */ --conflict with eMMC 42 | 43 | //"P8.21", /* pru1: pr1_pru1_pru_r30_12 */ 44 | "P8.27", /* pru1: pr1_pru1_pru_r30_8 */ 45 | "P8.28", /* pru1: pr1_pru1_pru_r30_10 */ 46 | "P8.29", /* pru1: pr1_pru1_pru_r30_9 */ 47 | "P8.30", /* pru1: pr1_pru1_pru_r30_11 */ 48 | "P8.39", /* pru1: pr1_pru1_pru_r30_6 */ 49 | "P8.40", /* pru1: pr1_pru1_pru_r30_7 */ 50 | "P8.41", /* pru1: pr1_pru1_pru_r30_4 */ 51 | "P8.42", /* pru1: pr1_pru1_pru_r30_5 */ 52 | "P8.43", /* pru1: pr1_pru1_pru_r30_2 */ 53 | "P8.44", /* pru1: pr1_pru1_pru_r30_3 */ 54 | "P8.45", /* pru1: pr1_pru1_pru_r30_0 */ 55 | "P8.46", /* pru1: pr1_pru1_pru_r30_1 */ 56 | /* pru1: pr1_pru1_pru_r30_14 is on UART0_RXD */ 57 | /* pru1: pr1_pru1_pru_r30_15 is on UART0_TXD */ 58 | /* the hardware IP uses */ 59 | "pru0", 60 | "pru1"; 61 | 62 | fragment@0 { 63 | target = <&am33xx_pinmux>; 64 | __overlay__ { 65 | 66 | pru_gpio_pins: pinmux_pru_gpio_pins { 67 | pinctrl-single,pins = < 68 | 0x1a4 0x0f /* P9 27 GPIO3_19: mcasp0_fsr.gpio3[19] | MODE7 | OUTPUT */ 69 | >; 70 | }; 71 | 72 | pru_pru_pins: pinmux_pru_pru_pins { 73 | pinctrl-single,pins = < 74 | 0x1a4 0x25 /* mcasp0_fsr.pr1_pru0_pru_r30_5, MODE5 | OUTPUT | PRU */ 75 | 0x034 0x26 /* gpmc_ad13.pr1_pru0_pru_r30_15, MODE6 | OUTPUT | PRU */ 76 | 0x030 0x26 /* gpmc_ad12.pr1_pru0_pru_r30_14, MODE6 | OUTPUT | PRU */ 77 | 0x1ac 0x25 /* mcasp0_ahclkx.pr1_pru0_pru_r30_7, MODE5 | OUTPUT | PRU */ 78 | 0x1a8 0x25 /* mcasp0_axr1.pr1_pru0_pru_r30_6, MODE5 | OUTPUT | PRU */ 79 | 0x1a0 0x25 /* mcasp0_aclkr.pr1_pru0_pru_r30_4, MODE5 | OUTPUT | PRU */ 80 | 0x19c 0x25 /* mcasp0_ahclkr.pr1_pru0_pru_r30_3, MODE5 | OUTPUT | PRU */ 81 | 0x198 0x25 /* mcasp0_axr0.pr1_pru0_pru_r30_2, MODE5 | OUTPUT | PRU */ 82 | 0x194 0x25 /* mcasp0_fsx.pr1_pru0_pru_r30_1, MODE5 | OUTPUT | PRU */ 83 | 0x190 0x25 /* mcasp0_aclkx.pr1_pru0_pru_r30_0, MODE5 | OUTPUT | PRU */ 84 | 0x03c 0x26 /* GPMC_AD15.pr1_pru0_pru_r31_15, MODE6 | INPUT | PRU*/ 85 | 0x038 0x26 /* GPMC_AD14.pr1_pru0_pru_r31_14, MODE6 | INPUT | PRU*/ 86 | 87 | //0x084 0x25 /* gpmc_csn2.pr1_pru1_pru_r30_13, MODE5 | OUTPUT | PRU */ --conflict with eMMC 88 | //0x080 0x25 /* gpmc_csn1.pr1_pru1_pru_r30_12, MODE5 | OUTPUT | PRU */ 89 | 0x0e0 0x25 /* lcd_vsync.pr1_pru1_pru_r30_8, MODE5 | OUTPUT | PRU */ 90 | 0x0e8 0x25 /* lcd_pclk.pr1_pru1_pru_r30_10, MODE5 | OUTPUT | PRU */ 91 | 0x0e4 0x25 /* lcd_hsync.pr1_pru1_pru_r30_9, MODE5 | OUTPUT | PRU */ 92 | 0x0ec 0x25 /* lcd_ac_bias_en.pr1_pru1_pru_r30_11, MODE5 | OUTPUT | PRU */ 93 | 0x0bc 0x25 /* lcd_data7.pr1_pru1_pru_r30_7, MODE5 | OUTPUT | PRU */ 94 | 0x0b0 0x25 /* lcd_data4.pr1_pru1_pru_r30_4, MODE5 | OUTPUT | PRU */ 95 | 0x0b4 0x25 /* lcd_data5.pr1_pru1_pru_r30_5, MODE5 | OUTPUT | PRU */ 96 | 0x0ac 0x25 /* lcd_data3.pr1_pru1_pru_r30_3, MODE5 | OUTPUT | PRU */ 97 | 0x0a0 0x25 /* lcd_data0.pr1_pru1_pru_r30_0, MODE5 | OUTPUT | PRU */ 98 | 0x0a4 0x25 /* lcd_data1.pr1_pru1_pru_r30_1, MODE5 | OUTPUT | PRU */ 99 | >; 100 | }; 101 | }; 102 | }; 103 | 104 | fragment@2 { 105 | target = <&ocp>; 106 | 107 | __overlay__ { 108 | 109 | /* avoid stupid warning */ 110 | #address-cells = <1>; 111 | #size-cells = <1>; 112 | 113 | prurproc { 114 | compatible = "ti,pru-rproc"; 115 | 116 | pinctrl-names = "default"; 117 | pinctrl-0 = <&pru_pru_pins>; 118 | 119 | reg = <0x4a300000 0x080000>; 120 | 121 | status = "okay"; 122 | 123 | ti,hwmods = "pruss"; 124 | ti,deassert-hard-reset = "pruss", "pruss"; 125 | interrupt-parent = <&intc>; 126 | 127 | /* interrupts on the host */ 128 | interrupts = <20 21 22 23 24 25 26 27>; 129 | 130 | /* events these interrupts map to (host interrupt) */ 131 | events = <2 3 4 5 6 7 8 9>; 132 | 133 | /* PRU interrupt controller offset */ 134 | pintc = <0x20000>; 135 | 136 | /* 12K Shared Data RAM global, size, local */ 137 | pdram = <0x10000 0x03000 0x10000>; 138 | 139 | /* 140 | * SYSEVENT ids 141 | * 142 | * - PRU/ARM communication 143 | * PRU0_PRU1 17 144 | * PRU1_PRU0 18 145 | * PRU0_ARM 19 146 | * PRU1_ARM 20 147 | * ARM_PRU0 21 148 | * ARM_PRU1 22 149 | * 150 | * Full SYSEVENT list 151 | * 152 | * parity_err_intr_pend 0 153 | * pru0_r31_status_cnt16 1 154 | * pru1_r31_status_cnt16 2 155 | * uart_urxevt_intr_req 4 156 | * uart_utxevt_intr_req 5 157 | * uart_uint_intr_req 6 158 | * iep_tim_cap_cmp_pend 7 159 | * ecap_intr_req 15 160 | * pru_mst_intr[0-15]_intr_req 16-31 161 | * nirq 32 (UART1) 162 | * mcasp_x_intr_pend 33 (MCASP1) 163 | * mcasp_r_intr_pend 34 (MCASP1) 164 | * ecap_intr_intr_pend 35 (ECAP1) 165 | * ecap_intr_intr_pend 36 (ECAP2) 166 | * epwm_intr_intr_pend 37 (eHRPWM2) 167 | * dcan_uerr 38 (DCAN0) 168 | * dcan_int1 39 (DCAN0) 169 | * dcan_intr 40 (DCAN0) 170 | * POINTRPEND 41 (I2C0) 171 | * ecap_intr_intr_pend 42 (ECAP0) 172 | * epwm_intr_intr_pend 43 (eHRPWM0) 173 | * SINTERRUPTN 44 (McSPI0) 174 | * eqep_intr_intr_pend 45 (eQEP0) 175 | * epwm_intr_intr_pend 46 (eHRPWM1) 176 | * c0_misc_pend 47 3PGSW (GEMAC) 177 | * c0_tx_pend 48 3PGSW (GEMAC) 178 | * c0_rx_pend 49 3PGSW (GEMAC) 179 | * c0_rx_thresh_pend 50 3PGSW (GEMAC) 180 | * nirq 51 (UART0) 181 | * nirq 52 (UART2) 182 | * gen_intr_pend 53 (ADC_TSC) 183 | * mcasp_r_intr_pend 54 (McASP0) 184 | * mcasp_x_intr_pend 55 (McASP1) 185 | * pwm_trip_zone 56 (eHRPWM0/eHRPWM1/eHRP WM2) 186 | * POINTRPEND1 57 (GPIO0) 187 | * Emulation Suspend Signal 58 (Debugss) 188 | * initiator_sinterrupt_q_n2 59 (Mbox0 - mail_u2_irq (mailbox interrupt for pru1)) 189 | * initiator_sinterrupt_q_n1 60 (Mbox0 - mail_u1_irq (mailbox interrupt for pru0)) 190 | * tptc_erint_pend_po 61 (TPTC0 (EDMA)) 191 | * tpcc_errint_pend_po 62 (TPCC (EDMA)) 192 | * tpcc_int_pend_po1 63 (TPCC (EDMA)) 193 | * 194 | * HOST interrupt ids 195 | * 196 | * PRU0 0 197 | * PRU1 1 198 | * EVTOUT0-7 2-9 199 | */ 200 | 201 | /* sysevent map to intc channel */ 202 | sysevent-to-channel-map = 203 | <17 1>, /* PRU0_PRU1 -> CH1 */ 204 | <18 0>, /* PRU1_PRU0 -> CH0 */ 205 | <19 2>, /* PRU0_ARM -> CH2 */ 206 | <20 3>, /* PRU1_ARM -> CH3 */ 207 | <21 0>, /* ARM_PRU0 -> CH0 */ 208 | <22 1>, /* ARM_PRU1 -> CH1 */ 209 | <24 4>, /* VRING Host->PRU0 -> CH4 */ 210 | <25 5>, /* VRING PRU0->Host -> CH5 */ 211 | <26 6>, /* VRING Host->PRU1 -> CH6 */ 212 | <27 7>; /* VRING PRU1->Host -> CH7 */ 213 | 214 | /* channel to host interrupt map */ 215 | channel-to-host-interrupt-map = 216 | <0 0>, /* CH0 -> PRU0 */ 217 | <1 1>, /* CH1 -> PRU1 */ 218 | <2 2>, /* CH2 -> EVTOUT0 */ 219 | <3 3>, /* CH3 -> EVTOUT1 */ 220 | <4 0>, /* CH4 -> PRU0 */ 221 | <5 6>, /* CH5 -> EVTOUT4 */ 222 | <6 1>, /* CH6 -> PRU1 */ 223 | <7 7>; /* CH7 -> EVTOUT5 */ 224 | 225 | /* indices are ARM=0, PRU0=1, PRU1=2 */ 226 | target-to-sysevent-map = 227 | <0xffffffff 21 22>, /* ARM: DONTCARE, ARM_PRU0, ARM_PRU1 */ 228 | < 19 0xffffffff 17>, /* PRU0: PRU0_ARM, DONTCARE, PRU0_PRU1 */ 229 | < 20 18 0xffffffff>; /* PRU1: PRU1_ARM, PRU1_PRU0, DONTCARE */ 230 | 231 | /* both the PRUs have 200MHz frequency so period is 5ns */ 232 | clock-freq = <200000000>; 233 | 234 | /* the linux pwms we support */ 235 | pru-pwm-channels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 21>; 236 | /* first PRU controls the PWMs */ 237 | pru-pwm-controller = <0>; 238 | /* the IDs of the downcalls the firmware expects for PWMs */ 239 | /* CONFIG=0, ENABLE=1, DISABLE=2 */ 240 | pru-pwm-dc-ids = <0 1 2>; 241 | 242 | /* definition for the first PRU */ 243 | pru0 { 244 | pru-index = <0>; 245 | 246 | /* offset, size, local */ 247 | iram = <0x34000 0x02000 0x00000>; /* code ram (8K) */ 248 | 249 | /* offset, size, local, other */ 250 | dram = <0x00000 0x02000 0x00000 0x10000>; /* data ram (8K) */ 251 | 252 | pctrl = <0x22000>; 253 | pdbg = <0x22400>; 254 | 255 | firmware-elf; 256 | firmware = "pru0_firmware"; 257 | 258 | /* sysevents signaling ring activity (host, pru)*/ 259 | vring-sysev = <24 25>; 260 | 261 | /* shared memory count */ 262 | shm-count = <2>; 263 | 264 | /* corresponding size of each shm segment - in units of pages*/ 265 | shm-size = <1 1>; 266 | 267 | resource_table { 268 | resource-table; 269 | version = <1>; 270 | 271 | pru0_rproc_serial: pru0_vdev_rproc_serial { 272 | vdev-rproc-serial; 273 | 274 | /* notification IDs are totally bogus */ 275 | /* rproc will idr_alloc anyway */ 276 | 277 | notifyid = <8>; /* <- bogus */ 278 | /* da align num notifyid */ 279 | vring-0 = <0 16 8 0>; 280 | vring-1 = <0 16 8 0>; 281 | }; 282 | 283 | // pru0_rproc_rpmsg: pru0_vdev_rproc_rpmsg { 284 | // vdev-rpmsg; 285 | // 286 | // /* notification IDs are totally bogus */ 287 | // /* rproc will idr_alloc anyway */ 288 | // 289 | // notifyid = <9>; /* <- bogus */ 290 | // /* da align num notifyid */ 291 | // vring-0 = <0 16 512 0>; 292 | // vring-1 = <0 16 512 0>; 293 | // }; 294 | }; 295 | }; 296 | 297 | /* definition for the second PRU */ 298 | pru1 { 299 | pru-index = <1>; 300 | 301 | /* offset, size, local */ 302 | iram = <0x38000 0x02000 0x00000>; /* code ram (8K) */ 303 | 304 | /* offset, size, local, other */ 305 | dram = <0x02000 0x02000 0x00000 0x10000>; /* data ram (8K) */ 306 | 307 | pctrl = <0x24000>; 308 | pdbg = <0x24400>; 309 | 310 | firmware-elf; 311 | firmware = "pru1_firmware"; 312 | 313 | /* shared memory count */ 314 | shm-count = <2>; 315 | 316 | /* corresponding size of each shm segment - in units of pages*/ 317 | shm-size = <1 1>; 318 | 319 | }; 320 | 321 | }; 322 | 323 | pru_speak { 324 | compatible = "ti,pru_speak"; 325 | status = "okay"; 326 | }; 327 | }; 328 | }; 329 | }; 330 | -------------------------------------------------------------------------------- /src/dts/Makefile: -------------------------------------------------------------------------------- 1 | all: BB-PRUSPEAK-00A0.dts 2 | dtc -O dtb -o BB-PRUSPEAK-00A0.dtbo -b 0 -@ BB-PRUSPEAK-00A0.dts 3 | 4 | install: 5 | install -m 644 BB-PRUSPEAK-00A0.dtbo /lib/firmware 6 | 7 | -------------------------------------------------------------------------------- /src/dts/README.md: -------------------------------------------------------------------------------- 1 | This is the Device tree overlay for the PRU speak firmware. 2 | -------------------------------------------------------------------------------- /src/dts/am335x-boneblack.dts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation. 7 | */ 8 | /dts-v1/; 9 | 10 | /include/ "am33xx.dtsi" 11 | 12 | /include/ "am335x-bone-common.dtsi" 13 | 14 | &am33xx_pinmux { 15 | rstctl_pins: pinmux_rstctl_pins { 16 | pinctrl-single,pins = < 17 | /* eMMC_RSTn */ 18 | 0x50 0x17 /* gpmc_a4.gpio1_20, OUTPUT | MODE7 | PULLUP */ 19 | >; 20 | }; 21 | }; 22 | 23 | &ldo3_reg { 24 | regulator-min-microvolt = <1800000>; 25 | regulator-max-microvolt = <1800000>; 26 | regulator-always-on; 27 | }; 28 | 29 | &rstctl { 30 | status = "okay"; 31 | compatible = "gpio-rctrl"; 32 | pinctrl-names = "default"; 33 | pinctrl-0 = <&rstctl_pins>; 34 | 35 | #reset-cells = <2>; 36 | 37 | gpios = <&gpio2 20 0x00>; 38 | gpio-names = "eMMC_RSTn"; 39 | }; 40 | 41 | &mmc1 { 42 | vmmc-supply = <&vmmcsd_fixed>; 43 | }; 44 | 45 | &mmc2 { 46 | vmmc-supply = <&vmmcsd_fixed>; 47 | pinctrl-names = "default"; 48 | pinctrl-0 = <&emmc_pins>; 49 | bus-width = <8>; 50 | ti,non-removable; 51 | status = "disabled"; 52 | ti,vcc-aux-disable-is-sleep; 53 | }; 54 | 55 | &am33xx_pinmux { 56 | /************************/ 57 | /* P8 Header */ 58 | /************************/ 59 | 60 | /* P8_01 GND */ 61 | /* P8_02 GND */ 62 | /* P8_03 (ZCZ ball R9 ) emmc */ 63 | /* P8_04 (ZCZ ball T9 ) emmc */ 64 | /* P8_05 (ZCZ ball R8 ) emmc */ 65 | /* P8_06 (ZCZ ball T8 ) emmc */ 66 | 67 | /* P8_07 (ZCZ ball R7 ) */ 68 | P8_07_default_pin: pinmux_P8_07_default_pin { 69 | pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 70 | P8_07_gpio_pin: pinmux_P8_07_gpio_pin { 71 | pinctrl-single,pins = <0x090 0x2F>; }; /* Mode 7, RxActive */ 72 | P8_07_gpio_pu_pin: pinmux_P8_07_gpio_pu_pin { 73 | pinctrl-single,pins = <0x090 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 74 | P8_07_gpio_pd_pin: pinmux_P8_07_gpio_pd_pin { 75 | pinctrl-single,pins = <0x090 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 76 | P8_07_timer_pin: pinmux_P8_07_timer_pin { 77 | pinctrl-single,pins = <0x090 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 78 | 79 | /* P8_08 (ZCZ ball T7 ) */ 80 | P8_08_default_pin: pinmux_P8_08_default_pin { 81 | pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 82 | P8_08_gpio_pin: pinmux_P8_08_gpio_pin { 83 | pinctrl-single,pins = <0x094 0x2F>; }; /* Mode 7, RxActive */ 84 | P8_08_gpio_pu_pin: pinmux_P8_08_gpio_pu_pin { 85 | pinctrl-single,pins = <0x094 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 86 | P8_08_gpio_pd_pin: pinmux_P8_08_gpio_pd_pin { 87 | pinctrl-single,pins = <0x094 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 88 | P8_08_timer_pin: pinmux_P8_08_timer_pin { 89 | pinctrl-single,pins = <0x094 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 90 | 91 | /* P8_09 (ZCZ ball T6 ) */ 92 | P8_09_default_pin: pinmux_P8_09_default_pin { 93 | pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 94 | P8_09_gpio_pin: pinmux_P8_09_gpio_pin { 95 | pinctrl-single,pins = <0x09c 0x2F>; }; /* Mode 7, RxActive */ 96 | P8_09_gpio_pu_pin: pinmux_P8_09_gpio_pu_pin { 97 | pinctrl-single,pins = <0x09c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 98 | P8_09_gpio_pd_pin: pinmux_P8_09_gpio_pd_pin { 99 | pinctrl-single,pins = <0x09c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 100 | P8_09_timer_pin: pinmux_P8_09_timer_pin { 101 | pinctrl-single,pins = <0x09c 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 102 | 103 | /* P8_10 (ZCZ ball U6 ) */ 104 | P8_10_default_pin: pinmux_P8_10_default_pin { 105 | pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 106 | P8_10_gpio_pin: pinmux_P8_10_gpio_pin { 107 | pinctrl-single,pins = <0x098 0x2F>; }; /* Mode 7, RxActive */ 108 | P8_10_gpio_pu_pin: pinmux_P8_10_gpio_pu_pin { 109 | pinctrl-single,pins = <0x098 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 110 | P8_10_gpio_pd_pin: pinmux_P8_10_gpio_pd_pin { 111 | pinctrl-single,pins = <0x098 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 112 | P8_10_timer_pin: pinmux_P8_10_timer_pin { 113 | pinctrl-single,pins = <0x098 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 114 | 115 | /* P8_11 (ZCZ ball R12) */ 116 | P8_11_default_pin: pinmux_P8_11_default_pin { 117 | pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 118 | P8_11_gpio_pin: pinmux_P8_11_gpio_pin { 119 | pinctrl-single,pins = <0x034 0x2F>; }; /* Mode 7, RxActive */ 120 | P8_11_gpio_pu_pin: pinmux_P8_11_gpio_pu_pin { 121 | pinctrl-single,pins = <0x034 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 122 | P8_11_gpio_pd_pin: pinmux_P8_11_gpio_pd_pin { 123 | pinctrl-single,pins = <0x034 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 124 | P8_11_pruout_pin: pinmux_P8_11_pruout_pin { 125 | pinctrl-single,pins = <0x034 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 126 | P8_11_qep_pin: pinmux_P8_11_qep_pin { 127 | pinctrl-single,pins = <0x034 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 128 | 129 | /* P8_12 (ZCZ ball T12) */ 130 | P8_12_default_pin: pinmux_P8_12_default_pin { 131 | pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 132 | P8_12_gpio_pin: pinmux_P8_12_gpio_pin { 133 | pinctrl-single,pins = <0x030 0x2F>; }; /* Mode 7, RxActive */ 134 | P8_12_gpio_pu_pin: pinmux_P8_12_gpio_pu_pin { 135 | pinctrl-single,pins = <0x030 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 136 | P8_12_gpio_pd_pin: pinmux_P8_12_gpio_pd_pin { 137 | pinctrl-single,pins = <0x030 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 138 | P8_12_pruout_pin: pinmux_P8_12_pruout_pin { 139 | pinctrl-single,pins = <0x030 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 140 | P8_12_qep_pin: pinmux_P8_12_qep_pin { 141 | pinctrl-single,pins = <0x030 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 142 | 143 | /* P8_13 (ZCZ ball T10) */ 144 | P8_13_default_pin: pinmux_P8_13_default_pin { 145 | pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 146 | P8_13_gpio_pin: pinmux_P8_13_gpio_pin { 147 | pinctrl-single,pins = <0x024 0x2F>; }; /* Mode 7, RxActive */ 148 | P8_13_gpio_pu_pin: pinmux_P8_13_gpio_pu_pin { 149 | pinctrl-single,pins = <0x024 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 150 | P8_13_gpio_pd_pin: pinmux_P8_13_gpio_pd_pin { 151 | pinctrl-single,pins = <0x024 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 152 | P8_13_pwm_pin: pinmux_P8_13_pwm_pin { 153 | pinctrl-single,pins = <0x024 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 154 | 155 | /* P8_14 (ZCZ ball T11) */ 156 | P8_14_default_pin: pinmux_P8_14_default_pin { 157 | pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 158 | P8_14_gpio_pin: pinmux_P8_14_gpio_pin { 159 | pinctrl-single,pins = <0x028 0x2F>; }; /* Mode 7, RxActive */ 160 | P8_14_gpio_pu_pin: pinmux_P8_14_gpio_pu_pin { 161 | pinctrl-single,pins = <0x028 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 162 | P8_14_gpio_pd_pin: pinmux_P8_14_gpio_pd_pin { 163 | pinctrl-single,pins = <0x028 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 164 | P8_14_pwm_pin: pinmux_P8_14_pwm_pin { 165 | pinctrl-single,pins = <0x028 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 166 | 167 | /* P8_15 (ZCZ ball U13) */ 168 | P8_15_default_pin: pinmux_P8_15_default_pin { 169 | pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 170 | P8_15_gpio_pin: pinmux_P8_15_gpio_pin { 171 | pinctrl-single,pins = <0x03c 0x2F>; }; /* Mode 7, RxActive */ 172 | P8_15_gpio_pu_pin: pinmux_P8_15_gpio_pu_pin { 173 | pinctrl-single,pins = <0x03c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 174 | P8_15_gpio_pd_pin: pinmux_P8_15_gpio_pd_pin { 175 | pinctrl-single,pins = <0x03c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 176 | P8_15_pruin_pin: pinmux_P8_15_pruin_pin { 177 | pinctrl-single,pins = <0x03c 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 178 | P8_15_qep_pin: pinmux_P8_15_qep_pin { 179 | pinctrl-single,pins = <0x03c 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 180 | 181 | /* P8_16 (ZCZ ball V13) */ 182 | P8_16_default_pin: pinmux_P8_16_default_pin { 183 | pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 184 | P8_16_gpio_pin: pinmux_P8_16_gpio_pin { 185 | pinctrl-single,pins = <0x038 0x2F>; }; /* Mode 7, RxActive */ 186 | P8_16_gpio_pu_pin: pinmux_P8_16_gpio_pu_pin { 187 | pinctrl-single,pins = <0x038 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 188 | P8_16_gpio_pd_pin: pinmux_P8_16_gpio_pd_pin { 189 | pinctrl-single,pins = <0x038 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 190 | P8_16_pruin_pin: pinmux_P8_16_pruin_pin { 191 | pinctrl-single,pins = <0x038 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 192 | P8_16_qep_pin: pinmux_P8_16_qep_pin { 193 | pinctrl-single,pins = <0x038 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 194 | 195 | /* P8_17 (ZCZ ball U12) */ 196 | P8_17_default_pin: pinmux_P8_17_default_pin { 197 | pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 198 | P8_17_gpio_pin: pinmux_P8_17_gpio_pin { 199 | pinctrl-single,pins = <0x02c 0x2F>; }; /* Mode 7, RxActive */ 200 | P8_17_gpio_pu_pin: pinmux_P8_17_gpio_pu_pin { 201 | pinctrl-single,pins = <0x02c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 202 | P8_17_gpio_pd_pin: pinmux_P8_17_gpio_pd_pin { 203 | pinctrl-single,pins = <0x02c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 204 | P8_17_pwm_pin: pinmux_P8_17_pwm_pin { 205 | pinctrl-single,pins = <0x02c 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 206 | 207 | /* P8_18 (ZCZ ball V12) */ 208 | P8_18_default_pin: pinmux_P8_18_default_pin { 209 | pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 210 | P8_18_gpio_pin: pinmux_P8_18_gpio_pin { 211 | pinctrl-single,pins = <0x08c 0x2F>; }; /* Mode 7, RxActive */ 212 | P8_18_gpio_pu_pin: pinmux_P8_18_gpio_pu_pin { 213 | pinctrl-single,pins = <0x08c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 214 | P8_18_gpio_pd_pin: pinmux_P8_18_gpio_pd_pin { 215 | pinctrl-single,pins = <0x08c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 216 | 217 | /* P8_19 (ZCZ ball U10) */ 218 | P8_19_default_pin: pinmux_P8_19_default_pin { 219 | pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 220 | P8_19_gpio_pin: pinmux_P8_19_gpio_pin { 221 | pinctrl-single,pins = <0x020 0x2F>; }; /* Mode 7, RxActive */ 222 | P8_19_gpio_pu_pin: pinmux_P8_19_gpio_pu_pin { 223 | pinctrl-single,pins = <0x020 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 224 | P8_19_gpio_pd_pin: pinmux_P8_19_gpio_pd_pin { 225 | pinctrl-single,pins = <0x020 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 226 | P8_19_pwm_pin: pinmux_P8_19_pwm_pin { 227 | pinctrl-single,pins = <0x020 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 228 | 229 | /* P8_20 (ZCZ ball V9 ) emmc */ 230 | /* P8_21 (ZCZ ball U9 ) emmc */ 231 | /* P8_22 (ZCZ ball V8 ) emmc */ 232 | /* P8_23 (ZCZ ball U8 ) emmc */ 233 | /* P8_24 (ZCZ ball V7 ) emmc */ 234 | /* P8_25 (ZCZ ball U7 ) emmc */ 235 | 236 | /* P8_26 (ZCZ ball V6 ) */ 237 | P8_26_default_pin: pinmux_P8_26_default_pin { 238 | pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 239 | P8_26_gpio_pin: pinmux_P8_26_gpio_pin { 240 | pinctrl-single,pins = <0x07c 0x2F>; }; /* Mode 7, RxActive */ 241 | P8_26_gpio_pu_pin: pinmux_P8_26_gpio_pu_pin { 242 | pinctrl-single,pins = <0x07c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 243 | P8_26_gpio_pd_pin: pinmux_P8_26_gpio_pd_pin { 244 | pinctrl-single,pins = <0x07c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 245 | 246 | /* P8_27 (ZCZ ball U5 ) hdmi */ 247 | /* P8_28 (ZCZ ball V5 ) hdmi */ 248 | /* P8_29 (ZCZ ball R5 ) hdmi */ 249 | /* P8_30 (ZCZ ball R6 ) hdmi */ 250 | /* P8_31 (ZCZ ball V4 ) hdmi */ 251 | /* P8_32 (ZCZ ball T5 ) hdmi */ 252 | /* P8_33 (ZCZ ball V3 ) hdmi */ 253 | /* P8_34 (ZCZ ball U4 ) hdmi */ 254 | /* P8_35 (ZCZ ball V2 ) hdmi */ 255 | /* P8_36 (ZCZ ball U3 ) hdmi */ 256 | /* P8_37 (ZCZ ball U1 ) hdmi */ 257 | /* P8_38 (ZCZ ball U2 ) hdmi */ 258 | /* P8_39 (ZCZ ball T3 ) hdmi */ 259 | /* P8_40 (ZCZ ball T4 ) hdmi */ 260 | /* P8_41 (ZCZ ball T1 ) hdmi */ 261 | /* P8_42 (ZCZ ball T2 ) hdmi */ 262 | /* P8_43 (ZCZ ball R3 ) hdmi */ 263 | /* P8_44 (ZCZ ball R4 ) hdmi */ 264 | /* P8_45 (ZCZ ball R1 ) hdmi */ 265 | /* P8_46 (ZCZ ball R2 ) hdmi */ 266 | 267 | 268 | /************************/ 269 | /* P9 Header */ 270 | /************************/ 271 | 272 | /* P9_01 GND */ 273 | /* P9_02 GND */ 274 | /* P9_03 3.3V */ 275 | /* P9_04 3.3V */ 276 | /* P9_05 VDD_5V */ 277 | /* P9_06 VDD_5V */ 278 | /* P9_07 SYS_5V */ 279 | /* P9_08 SYS_5V */ 280 | /* P9_09 PWR_BUT */ 281 | /* P9_10 (ZCZ ball A10) RESETn */ 282 | 283 | /* P9_11 (ZCZ ball T17) */ 284 | P9_11_default_pin: pinmux_P9_11_default_pin { 285 | pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 286 | P9_11_gpio_pin: pinmux_P9_11_gpio_pin { 287 | pinctrl-single,pins = <0x070 0x2F>; }; /* Mode 7, RxActive */ 288 | P9_11_gpio_pu_pin: pinmux_P9_11_gpio_pu_pin { 289 | pinctrl-single,pins = <0x070 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 290 | P9_11_gpio_pd_pin: pinmux_P9_11_gpio_pd_pin { 291 | pinctrl-single,pins = <0x070 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 292 | P9_11_uart_pin: pinmux_P9_11_uart_pin { 293 | pinctrl-single,pins = <0x070 0x36>; }; /* Mode 6, Pull-Up, RxActive */ 294 | 295 | /* P9_12 (ZCZ ball U18) */ 296 | P9_12_default_pin: pinmux_P9_12_default_pin { 297 | pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 298 | P9_12_gpio_pin: pinmux_P9_12_gpio_pin { 299 | pinctrl-single,pins = <0x078 0x2F>; }; /* Mode 7, RxActive */ 300 | P9_12_gpio_pu_pin: pinmux_P9_12_gpio_pu_pin { 301 | pinctrl-single,pins = <0x078 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 302 | P9_12_gpio_pd_pin: pinmux_P9_12_gpio_pd_pin { 303 | pinctrl-single,pins = <0x078 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 304 | 305 | /* P9_13 (ZCZ ball U17) */ 306 | P9_13_default_pin: pinmux_P9_13_default_pin { 307 | pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 308 | P9_13_gpio_pin: pinmux_P9_13_gpio_pin { 309 | pinctrl-single,pins = <0x074 0x2F>; }; /* Mode 7, RxActive */ 310 | P9_13_gpio_pu_pin: pinmux_P9_13_gpio_pu_pin { 311 | pinctrl-single,pins = <0x074 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 312 | P9_13_gpio_pd_pin: pinmux_P9_13_gpio_pd_pin { 313 | pinctrl-single,pins = <0x074 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 314 | P9_13_uart_pin: pinmux_P9_13_uart_pin { 315 | pinctrl-single,pins = <0x074 0x36>; }; /* Mode 6, Pull-Up, RxActive */ 316 | 317 | /* P9_14 (ZCZ ball U14) */ 318 | P9_14_default_pin: pinmux_P9_14_default_pin { 319 | pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 320 | P9_14_gpio_pin: pinmux_P9_14_gpio_pin { 321 | pinctrl-single,pins = <0x048 0x2F>; }; /* Mode 7, RxActive */ 322 | P9_14_gpio_pu_pin: pinmux_P9_14_gpio_pu_pin { 323 | pinctrl-single,pins = <0x048 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 324 | P9_14_gpio_pd_pin: pinmux_P9_14_gpio_pd_pin { 325 | pinctrl-single,pins = <0x048 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 326 | P9_14_pwm_pin: pinmux_P9_14_pwm_pin { 327 | pinctrl-single,pins = <0x048 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 328 | 329 | /* P9_15 (ZCZ ball R13) */ 330 | P9_15_default_pin: pinmux_P9_15_default_pin { 331 | pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 332 | P9_15_gpio_pin: pinmux_P9_15_gpio_pin { 333 | pinctrl-single,pins = <0x040 0x2F>; }; /* Mode 7, RxActive */ 334 | P9_15_gpio_pu_pin: pinmux_P9_15_gpio_pu_pin { 335 | pinctrl-single,pins = <0x040 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 336 | P9_15_gpio_pd_pin: pinmux_P9_15_gpio_pd_pin { 337 | pinctrl-single,pins = <0x040 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 338 | P9_15_pwm_pin: pinmux_P9_15_pwm_pin { 339 | pinctrl-single,pins = <0x040 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 340 | 341 | /* P9_16 (ZCZ ball T14) */ 342 | P9_16_default_pin: pinmux_P9_16_default_pin { 343 | pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 344 | P9_16_gpio_pin: pinmux_P9_16_gpio_pin { 345 | pinctrl-single,pins = <0x04c 0x2F>; }; /* Mode 7, RxActive */ 346 | P9_16_gpio_pu_pin: pinmux_P9_16_gpio_pu_pin { 347 | pinctrl-single,pins = <0x04c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 348 | P9_16_gpio_pd_pin: pinmux_P9_16_gpio_pd_pin { 349 | pinctrl-single,pins = <0x04c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 350 | P9_16_pwm_pin: pinmux_P9_16_pwm_pin { 351 | pinctrl-single,pins = <0x04c 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 352 | 353 | /* P9_17 (ZCZ ball A16) */ 354 | P9_17_default_pin: pinmux_P9_17_default_pin { 355 | pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 356 | P9_17_gpio_pin: pinmux_P9_17_gpio_pin { 357 | pinctrl-single,pins = <0x15c 0x2F>; }; /* Mode 7, RxActive */ 358 | P9_17_gpio_pu_pin: pinmux_P9_17_gpio_pu_pin { 359 | pinctrl-single,pins = <0x15c 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 360 | P9_17_gpio_pd_pin: pinmux_P9_17_gpio_pd_pin { 361 | pinctrl-single,pins = <0x15c 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 362 | P9_17_spi_pin: pinmux_P9_17_spi_pin { 363 | pinctrl-single,pins = <0x15c 0x30>; }; /* Mode 0, Pull-Up, RxActive */ 364 | P9_17_i2c_pin: pinmux_P9_17_i2c_pin { 365 | pinctrl-single,pins = <0x15c 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 366 | P9_17_pwm_pin: pinmux_P9_17_pwm_pin { 367 | pinctrl-single,pins = <0x15c 0x33>; }; /* Mode 3, Pull-Up, RxActive */ 368 | 369 | /* P9_18 (ZCZ ball B16) */ 370 | P9_18_default_pin: pinmux_P9_18_default_pin { 371 | pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 372 | P9_18_gpio_pin: pinmux_P9_18_gpio_pin { 373 | pinctrl-single,pins = <0x158 0x2F>; }; /* Mode 7, RxActive */ 374 | P9_18_gpio_pu_pin: pinmux_P9_18_gpio_pu_pin { 375 | pinctrl-single,pins = <0x158 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 376 | P9_18_gpio_pd_pin: pinmux_P9_18_gpio_pd_pin { 377 | pinctrl-single,pins = <0x158 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 378 | P9_18_spi_pin: pinmux_P9_18_spi_pin { 379 | pinctrl-single,pins = <0x158 0x30>; }; /* Mode 0, Pull-Up, RxActive */ 380 | P9_18_i2c_pin: pinmux_P9_18_i2c_pin { 381 | pinctrl-single,pins = <0x158 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 382 | P9_18_pwm_pin: pinmux_P9_18_pwm_pin { 383 | pinctrl-single,pins = <0x158 0x33>; }; /* Mode 3, Pull-Up, RxActive */ 384 | 385 | // Leave the cape I2C EEPROM bus alone 386 | /* P9_19 (ZCZ ball D17) I2C */ 387 | /* P9_20 (ZCZ ball D18) I2C */ 388 | 389 | /* P9_21 (ZCZ ball B17) */ 390 | P9_21_default_pin: pinmux_P9_21_default_pin { 391 | pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 392 | P9_21_gpio_pin: pinmux_P9_21_gpio_pin { 393 | pinctrl-single,pins = <0x154 0x2F>; }; /* Mode 7, RxActive */ 394 | P9_21_gpio_pu_pin: pinmux_P9_21_gpio_pu_pin { 395 | pinctrl-single,pins = <0x154 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 396 | P9_21_gpio_pd_pin: pinmux_P9_21_gpio_pd_pin { 397 | pinctrl-single,pins = <0x154 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 398 | P9_21_spi_pin: pinmux_P9_21_spi_pin { 399 | pinctrl-single,pins = <0x154 0x30>; }; /* Mode 0, Pull-Up, RxActive */ 400 | P9_21_uart_pin: pinmux_P9_21_uart_pin { 401 | pinctrl-single,pins = <0x154 0x31>; }; /* Mode 1, Pull-Up, RxActive */ 402 | P9_21_i2c_pin: pinmux_P9_21_i2c_pin { 403 | pinctrl-single,pins = <0x154 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 404 | P9_21_pwm_pin: pinmux_P9_21_pwm_pin { 405 | pinctrl-single,pins = <0x154 0x33>; }; /* Mode 3, Pull-Up, RxActive */ 406 | 407 | /* P9_22 (ZCZ ball A17) */ 408 | P9_22_default_pin: pinmux_P9_22_default_pin { 409 | pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 410 | P9_22_gpio_pin: pinmux_P9_22_gpio_pin { 411 | pinctrl-single,pins = <0x150 0x2F>; }; /* Mode 7, RxActive */ 412 | P9_22_gpio_pu_pin: pinmux_P9_22_gpio_pu_pin { 413 | pinctrl-single,pins = <0x150 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 414 | P9_22_gpio_pd_pin: pinmux_P9_22_gpio_pd_pin { 415 | pinctrl-single,pins = <0x150 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 416 | P9_22_spi_pin: pinmux_P9_22_spi_pin { 417 | pinctrl-single,pins = <0x150 0x30>; }; /* Mode 0, Pull-Up, RxActive */ 418 | P9_22_uart_pin: pinmux_P9_22_uart_pin { 419 | pinctrl-single,pins = <0x150 0x31>; }; /* Mode 1, Pull-Up, RxActive */ 420 | P9_22_i2c_pin: pinmux_P9_22_i2c_pin { 421 | pinctrl-single,pins = <0x150 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 422 | P9_22_pwm_pin: pinmux_P9_22_pwm_pin { 423 | pinctrl-single,pins = <0x150 0x33>; }; /* Mode 3, Pull-Up, RxActive */ 424 | 425 | /* P9_23 (ZCZ ball V14) */ 426 | P9_23_default_pin: pinmux_P9_23_default_pin { 427 | pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 428 | P9_23_gpio_pin: pinmux_P9_23_gpio_pin { 429 | pinctrl-single,pins = <0x044 0x2F>; }; /* Mode 7, RxActive */ 430 | P9_23_gpio_pu_pin: pinmux_P9_23_gpio_pu_pin { 431 | pinctrl-single,pins = <0x044 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 432 | P9_23_gpio_pd_pin: pinmux_P9_23_gpio_pd_pin { 433 | pinctrl-single,pins = <0x044 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 434 | P9_23_pwm_pin: pinmux_P9_23_pwm_pin { 435 | pinctrl-single,pins = <0x044 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 436 | 437 | /* P9_24 (ZCZ ball D15) */ 438 | P9_24_default_pin: pinmux_P9_24_default_pin { 439 | pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 440 | P9_24_gpio_pin: pinmux_P9_24_gpio_pin { 441 | pinctrl-single,pins = <0x184 0x2F>; }; /* Mode 7, RxActive */ 442 | P9_24_gpio_pu_pin: pinmux_P9_24_gpio_pu_pin { 443 | pinctrl-single,pins = <0x184 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 444 | P9_24_gpio_pd_pin: pinmux_P9_24_gpio_pd_pin { 445 | pinctrl-single,pins = <0x184 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 446 | P9_24_uart_pin: pinmux_P9_24_uart_pin { 447 | pinctrl-single,pins = <0x184 0x30>; }; /* Mode 0, Pull-Up, RxActive */ 448 | P9_24_can_pin: pinmux_P9_24_can_pin { 449 | pinctrl-single,pins = <0x184 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 450 | P9_24_i2c_pin: pinmux_P9_24_i2c_pin { 451 | pinctrl-single,pins = <0x184 0x33>; }; /* Mode 3, Pull-Up, RxActive */ 452 | P9_24_pruin_pin: pinmux_P9_24_pruin_pin { 453 | pinctrl-single,pins = <0x184 0x36>; }; /* Mode 6, Pull-Up, RxActive */ 454 | 455 | /* P9_25 (ZCZ ball A14) Audio */ 456 | 457 | /* P9_26 (ZCZ ball D16) */ 458 | P9_26_default_pin: pinmux_P9_26_default_pin { 459 | pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 460 | P9_26_gpio_pin: pinmux_P9_26_gpio_pin { 461 | pinctrl-single,pins = <0x180 0x2F>; }; /* Mode 7, RxActive */ 462 | P9_26_gpio_pu_pin: pinmux_P9_26_gpio_pu_pin { 463 | pinctrl-single,pins = <0x180 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 464 | P9_26_gpio_pd_pin: pinmux_P9_26_gpio_pd_pin { 465 | pinctrl-single,pins = <0x180 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 466 | P9_26_uart_pin: pinmux_P9_26_uart_pin { 467 | pinctrl-single,pins = <0x180 0x30>; }; /* Mode 0, Pull-Up, RxActive */ 468 | P9_26_can_pin: pinmux_P9_26_can_pin { 469 | pinctrl-single,pins = <0x180 0x32>; }; /* Mode 2, Pull-Up, RxActive */ 470 | P9_26_i2c_pin: pinmux_P9_26_i2c_pin { 471 | pinctrl-single,pins = <0x180 0x33>; }; /* Mode 3, Pull-Up, RxActive */ 472 | P9_26_pruin_pin: pinmux_P9_26_pruin_pin { 473 | pinctrl-single,pins = <0x180 0x36>; }; /* Mode 6, Pull-Up, RxActive */ 474 | 475 | /* P9_27 (ZCZ ball C13) */ 476 | P9_27_default_pin: pinmux_P9_27_default_pin { 477 | pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 478 | P9_27_gpio_pin: pinmux_P9_27_gpio_pin { 479 | pinctrl-single,pins = <0x1a4 0x2F>; }; /* Mode 7, RxActive */ 480 | P9_27_gpio_pu_pin: pinmux_P9_27_gpio_pu_pin { 481 | pinctrl-single,pins = <0x1a4 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 482 | P9_27_gpio_pd_pin: pinmux_P9_27_gpio_pd_pin { 483 | pinctrl-single,pins = <0x1a4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 484 | P9_27_qep_pin: pinmux_P9_27_qep_pin { 485 | pinctrl-single,pins = <0x1a4 0x21>; }; /* Mode 1, Pull-Down, RxActive */ 486 | P9_27_pruout_pin: pinmux_P9_27_pruout_pin { 487 | pinctrl-single,pins = <0x1a4 0x25>; }; /* Mode 5, Pull-Down, RxActive */ 488 | P9_27_pruin_pin: pinmux_P9_27_pruin_pin { 489 | pinctrl-single,pins = <0x1a4 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 490 | 491 | /* P9_28 (ZCZ ball C12) Audio */ 492 | /* P9_29 (ZCZ ball B13) Audio */ 493 | 494 | /* P9_30 (ZCZ ball D12) */ 495 | P9_30_default_pin: pinmux_P9_30_default_pin { 496 | pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 497 | P9_30_gpio_pin: pinmux_P9_30_gpio_pin { 498 | pinctrl-single,pins = <0x198 0x2F>; }; /* Mode 7, RxActive */ 499 | P9_30_gpio_pu_pin: pinmux_P9_30_gpio_pu_pin { 500 | pinctrl-single,pins = <0x198 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 501 | P9_30_gpio_pd_pin: pinmux_P9_30_gpio_pd_pin { 502 | pinctrl-single,pins = <0x198 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 503 | P9_30_pwm_pin: pinmux_P9_30_pwm_pin { 504 | pinctrl-single,pins = <0x198 0x21>; }; /* Mode 1, Pull-Down, RxActive */ 505 | P9_30_spi_pin: pinmux_P9_30_spi_pin { 506 | pinctrl-single,pins = <0x198 0x23>; }; /* Mode 3, Pull-Down, RxActive */ 507 | P9_30_pruout_pin: pinmux_P9_30_pruout_pin { 508 | pinctrl-single,pins = <0x198 0x25>; }; /* Mode 5, Pull-Down, RxActive */ 509 | P9_30_pruin_pin: pinmux_P9_30_pruin_pin { 510 | pinctrl-single,pins = <0x198 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 511 | 512 | /* P9_31 (ZCZ ball A13) Audio */ 513 | 514 | /* P9_32 VADC */ 515 | /* P9_33 (ZCZ ball C8 ) AIN4 */ 516 | /* P9_34 AGND */ 517 | /* P9_35 (ZCZ ball A8 ) AIN6 */ 518 | /* P9_36 (ZCZ ball B8 ) AIN5 */ 519 | /* P9_37 (ZCZ ball B7 ) AIN2 */ 520 | /* P9_38 (ZCZ ball A7 ) AIN3 */ 521 | /* P9_39 (ZCZ ball B6 ) AIN0 */ 522 | /* P9_40 (ZCZ ball C7 ) AIN1 */ 523 | 524 | /* P9_41 (ZCZ ball D14) */ 525 | P9_41_default_pin: pinmux_P9_41_default_pin { 526 | pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 527 | P9_41_gpio_pin: pinmux_P9_41_gpio_pin { 528 | pinctrl-single,pins = <0x1b4 0x2F>; }; /* Mode 7, RxActive */ 529 | P9_41_gpio_pu_pin: pinmux_P9_41_gpio_pu_pin { 530 | pinctrl-single,pins = <0x1b4 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 531 | P9_41_gpio_pd_pin: pinmux_P9_41_gpio_pd_pin { 532 | pinctrl-single,pins = <0x1b4 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 533 | P9_41_timer_pin: pinmux_P9_41_timer_pin { 534 | pinctrl-single,pins = <0x1b4 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 535 | P9_41_pruin_pin: pinmux_P9_41_pruin_pin { 536 | pinctrl-single,pins = <0x1b4 0x25>; }; /* Mode 5, Pull-Down, RxActive */ 537 | 538 | /* P9_41.1 */ 539 | /* P9_91 (ZCZ ball D13) */ 540 | P9_91_default_pin: pinmux_P9_91_default_pin { 541 | pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 542 | P9_91_gpio_pin: pinmux_P9_91_gpio_pin { 543 | pinctrl-single,pins = <0x1a8 0x2F>; }; /* Mode 7, RxActive */ 544 | P9_91_gpio_pu_pin: pinmux_P9_91_gpio_pu_pin { 545 | pinctrl-single,pins = <0x1a8 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 546 | P9_91_gpio_pd_pin: pinmux_P9_91_gpio_pd_pin { 547 | pinctrl-single,pins = <0x1a8 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 548 | P9_91_qep_pin: pinmux_P9_91_qep_pin { 549 | pinctrl-single,pins = <0x1a8 0x21>; }; /* Mode 1, Pull-Down, RxActive */ 550 | P9_91_pruout_pin: pinmux_P9_91_pruout_pin { 551 | pinctrl-single,pins = <0x1a8 0x25>; }; /* Mode 5, Pull-Down, RxActive */ 552 | P9_91_pruin_pin: pinmux_P9_91_pruin_pin { 553 | pinctrl-single,pins = <0x1a8 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 554 | 555 | /* P9_42 (ZCZ ball C18) */ 556 | P9_42_default_pin: pinmux_P9_42_default_pin { 557 | pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 558 | P9_42_gpio_pin: pinmux_P9_42_gpio_pin { 559 | pinctrl-single,pins = <0x164 0x2F>; }; /* Mode 7, RxActive */ 560 | P9_42_gpio_pu_pin: pinmux_P9_42_gpio_pu_pin { 561 | pinctrl-single,pins = <0x164 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 562 | P9_42_gpio_pd_pin: pinmux_P9_42_gpio_pd_pin { 563 | pinctrl-single,pins = <0x164 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 564 | P9_42_pwm_pin: pinmux_P9_42_pwm_pin { 565 | pinctrl-single,pins = <0x164 0x20>; }; /* Mode 0, Pull-Down, RxActive */ 566 | P9_42_uart_pin: pinmux_P9_42_uart_pin { 567 | pinctrl-single,pins = <0x164 0x21>; }; /* Mode 1, Pull-Down, RxActive */ 568 | P9_42_spics_pin: pinmux_P9_42_spics_pin { 569 | pinctrl-single,pins = <0x164 0x22>; }; /* Mode 2, Pull-Down, RxActive */ 570 | P9_42_spiclk_pin: pinmux_P9_42_spiclk_pin { 571 | pinctrl-single,pins = <0x164 0x24>; }; /* Mode 4, Pull-Down, RxActive */ 572 | 573 | /* P9_42.1 */ 574 | /* P9_92 (ZCZ ball B12) */ 575 | P9_92_default_pin: pinmux_P9_92_default_pin { 576 | pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 577 | P9_92_gpio_pin: pinmux_P9_92_gpio_pin { 578 | pinctrl-single,pins = <0x1a0 0x2F>; }; /* Mode 7, RxActive */ 579 | P9_92_gpio_pu_pin: pinmux_P9_92_gpio_pu_pin { 580 | pinctrl-single,pins = <0x1a0 0x37>; }; /* Mode 7, Pull-Up, RxActive */ 581 | P9_92_gpio_pd_pin: pinmux_P9_92_gpio_pd_pin { 582 | pinctrl-single,pins = <0x1a0 0x27>; }; /* Mode 7, Pull-Down, RxActive */ 583 | P9_92_qep_pin: pinmux_P9_92_qep_pin { 584 | pinctrl-single,pins = <0x1a0 0x21>; }; /* Mode 1, Pull-Down, RxActive */ 585 | P9_92_pruout_pin: pinmux_P9_92_pruout_pin { 586 | pinctrl-single,pins = <0x1a0 0x25>; }; /* Mode 5, Pull-Down, RxActive */ 587 | P9_92_pruin_pin: pinmux_P9_92_pruin_pin { 588 | pinctrl-single,pins = <0x1a0 0x26>; }; /* Mode 6, Pull-Down, RxActive */ 589 | 590 | /* P9_43 GND */ 591 | /* P9_44 GND */ 592 | /* P9_45 GND */ 593 | /* P9_46 GND */ 594 | }; 595 | 596 | &lcdc { 597 | status = "okay"; 598 | }; 599 | 600 | / { 601 | hdmi { 602 | compatible = "ti,tilcdc,slave"; 603 | i2c = <&i2c0>; 604 | pinctrl-names = "default", "off"; 605 | pinctrl-0 = <&nxp_hdmi_bonelt_pins>; 606 | pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; 607 | status = "okay"; 608 | }; 609 | }; 610 | 611 | &ocp { 612 | /************************/ 613 | /* P8 Header */ 614 | /************************/ 615 | 616 | P8_07_pinmux { 617 | compatible = "bone-pinmux-helper"; 618 | status = "okay"; 619 | 620 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; 621 | pinctrl-0 = <&P8_07_default_pin>; 622 | pinctrl-1 = <&P8_07_gpio_pin>; 623 | pinctrl-2 = <&P8_07_gpio_pu_pin>; 624 | pinctrl-3 = <&P8_07_gpio_pd_pin>; 625 | pinctrl-4 = <&P8_07_timer_pin>; 626 | }; 627 | 628 | P8_08_pinmux { 629 | compatible = "bone-pinmux-helper"; 630 | status = "okay"; 631 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; 632 | pinctrl-0 = <&P8_08_default_pin>; 633 | pinctrl-1 = <&P8_08_gpio_pin>; 634 | pinctrl-2 = <&P8_08_gpio_pu_pin>; 635 | pinctrl-3 = <&P8_08_gpio_pd_pin>; 636 | pinctrl-4 = <&P8_08_timer_pin>; 637 | }; 638 | 639 | P8_09_pinmux { 640 | compatible = "bone-pinmux-helper"; 641 | status = "okay"; 642 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; 643 | pinctrl-0 = <&P8_09_default_pin>; 644 | pinctrl-1 = <&P8_09_gpio_pin>; 645 | pinctrl-2 = <&P8_09_gpio_pu_pin>; 646 | pinctrl-3 = <&P8_09_gpio_pd_pin>; 647 | pinctrl-4 = <&P8_09_timer_pin>; 648 | }; 649 | 650 | P8_10_pinmux { 651 | compatible = "bone-pinmux-helper"; 652 | status = "okay"; 653 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; 654 | pinctrl-0 = <&P8_10_default_pin>; 655 | pinctrl-1 = <&P8_10_gpio_pin>; 656 | pinctrl-2 = <&P8_10_gpio_pu_pin>; 657 | pinctrl-3 = <&P8_10_gpio_pd_pin>; 658 | pinctrl-4 = <&P8_10_timer_pin>; 659 | }; 660 | 661 | P8_11_pinmux { 662 | compatible = "bone-pinmux-helper"; 663 | status = "okay"; 664 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "qep"; 665 | pinctrl-0 = <&P8_11_default_pin>; 666 | pinctrl-1 = <&P8_11_gpio_pin>; 667 | pinctrl-2 = <&P8_11_gpio_pu_pin>; 668 | pinctrl-3 = <&P8_11_gpio_pd_pin>; 669 | pinctrl-4 = <&P8_11_pruout_pin>; 670 | pinctrl-5 = <&P8_11_qep_pin>; 671 | }; 672 | 673 | P8_12_pinmux { 674 | compatible = "bone-pinmux-helper"; 675 | status = "okay"; 676 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "qep"; 677 | pinctrl-0 = <&P8_12_default_pin>; 678 | pinctrl-1 = <&P8_12_gpio_pin>; 679 | pinctrl-2 = <&P8_12_gpio_pu_pin>; 680 | pinctrl-3 = <&P8_12_gpio_pd_pin>; 681 | pinctrl-4 = <&P8_12_pruout_pin>; 682 | pinctrl-5 = <&P8_12_qep_pin>; 683 | }; 684 | 685 | P8_13_pinmux { 686 | compatible = "bone-pinmux-helper"; 687 | status = "okay"; 688 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; 689 | pinctrl-0 = <&P8_13_default_pin>; 690 | pinctrl-1 = <&P8_13_gpio_pin>; 691 | pinctrl-2 = <&P8_13_gpio_pu_pin>; 692 | pinctrl-3 = <&P8_13_gpio_pd_pin>; 693 | pinctrl-4 = <&P8_13_pwm_pin>; 694 | }; 695 | 696 | P8_14_pinmux { 697 | compatible = "bone-pinmux-helper"; 698 | status = "okay"; 699 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; 700 | pinctrl-0 = <&P8_14_default_pin>; 701 | pinctrl-1 = <&P8_14_gpio_pin>; 702 | pinctrl-2 = <&P8_14_gpio_pu_pin>; 703 | pinctrl-3 = <&P8_14_gpio_pd_pin>; 704 | pinctrl-4 = <&P8_14_pwm_pin>; 705 | }; 706 | 707 | P8_15_pinmux { 708 | compatible = "bone-pinmux-helper"; 709 | status = "okay"; 710 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruin", "qep"; 711 | pinctrl-0 = <&P8_15_default_pin>; 712 | pinctrl-1 = <&P8_15_gpio_pin>; 713 | pinctrl-2 = <&P8_15_gpio_pu_pin>; 714 | pinctrl-3 = <&P8_15_gpio_pd_pin>; 715 | pinctrl-4 = <&P8_15_pruin_pin>; 716 | pinctrl-5 = <&P8_15_qep_pin>; 717 | }; 718 | 719 | P8_16_pinmux { 720 | compatible = "bone-pinmux-helper"; 721 | status = "okay"; 722 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruin", "qep"; 723 | pinctrl-0 = <&P8_16_default_pin>; 724 | pinctrl-1 = <&P8_16_gpio_pin>; 725 | pinctrl-2 = <&P8_16_gpio_pu_pin>; 726 | pinctrl-3 = <&P8_16_gpio_pd_pin>; 727 | pinctrl-4 = <&P8_16_pruin_pin>; 728 | pinctrl-5 = <&P8_16_qep_pin>; 729 | }; 730 | 731 | P8_17_pinmux { 732 | compatible = "bone-pinmux-helper"; 733 | status = "okay"; 734 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; 735 | pinctrl-0 = <&P8_17_default_pin>; 736 | pinctrl-1 = <&P8_17_gpio_pin>; 737 | pinctrl-2 = <&P8_17_gpio_pu_pin>; 738 | pinctrl-3 = <&P8_17_gpio_pd_pin>; 739 | pinctrl-4 = <&P8_17_pwm_pin>; 740 | }; 741 | 742 | P8_18_pinmux { 743 | compatible = "bone-pinmux-helper"; 744 | status = "okay"; 745 | pinctrl-names = "default", "gpio"; 746 | pinctrl-0 = <&P8_18_default_pin>; 747 | pinctrl-1 = <&P8_18_gpio_pin>; 748 | pinctrl-2 = <&P8_18_gpio_pu_pin>; 749 | pinctrl-3 = <&P8_18_gpio_pd_pin>; 750 | }; 751 | 752 | P8_19_pinmux { 753 | compatible = "bone-pinmux-helper"; 754 | status = "okay"; 755 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; 756 | pinctrl-0 = <&P8_19_default_pin>; 757 | pinctrl-1 = <&P8_19_gpio_pin>; 758 | pinctrl-2 = <&P8_19_gpio_pu_pin>; 759 | pinctrl-3 = <&P8_19_gpio_pd_pin>; 760 | pinctrl-4 = <&P8_19_pwm_pin>; 761 | }; 762 | 763 | P8_26_pinmux { 764 | compatible = "bone-pinmux-helper"; 765 | status = "okay"; 766 | pinctrl-names = "default", "gpio"; 767 | pinctrl-0 = <&P8_26_default_pin>; 768 | pinctrl-1 = <&P8_26_gpio_pin>; 769 | pinctrl-2 = <&P8_26_gpio_pu_pin>; 770 | pinctrl-3 = <&P8_26_gpio_pd_pin>; 771 | }; 772 | 773 | 774 | /************************/ 775 | /* P9 Header */ 776 | /************************/ 777 | 778 | P9_11_pinmux { 779 | compatible = "bone-pinmux-helper"; 780 | status = "okay"; 781 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; 782 | pinctrl-0 = <&P9_11_default_pin>; 783 | pinctrl-1 = <&P9_11_gpio_pin>; 784 | pinctrl-2 = <&P9_11_gpio_pu_pin>; 785 | pinctrl-3 = <&P9_11_gpio_pd_pin>; 786 | pinctrl-4 = <&P9_11_uart_pin>; 787 | }; 788 | 789 | P9_12_pinmux { 790 | compatible = "bone-pinmux-helper"; 791 | status = "okay"; 792 | pinctrl-names = "default", "gpio"; 793 | pinctrl-0 = <&P9_12_default_pin>; 794 | pinctrl-1 = <&P9_12_gpio_pin>; 795 | pinctrl-2 = <&P9_12_gpio_pu_pin>; 796 | pinctrl-3 = <&P9_12_gpio_pd_pin>; 797 | }; 798 | 799 | P9_13_pinmux { 800 | compatible = "bone-pinmux-helper"; 801 | status = "okay"; 802 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; 803 | pinctrl-0 = <&P9_13_default_pin>; 804 | pinctrl-1 = <&P9_13_gpio_pin>; 805 | pinctrl-2 = <&P9_13_gpio_pu_pin>; 806 | pinctrl-3 = <&P9_13_gpio_pd_pin>; 807 | pinctrl-4 = <&P9_13_uart_pin>; 808 | }; 809 | 810 | P9_14_pinmux { 811 | compatible = "bone-pinmux-helper"; 812 | status = "okay"; 813 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; 814 | pinctrl-0 = <&P9_14_default_pin>; 815 | pinctrl-1 = <&P9_14_gpio_pin>; 816 | pinctrl-2 = <&P9_14_gpio_pu_pin>; 817 | pinctrl-3 = <&P9_14_gpio_pd_pin>; 818 | pinctrl-4 = <&P9_14_pwm_pin>; 819 | }; 820 | 821 | P9_15_pinmux { 822 | compatible = "bone-pinmux-helper"; 823 | status = "okay"; 824 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; 825 | pinctrl-0 = <&P9_15_default_pin>; 826 | pinctrl-1 = <&P9_15_gpio_pin>; 827 | pinctrl-2 = <&P9_15_gpio_pu_pin>; 828 | pinctrl-3 = <&P9_15_gpio_pd_pin>; 829 | pinctrl-4 = <&P9_15_pwm_pin>; 830 | }; 831 | 832 | P9_16_pinmux { 833 | compatible = "bone-pinmux-helper"; 834 | status = "okay"; 835 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; 836 | pinctrl-0 = <&P9_16_default_pin>; 837 | pinctrl-1 = <&P9_16_gpio_pin>; 838 | pinctrl-2 = <&P9_16_gpio_pu_pin>; 839 | pinctrl-3 = <&P9_16_gpio_pd_pin>; 840 | pinctrl-4 = <&P9_16_pwm_pin>; 841 | }; 842 | 843 | P9_17_pinmux { 844 | compatible = "bone-pinmux-helper"; 845 | status = "okay"; 846 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm"; 847 | pinctrl-0 = <&P9_17_default_pin>; 848 | pinctrl-1 = <&P9_17_gpio_pin>; 849 | pinctrl-2 = <&P9_17_gpio_pu_pin>; 850 | pinctrl-3 = <&P9_17_gpio_pd_pin>; 851 | pinctrl-4 = <&P9_17_spi_pin>; 852 | pinctrl-5 = <&P9_17_i2c_pin>; 853 | pinctrl-6 = <&P9_17_pwm_pin>; 854 | }; 855 | 856 | P9_18_pinmux { 857 | compatible = "bone-pinmux-helper"; 858 | status = "okay"; 859 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm"; 860 | pinctrl-0 = <&P9_18_default_pin>; 861 | pinctrl-1 = <&P9_18_gpio_pin>; 862 | pinctrl-2 = <&P9_18_gpio_pu_pin>; 863 | pinctrl-3 = <&P9_18_gpio_pd_pin>; 864 | pinctrl-4 = <&P9_18_spi_pin>; 865 | pinctrl-5 = <&P9_18_i2c_pin>; 866 | pinctrl-6 = <&P9_18_pwm_pin>; 867 | }; 868 | 869 | // I2C Pins 870 | // P9_19_pinmux 871 | // P9_20_pinmux 872 | 873 | P9_21_pinmux { 874 | compatible = "bone-pinmux-helper"; 875 | status = "okay"; 876 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm"; 877 | pinctrl-0 = <&P9_21_default_pin>; 878 | pinctrl-1 = <&P9_21_gpio_pin>; 879 | pinctrl-2 = <&P9_21_gpio_pu_pin>; 880 | pinctrl-3 = <&P9_21_gpio_pd_pin>; 881 | pinctrl-4 = <&P9_21_spi_pin>; 882 | pinctrl-5 = <&P9_21_uart_pin>; 883 | pinctrl-6 = <&P9_21_i2c_pin>; 884 | pinctrl-7 = <&P9_21_pwm_pin>; 885 | }; 886 | 887 | P9_22_pinmux { 888 | compatible = "bone-pinmux-helper"; 889 | status = "okay"; 890 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm"; 891 | pinctrl-0 = <&P9_22_default_pin>; 892 | pinctrl-1 = <&P9_22_gpio_pin>; 893 | pinctrl-2 = <&P9_22_gpio_pu_pin>; 894 | pinctrl-3 = <&P9_22_gpio_pd_pin>; 895 | pinctrl-4 = <&P9_22_spi_pin>; 896 | pinctrl-5 = <&P9_22_uart_pin>; 897 | pinctrl-6 = <&P9_22_i2c_pin>; 898 | pinctrl-7 = <&P9_22_pwm_pin>; 899 | }; 900 | 901 | P9_23_pinmux { 902 | compatible = "bone-pinmux-helper"; 903 | status = "okay"; 904 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; 905 | pinctrl-0 = <&P9_23_default_pin>; 906 | pinctrl-1 = <&P9_23_gpio_pin>; 907 | pinctrl-2 = <&P9_23_gpio_pu_pin>; 908 | pinctrl-3 = <&P9_23_gpio_pd_pin>; 909 | pinctrl-4 = <&P9_23_pwm_pin>; 910 | }; 911 | 912 | P9_24_pinmux { 913 | compatible = "bone-pinmux-helper"; 914 | status = "okay"; 915 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin"; 916 | pinctrl-0 = <&P9_24_default_pin>; 917 | pinctrl-1 = <&P9_24_gpio_pin>; 918 | pinctrl-2 = <&P9_24_gpio_pu_pin>; 919 | pinctrl-3 = <&P9_24_gpio_pd_pin>; 920 | pinctrl-4 = <&P9_24_uart_pin>; 921 | pinctrl-5 = <&P9_24_can_pin>; 922 | pinctrl-6 = <&P9_24_i2c_pin>; 923 | pinctrl-7 = <&P9_24_pruin_pin>; 924 | }; 925 | 926 | 927 | // Audio pin 928 | // P9_25_pinmux 929 | 930 | P9_26_pinmux { 931 | compatible = "bone-pinmux-helper"; 932 | status = "okay"; 933 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pruin"; 934 | pinctrl-0 = <&P9_26_default_pin>; 935 | pinctrl-1 = <&P9_26_gpio_pin>; 936 | pinctrl-2 = <&P9_26_gpio_pu_pin>; 937 | pinctrl-3 = <&P9_26_gpio_pd_pin>; 938 | pinctrl-4 = <&P9_26_uart_pin>; 939 | pinctrl-5 = <&P9_26_can_pin>; 940 | pinctrl-6 = <&P9_26_i2c_pin>; 941 | pinctrl-7 = <&P9_26_pruin_pin>; 942 | }; 943 | 944 | P9_27_pinmux { 945 | compatible = "bone-pinmux-helper"; 946 | status = "okay"; 947 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; 948 | pinctrl-0 = <&P9_27_default_pin>; 949 | pinctrl-1 = <&P9_27_gpio_pin>; 950 | pinctrl-2 = <&P9_27_gpio_pu_pin>; 951 | pinctrl-3 = <&P9_27_gpio_pd_pin>; 952 | pinctrl-4 = <&P9_27_qep_pin>; 953 | pinctrl-5 = <&P9_27_pruout_pin>; 954 | pinctrl-6 = <&P9_27_pruin_pin>; 955 | }; 956 | 957 | // Audio pins 958 | // P9_28_pinmux 959 | // P9_29_pinmux 960 | 961 | P9_30_pinmux { 962 | compatible = "bone-pinmux-helper"; 963 | status = "okay"; 964 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "spi", "pruout", "pruin"; 965 | pinctrl-0 = <&P9_30_default_pin>; 966 | pinctrl-1 = <&P9_30_gpio_pin>; 967 | pinctrl-2 = <&P9_30_gpio_pu_pin>; 968 | pinctrl-3 = <&P9_30_gpio_pd_pin>; 969 | pinctrl-4 = <&P9_30_pwm_pin>; 970 | pinctrl-5 = <&P9_30_spi_pin>; 971 | pinctrl-6 = <&P9_30_pruout_pin>; 972 | pinctrl-7 = <&P9_30_pruin_pin>; 973 | }; 974 | 975 | // Audio pin 976 | // P9_31_pinmux 977 | 978 | P9_41_pinmux { 979 | compatible = "bone-pinmux-helper"; 980 | status = "okay"; 981 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer", "pruin"; 982 | pinctrl-0 = <&P9_41_default_pin>; 983 | pinctrl-1 = <&P9_41_gpio_pin>; 984 | pinctrl-2 = <&P9_41_gpio_pu_pin>; 985 | pinctrl-3 = <&P9_41_gpio_pd_pin>; 986 | pinctrl-4 = <&P9_41_timer_pin>; 987 | pinctrl-5 = <&P9_41_pruin_pin>; 988 | }; 989 | 990 | P9_91_pinmux { 991 | compatible = "bone-pinmux-helper"; 992 | status = "okay"; 993 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; 994 | pinctrl-0 = <&P9_91_default_pin>; 995 | pinctrl-1 = <&P9_91_gpio_pin>; 996 | pinctrl-2 = <&P9_91_gpio_pu_pin>; 997 | pinctrl-3 = <&P9_91_gpio_pd_pin>; 998 | pinctrl-4 = <&P9_91_qep_pin>; 999 | pinctrl-5 = <&P9_91_pruout_pin>; 1000 | pinctrl-6 = <&P9_91_pruin_pin>; 1001 | }; 1002 | 1003 | P9_42_pinmux { 1004 | compatible = "bone-pinmux-helper"; 1005 | status = "okay"; 1006 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "uart", "spics", "spiclk"; 1007 | pinctrl-0 = <&P9_42_default_pin>; 1008 | pinctrl-1 = <&P9_42_gpio_pin>; 1009 | pinctrl-2 = <&P9_42_gpio_pu_pin>; 1010 | pinctrl-3 = <&P9_42_gpio_pd_pin>; 1011 | pinctrl-4 = <&P9_42_pwm_pin>; 1012 | pinctrl-5 = <&P9_42_uart_pin>; 1013 | pinctrl-6 = <&P9_42_spics_pin>; 1014 | pinctrl-7 = <&P9_42_spiclk_pin>; 1015 | }; 1016 | 1017 | P9_92_pinmux { 1018 | compatible = "bone-pinmux-helper"; 1019 | status = "okay"; 1020 | pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "qep", "pruout", "pruin"; 1021 | pinctrl-0 = <&P9_92_default_pin>; 1022 | pinctrl-1 = <&P9_92_gpio_pin>; 1023 | pinctrl-2 = <&P9_92_gpio_pu_pin>; 1024 | pinctrl-3 = <&P9_92_gpio_pd_pin>; 1025 | pinctrl-4 = <&P9_92_qep_pin>; 1026 | pinctrl-5 = <&P9_92_pruout_pin>; 1027 | pinctrl-6 = <&P9_92_pruin_pin>; 1028 | }; 1029 | 1030 | // !!!WARNING!!! 1031 | // gpio-of-helper &gpio pointers are off-by-one vs. the hardware: 1032 | // hardware GPIO bank 0 = &gpio1 1033 | cape-universal { 1034 | compatible = "gpio-of-helper"; 1035 | status = "okay"; 1036 | pinctrl-names = "default"; 1037 | pinctrl-0 = <>; 1038 | 1039 | P8_07 { 1040 | gpio-name = "P8_07"; 1041 | gpio = <&gpio3 2 0>; 1042 | input; 1043 | dir-changeable; 1044 | }; 1045 | P8_08 { 1046 | gpio-name = "P8_08"; 1047 | gpio = <&gpio3 3 0>; 1048 | input; 1049 | dir-changeable; 1050 | }; 1051 | P8_09 { 1052 | gpio-name = "P8_09"; 1053 | gpio = <&gpio3 5 0>; 1054 | input; 1055 | dir-changeable; 1056 | }; 1057 | P8_10 { 1058 | gpio-name = "P8_10"; 1059 | gpio = <&gpio3 4 0>; 1060 | input; 1061 | dir-changeable; 1062 | }; 1063 | P8_11 { 1064 | gpio-name = "P8_11"; 1065 | gpio = <&gpio2 13 0>; 1066 | input; 1067 | dir-changeable; 1068 | }; 1069 | P8_12 { 1070 | gpio-name = "P8_12"; 1071 | gpio = <&gpio2 12 0>; 1072 | input; 1073 | dir-changeable; 1074 | }; 1075 | P8_13 { 1076 | gpio-name = "P8_13"; 1077 | gpio = <&gpio1 23 0>; 1078 | input; 1079 | dir-changeable; 1080 | }; 1081 | P8_14 { 1082 | gpio-name = "P8_14"; 1083 | gpio = <&gpio1 26 0>; 1084 | input; 1085 | dir-changeable; 1086 | }; 1087 | P8_15 { 1088 | gpio-name = "P8_15"; 1089 | gpio = <&gpio2 15 0>; 1090 | input; 1091 | dir-changeable; 1092 | }; 1093 | P8_16 { 1094 | gpio-name = "P8_16"; 1095 | gpio = <&gpio2 14 0>; 1096 | input; 1097 | dir-changeable; 1098 | }; 1099 | P8_17 { 1100 | gpio-name = "P8_17"; 1101 | gpio = <&gpio1 27 0>; 1102 | input; 1103 | dir-changeable; 1104 | }; 1105 | P8_18 { 1106 | gpio-name = "P8_18"; 1107 | gpio = <&gpio3 1 0>; 1108 | input; 1109 | dir-changeable; 1110 | }; 1111 | P8_19 { 1112 | gpio-name = "P8_19"; 1113 | gpio = <&gpio1 22 0>; 1114 | input; 1115 | dir-changeable; 1116 | }; 1117 | P8_26 { 1118 | gpio-name = "P8_26"; 1119 | gpio = <&gpio2 29 0>; 1120 | input; 1121 | dir-changeable; 1122 | }; 1123 | 1124 | 1125 | P9_11 { 1126 | gpio-name = "P9_11"; 1127 | gpio = <&gpio1 30 0>; 1128 | input; 1129 | dir-changeable; 1130 | }; 1131 | P9_12 { 1132 | gpio-name = "P9_12"; 1133 | gpio = <&gpio2 28 0>; 1134 | input; 1135 | dir-changeable; 1136 | }; 1137 | P9_13 { 1138 | gpio-name = "P9_13"; 1139 | gpio = <&gpio1 31 0>; 1140 | input; 1141 | dir-changeable; 1142 | }; 1143 | P9_14 { 1144 | gpio-name = "P9_14"; 1145 | gpio = <&gpio2 18 0>; 1146 | input; 1147 | dir-changeable; 1148 | }; 1149 | P9_15 { 1150 | gpio-name = "P9_15"; 1151 | gpio = <&gpio2 16 0>; 1152 | input; 1153 | dir-changeable; 1154 | }; 1155 | P9_16 { 1156 | gpio-name = "P9_16"; 1157 | gpio = <&gpio2 19 0>; 1158 | input; 1159 | dir-changeable; 1160 | }; 1161 | P9_17 { 1162 | gpio-name = "P9_17"; 1163 | gpio = <&gpio1 5 0>; 1164 | input; 1165 | dir-changeable; 1166 | }; 1167 | P9_18 { 1168 | gpio-name = "P9_18"; 1169 | gpio = <&gpio1 4 0>; 1170 | input; 1171 | dir-changeable; 1172 | }; 1173 | 1174 | // I2C pins 1175 | // P9_19 1176 | // P9_20 1177 | 1178 | P9_21 { 1179 | gpio-name = "P9_21"; 1180 | gpio = <&gpio1 3 0>; 1181 | input; 1182 | dir-changeable; 1183 | }; 1184 | P9_22 { 1185 | gpio-name = "P9_22"; 1186 | gpio = <&gpio1 2 0>; 1187 | input; 1188 | dir-changeable; 1189 | }; 1190 | P9_23 { 1191 | gpio-name = "P9_23"; 1192 | gpio = <&gpio2 17 0>; 1193 | input; 1194 | dir-changeable; 1195 | }; 1196 | P9_24 { 1197 | gpio-name = "P9_24"; 1198 | gpio = <&gpio1 15 0>; 1199 | input; 1200 | dir-changeable; 1201 | }; 1202 | 1203 | // Audio pin 1204 | // P9_25 1205 | 1206 | P9_26 { 1207 | gpio-name = "P9_26"; 1208 | gpio = <&gpio1 14 0>; 1209 | input; 1210 | dir-changeable; 1211 | }; 1212 | P9_27 { 1213 | gpio-name = "P9_27"; 1214 | gpio = <&gpio4 19 0>; 1215 | input; 1216 | dir-changeable; 1217 | }; 1218 | 1219 | // Audio pins 1220 | // P9_28 1221 | // P9_29 1222 | 1223 | P9_30 { 1224 | gpio-name = "P9_30"; 1225 | gpio = <&gpio4 16 0>; 1226 | input; 1227 | dir-changeable; 1228 | }; 1229 | 1230 | // Audio pin 1231 | // P9_31 1232 | 1233 | P9_41 { 1234 | gpio-name = "P9_41"; 1235 | gpio = <&gpio1 20 0>; 1236 | input; 1237 | dir-changeable; 1238 | }; 1239 | P9_91 { 1240 | gpio-name = "P9_91"; 1241 | gpio = <&gpio4 20 0>; 1242 | input; 1243 | dir-changeable; 1244 | }; 1245 | P9_42 { 1246 | gpio-name = "P9_42"; 1247 | gpio = <&gpio1 7 0>; 1248 | input; 1249 | dir-changeable; 1250 | }; 1251 | P9_92 { 1252 | gpio-name = "P9_92"; 1253 | gpio = <&gpio4 18 0>; 1254 | input; 1255 | dir-changeable; 1256 | }; 1257 | }; 1258 | }; 1259 | 1260 | &cpu { 1261 | /* 1262 | * To consider voltage drop between PMIC and SoC, 1263 | * tolerance value is reduced to 2% from 4% and 1264 | * voltage value is increased as a precaution. 1265 | */ 1266 | operating-points = < 1267 | /* kHz uV */ 1268 | 1000000 1350000 1269 | 800000 1300000 1270 | 600000 1112000 1271 | 300000 969000 1272 | >; 1273 | }; 1274 | -------------------------------------------------------------------------------- /src/pru-firmware/AM3359_PRU.cmd: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | /* AM3359_PRU.cmd */ 3 | /* Description: This file is a sample linker command file that can be */ 4 | /* used for linking programs built with the PRU C compiler and running the */ 5 | /* resulting .out file on an AM3359 PRU0. Use it as a guideline. You will */ 6 | /* want to change the memory layout to match your specific target system. */ 7 | /* You may want to change the allocation scheme according to the size of */ 8 | /* your program. */ 9 | /******************************************************************************/ 10 | 11 | -cr 12 | -stack 0x100 13 | -heap 0x100 14 | 15 | 16 | MEMORY 17 | { 18 | PAGE 0: 19 | PRUIMEM: o = 0x00000000 l = 0x00002000 /* 8kB PRU0 Instruction RAM */ 20 | PAGE 1: 21 | PRUDMEM: o = 0x00000000 l = 0x00002000 /* 8kB PRU Data RAM 0 */ 22 | C0: o = 0x00020000 l = 0x00000300 CREGISTER=0 23 | C4: o = 0x00026000 l = 0x00000100 CREGISTER=4 24 | C26:o = 0x0002E000 l = 0x00000100 CREGISTER=26 25 | } 26 | 27 | SECTIONS 28 | { 29 | .text > PRUIMEM, PAGE 0 30 | .stack > PRUDMEM, PAGE 1 31 | .bss > PRUDMEM, PAGE 1 32 | .cio > PRUDMEM, PAGE 1 33 | .const > PRUDMEM, PAGE 1 34 | .data > PRUDMEM, PAGE 1 35 | .switch > PRUDMEM, PAGE 1 36 | .sysmem > PRUDMEM, PAGE 1 37 | .cinit > PRUDMEM, PAGE 1 38 | } 39 | -------------------------------------------------------------------------------- /src/pru-firmware/Makefile: -------------------------------------------------------------------------------- 1 | C_DIR := /usr/share/ti/cgt-pru/include 2 | A_DIR := /usr/share/ti/cgt-pru/lib 3 | 4 | all: pru0_firmware pru1_firmware 5 | 6 | #PRU0 7 | pru0_firmware: pru0_firmware.obj pru0_syscall.obj AM3359_PRU.cmd 8 | lnkpru -i$(A_DIR) pru0_firmware.obj pru0_syscall.obj AM3359_PRU.cmd -o=pru0_firmware 9 | 10 | pru0_firmware.obj: pru0_firmware.c pru0_firmware.h pru_firmware.h 11 | clpru -O3 --c99 pru0_firmware.c 12 | 13 | pru0_syscall.obj: pru0_syscall.asm 14 | clpru pru0_syscall.asm 15 | 16 | #PRU1 17 | pru1_firmware: pru1_firmware.obj AM3359_PRU.cmd 18 | lnkpru -i$(A_DIR) pru1_firmware.obj AM3359_PRU.cmd -o=pru1_firmware 19 | 20 | pru1_firmware.obj: pru1_firmware.c pru1_firmware.h pru_firmware.h 21 | clpru -O3 --c99 pru1_firmware.c 22 | 23 | 24 | install: all 25 | install -m 444 pru0_firmware /lib/firmware 26 | install -m 444 pru1_firmware /lib/firmware 27 | -------------------------------------------------------------------------------- /src/pru-firmware/README.md: -------------------------------------------------------------------------------- 1 | PRU Speak firmware 2 | =================== 3 | 4 | This is the firmware that gets loaded on the PRU by the driver on loading the Device Tree Overlay (DTO). 5 | 6 | This firmware behaves as a BotSpeak bytecode interpreter. Handles commands and instruction/data streams from the ARM CPU. 7 | 8 | Build 9 | ===== 10 | * Download ARM installer for PRU compiler on BeagleBone from http://software-dl.ti.com/codegen/non-esd/downloads/beta.htm 11 | * Make installer executable and run it from your desired install directory 12 | * Set environment variables (example placed in .bashrc) 13 | export MANPATH=$MANPATH:$HOME/pru_2.0.0B2/man 14 | export PATH=$PATH:$HOME/pru_2.0.0B2/bin 15 | export PRU_C_DIR=$HOME/pru_2.0.0B2/lib 16 | export PRU_A_DIR=$HOME/pru_2.0.0B2/lib 17 | * make 18 | -------------------------------------------------------------------------------- /src/pru-firmware/pru0_firmware.c: -------------------------------------------------------------------------------- 1 | #include "pru_firmware.h" 2 | #include "pru0_firmware.h" 3 | 4 | int var_loc[256]; 5 | void wait(int); 6 | int pwm_val = 0; 7 | 8 | static void send_ret_value(int val) 9 | { 10 | //TODO : handle multiple params? 11 | //TODO : change to sysfs 12 | /*enable gloabl access*/ 13 | PRUCFG_SYSCFG = PRUCFG_SYSCFG & (~SYSCFG_STANDBY_INIT); 14 | 15 | /* write val to the loc pointed to by current ret_pointer */ 16 | *(shm_ret + ret_pointer) = val; 17 | 18 | /*inc the ret_pointer to point to the next empty loc*/ 19 | ret_pointer = (ret_pointer % 1023) + 1; 20 | //max buffer space is 4096 => 1023 (free)words. 21 | 22 | /*inc the num_ret_value*/ 23 | *shm_ret = ret_pointer; //ret_pointer is like a stack pointer, 24 | //userspace will read this value to figure out till where the buffer has been filled 25 | //e.g. if the ret_pointer = 10; ARM will read 9 slots uptill 10 26 | 27 | PRUCFG_SYSCFG = PRUCFG_SYSCFG | SYSCFG_STANDBY_INIT; 28 | 29 | } 30 | 31 | /* to fetch 2nd part of 64 bit instruction */ 32 | static u32 get_second_word() 33 | { 34 | u32 inst; 35 | 36 | /* when the 64 bit inst is part of the script */ 37 | if(!single_command){ 38 | PRUCFG_SYSCFG = PRUCFG_SYSCFG & (~SYSCFG_STANDBY_INIT); /*enable gloabl access*/ 39 | inst = *(shm_code + inst_pointer); 40 | PRUCFG_SYSCFG = PRUCFG_SYSCFG | SYSCFG_STANDBY_INIT; 41 | inst_pointer++; 42 | } 43 | 44 | /* when the 64 bit inst is a single_inst */ 45 | else { 46 | inst = single_command_2; 47 | } 48 | 49 | return inst; 50 | } 51 | 52 | /* used to get value of a variable*/ 53 | int get_var_val(int addr) 54 | { 55 | if (addr > MAX_DATA){ 56 | if(addr < AIO_OFF){ 57 | //case DIO 58 | //240 to 255 -> DIO[0] to DIO[15] 59 | 60 | addr -= 1; 61 | //this is there since if the code reaces here it is Arr[c/v] 62 | //so either the userspace compiler or calling pru func here 63 | //would have added 1. this should be taken care of. 64 | 65 | addr -= DIO_OFF; 66 | return GET_BIT(__R31, addr); 67 | } 68 | } 69 | 70 | else{ 71 | return var_loc[addr]; 72 | } 73 | 74 | return 0; 75 | } 76 | 77 | /*instruction handlers*/ 78 | 79 | void dio_handler(int opcode, u32 inst) 80 | { 81 | int val1, val2; 82 | if(opcode == SET_DIO_a){ 83 | /* SET DIO[c/v], c/v */ 84 | 85 | val1 = GET_BIT(inst, 23) ? var_loc[GET_BYTE(inst, 1)]: GET_BYTE(inst, 1); 86 | val2 = GET_BIT(inst, 22) ? var_loc[GET_BYTE(inst, 0)]: GET_BYTE(inst, 0); 87 | } 88 | 89 | else{ 90 | // "SET DIO[c], arr[v]" orelse "SET DIO[v] , arr[v]" 91 | val1 = (opcode == SET_DIO_b) ? GET_BYTE(inst, 2) : var_loc[GET_BYTE(inst,2)]; 92 | 93 | //array size check -- this case same for both case 94 | int index = var_loc[GET_BYTE(inst, 0)]; 95 | if (var_loc[GET_BYTE(inst,1)] <= index ){ 96 | //error 97 | if (single_command) 98 | send_ret_value(0); 99 | return; 100 | } 101 | //if everything okay 102 | int addr = GET_BYTE(inst, 1) + index + 1; 103 | val2 = var_loc[addr]; 104 | } 105 | /* set hi*/ 106 | if(val2 && (val1 < MAX_DIO)){ 107 | __R30 = __R30 | ( 1 << val1); 108 | } 109 | 110 | /* set low*/ 111 | else{ 112 | __R30 = __R30 & ~( 1 << val1); 113 | } 114 | 115 | if(single_command) 116 | send_ret_value(val2 ? 1 : 0); 117 | } 118 | 119 | void pwm_handler(int opcode, u32 inst) 120 | { 121 | //takes in only PWM[c], c. This will be merged with dio later 122 | int val1, val2; 123 | if(opcode == SET_PWM_a){ 124 | /* SET PWM[c/v], c/v */ 125 | 126 | val1 = GET_BIT(inst, 23) ? var_loc[GET_BYTE(inst, 1)]: GET_BYTE(inst, 1); 127 | val2 = GET_BIT(inst, 22) ? var_loc[GET_BYTE(inst, 0)]: GET_BYTE(inst, 0); 128 | } 129 | 130 | else{ 131 | // "SET PWM[c], arr[v]" orelse "SET PWM[v] , arr[v]" 132 | val1 = (opcode == SET_PWM_b) ? GET_BYTE(inst, 2) : var_loc[GET_BYTE(inst,2)]; 133 | 134 | //array size check -- this case same for both case 135 | int index = var_loc[GET_BYTE(inst, 0)]; 136 | if (var_loc[GET_BYTE(inst,1)] <= index ){ 137 | //error 138 | if (single_command) 139 | send_ret_value(0); 140 | return; 141 | } 142 | //if everything okay 143 | int addr = GET_BYTE(inst, 1) + index + 1; 144 | val2 = var_loc[addr]; 145 | } 146 | 147 | /* set pwm value */ 148 | data_sock->info[PRU1][val1] = val2; 149 | SIGNAL_EVENT(EV_PRU0_PRU1); 150 | send_ret_value(val2); 151 | } 152 | 153 | void set_handler(int opcode, u32 inst) 154 | { 155 | int val2, addr1, addr2; 156 | 157 | if(opcode == SET_32_a){ 158 | /* SET V, C */ 159 | addr1 = GET_BYTE(inst,2); 160 | val2 = inst & 0xffff; //16 bit constant 161 | var_loc[addr1] = val2; 162 | if(single_command) 163 | send_ret_value(val2); 164 | 165 | } 166 | 167 | else if(opcode == SET_32_b){ 168 | /* SET V, V */ 169 | addr1 = GET_BYTE(inst,2); 170 | addr2 = GET_BYTE(inst,0); 171 | var_loc[addr1] = get_var_val(addr2); 172 | if(single_command) 173 | send_ret_value(var_loc[addr1]); 174 | 175 | } 176 | 177 | else{ 178 | /* SET V/Arr[v], C/V/Arr[v] */ 179 | int op = GET_BYTE(inst, 2) >> 6; 180 | 181 | //if op == 1, operand1 is a variable; else it is a Arr[v] type 182 | if (op == 1){ 183 | addr1 = GET_BYTE(inst, 0); 184 | } 185 | 186 | //Arr[v] 187 | else{ 188 | //array size check 189 | int index = var_loc[GET_BYTE(inst, 0)]; 190 | if (var_loc[GET_BYTE(inst,1)] <= index ){ 191 | //error 192 | if (single_command) 193 | send_ret_value(0); 194 | return; 195 | } 196 | addr1 = GET_BYTE(inst,1) + index + 1; 197 | } 198 | 199 | u32 old_inst = inst; 200 | 201 | //get the next 32 bits of the inst 202 | inst = get_second_word(); 203 | 204 | op = ((GET_BYTE(old_inst, 2) >> 4) & 3); //get bits 4 and 5 of byte2 205 | 206 | if (op == 0){ 207 | //operand2 is of type C 208 | val2 = inst & 0xFF; 209 | var_loc[addr1] = val2; 210 | if(single_command) 211 | send_ret_value(val2); 212 | 213 | } 214 | 215 | if (op == 1){ 216 | //operand2 is of type V 217 | addr2 = GET_BYTE(inst,0); 218 | var_loc[addr1] = get_var_val(addr2); 219 | if(single_command) 220 | send_ret_value(var_loc[addr1]); 221 | 222 | } 223 | 224 | else{ 225 | //second operand is of type Arr[v] 226 | //array size check 227 | int index = var_loc[GET_BYTE(inst, 0)]; 228 | if (var_loc[GET_BYTE(inst,1)] <= index ){ 229 | //error 230 | if (single_command) 231 | send_ret_value(0); 232 | return; 233 | } 234 | addr2 = GET_BYTE(inst,1) + index + 1; 235 | var_loc[addr1] = get_var_val(addr2); 236 | if(single_command) 237 | send_ret_value(var_loc[addr1]); 238 | } 239 | 240 | } 241 | } 242 | 243 | void array_dec_handler(int opcode, u32 inst) 244 | { 245 | int arr = GET_BYTE(inst, 1); 246 | int size = GET_BIT(inst, 23) ? var_loc[GET_BYTE(inst, 0)]: GET_BYTE(inst, 0); 247 | var_loc[arr] = size; 248 | send_ret_value(size); 249 | } 250 | 251 | //three in one :) 252 | void wait_goto_get_handler(int opcode, u32 inst) 253 | { 254 | int op = (GET_BYTE(inst, 2) >> 6); 255 | int val; 256 | if(op == 0){ 257 | /* WAIT c*/ 258 | val = inst & 0xFFFF; 259 | } 260 | 261 | else if (op == 1){ 262 | /* WAIT v*/ 263 | val = get_var_val(GET_BYTE(inst, 0)); 264 | } 265 | 266 | else{ 267 | /* WAIT Arr[v] */ 268 | //array size check 269 | int index = var_loc[GET_BYTE(inst, 0)]; 270 | if (var_loc[GET_BYTE(inst,1)] <= index ){ 271 | //error 272 | if (single_command) 273 | send_ret_value(0); 274 | return; 275 | } 276 | 277 | val = get_var_val(GET_BYTE(inst,1) + index + 1); 278 | } 279 | 280 | if(opcode == WAIT){ 281 | wait(val); 282 | } 283 | 284 | else if (opcode == GOTO) 285 | inst_pointer = val; 286 | 287 | else if((opcode == GET) && single_command) 288 | send_ret_value(val); 289 | } 290 | 291 | #if 1 292 | void if_handler(int opcode, u32 inst) 293 | { 294 | /* IF (a b) GOTO c 295 | a => C/V/Arr[V] (byte1, byte0) 296 | b => C/V/Arr[V] (byte5, byte4) 297 | c => C/V/Arr[V] (byte7, byte6) 298 | */ 299 | int val1, val2, val3; 300 | int op = GET_BYTE(inst, 2) >> 6; 301 | int rel_op, res; 302 | 303 | rel_op = opcode & 0x0F; 304 | 305 | if(op == 0){ 306 | /* operand1 is of type C */ 307 | val1 = GET_BYTE(inst, 0); 308 | } 309 | 310 | else if(op == 1){ 311 | /* operand1 is of type V */ 312 | val1 = get_var_val(GET_BYTE(inst, 0)); 313 | } 314 | 315 | else{ 316 | /* operand1 is of type Arr[v] */ 317 | 318 | //array size check 319 | int index = var_loc[GET_BYTE(inst, 0)]; 320 | if (var_loc[GET_BYTE(inst,1)] <= index ){ 321 | //error 322 | if (single_command) 323 | send_ret_value(0); 324 | return; 325 | } 326 | 327 | val1 = get_var_val(GET_BYTE(inst,1) + index + 1); 328 | } 329 | 330 | u32 old_inst = inst; //old_inst is the 1st 32 bits of the inst. 331 | 332 | //get the next 32 bits of the inst 333 | inst = get_second_word(); 334 | 335 | /*** GET val2 from second part of the inst ***/ 336 | 337 | op = (GET_BYTE(old_inst, 2) >> 4) & 3; 338 | 339 | if(op == 0){ 340 | /* operand2 is of type C */ 341 | val2 = GET_BYTE(inst, 0); 342 | } 343 | 344 | else if(op == 1){ 345 | /* operand2 is of type V */ 346 | val2 = get_var_val(GET_BYTE(inst, 0)); 347 | } 348 | 349 | else{ 350 | /* operand2 is of type Arr[v] */ 351 | 352 | //array size check 353 | int index = var_loc[GET_BYTE(inst, 0)]; 354 | if (var_loc[GET_BYTE(inst,1)] <= index ){ 355 | //error 356 | if (single_command) 357 | send_ret_value(0); 358 | return; 359 | } 360 | 361 | val2 = get_var_val(GET_BYTE(inst,1) + index + 1); 362 | } 363 | 364 | /*** GET val3 from second part of the inst ***/ 365 | 366 | op = (GET_BYTE(old_inst, 2) >> 2) & 3; 367 | 368 | if(op == 0){ 369 | /* operand3 is of type C */ 370 | val3 = GET_BYTE(inst, 2); 371 | } 372 | 373 | else if(op == 1){ 374 | /* operand3 is of type V */ 375 | val3 = get_var_val(GET_BYTE(inst, 2)); 376 | } 377 | 378 | else{ 379 | /* operand3 is of type Arr[v] */ 380 | 381 | //array size check 382 | int index = var_loc[GET_BYTE(inst, 2)]; 383 | if (var_loc[GET_BYTE(inst,3)] <= index ){ 384 | //error 385 | if (single_command) 386 | send_ret_value(0); 387 | return; 388 | } 389 | 390 | val3 = get_var_val(GET_BYTE(inst,3) + index + 1); 391 | } 392 | 393 | /* calculate the result based on rel_op 394 | == 0 395 | != 1 396 | >= 2 397 | <= 3 398 | > 4 399 | < 5 400 | */ 401 | switch(rel_op){ 402 | case 0: 403 | res = (val1 == val2); 404 | break; 405 | 406 | case 1: 407 | res = (val1 != val2); 408 | break; 409 | 410 | case 2: 411 | res = (val1 >= val2); 412 | break; 413 | 414 | case 3: 415 | res = (val1 <= val2); 416 | break; 417 | 418 | case 4: 419 | res = (val1 > val2); 420 | break; 421 | 422 | case 5: 423 | res = (val1 < val2); 424 | break; 425 | 426 | default: 427 | res = 0; 428 | break; 429 | } 430 | 431 | if(res){ 432 | inst_pointer = val3; 433 | } 434 | 435 | } 436 | 437 | /* handler for all inst like ADD, SUB, AND, OR*/ 438 | void math_handler(int opcode, u32 inst) 439 | { 440 | int val1, val2, res; 441 | int addr; //address of var to modify 442 | if(opcode % 2 == 0){ 443 | /* 32 bit inst */ 444 | //val1 = GET_BIT(inst, 23) ? var_loc[GET_BYTE(inst, 1)]: GET_BYTE(inst, 1); 445 | addr = GET_BYTE(inst,1); 446 | val1 = var_loc[addr]; //val1 can't be const 447 | val2 = GET_BIT(inst, 22) ? var_loc[GET_BYTE(inst, 0)]: GET_BYTE(inst, 0); 448 | } 449 | 450 | else{ 451 | /* 64 bit inst */ 452 | //TODO the following should be abstracted away into a fn 453 | //since all 64 bit inst have the same operator placement, common fn to extract all values 454 | 455 | int op = GET_BYTE(inst, 2) >> 6; 456 | 457 | if(op == 0){//XXX : this case is not possible 458 | /* operand1 is of type C */ 459 | val1 = GET_BYTE(inst, 0); 460 | } 461 | 462 | else if(op == 1){ 463 | /* operand1 is of type V */ 464 | addr = GET_BYTE(inst,0); 465 | val1 = get_var_val(addr); 466 | } 467 | 468 | else{ 469 | /* operand1 is of type Arr[v] */ 470 | 471 | //array size check 472 | int index = var_loc[GET_BYTE(inst, 0)]; 473 | if (var_loc[GET_BYTE(inst,1)] <= index ){ 474 | //error 475 | if (single_command) 476 | send_ret_value(0); 477 | return; 478 | } 479 | 480 | val1 = get_var_val(GET_BYTE(inst,1) + index + 1); 481 | } 482 | 483 | u32 old_inst = inst; //old_inst is the 1st 32 bits of the inst. 484 | 485 | //get the next 32 bits of the inst 486 | inst = get_second_word(); 487 | 488 | /*** GET val2 from second part of the inst ***/ 489 | 490 | op = (GET_BYTE(old_inst, 2) >> 4) & 3; 491 | 492 | if(op == 0){ 493 | /* operand2 is of type C */ 494 | val2 = GET_BYTE(inst, 0); 495 | } 496 | 497 | else if(op == 1){ 498 | /* operand2 is of type V */ 499 | val2 = get_var_val(GET_BYTE(inst, 0)); 500 | } 501 | 502 | else{ 503 | /* operand2 is of type Arr[v] */ 504 | 505 | //array size check 506 | int index = var_loc[GET_BYTE(inst, 0)]; 507 | if (var_loc[GET_BYTE(inst,1)] <= index ){ 508 | //error 509 | if (single_command) 510 | send_ret_value(0); 511 | return; 512 | } 513 | 514 | val2 = get_var_val(GET_BYTE(inst,1) + index + 1); 515 | } 516 | } 517 | 518 | switch(opcode){ 519 | case ADD_32: 520 | case ADD_64: 521 | res = val1 + val2; 522 | break; 523 | 524 | case SUB_32: 525 | case SUB_64: 526 | res = val1 - val2; 527 | break; 528 | 529 | case AND_32: 530 | case AND_64: 531 | res = val1 & val2; 532 | break; 533 | 534 | case OR_32: 535 | case OR_64: 536 | res = val1 | val2; 537 | break; 538 | 539 | case NOT_32: 540 | case NOT_64: 541 | res = ~val2; 542 | break; 543 | 544 | 545 | default: 546 | res = val1; 547 | break; 548 | } 549 | 550 | var_loc[addr] = res; 551 | 552 | if(single_command) 553 | send_ret_value(res); 554 | 555 | } 556 | #endif 557 | 558 | static int handle_downcall(u32 id, u32 arg0, u32 arg1, u32 arg2, 559 | u32 arg3, u32 arg4) 560 | { 561 | switch(id) 562 | { 563 | case SYS_DEBUG: 564 | if(arg0){ 565 | __R30 = 0x0000FFFF; 566 | } 567 | else{ 568 | __R30 = 0x00000000; 569 | } 570 | break; 571 | 572 | case SYS_INIT: 573 | is_executing = 0; 574 | is_waiting = false; 575 | var_loc[DIO_OFF] = 0xFFFFFF; //no index out of bounds for DIO, AIO etc. 576 | PRUCFG_SYSCFG = PRUCFG_SYSCFG & (~SYSCFG_STANDBY_INIT); /*enable gloabl access*/ 577 | shm_code = (u32 *)arg0; 578 | shm_ret = (u32 *)arg1; 579 | *shm_code = 25; /*for test purposes - checked by kernel*/ 580 | *shm_ret = 1; 581 | PRUCFG_SYSCFG = PRUCFG_SYSCFG | SYSCFG_STANDBY_INIT; 582 | break; 583 | 584 | case SYS_EXEC: 585 | /* 586 | arg0 == 0 : pause 587 | arg0 == 1 : start/continue 588 | */ 589 | if(arg0){ 590 | if (!inst_pointer) 591 | inst_pointer = 0; // incase it was not executing before, start 592 | // else all we want to do is continue 593 | is_executing = true; 594 | } 595 | else{ 596 | is_executing = false; 597 | } 598 | break; 599 | 600 | case SYS_ABRT: 601 | is_executing = false; 602 | is_waiting = false; 603 | inst_pointer = 0; 604 | ret_pointer = 1; 605 | PRUCFG_SYSCFG = PRUCFG_SYSCFG & (~SYSCFG_STANDBY_INIT); 606 | *shm_ret = 1; 607 | PRUCFG_SYSCFG = PRUCFG_SYSCFG | SYSCFG_STANDBY_INIT; 608 | break; 609 | 610 | case SYS_STAT: 611 | /* returns the status of execution i.e. executing or not */ 612 | return (is_executing | is_waiting); 613 | break; 614 | 615 | case SYS_INST_32: 616 | /* an single 32 bit instruction has been recieved for execution */ 617 | single_command = (u32)arg0; 618 | break; 619 | 620 | case SYS_INST_64: 621 | /* an single 32 bit instruction has been recieved for execution */ 622 | single_command = (u32)arg0; 623 | single_command_2 = (u32)arg1; //2nd word for 64 bit inst 624 | //bad naming convention - alexanderhiam is not going to be happy 625 | break; 626 | 627 | default: 628 | return 0; /* error case - unknown instruction in memory */ 629 | break; 630 | } 631 | 632 | return 1; 633 | } 634 | 635 | /* make this an inline function? */ 636 | void check_event(void) 637 | { 638 | if( IF_EVENT ){ 639 | /* clear the system event */ 640 | PINTC_SICR = 21; 641 | 642 | /* call the handler to perform the downcall*/ 643 | sc_downcall(handle_downcall); 644 | } 645 | 646 | 647 | if(PIEP_CMP_STATUS & 1){ 648 | /* disable the timer */ 649 | //PIEP_GLOBAL_CFG &= ~(GLOBAL_CFG_CNT_ENABLE); 650 | 651 | /* reset the timer to 0 (timer is a clear to write reg) */ 652 | //PIEP_COUNT = 0XFFFFFFFF; 653 | 654 | /* set CMP0 value back to zero */ 655 | PIEP_CMP_CMP0 = 0; 656 | 657 | /* disable events from CMP0*/ 658 | PIEP_CMP_CFG &= ~(CMP_CFG_CMP_EN(0)); 659 | 660 | /* clear the timer event for CMP0 incase it has been set by mistake */ 661 | PIEP_CMP_STATUS = CMD_STATUS_CMP_HIT(0); 662 | 663 | /* change the current state of the PRU */ 664 | if (is_waiting){ 665 | //there could have been an abort. in case there wasn't : 666 | is_executing = true; 667 | is_waiting = false; 668 | } 669 | } 670 | 671 | } 672 | 673 | void wait(int ms) 674 | { 675 | /* set the CMP0 reg value */ 676 | //PIEP_CMP_CMP0 = MS * ms; 677 | 678 | /* change execution state of the PRU */ 679 | is_executing = false; 680 | is_waiting = true; 681 | 682 | /* enable events from CMP0*/ 683 | PIEP_CMP_CFG |= CMP_CFG_CMP_EN(0); 684 | 685 | /* set the CMP0 reg value */ 686 | PIEP_CMP_CMP0 = ((MS * ms) + PIEP_COUNT);// % 0xFFFFFFFF;//is the % op needed at all? 687 | 688 | /* clear the timer event for CMP0 incase it has been already set by mistake */ 689 | PIEP_CMP_STATUS = CMD_STATUS_CMP_HIT(0); 690 | 691 | /* start the timer */ 692 | //PIEP_GLOBAL_CFG |= GLOBAL_CFG_CNT_ENABLE; 693 | } 694 | 695 | void execute_instruction() 696 | { 697 | u32 inst; 698 | if(!single_command){ 699 | PRUCFG_SYSCFG = PRUCFG_SYSCFG & (~SYSCFG_STANDBY_INIT); /*enable gloabl access*/ 700 | inst = *(shm_code + inst_pointer); 701 | PRUCFG_SYSCFG = PRUCFG_SYSCFG | SYSCFG_STANDBY_INIT; 702 | inst_pointer++; 703 | } 704 | else { 705 | inst = single_command; 706 | } 707 | 708 | int opcode = inst >> 24; //most significant byte contains the cmd 709 | 710 | switch(opcode){ 711 | 712 | case SET_DIO_a: 713 | case SET_DIO_b: 714 | case SET_DIO_c: 715 | dio_handler(opcode, inst); 716 | break; 717 | 718 | case SET_PWM_a: 719 | pwm_handler(opcode, inst); 720 | break; 721 | 722 | case SET_32_a: 723 | case SET_32_b: 724 | case SET_64: 725 | set_handler(opcode, inst); 726 | break; 727 | 728 | case SET_ARR_DEC: 729 | array_dec_handler(opcode, inst); 730 | break; 731 | 732 | case WAIT: 733 | case GOTO: 734 | case GET: 735 | wait_goto_get_handler(opcode, inst); 736 | break; 737 | 738 | case IF_EQ: 739 | case IF_NEQ: 740 | case IF_GTE: 741 | case IF_LTE: 742 | case IF_GT: 743 | case IF_LT: 744 | if_handler(opcode, inst); 745 | break; 746 | 747 | case ADD_32: 748 | case ADD_64: 749 | case SUB_32: 750 | case SUB_64: 751 | case AND_32: 752 | case AND_64: 753 | case OR_32: 754 | case OR_64: 755 | math_handler(opcode, inst); 756 | break; 757 | 758 | case HALT: 759 | is_waiting = 0; 760 | is_executing = 0; 761 | inst_pointer = 0; 762 | break; 763 | 764 | default: 765 | /*no op*/ 766 | break; 767 | 768 | } 769 | 770 | single_command = 0; /*incase there was a single command executed this time, set to zero*/ 771 | } 772 | 773 | void timer_init() 774 | { 775 | /* set default inc to 1, set compensation inc to 1 (though this is never used)*/ 776 | PIEP_GLOBAL_CFG = GLOBAL_CFG_DEFAULT_INC(1) | GLOBAL_CFG_CMP_INC(1); 777 | 778 | /* Compare registers enable, enables signal from CMP0, on CMP0 --> counter is reset */ 779 | //PIEP_CMP_CFG |= RESET_ON_CMP0_EVENT; -- cant afford to do this when timer is shared 780 | 781 | /* clear the counter status bit for CMP0 register, i.e. PIEP_CMP_STATUS[0] */ 782 | PIEP_CMP_STATUS = CMD_STATUS_CMP_HIT(0); /* clear the interrupt */ 783 | 784 | /* start the timer */ 785 | PIEP_GLOBAL_CFG |= GLOBAL_CFG_CNT_ENABLE; 786 | } 787 | 788 | int main() 789 | { 790 | 791 | timer_init(); 792 | //send_ret_value(1000); 793 | while(1) 794 | { 795 | check_event(); 796 | 797 | if (is_executing || single_command){ //or if single_cmd 798 | execute_instruction(); 799 | //send_ret_value(is_executing); 800 | //send_ret_value(single_command); 801 | } 802 | 803 | } 804 | 805 | return 0; 806 | } 807 | -------------------------------------------------------------------------------- /src/pru-firmware/pru0_firmware.h: -------------------------------------------------------------------------------- 1 | //ARM -> pru0 2 | #define EVENT_BIT 21 //keep for now, later replace with 'EV_ARM_PRU0' 3 | #define IF_EVENT PINTC_SRSR0 & (1 << EVENT_BIT) 4 | 5 | #define MS 0x30d40 //number of clock cycles it takes for 1ms 6 | 7 | /*max number of DIO pins*/ 8 | #define MAX_DIO 12 9 | 10 | /* max data area (in terms of index for var_loc[])*/ 11 | #define MAX_DATA 239 12 | 13 | /* start of DIO, AIO */ 14 | #define DIO_OFF 240 15 | #define AIO_OFF 256 16 | 17 | /* 18 | sys calls ids 19 | Different syscall values, aliases and their meaning 20 | */ 21 | 22 | //DEBUG - Sets all output pins to high 23 | #define SYS_DEBUG 0 24 | 25 | //INIT - initializes the shm address, 26 | //writes into it so kernel knows that pru can talk via shm 27 | #define SYS_INIT 1 28 | 29 | //EXEC - start or pause script execution 30 | #define SYS_EXEC 2 31 | 32 | //ABORT - aborts the running script, resets env 33 | #define SYS_ABRT 3 34 | 35 | //returns the status of whether a script is executing 36 | #define SYS_STAT 4 37 | 38 | //a single inst cmd, 32 bit, to be executed next cycle. 39 | #define SYS_INST_32 5 40 | 41 | //a single inst cmd, 64 bit, to be executed next cycle. 42 | #define SYS_INST_64 6 43 | 44 | /* base address pointer of the instruction stream */ 45 | u32 *shm_code = 0; 46 | 47 | /* base address pointer of the return value stream */ 48 | u32 *shm_ret = 0; 49 | 50 | /* offset (from shm_ret) to current return value loc*/ 51 | int ret_pointer = 1; 52 | 53 | /* the compiled 32 bit instruction */ 54 | u32 single_command = 0; 55 | 56 | /* 2nd word of the compiled 64 bit instruction */ 57 | u32 single_command_2 = 0; 58 | 59 | /* pointer to current instruction in terms of offset */ 60 | int inst_pointer = 0; 61 | 62 | /* boolean value, true if there is a botspeak script under execution */ 63 | int is_executing = false; 64 | 65 | /* boolean value, true if wait is being executed */ 66 | int is_waiting = false; 67 | 68 | extern void sc_downcall(int (*handler)(u32 nr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)); 69 | 70 | /*instruction set encoding */ 71 | #define NOP 0 72 | 73 | /*SET RES[x], y - IO operations*/ 74 | #define SET_DIO_a 1 75 | #define SET_DIO_b 2 76 | #define SET_DIO_c 3 77 | #define SET_PWM_a 4 78 | #define SET_PWM_b 5 79 | #define SET_PWM_c 6 80 | #define SET_AIO_a 7 81 | #define SET_AIO_b 8 82 | #define SET_AIO_c 9 83 | 84 | /*Variable set operations*/ 85 | #define SET_32_a 16 86 | #define SET_32_b 17 87 | #define SET_64 18 88 | #define SET_ARR_DEC 19 89 | /*If conditions*/ 90 | #define IF_EQ 32 91 | #define IF_NEQ 33 92 | #define IF_GTE 34 93 | #define IF_LTE 35 94 | #define IF_GT 36 95 | #define IF_LT 37 96 | 97 | /*single operand instructions*/ 98 | #define WAIT 20 99 | #define GOTO 21 100 | #define GET 22 101 | 102 | /*arithmetic instructions*/ 103 | #define ADD_32 48 104 | #define ADD_64 49 105 | #define SUB_32 50 106 | #define SUB_64 51 107 | #define MUL_32 52 108 | #define MUL_64 53 109 | #define DIV_32 54 110 | #define DIV_64 55 111 | #define MOD_32 56 112 | #define MOD_64 57 113 | 114 | /*bit wise operations*/ 115 | #define BSL_32 64 116 | #define BSL_64 65 117 | #define BSR_32 66 118 | #define BSR_64 67 119 | #define AND_32 68 120 | #define AND_64 69 121 | #define OR_32 70 122 | #define OR_64 71 123 | #define NOT_32 72 124 | #define NOT_64 73 125 | 126 | #define HALT 127 127 | 128 | 129 | -------------------------------------------------------------------------------- /src/pru-firmware/pru0_syscall.asm: -------------------------------------------------------------------------------- 1 | .text 2 | .global sc_downcall 3 | sc_downcall: 4 | MOV R0.w0, R14.w0 ;* save the pointer to the handler function 5 | ;* first issue the downcall ready 6 | LDI R14, 254 ;* DOWNCALL_READY 7 | LDI R31, 35 ;* SYSCALL_VALUE 8 | HALT ;* host must save R3.w0 locally 9 | ;* the host will manipulate our state so that the arguments are correct 10 | JAL R3.w2, R0.w0 ;* call 11 | MOV R0, R14 ;* save the return code 12 | ;* when we return here, we will inform the host of the result 13 | LDI R14, 255 ;* DOWNCALL_DONE 14 | LDI R31, 35 ;* SYSCALL_VALUE 15 | HALT ;* host must return to save R3.w0 16 | -------------------------------------------------------------------------------- /src/pru-firmware/pru1_firmware.c: -------------------------------------------------------------------------------- 1 | #include "pru_firmware.h" 2 | #include "pru1_firmware.h" 3 | 4 | /* The number of TIME_UNIT elapsed in the current TIME_PERIOD */ 5 | int units_elapsed = 0; 6 | 7 | void timer_init() 8 | { 9 | /* set default inc to 1, set compensation inc to 1 (though this is never used)*/ 10 | PIEP_GLOBAL_CFG = GLOBAL_CFG_DEFAULT_INC(1) | GLOBAL_CFG_CMP_INC(1); 11 | 12 | /* Enable interrupts from cmp1 */ 13 | PIEP_CMP_CFG |= CMP_CFG_CMP_EN(1); 14 | 15 | /* set the value of cmp1 = (time_unit in us) * (no. of clk cycle for 1 us) */ 16 | PIEP_CMP_CMP1 = ((US * TIME_UNIT) + PIEP_COUNT); 17 | 18 | /* clear the interrupt from cmp1 in case it has been set by mistake */ 19 | PIEP_CMP_STATUS = CMD_STATUS_CMP_HIT(1); 20 | 21 | /* start the timer */ 22 | PIEP_GLOBAL_CFG |= GLOBAL_CFG_CNT_ENABLE; 23 | } 24 | 25 | 26 | int main() 27 | { 28 | /* init the structs in the array and shm area */ 29 | int i,j; 30 | for(i = 0; i < CHANNELS; i++ ){ 31 | pwm_sys[i].pin = i; 32 | pwm_sys[i].hi_time = 0; 33 | data_sock->info[PRU][i] = 0; 34 | } 35 | 36 | /* timer initializations */ 37 | timer_init(); 38 | 39 | pwm_sys[0].hi_time = 5; //just for test purposes 40 | 41 | /* main soft-pwm generation loop */ 42 | while(1){ 43 | j = 0; 44 | 45 | /* update pins */ 46 | 47 | //read the values of hi time 48 | i = (pwm_sys[0].hi_time > units_elapsed); 49 | j |= i << pwm_sys[0].pin; 50 | 51 | i = (pwm_sys[1].hi_time > units_elapsed); 52 | j |= i << pwm_sys[1].pin; 53 | 54 | i = (pwm_sys[2].hi_time > units_elapsed); 55 | j |= i << pwm_sys[2].pin; 56 | 57 | i = (pwm_sys[3].hi_time > units_elapsed); 58 | j |= i << pwm_sys[3].pin; 59 | 60 | i = (pwm_sys[4].hi_time > units_elapsed); 61 | j |= i << pwm_sys[4].pin; 62 | 63 | i = (pwm_sys[5].hi_time > units_elapsed); 64 | j |= i << pwm_sys[5].pin; 65 | 66 | i = (pwm_sys[6].hi_time > units_elapsed); 67 | j |= i << pwm_sys[6].pin; 68 | 69 | i = (pwm_sys[7].hi_time > units_elapsed); 70 | j |= i << pwm_sys[7].pin; 71 | 72 | //assign to the output 73 | __R30 = j; 74 | 75 | /* inc the counter */ 76 | units_elapsed++; 77 | 78 | /* if one time period is over */ 79 | if(units_elapsed == RESOLUTION){ 80 | //reset the time unit count => start of new time period 81 | units_elapsed = 0; 82 | 83 | if (CHECK_EVENT(EV_PRU0_PRU1)){ 84 | 85 | /* clear the system event */ 86 | PINTC_SICR = EV_PRU0_PRU1; //17 87 | 88 | /* update the pru_sys array */ 89 | for(i=0; iinfo[PRU][i]; 91 | 92 | } 93 | 94 | } 95 | 96 | 97 | /*** till here no more than 2K inst ***/ 98 | 99 | /* loop along till timer is up */ 100 | 101 | while(!( PIEP_CMP_STATUS & (2) )){ //0b10 102 | //just wait 103 | } 104 | 105 | /* the timer has gone off */ 106 | 107 | //reassign value cmp1 108 | PIEP_CMP_CMP1 = ((US * TIME_UNIT) + PIEP_COUNT); 109 | 110 | //clear the interrupt from cmp1 111 | PIEP_CMP_STATUS = CMD_STATUS_CMP_HIT(1); 112 | 113 | } 114 | 115 | return 0; 116 | } 117 | 118 | -------------------------------------------------------------------------------- /src/pru-firmware/pru1_firmware.h: -------------------------------------------------------------------------------- 1 | #define PRU 1 2 | 3 | //pru0 -> pru1 4 | #define IF_EVENT (CHECK_EVENT(EV_PRU0_PRU1)) // || CHECK_EVENT(EV_ARM_PRU0)) --not reqd as of now 5 | 6 | /* The number of clock cycles it takes for 1 micro sec*/ 7 | #define US 0xc8 //dec val = 200 8 | #define MS 0x30d40 9 | 10 | /* The number of PWM channels */ 11 | #define CHANNELS 8 12 | 13 | /* The time unit in terms of micro sec */ 14 | #define TIME_UNIT 5 //equivalent to 1K instructions 15 | 16 | /* The number of time units in one wave/time-period */ 17 | #define RESOLUTION 100 //should be atleast 20 :( 18 | 19 | /* time period of pwm o/p in micro seconds */ 20 | #define TIME_PERIOD ((TIME_UNIT) * (RESOLUTION)) 21 | //freq of PWM = (10^6) / (TIME_PERIOD) ; 10^6 since it is micro sec 22 | 23 | /* basic pwm unit structure */ 24 | struct pwm_unit{ 25 | int pin; //output pin 26 | int hi_time; //number of TIME_UNITs to stay high a TIME_PERIOD 27 | }; 28 | 29 | typedef struct pwm_unit PWM; 30 | 31 | /* array that represents all the soft PWM ports*/ 32 | PWM pwm_sys[CHANNELS]; 33 | 34 | 35 | //######################ALGORITHM############################ 36 | #if 0 37 | 38 | |_ _ _ _ _ _ _ _ _ _ | ==> one waveform (time period) 39 | 40 | PWM : 0.3 41 | |- - - _ _ _ _ _ _ _ | ==> up three time units 42 | 43 | each time unit == either 5us or 10us 44 | 45 | 8 PWM channels in PWM pwm_arr[8]; array of pwm structs 46 | 47 | PWM => { 48 | int channel; 49 | int hi_time; //number of time units high in waveform 50 | } 51 | 52 | every 100us PRU0->PRU1 flag is checked, if it is set, hi_time is updated in all struct. 53 | global int count is maintained to count till 10. count++ every time unit. 54 | 55 | 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /src/pru-firmware/pru_firmware.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int u32; 2 | 3 | volatile register unsigned int __R30; 4 | volatile register unsigned int __R31; 5 | 6 | /* The number of PRU's that exist */ 7 | #define NUM_PRU 2 8 | #define PRU0 0 9 | #define PRU1 1 10 | 11 | /* Events list */ 12 | #define EV_PRU0_PRU1 17 13 | #define EV_PRU1_PRU0 18 14 | #define EV_PRU0_ARM 19 15 | #define EV_PRU1_ARM 20 16 | #define EV_ARM_PRU0 21 17 | #define EV_ARM_PRU1 22 18 | 19 | 20 | __far volatile char C0[0x300] __attribute__((cregister("C0", far))); 21 | 22 | #define PINTC(_reg) \ 23 | (*(volatile u32 *)((char *)&C0[_reg])) 24 | 25 | #define PINTC_SISR PINTC(0x0020) 26 | #define PINTC_SICR PINTC(0x0024) 27 | #define PINTC_SRSR0 PINTC(0x0200) 28 | #define PINTC_SRSR1 PINTC(0x0204) 29 | #define PINTC_SECR0 PINTC(0x0280) 30 | #define PINTC_SECR1 PINTC(0x0284) 31 | 32 | /* Macro to set a system event */ 33 | #define SIGNAL_EVENT(x) \ 34 | do { \ 35 | __R31 = (1 << 5) | ((x) - 16); \ 36 | } while(0); 37 | 38 | /* Macro to check a system event */ 39 | #define CHECK_EVENT(x) \ 40 | ( PINTC_SRSR0 & ( 1 << (x) ) ) 41 | 42 | /* Macro to clear a system event */ 43 | #define CLEAR_EVENT(x) \ 44 | do { \ 45 | PINTC_SICR0 = (x); \ 46 | } while(0); 47 | 48 | 49 | __far volatile char C4[0x100] __attribute__((cregister("C4", near))); /* PRUCFG */ 50 | 51 | #define PRUCFG(_reg) \ 52 | (*(volatile u32 *)((char *)&C4 + (_reg))) 53 | 54 | #define PRUCFG_SYSCFG PRUCFG(0x0004) 55 | #define SYSCFG_STANDBY_INIT (1 << 4) 56 | #define PRUCFG_ENABLE_GLOBAL PRUCFG_SYSCFG = PRUCFG_SYSCFG & (~SYSCFG_STANDBY_INIT) 57 | #define PRUCFG_DISABLE_GLOBAL PRUCFG_SYSCFG = PRUCFG_SYSCFG | SYSCFG_STANDBY_INIT 58 | 59 | 60 | __far volatile char C26[0x100] __attribute__((cregister("C26", near))); /* PRUIEP */ 61 | #define PIEP(_reg) \ 62 | (*(volatile u32 *)((char *)&C26 + (_reg))) 63 | 64 | #define PIEP_GLOBAL_CFG PIEP(0x0000) 65 | #define GLOBAL_CFG_CNT_ENABLE (1 << 0) 66 | #define GLOBAL_CFG_DEFAULT_INC_S 4 67 | #define GLOBAL_CFG_DEFAULT_INC_W 4 68 | #define GLOBAL_CFG_DEFAULT_INC_M ((GLOBAL_CFG_DEFAULT_INC_W - 1) << GLOBAL_CFG_DEFAULT_INC_S) 69 | #define GLOBAL_CFG_DEFAULT_INC(x) (((x) << GLOBAL_CFG_DEFAULT_INC_S) & GLOBAL_CFG_DEFAULT_INC_M) 70 | #define GLOBAL_CFG_CMP_INC_S 8 71 | #define GLOBAL_CFG_CMP_INC_W 12 72 | #define GLOBAL_CFG_CMP_INC_M ((GLOBAL_CFG_CMP_INC_W - 1) << GLOBAL_CFG_CMP_INC_S) 73 | #define GLOBAL_CFG_CMP_INC(x) (((x) << GLOBAL_CFG_CMP_INC_S) & GLOBAL_CFG_CMP_INC_M) 74 | 75 | #define PIEP_GLOBAL_STATUS PIEP(0x0004) 76 | #define GLOBAL_STATUS_CNT_OVF (1 << 0) 77 | 78 | #define PIEP_COMPEN PIEP(0x0008) 79 | #define PIEP_COUNT PIEP(0x000C) 80 | #define RESET_COUNTER PIEP_COUNT = 0XFFFFFFFF 81 | 82 | #define PIEP_CMP_CFG PIEP(0x0040) 83 | #define CMP_CFG_CMP0_RST_CNT_EN (1 << 0) 84 | #define CMP_CFG_CMP_EN_S 1 85 | #define CMP_CFG_CMP_EN_W 8 86 | #define CMP_CFG_CMP_EN_M ((CMP_CFG_CMP_EN_W - 1) << CMP_CFG_CMP_EN_S) 87 | #define CMP_CFG_CMP_EN(x) ((1 << ((x) + CMP_CFG_CMP_EN_S)) & CMP_CFG_CMP_EN_M) 88 | 89 | #define PIEP_CMP_STATUS PIEP(0x0044) 90 | #define CMD_STATUS_CMP_HIT_S 0 91 | #define CMD_STATUS_CMP_HIT_W 8 92 | #define CMD_STATUS_CMP_HIT_M ((CMD_STATUS_CMP_HIT_W - 1) << CMD_STATUS_CMP_HIT_S) 93 | #define CMD_STATUS_CMP_HIT(x) ((1 << ((x) + CMD_STATUS_CMP_HIT_S)) & CMD_STATUS_CMP_HIT_M) 94 | 95 | #define PIEP_CMP_CMP0 PIEP(0x0048) 96 | #define PIEP_CMP_CMP1 PIEP(0x004C) 97 | #define PIEP_CMP_CMP2 PIEP(0x0050) 98 | #define PIEP_CMP_CMP3 PIEP(0x0054) 99 | #define PIEP_CMP_CMP4 PIEP(0x0058) 100 | #define PIEP_CMP_CMP5 PIEP(0x005C) 101 | #define PIEP_CMP_CMP6 PIEP(0x0060) 102 | #define PIEP_CMP_CMP7 PIEP(0x0064) 103 | #define PIEP_CMP_CMP(x) PIEP(0x0048 + ((x) << 2)) 104 | #define RESET_ON_CMP0_EVENT 1 105 | 106 | #define false 0 107 | #define true 1 108 | 109 | #define DPRAM_SHARED 0x00010000 110 | #define DATA_SLOTS 16 111 | /* structure used to pass information pru0 <--> pru1 112 | status[i] => pru has information for it to read 113 | info[i] => the data pru has received 114 | */ 115 | struct shared_data{ 116 | int status[NUM_PRU]; /* valid info waiting for PRU x */ 117 | int info[NUM_PRU][DATA_SLOTS]; /* each PRU has DATA_SLOTS loc reserved for it */ 118 | }; 119 | 120 | typedef struct shared_data SD; 121 | 122 | SD *data_sock = (SD *)((void*)DPRAM_SHARED); 123 | 124 | /*extract a byte #pos from value */ 125 | #define GET_BYTE(val, pos) \ 126 | (((val) >> ((pos)*8)) & 0xFF) 127 | 128 | /* extract a bit #pos from a value */ 129 | #define GET_BIT(val, pos) \ 130 | (((val) >> (pos)) & 1) 131 | 132 | -------------------------------------------------------------------------------- /src/userspace_lib/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | python setup.py build 3 | 4 | install: all 5 | python setup.py install 6 | install -m 755 bs_tcp_server.py /usr/bin 7 | install -m 755 bs_shell.py /usr/bin 8 | -------------------------------------------------------------------------------- /src/userspace_lib/README.md: -------------------------------------------------------------------------------- 1 | #PRU Speak encoding 2 | 3 | > NOTE : The short forms used in this encoding doc are as follows : 4 | 5 | > C : constant (value is the constant specified) 6 | 7 | > V : variable (value is the address where variable V is located) 8 | 9 | > Arr[C] => V (since, the final value is address(Arr) + C, viz a variable). 10 | Note that V will be used instead of Arr[C] throughout the document. 11 | 12 | > Arr[V] : array indexed by variable V 13 | 14 | (I should probably write how the variable stuff work here... 15 | and also how the doc is structured) 16 | 17 | ##1. SET instruction 18 | The SET instruction is of the form 19 | 20 | ``` 21 | SET x, y 22 | ``` 23 | where **x** (operand-1) can be either **V or Arr[v]** whereas **y** (operand-2) can be either **C, V, Arr[v]**. 24 | 25 | The general function of this instruction is to set variable values. 26 | (In some cases it is also used to create variables) 27 | 28 | There are many possible ways a **SET** instruction can be used based on how we choose **x** and **y** 29 | There are three possible opcodes (as given below) that handle all conditions of x, y. 30 | 31 | > OPCODE used : 0x10 (16) to 0x12 (18) 32 | 33 | ###1.a ```SET V, C``` 34 | 35 | This is a 32 bit instruction. This instruction is the case when operand-1 is a **V or A[c]** and opernad-2 is a **constant (max 16 bit)**. 36 | 37 | **opcode** 38 | 39 | ```c 40 | 0x10 (16) 41 | ``` 42 | 43 | **operation** 44 | ``` 45 | Sets the value of variable V to the 16 bit int value C. 46 | If V has not been previously defined, it creates and assigns. 47 | ``` 48 | 49 | **encoding format** (each value separated by a comma takes one byte) 50 | ```c 51 | OPCODE, VARIABLE, CONST-hi, CONST-lo 52 | 53 | Byte3 : 0001-0000 : (OPCODE - Fixed) 54 | Byte2 : VARIABLE : (address of the variable V) 55 | Byte1 : CONST-hi : (MS-byte of constant C) 56 | Byte0 : CONST-lo : (LS-byte of constant C) 57 | 58 | ``` 59 | 60 | **Example** 61 | ``` 62 | coming soon :) 63 | ``` 64 | 65 | ###1.b ```SET V1, V2``` 66 | 67 | This is a 32 bit instruction. This instruction is the case when operand-1 and operand-2 are either **V** (or Arr[c]) 68 | 69 | **opcode** 70 | 71 | ```c 72 | 0x11 (17) 73 | ``` 74 | 75 | **operation** 76 | ``` 77 | Sets the value of variable V1 to the value of variable V2. 78 | If V1 has not been previously defined, it creates and assigns. 79 | (give some more explanation? or put that in the examples? - I think in example is better) 80 | ``` 81 | 82 | **encoding format** (each value separated by a comma takes one byte) 83 | ```c 84 | OPCODE, VARIABLE, unused, VARIABLE 85 | 86 | Byte3 : OPCODE : 0001-0001 (OPCODE - Fixed) 87 | Byte2 : VARIABLE : (address of the variable V1) 88 | Byte1 : unused : (unused) 89 | Byte0 : VARIABLE : (address of the variable V2) 90 | 91 | ``` 92 | 93 | **Example** 94 | ``` 95 | coming soon :) 96 | ``` 97 | 98 | ###1.c ```SET x, y``` 99 | 100 | This is a **64 bit** instruction. This instruction is the case when either **x** (operand-1) or **y** (operand-2) 101 | is of the form **Arr[v]**. 102 | 103 | The possible forms of instructions : 104 | ``` 105 | SET V1, Arr[V2] 106 | SET Arr[V], 280 107 | SET Arr[V1], V2 108 | SET Arr[V1], Arr[V2] 109 | ``` 110 | 111 | **opcode** 112 | 113 | ```c 114 | 0x12 (18) 115 | ``` 116 | 117 | **operation** 118 | ``` 119 | Sets the value of variable "x" to the value of "y" 120 | If "x" is a variable (not Arr[v]) and has not been previously defined, it creates and assigns. 121 | If "x" is of type Arr[v], and Arr has not been defined, it is an error. 122 | ``` 123 | 124 | **encoding format** (each value separated by a comma takes one byte) 125 | ``` 126 | OPCODE, OP_type , OP1.b, OP1.a 127 | unused, unused , OP2.b, OP2.a 128 | 129 | (OP1 : x, OP2 : y) 130 | 131 | Byte3 : OPCODE : 0001-0010 (OPCODE - Fixed) 132 | Byte2 : OP_type : (operand type - since the operands can be of any type, this indicates what the operands are) 133 | Byte1 : OP1.b : (reserved for operator 1, actual value depends on OP_decider) 134 | Byte0 : OP1.a : (reserved for operator 1, actual value depends on OP_decider) 135 | 136 | Byte4 : OP2.b : (reserved for operator 2, actual value depends on OP_decider) 137 | Byte5 : OP2.a : (reserved for operator 2, actual value depends on OP_decider) 138 | Byte6 : unused : unused 139 | Byte7 : unused : unused 140 | 141 | 142 | OP_Type (8 bits) 143 | 144 | 00 00 - 0000 145 | \ / \ / \ / 146 | x y unused 147 | 148 | bit 7,6 : type of operand x 149 | bit 5,4 : type of operand y 150 | 151 | bit encoding that indicate what the corresponding operators are : 152 | (and what they represent in the encoding in each case) 153 | 154 | 00 => C (Constant) 155 | OP.a : Const-lo 156 | OP.b : Const-hi 157 | 158 | 01 => V (Variable) 159 | OP.a : Variable address of V 160 | OP.b : unused 161 | 162 | 10 => Arr[V] 163 | OP.a : Variable address of V 164 | OP.b : Array address of Arr. 165 | 166 | (add a simple example here) 167 | ``` 168 | 169 | **Example** 170 | ``` 171 | coming soon :) 172 | ``` 173 | 174 | 175 | ##2. SET RES[] instruction 176 | 177 | This instruction is of the form 178 | ``` 179 | SET RES[x], y 180 | ``` 181 | Where **RES** is a reserved array variable such as **DIO, PWM, COM, TMR, AIO**; 182 | 183 | **x** can be either **C or V** where as **y** (operand-2) can be either **C, V, Arr[v]**. 184 | 185 | This behaves like a regular SET instruction, but has been given special opcodes as : 186 | * These instruction use reserved arrays 187 | * They are used often, so giving exclusive byte code makes execution faster on the PRU 188 | * Normally these sort of instructions will take 64bits; whereas here all take only 32bits 189 | 190 | Hence these inst are not compiled as a part of normal **SET** instruction. 191 | 192 | > OPCODE used : 0x01 (1) to 0xFF (15) 193 | 194 | ###2.a ```SET DIO[x], y``` 195 | 196 | This is a 32 bit instruction. Here **x** and **y** can be either a Constant (C) or Vriable(V). 197 | 198 | The possible forms of the instruction : 199 | 200 | ``` 201 | SET DIO[C], C 202 | SET DIO[C], V 203 | SET DIO[V], C 204 | SET DIO[V], V 205 | ``` 206 | 207 | **opcode** 208 | ```c 209 | 0x01 (01) 210 | ``` 211 | 212 | **operation** 213 | ``` 214 | Sets the specified digital output to either high or low 215 | (see more in the examples) 216 | ``` 217 | 218 | **encoding format** 219 | ``` 220 | OPCODE, OP_type, OP1, OP2 221 | 222 | Byte3 : OPCODE : 0000-0001 (OPCODE - Fixed) 223 | Byte2 : OP_type : (operand type - this indicates what type the operands are) 224 | Byte1 : OP1 : (not exactly operand1, but rather 'x' in DIO[x]) 225 | Byte0 : OP2 : (operand2, (i.e.) "y")) 226 | 227 | Note : actual value of OP1 and OP2 will depend on type of "x" and "y". 228 | and the type information is encoded in OP_type as given below. 229 | 230 | OP_type (making sense of the 8 bits) 231 | 232 | 0 0 00-0000 233 | | | \ / 234 | x y unused 235 | 236 | bit 7 - type of "x" 237 | bit 6 - type of "y" 238 | 239 | semantics 240 | 0 => type is constant C 241 | 1 => type is Variable V 242 | 243 | (add a simple example here) 244 | ``` 245 | 246 | **Example** 247 | ``` 248 | coming soon :) 249 | ``` 250 | 251 | ###2.b ```SET DIO[C], Arr[V]``` 252 | 253 | This is a 32 bit instruction. Here first operand is **DIO** indexed by a Constant (C) and the second operand is a variable indexed Array (Arr[v]). 254 | 255 | **opcode** 256 | ```c 257 | 0x02 (02) 258 | ``` 259 | 260 | **operation** 261 | ``` 262 | Sets the specified digital output to either high or low 263 | (see more in the examples) 264 | ``` 265 | 266 | **encoding format** 267 | ``` 268 | OPCODE, CONST, Arr, VARIABLE 269 | 270 | Byte3 : OPCODE : 0000-0010 (OPCODE - Fixed) 271 | Byte2 : CONST : CONSTANT value C 272 | Byte1 : Arr : Array address 273 | Byte0 : VARIABLE : address of variable V 274 | 275 | (add a simple example here) 276 | ``` 277 | 278 | **Example** 279 | ``` 280 | coming soon :) 281 | ``` 282 | 283 | ###2.c ```SET DIO[V1], Arr[V2]``` 284 | 285 | This is a 32 bit instruction. Here first operand is **DIO** indexed by a Variable (V1) and the second operand is a variable indexed Array (Arr[v2]). 286 | 287 | **opcode** 288 | ```c 289 | 0x03 (03) 290 | ``` 291 | 292 | **operation** 293 | ``` 294 | Sets the specified digital output to either high or low 295 | (see more in the examples) 296 | ``` 297 | 298 | **encoding format** 299 | ``` 300 | OPCODE, VARIABLE, Arr, VARIABLE 301 | 302 | Byte3 : OPCODE : 0000-0010 (OPCODE - Fixed) 303 | Byte2 : VARIABLE : address of variable V1 304 | Byte1 : Arr : Array address 305 | Byte0 : VARIABLE : the array index value - variable value V2 306 | 307 | (add a simple example here) 308 | ``` 309 | 310 | **Example** 311 | ``` 312 | coming soon :) 313 | ``` 314 | 315 | 316 | ###2.d ```SET PWM[x], y``` 317 | 318 | This is a 32 bit instruction. Here **x** and **y** can be either a Constant (C) or Vriable(V). 319 | 320 | The possible forms of the instruction : 321 | 322 | ``` 323 | SET PWM[C], C 324 | SET PWM[C], V 325 | SET PWM[V], C 326 | SET PWM[V], V 327 | ``` 328 | 329 | **opcode** 330 | ```c 331 | 0x04 (04) 332 | ``` 333 | 334 | **operation** 335 | ``` 336 | Sets the specified PWM output to the mentioned value 337 | (see more in the examples) 338 | ``` 339 | 340 | **encoding format** 341 | ``` 342 | Same as 2.a (change only opcode) 343 | ``` 344 | 345 | **Example** 346 | ``` 347 | coming soon :) - or see 2.a again? 348 | ``` 349 | 350 | ###2.e ```SET PWM[C], Arr[V]``` 351 | 352 | This is a 32 bit instruction. Here first operand is **DIO** indexed by a Constant (C) and the second operand is a variable indexed Array (Arr[v]). 353 | 354 | **opcode** 355 | ```c 356 | 0x05 (05) 357 | ``` 358 | 359 | **operation** 360 | ``` 361 | Sets the specified PWM output to the mentioned value 362 | (see more in the examples) 363 | ``` 364 | 365 | **encoding format** 366 | ``` 367 | same as 2.a 368 | ``` 369 | 370 | **Example** 371 | ``` 372 | coming soon :) 373 | ``` 374 | 375 | ###2.f ```SET PWM[V1], Arr[V2]``` 376 | 377 | This is a 32 bit instruction. Here first operand is **DIO** indexed by a Variable (V1) and the second operand is a variable indexed Array (Arr[v2]). 378 | 379 | **opcode** 380 | ```c 381 | 0x06 (06) 382 | ``` 383 | 384 | **operation** 385 | ``` 386 | Sets the specified PWM output to the mentioned value 387 | (see more in the examples) 388 | ``` 389 | 390 | **encoding format** 391 | ``` 392 | same as 2.a 393 | ``` 394 | 395 | **Example** 396 | ``` 397 | coming soon :) 398 | ``` 399 | 400 | ###2.x AIO, TMR, COM Instructions 401 | 402 | > Just like DIO & PWM, the above mentioned instructions have 3 opcodes for each of the following instruction type 403 | * SET RES[C], C/V 404 | * SET RES[C], Arr[V] 405 | * SET RES[V], Arr[V] 406 | 407 | **Only** things that change are the **operation** and **OPCODE**. (encoding and examples are more or less the same) 408 | 409 | ####Operation 410 | ``` 411 | AIO : Sets the value of the anolog output 412 | COM : Writes the value to the indexed com port. 413 | TMR : Sets the timer value 414 | ``` 415 | 416 | ####OPCODE 417 | ``` 418 | AIO : 0x07, 0x08, 0x09 419 | COM : 0x0A, 0x0B, 0x0C 420 | TMR : 0x0D, 0x0E, 0x0F 421 | ``` 422 | 423 | ##3. IF instruction 424 | 425 | This instruction is of the form 426 | ``` 427 | IF ( x y ) GOTO z 428 | ``` 429 | Where **x** (first operand), **y** (second operand), **z** (third operand) can be any of C, V, Arr[V]. 430 | Here is a relational operator such as '>', '<', '==', '!=' etc. 431 | 432 | There is no different cases for this instruction, rather one **64 bit** instruction which handles all possible variable types internally. 433 | 434 | **opcode** 435 | ```python 436 | The **OPCODE** starts from 0x20 (0b0010-0000) and ends at 0x2F (0b0010-1111). 437 | How this works is this instruction reserves the "0b0010-xxxx" instruction space. 438 | The last 4 bits takes its value based upon . The mapping is as shown below. 439 | 440 | cond_code = { 441 | '==' : 0b0000, 442 | '!=' : 0b0001, 443 | '>=' : 0b0010, 444 | '<=' : 0b0011, 445 | '>' : 0b0100, 446 | '<' : 0b0101 447 | } 448 | 449 | ``` 450 | 451 | **operation** 452 | ``` 453 | The comparision is carried out between "x" and "y", if the result is true, then the IP (inst pointer) jumps to the inst number specified by "x" 454 | ``` 455 | 456 | **encoding** 457 | ``` 458 | OPCODE, OP_type, OP1.b, OP1.a 459 | OP3.b , OP3.a, OP2.b, OP2.a 460 | 461 | (x : OP1, y: OP2, z : OP3) 462 | 463 | Byte3 : OPCODE : 0001-0010 (OPCODE - Fixed) 464 | Byte2 : OP_type : (operand type - since the operands can be of any type, this indicates what the operands are) 465 | Byte1 : OP1.b : (reserved for operator 1, actual value depends on OP_decider) 466 | Byte0 : OP1.a : (reserved for operator 1, actual value depends on OP_decider) 467 | 468 | Byte4 : OP2.b : (reserved for operator 2, actual value depends on OP_decider) 469 | Byte5 : OP2.a : (reserved for operator 2, actual value depends on OP_decider) 470 | Byte6 : OP3.a : (reserved for operator 3, actual value depends on OP_decider) 471 | Byte7 : OP3.b : (reserved for operator 3, actual value depends on OP_decider) 472 | 473 | Note : actual value of OP1 and OP2 will depend on type of "x" and "y". 474 | and the type information is encoded in OP_type as given below. 475 | 476 | OP_type (making sense of the 8 bits) 477 | 478 | 00 00 - 00 00 479 | \ / \ / \ /\ / 480 | x y z unused 481 | 482 | bit 7,6 : type of operand x 483 | bit 5,4 : type of operand y 484 | bit 3,2 : type of operand z 485 | 486 | bit encoding that indicate what types the corresponding operators are : 487 | (and how they are placed in the byte encoding in each case) 488 | 489 | 00 => C (Constant) 490 | OP.a : Const 491 | OP.b : unused 492 | 493 | 01 => V (Variable) 494 | OP.a : Variable address of V 495 | OP.b : unused 496 | 497 | 10 => Arr[V] 498 | OP.a : Variable address of V 499 | OP.b : Array address of Arr. 500 | 501 | (add a simple example here) 502 | ``` 503 | 504 | **Example** 505 | ``` 506 | coming soon :) 507 | ``` 508 | 509 | ##4. WAIT instruction 510 | This instruction is of the form 511 | ``` 512 | WAIT x 513 | ``` 514 | where **x** (the only operand) can be of type **C or V or Arr[v]** 515 | 516 | This is a 32 bit instruction. 517 | 518 | **opcode** 519 | ```c 520 | 0x14 (20) 521 | ``` 522 | **operation** 523 | ``` 524 | Executing this command will pause the execution of the running script for 525 | "x" mili seconds. (The wait is non blocking - more about this later) 526 | ``` 527 | **encoding** 528 | ``` 529 | OPCODE, OP_type, OP.b, OP.a 530 | 531 | since the operand can be any of three types, the OP_type will tell us the 532 | type of "x" in the instruction. 533 | 534 | The OP_type is encoded as follows 535 | 536 | 00 00 - 0000 537 | \/ \ / 538 | x unused 539 | 540 | bit value to type of OP ("x") mapping : 541 | 00 => OP is of type 'C' 542 | OP.a = Const 543 | OP.b = unused 544 | 545 | 01 => OP is of type 'V' 546 | OP.a = VARIABLE 547 | OP.b = unused 548 | 549 | 10 => OP is of type Arr[V] 550 | OP.a = VARIABLE 551 | OP.b = ARR 552 | 553 | ``` 554 | 555 | **examples** 556 | ``` 557 | coming soon :) 558 | ``` 559 | 560 | ##5. GOTO instruction 561 | This instruction is of the form 562 | ``` 563 | GOTO x 564 | ``` 565 | where **x** (the only operand) can be of type **C or V or Arr[v]** 566 | 567 | This is a 32 bit instruction. 568 | 569 | **opcode** 570 | ```c 571 | 0x15 (21) 572 | ``` 573 | **operation** 574 | ``` 575 | Executing this command will cause the IP (instruction pointer) to jump to instruction number "x" 576 | ``` 577 | **encoding** 578 | ``` 579 | OPCODE, OP_type, OP.b, OP.a 580 | 581 | since the operand can be any of three types, the OP_type will tell us the 582 | type of "x" in the instruction. 583 | 584 | The OP_type is encoded as follows 585 | 586 | 00 00 - 0000 587 | \/ \ / 588 | x unused 589 | 590 | bit value to type of OP ("x") mapping : 591 | 00 => OP is of type 'C' 592 | OP.a = Const 593 | OP.b = unused 594 | 595 | 01 => OP is of type 'V' 596 | OP.a = VARIABLE 597 | OP.b = unused 598 | 599 | 10 => OP is of type Arr[V] 600 | OP.a = VARIABLE 601 | OP.b = ARR 602 | 603 | ``` 604 | 605 | **examples** 606 | ``` 607 | coming soon :) 608 | ``` 609 | ##6. GET instruction 610 | This instruction is of the form 611 | ``` 612 | GET x 613 | ``` 614 | where **x** (the only operand) can be of type **C or V or Arr[v]** 615 | 616 | This is a 32 bit instruction. 617 | 618 | **opcode** 619 | ```c 620 | 0x16 (22) 621 | ``` 622 | **operation** 623 | ``` 624 | Executing this command will return the value of "x" 625 | ``` 626 | **encoding** 627 | ``` 628 | OPCODE, OP_type, OP.b, OP.a 629 | 630 | since the operand can be any of three types, the OP_type will tell us the 631 | type of "x" in the instruction. 632 | 633 | The OP_type is encoded as follows 634 | 635 | 00 00 - 0000 636 | \/ \ / 637 | x unused 638 | 639 | bit value to type of OP ("x") mapping : 640 | 00 => OP is of type 'C' 641 | OP.a = Const 642 | OP.b = unused 643 | 644 | 01 => OP is of type 'V' 645 | OP.a = VARIABLE 646 | OP.b = unused 647 | 648 | 10 => OP is of type Arr[V] 649 | OP.a = VARIABLE 650 | OP.b = ARR 651 | 652 | ``` 653 | 654 | **examples** 655 | ``` 656 | coming soon :) 657 | ``` 658 | 659 | ##7. ARITHMETIC and BIT instructions 660 | This instruction is of the form 661 | ``` 662 | INS x, y 663 | ``` 664 | where **INS** is a arithmetic or bitwise operation command; 665 | **x** (operand1) and **y** (operand2) can be of type **C or V or Arr[v]** 666 | 667 | There are **32 bit** and **64 bit** variations for each instruction. 668 | 669 | **opcode** 670 | > Each **INST** uses 2 opcodes (one for 32 bit encoding, another for 64 bit) based on what the **x**, **y** values are. 671 | opcode starts from 48 (0011-0000), ends at 79 (0100-1111). Bit excoding is done based on this 672 | map containing **INST** to the LS nibble value of the corresponding OPCODE. 673 | ```python 674 | opcode_dict = { 675 | #These inst own the (0011-XXXX) address space 676 | 'ADD' : 48, 677 | 'SUB' : 50, 678 | 'MUL' : 52, 679 | 'DIV' : 54, 680 | 'MOD' : 56, 681 | #These inst own the (0100-XXXX) address space 682 | 'BSL' : 64, 683 | 'BSR' : 66, 684 | 'AND' : 68, 685 | 'OR' : 70, 686 | 'NOT' : 72 687 | } 688 | ``` 689 | 690 | ###7.a ADD V, y 691 | 692 | This is a 32 bit instruction where **y** can be a variable or constant. 693 | 694 | **opcode** 695 | ```c 696 | 0x30 (48) 697 | ``` 698 | 699 | **operation** 700 | ``` 701 | Executing this command will add y to V and return the new value of V 702 | ``` 703 | 704 | **encoding** 705 | ``` 706 | OPCODE, OP_type, VARIABLE, OP 707 | 708 | Byte3 : OPCODE : 0011-0000 (OPCODE - Fixed) 709 | Byte2 : OP_type : (operand type - since the operands can be of any type, this indicates what the operands are) 710 | Byte1 : VARIABLE : (the address of variable V) 711 | Byte0 : OP : (reserved for operator 1, actual value depends on OP_decider) 712 | 713 | since the operand can be C or V, the OP_type will tell us the type of "y" in the instruction. 714 | The OP_type (8bits) is encoded as follows : 715 | 1000 - 0000 716 | | 717 | y 718 | 719 | if bit 6 == 0 720 | type(y) = C 721 | OP -> C 722 | 723 | if bit 6 == 1 724 | type(y) = VARIABLE 725 | OP -> address of variable "y" 726 | ``` 727 | 728 | **examples** 729 | ``` 730 | coming soon :) 731 | ``` 732 | 733 | ###7.b ADD x, y 734 | 735 | This is a **64 bit** instruction where either **x** or **y** is of type Arr[V] 736 | Note that **x** can't be of type C, while **y** can be of any type. 737 | 738 | **opcode** 739 | ```c 740 | 0x31 (49) 741 | ``` 742 | 743 | **operation** 744 | ``` 745 | Executing this command will add y to x and return the new value of x 746 | ``` 747 | 748 | **encoding** 749 | ``` 750 | OPCODE, OP_type , OP1.b, OP1.a 751 | unused, unused , OP2.b, OP2.a 752 | 753 | (OP1 : x, OP2 : y) 754 | 755 | Byte3 : OPCODE : 0011-0001 (OPCODE - Fixed) 756 | Byte2 : OP_type : (operand type - since the operands can be of any type, this indicates what the operands are) 757 | Byte1 : OP1.b : (reserved for operator 1, actual value depends on OP_decider) 758 | Byte0 : OP1.a : (reserved for operator 1, actual value depends on OP_decider) 759 | 760 | Byte4 : OP2.b : (reserved for operator 2, actual value depends on OP_decider) 761 | Byte5 : OP2.a : (reserved for operator 2, actual value depends on OP_decider) 762 | Byte6 : unused : unused 763 | Byte7 : unused : unused 764 | 765 | 766 | OP_Type (8 bits) 767 | 768 | 00 00 - 0000 769 | \ / \ / \ / 770 | x y unused 771 | 772 | bit 7,6 : type of operand x 773 | bit 5,4 : type of operand y 774 | 775 | bit encoding that indicate what the corresponding operators are : 776 | (and what they represent in the encoding in each case) 777 | 778 | 00 => C (Constant) 779 | OP.a : Const-lo 780 | OP.b : Const-hi 781 | 782 | 01 => V (Variable) 783 | OP.a : Variable address of V 784 | OP.b : unused 785 | 786 | 10 => Arr[V] 787 | OP.a : Variable address of V 788 | OP.b : Array address of Arr. 789 | 790 | (add a simple example here) 791 | ``` 792 | 793 | **examples** 794 | ``` 795 | coming soon :) 796 | ``` 797 | 798 | ###7.x SUB, MUL, DIV, OR, AND, BSL/R, NOT instructions 799 | 800 | These instructions are similar to **ADD** discussed above. Each have two versions - 32bit and 64 bit version. 801 | The opcode for the 32 bit version has been mentioned at the begining of section 7, the OPCODE for 64 bit is opcode for 32 bit + 1 802 | The encoding pattern is the same, only thing that changes is the pattern 803 | **operation** 804 | ``` 805 | SUB x, y : x = x - y, return x 806 | MUL x, y : x = x * y, return x 807 | DIV x, y : x = x / y, return x 808 | AND x, y : x = x & y, return x 809 | OR x, y : x = x | y, return x 810 | BSL x, y : x = x >> y, return x 811 | BSR x, y : x = x << y, return x 812 | NOT x, y : x = ~y, return x 813 | ``` 814 | 815 | ##8. HALT instruction 816 | 817 | Simple instruction with no operands 818 | 819 | **opcode** 820 | ```c 821 | 0x7F (127) 822 | ``` 823 | 824 | **operation** 825 | ``` 826 | Executing this instruction halts an ongoing BotSpeak script in the PRU. 827 | If no script is running, this instruction does nothing. 828 | ``` 829 | 830 | **encoding** 831 | ``` 832 | OPCODE, unused, unused, unused 833 | 834 | Byte3 : OPCODE : 0111-1111 (fixed) 835 | Byte2-0 : unused : unused 836 | ``` 837 | 838 | **examples** 839 | ``` 840 | coming soon 841 | ``` 842 | 843 | ##9. ABORT, DEBUG, RUN, (END)SCRIPT instructions 844 | 845 | These instructions are known as **control instructions**. They are not run on the PRU, rather are interpreted on the Linux side. (userspace python lib for now, may later be moved to the kernel) 846 | 847 | **opcode** 848 | ```c 849 | None - it is not compiled, 850 | rather the compiler framework itself interprets the cmd and does the needful. 851 | ``` 852 | 853 | **operation** 854 | ``` 855 | ABORT : kills the current script, all variables and arrays defined are freed. 856 | DEBUG : streams the PRU Speak variables and state to the userspace. 857 | SCRIPT : marks the starting of a script. 858 | ENDSCRIPT : marks the ending of a script. 859 | RUN : runs the most recently defined script. 860 | ``` 861 | 862 | **encoding** 863 | ``` 864 | NO enccoding 865 | ``` 866 | 867 | **examples** 868 | ``` 869 | coming soon 870 | ``` 871 | 872 | -------------------------------------------------------------------------------- /src/userspace_lib/bs_fifo.py: -------------------------------------------------------------------------------- 1 | from pru_speak import pru_speak 2 | import os.path 3 | import os 4 | 5 | PATH = "/dev/pruspeak" 6 | 7 | if os.path.exists(PATH): 8 | os.remove(PATH) 9 | 10 | os.mkfifo(PATH) 11 | f_read = open(PATH, "r") 12 | 13 | while True: 14 | #blocking wait for data from client 15 | bs_code = f_read.read() 16 | 17 | if not bs_code: 18 | continue 19 | 20 | try: 21 | ret = pru_speak.execute_instruction(bs_code) 22 | print ret 23 | #move this to 'cat' implementation later on. may need another thread for this. 24 | 25 | except Exception as e: 26 | print e 27 | 28 | 29 | f_read.close() 30 | os.remove(PATH) 31 | 32 | -------------------------------------------------------------------------------- /src/userspace_lib/bs_shell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #This is a shell to use pruspeak 3 | 4 | from pru_speak import pru_speak 5 | import sys 6 | out = sys.stdout 7 | sentinel = '' 8 | def get_data(): 9 | out.write("ps>") #prompt the user 10 | l = [] 11 | try: 12 | for line in iter(raw_input, sentinel): 13 | l.append(line) #get the input 14 | out.write("...") 15 | except KeyboardInterrupt as e: 16 | print "Closing terminal" 17 | return -1 18 | 19 | except EOFError as e: 20 | print "Closing terminal" 21 | return -1 22 | 23 | return '\n'.join(l) #return the data entered 24 | 25 | 26 | while True: 27 | code = get_data() 28 | if (code == -1) or (code == 'exit'): 29 | exit() 30 | 31 | if code == '': 32 | continue 33 | 34 | try: 35 | ret = pru_speak.execute_instruction(code) 36 | print ret 37 | except Exception as e: 38 | print e 39 | 40 | -------------------------------------------------------------------------------- /src/userspace_lib/bs_tcp_client.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import sys 3 | out = sys.stdout 4 | sentinel = '' 5 | 6 | TCP_IP = '127.0.0.1' 7 | TCP_PORT = 6060 8 | BUFFER_SIZE = 1024 * 2 9 | 10 | def get_data(): 11 | out.write("ps>") #prompt the user 12 | l = [] 13 | 14 | for line in iter(raw_input, sentinel): 15 | l.append(line) #get the input 16 | out.write("...") 17 | 18 | return '\n'.join(l) #return the data entered 19 | 20 | 21 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 22 | s.connect((TCP_IP, TCP_PORT)) 23 | 24 | while 1: 25 | try: 26 | msg = get_data() 27 | print "sending message\n", msg, "\n" 28 | s.send(msg) 29 | data = s.recv(BUFFER_SIZE) 30 | if data != '\n': 31 | print "return value:", data 32 | 33 | except Exception as e: 34 | print e 35 | print "Ending Connection" 36 | s.close() 37 | break 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/userspace_lib/bs_tcp_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from pru_speak import pru_speak 3 | import socket 4 | #Server on local host @ port 6060 5 | TCP_IP = '127.0.0.1' 6 | TCP_PORT = 6060 7 | 8 | #The max size upto which is recieved at one go 9 | BUFFER_SIZE = 1024 * 2 10 | 11 | #create a passive socket and bind it to 127.0.0.1:6060 12 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 13 | s.bind((TCP_IP, TCP_PORT)) 14 | 15 | #Take max of one connection 16 | s.listen(1) 17 | print "PRU Speak server at ", TCP_IP + ":" + str(TCP_PORT) 18 | 19 | #connection is a one time affair - handles only one client 20 | conn, addr = s.accept() 21 | print 'Connection address:', addr 22 | 23 | while True: 24 | try: 25 | #blocking wait for data from client 26 | bs_code = conn.recv(BUFFER_SIZE) 27 | print "recieved : \n", bs_code, "\n" 28 | 29 | if (not bs_code) or (bs_code == 'EXIT'): 30 | break #send empty data to shutdown server 31 | 32 | try: 33 | ret = pru_speak.execute_instruction(bs_code) 34 | print "Return value : ", ret 35 | if ret == []: 36 | #no return value 37 | conn.send('\n') 38 | else: 39 | #the sends the list of ret values as a string sperated by " " 40 | conn.send(" ".join(map(str, ret)) + "\n") 41 | 42 | except Exception as e: 43 | print e 44 | 45 | 46 | except Exception as e: 47 | print "error : ", e 48 | break 49 | 50 | conn.close() 51 | -------------------------------------------------------------------------------- /src/userspace_lib/example_code.py: -------------------------------------------------------------------------------- 1 | from pru_speak import pru_speak 2 | 3 | #set pin 0 [pru0_r30_0] high for two second 4 | EX1 = '''\ 5 | SET var1, 1 6 | SET DIO[0], var1 7 | ''' 8 | 9 | EX2 = '''\ 10 | SCRIPT 11 | SET DIO[0], 1 12 | WAIT 1000 13 | SET DIO[0], 0 14 | WAIT 1000 15 | GOTO 0 16 | ENDSCRIPT 17 | RUN 18 | ''' 19 | #triangle wave of frequence 0.5Hz 20 | EX3 = '''\ 21 | SCRIPT 22 | SET var1, 0 23 | SET PWM[0], var1 24 | WAIT 30 25 | ADD var1, 1 26 | IF (var1 < 100) GOTO 1 27 | SET PWM[0], var1 28 | WAIT 30 29 | SUB var1, 1 30 | IF (var1 > 0) GOTO 5 31 | IF (1 > 0) GOTO 0 32 | ENDSCRIPT 33 | RUN 34 | ''' 35 | 36 | ret = pru_speak.execute_instruction(EX3) 37 | print ret 38 | 39 | while True: 40 | pass 41 | 42 | -------------------------------------------------------------------------------- /src/userspace_lib/legacy_code/bs_client.py: -------------------------------------------------------------------------------- 1 | import pru_speak 2 | import socket 3 | import sys 4 | out = sys.stdout 5 | sentinel = '' 6 | 7 | TCP_IP = '127.0.0.1' 8 | TCP_PORT = 6060 9 | BUFFER_SIZE = pru_speak.PAGE_SIZE * 2 10 | 11 | def get_data(): 12 | out.write("ps>") #prompt the user 13 | l = [] 14 | 15 | for line in iter(raw_input, sentinel): 16 | l.append(line) #get the input 17 | out.write("...") 18 | 19 | return '\n'.join(l) #return the data entered 20 | 21 | 22 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 23 | s.connect((TCP_IP, TCP_PORT)) 24 | 25 | while 1: 26 | try: 27 | msg = get_data() 28 | print "sending message\n", msg, "\n" 29 | s.send(msg) 30 | data = s.recv(BUFFER_SIZE) 31 | print "received data:", data 32 | 33 | except Exception as e: 34 | print e 35 | print "Ending Connection" 36 | s.close() 37 | break 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/userspace_lib/legacy_code/bs_server.py: -------------------------------------------------------------------------------- 1 | import pru_speak 2 | import socket 3 | 4 | def handle_data(bs_code): 5 | ''' 6 | handles the BS commands which are part of the incoming packet 7 | seperately takes care of single instructions and scripts 8 | bs_code (str) : TCP packet data. The code block with BS instructions seperated by new lines. 9 | ''' 10 | #print "bs_code.strip() " , bs_code.strip() 11 | bs_code = bs_code.strip().split("\n") 12 | bs_code = map(str.strip, bs_code) 13 | print "bs_code \n", bs_code 14 | # change logic either here or in compiler.py to make 15 | # all this more clean and efficient. but this is ok for now. 16 | 17 | if "SCRIPT" in bs_code: 18 | #download and keep the script 19 | start = bs_code.index("SCRIPT") 20 | try: 21 | end = bs_code.index("ENDSCRIPT") 22 | #get the script postion 23 | script_list = bs_code[start+1 : end] 24 | #remove it out of the original list of inst. 25 | bs_code = bs_code[:start] + bs_code[end+1 :] 26 | 27 | pru_speak.SCRIPT_CODE = '\n'.join(script_list) 28 | print "SCRIPT loaded\n", pru_speak.SCRIPT_CODE + "\n ENDSCRIPT \n" 29 | except Exception as e: 30 | print "ENDSCRIPT NOT FOUND" 31 | return -1 #ENDSCRIPT not found - syntax error 32 | 33 | for inst in bs_code : 34 | if inst == "RUN": #have to move run to PRU, why simply put it here? 35 | if pru_speak.SCRIPT_CODE : 36 | #maybe abort the previous script before this? 37 | pru_speak.load(pru_speak.SCRIPT_CODE, trigger = True) 38 | else : 39 | return -1 40 | else : 41 | pru_speak.single_instruction(inst) 42 | 43 | return 1 44 | 45 | #Server on local host @ port 6060 46 | TCP_IP = '127.0.0.1' 47 | TCP_PORT = 6060 48 | 49 | #The max size upto which is recieved at one go 50 | BUFFER_SIZE = pru_speak.PAGE_SIZE * 2 # Normally 1024, but we want fast response 51 | 52 | #create a passive socket and bind it to 127.0.0.1:6060 53 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 54 | s.bind((TCP_IP, TCP_PORT)) 55 | 56 | #Take max of one connection 57 | s.listen(1) 58 | print "PRU Speak server at ", TCP_IP + ":" + str(TCP_PORT) 59 | 60 | #connection is a one time affair - handles only one client 61 | conn, addr = s.accept() 62 | print 'Connection address:', addr 63 | 64 | while 1: 65 | try: 66 | #blocking wait for data from client 67 | bs_code = conn.recv(BUFFER_SIZE) 68 | print "recieved\n", bs_code, "\n" 69 | #print type(bs_code) 70 | if not bs_code: break #why did I keep this? would I ever want to break out of the loop? 71 | 72 | #have to take care of return values later! 73 | if handle_data(bs_code) == 1: #does all the single_instruction, load, execute etc 74 | conn.send('ok\n') 75 | print "ok" 76 | else: 77 | conn.send('syntax error') 78 | print "syntax error" 79 | 80 | except Exception as e: 81 | print "error : ", e 82 | break 83 | 84 | conn.close() 85 | 86 | -------------------------------------------------------------------------------- /src/userspace_lib/legacy_code/client.py: -------------------------------------------------------------------------------- 1 | import pru_speak 2 | #import compiler 3 | 4 | botspeak_code = \ 5 | ''' SET DIO[4], 1 6 | WAIT 1000 7 | SET DIO[4], 0 8 | WAIT 1000 9 | GOTO 0''' 10 | 11 | #print map(lambda x : hex(x), compiler.compile(botspeak_code)) 12 | pru_speak.load(botspeak_code) 13 | pru_speak.execute() 14 | pru_speak.single_instruction("SET DIO[0], 1") 15 | -------------------------------------------------------------------------------- /src/userspace_lib/legacy_code/compiler.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | def f_set(cmd): 5 | ''' 6 | as of now only handles DIO, should let is handle PWM etc 7 | ''' 8 | def f_dio(pin, state): 9 | ''' 10 | function handler for DIO. takes state (int) and pin (int) 11 | ''' 12 | op = 0x01000000 13 | 14 | if pin > 16: 15 | raise Exception #bad hack 16 | 17 | op += pin 18 | 19 | if state: 20 | op = op | 0x80 21 | return op 22 | 23 | 24 | args = cmd[1].split(',') 25 | op_code = re.match('(DIO)\[(.)*\]' , args[0]) 26 | 27 | if (op_code.group(1) == 'DIO') : 28 | return f_dio(int(op_code.group(2)), int(args[1])) 29 | 30 | 31 | def f_wait(cmd): 32 | ''' 33 | return the wait time 34 | ''' 35 | op = 0x02000000 36 | op += int(cmd[1]) 37 | return op 38 | 39 | def f_goto(cmd): 40 | ''' 41 | jump to address 42 | ''' 43 | op = 0x03000000 44 | op += int(cmd[1]) 45 | return op 46 | 47 | CMD = { 48 | 'SET' : f_set, 49 | 'WAIT' : f_wait, 50 | 'GOTO' : f_goto 51 | # 'LABEL' : f_label 52 | } 53 | 54 | def compile(code): 55 | ''' 56 | takes in the code block, returns a list of BotSpeak bytecode 57 | code (str) : the code block with BS instructions seperated by new lines 58 | ''' 59 | code = code.strip() 60 | #print "pgm :", pgm 61 | pgm = code.split('\n') 62 | byte_code = [] 63 | 64 | for inst in pgm: 65 | inst = inst.strip() 66 | cmd = re.split('\s+', inst, 1) #max of one split 67 | print cmd 68 | byte_code.append( CMD[ cmd[0] ](cmd) ) 69 | #cmd[0] contains the actual command eg: SET, WAIT, GOTO 70 | #cmd[1] contains rest of the args eg : "DIO[1] , 0" 71 | 72 | return byte_code 73 | 74 | if __name__ == '__main__': 75 | s = ''' SET DIO[0] , 1 76 | WAIT 1 77 | SET DIO[0], 0 78 | WAIT 1 79 | GOTO 0''' 80 | 81 | l = compile(s) 82 | print map( lambda x : hex(x), l) 83 | 84 | 85 | -------------------------------------------------------------------------------- /src/userspace_lib/legacy_code/fifo_server.py: -------------------------------------------------------------------------------- 1 | import pru_speak 2 | import os 3 | 4 | script = False 5 | pru_speak.SCRIPT_CODE = '' 6 | def handle_inst_fifo(bs_code): 7 | ''' 8 | handles the BS command that comes in one by one. 9 | maintains state in case of SCRIPT 10 | ''' 11 | global script 12 | bs_code = bs_code.strip() #only single BS inst 13 | print "bs_code : ", bs_code 14 | 15 | if bs_code == "ENDSCRIPT": 16 | if not script: #endscript without a startscript? 17 | return 0 #some problem 18 | script = False 19 | 20 | elif bs_code == "SCRIPT": 21 | if script: #startscript in a script 22 | return 0 23 | script = True 24 | 25 | elif script: 26 | pru_speak.SCRIPT_CODE += '\n' + bs_code 27 | 28 | elif bs_code == "RUN": 29 | if pru_speak.SCRIPT_CODE : 30 | print "running script :" 31 | print pru_speak.SCRIPT_CODE 32 | pru_speak.load(pru_speak.SCRIPT_CODE, trigger = True) 33 | else : 34 | return 0 35 | 36 | else :#normal single inst execution 37 | pru_speak.single_instruction(bs_code) 38 | 39 | return 1 40 | 41 | os.mkfifo("/dev/pruspeak") 42 | f_read = open("/dev/pruspeak", "r") 43 | 44 | while 1: 45 | #blocking wait for data from client 46 | while 1: 47 | bs_code = f_read.read() 48 | if bs_code: 49 | print "handle_inst_fifo return value : ", handle_inst_fifo(bs_code) 50 | 51 | 52 | f_read.close() 53 | 54 | -------------------------------------------------------------------------------- /src/userspace_lib/legacy_code/pru_speak.py: -------------------------------------------------------------------------------- 1 | from mmap import mmap 2 | from compiler import compile 3 | import time, struct 4 | 5 | PAGE_SIZE = 4096 6 | HOME = "/sys/devices/ocp.3/4a300000.prurproc/" 7 | INIT_FILE = HOME + "pru_speak_shm_init" 8 | EXEC_FILE = HOME + "pru_speak_execute" 9 | SINGLE_INST = HOME + "pru_speak_single_cmd" 10 | MEM_OFF = None 11 | SCRIPT_CODE = None #string variable. Contains the BS code for a script 12 | #this is loaded into the PRU on RUNSCRIPT command 13 | 14 | def _mem_init( ): 15 | #read the starting address (physical) of shared memory, also pass it on to the PRU (via downcall) 16 | global MEM_OFF 17 | with open(INIT_FILE) as f: 18 | MEM_OFF = int(f.read(), 16) 19 | 20 | 21 | def load(code, trigger=False): 22 | ''' 23 | loads the BotSpeak code into memory. Internally calls the compile module. 24 | ''' 25 | #if the shared memory is not initialized 26 | if not MEM_OFF: 27 | _mem_init() 28 | 29 | #open /dev/mem and mmap it to access the physical memory through our virtual space. 30 | with open("/dev/mem", "r+b" ) as f: 31 | 32 | mem = mmap(f.fileno(), PAGE_SIZE, offset=MEM_OFF) 33 | #var mem contains the map if successful 34 | 35 | byte_code = compile(code) 36 | code_offset = 0 37 | 38 | #write every 32 bit byte code into the shared memory 39 | for inst in byte_code: 40 | mem[code_offset : code_offset + 4] = struct.pack("=' 38 | 'LTE', # '<=' 39 | 'GT', # '>' 40 | 'LT', # '<' 41 | 'EQ', # '==' 42 | 'NEQ', # '!=' 43 | ] + reserved 44 | 45 | t_GTE = r'>=' 46 | t_LTE = r'<=' 47 | t_GT = r'>' 48 | t_LT = r'<' 49 | t_EQ = r'==' 50 | t_NEQ = r'!=' 51 | t_ignore = ' \t' 52 | t_ignore_comment = r';.*$' 53 | 54 | literals = '[](),' 55 | 56 | def t_HEX_INT(t): 57 | '0x[0-9a-fA-F]+' 58 | t.type = 'INT' 59 | value = t.value[2:].replace("_", "") 60 | t.value = int(value, 16) 61 | return t 62 | 63 | def t_INT(t): 64 | '\d+' 65 | t.value = int(t.value) 66 | return t 67 | 68 | def t_VAR(t): 69 | r'[a-zA-Z_][a-zA-Z_0-9]*' 70 | if t.value in reserved: 71 | #eg t.value == 'SET' 72 | t.type = t.value 73 | #then change the token to 'SET' 74 | return t 75 | 76 | def t_error(t): 77 | print "Illegal character '%s'" % t.value[0] 78 | 79 | lexer = lex.lex() 80 | data = '''SET DIO[myvar], 1''' 81 | lexer.input(data) 82 | 83 | if __name__ == '__main__': 84 | for tok in lexer: 85 | print tok 86 | 87 | -------------------------------------------------------------------------------- /src/userspace_lib/pru_speak/bs_parse.py: -------------------------------------------------------------------------------- 1 | ## This is the parser cum code generator module for PRU Speak 2 | ## The only thing exposed from this module is the parser object 3 | ## The parser object takes in a BS instruction and returns the bytecode encoding 4 | ## If there is an error (syntax or semantic); None is returned; in the future throw custom Exception 5 | 6 | import ply.yacc as yacc 7 | from bs_lex import * 8 | from node import * 9 | 10 | #**********INCASE opcodes get over, we can compress a few later*************** 11 | 12 | #keeps track of next available memory offset to place a variable 13 | pru_var_count = 0 14 | #max variable slots 15 | PRU_VAR_AREA = 239 16 | 17 | #size of each inst in the script 18 | #used by GOTO to find exact location to jump to 19 | script_inst_size = [] 20 | #e.g. [1,1,1,2,2,2,2] 21 | 22 | #Are the incoming instruction parts of scripts? 23 | script_mode = False 24 | 25 | #does the variable to memory mapping work 26 | pru_vars = { 27 | #e.g. "var1" : 0x02, 28 | } 29 | 30 | #does the array to (address, size) mapping. 31 | pru_arrs = { 32 | #e.g. "arr1" : (0x10, 5) 33 | #start, size 34 | 'DIO' : (240, 16), 35 | 'AIO' : (248, 8) 36 | } 37 | 38 | def BYTE(val, n): 39 | ''' 40 | makes value 'val' the 'n'th byte in return value 41 | e.g. BYTE(0x13, 3) will return a number with 0x13 as the 3rd byte 42 | here pos will be from 0 to 3 43 | ''' 44 | return val << (n*8) 45 | 46 | def SET_BIT(val, n): 47 | ''' 48 | returns val with the Nth bit set high 49 | ''' 50 | return val | (1 << n) 51 | 52 | def CLEAR_BIT(val, n): 53 | ''' 54 | returns val with the Nth bit set low 55 | ''' 56 | return val & ~(1 << n) 57 | 58 | def pack_byte(b3, b2, b1, b0): 59 | ''' 60 | takes 4 bytes and packs it into an integer 61 | ''' 62 | if len (filter(lambda x : x < 256, (b3, b2, b1, b0))) < 4: 63 | print "error - param > 256 ", b3,b2,b1,b0 64 | return 0 65 | 66 | return b3 << 3*8 | b2 << 2*8 | b1 << 1*8 | b0 67 | 68 | def get_var(val): 69 | ''' 70 | takes a val object, value is a var or arr[const] 71 | returns the value 72 | ''' 73 | if val.arr_const: 74 | #val1 is an const indexed array 75 | 76 | #check out of bounds 77 | arr, size = pru_arrs[val.val[0]] 78 | size -= 1 79 | index = val.val[1] 80 | if(index < size): 81 | return pru_arrs[val.val[0]][0] + index + 1 82 | else: 83 | print "array out of bounds" 84 | return -1 #throw exception later 85 | else: 86 | #val1 is an VAR 87 | #return pru_vars[val.val] 88 | global pru_var_count 89 | val_index = pru_vars.get(val.val, None) 90 | if val_index == None: 91 | pru_vars[val.val] = pru_var_count 92 | val_index = pru_var_count 93 | pru_var_count += 1 94 | return val_index 95 | 96 | 97 | def byte_code_set_r(val1, val2): 98 | ''' 99 | encodes instructions of the form SET DIO[a], arr[b]; 100 | where DIO can replaced by PWM, TMR, AI etc 101 | ''' 102 | #opcodes used 1-15 103 | OPCODE_SET = { 104 | 'DIO' : 0x01, 105 | 'PWM' : 0x04, 106 | 'AIO' : 0x07, 107 | 'TONE' : 0x0A, 108 | 'TMR' : 0x0D #till 0x0F 109 | } 110 | 111 | OPCODE = OPCODE_SET[val1.val[0]] #byte3 112 | byte0 = 0 113 | byte1 = 0 114 | byte2 = 0 115 | 116 | #x == val1.val[1] (val1.val[0] = 'DIO' ) 117 | #y == val2.val 118 | if val2.arr_var: 119 | #SET DIO[x], y; where x is C/V 120 | #and y is an variable indexed array value. 121 | 122 | if not val1.arr_var: 123 | #x is a constant 124 | OPCODE += 1 125 | else : 126 | #x is a variable 127 | OPCODE += 2 128 | 129 | byte2 = pru_vars.get(val1.val[1], val1.val[1]) 130 | #if x is a const, it is returned; else value of variable in pru_vars is returned 131 | 132 | byte1 = pru_arrs[val2.val[0]][0] 133 | #gets the address where pru mem is located 134 | 135 | byte0 = pru_vars[val2.val[1]] 136 | 137 | else: 138 | #SET DIO[x], y; where x is C/V 139 | #and y is C/V/arr[const_val] 140 | 141 | if val1.arr_var: 142 | #implies x is an V 143 | byte2 |= 1<<7 144 | 145 | if val2.type == 'VAR' or val2.type == 'ARR': 146 | #implies y is a V 147 | byte2 |= 1<<6 148 | 149 | byte1 = pru_vars.get(val1.val[1], val1.val[1]) 150 | #if x is a const, it is returned; else value of variable in pru_vars is returned 151 | 152 | if val2.type == 'INT': 153 | #y is an constant 154 | byte0 = val2.val 155 | 156 | else : 157 | #y is V or Arr[c] 158 | byte0 = get_var(val2) 159 | if byte0 == -1: 160 | return 0 161 | 162 | #pack all the bytes 163 | return pack_byte(OPCODE, byte2, byte1, byte0) 164 | 165 | print OPCODE, byte2, byte1, byte0 #packed_bytes 166 | 167 | 168 | def byte_code_set(val1, val2): 169 | ''' 170 | encodes instruction of the form SET val1, val2 171 | val1 is V/Arr ; val2 can be C/V/Arr(with const or var index) 172 | ''' 173 | global pru_var_count 174 | #opcodes used 16, 17, 18 -19 is reserved, just incase for future 175 | OPCODE = 0x10 176 | byte0, byte1, byte2 = 0, 0, 0 177 | byte4, byte5, byte6, byte7 = 0, 0, 0, 0 178 | 179 | if val1.arr_var or val2.arr_var: 180 | #it is a 64 bit instruction 181 | #SET x, y; x or y or both are of form 'Arr[var]' 182 | OPCODE += 2 183 | 184 | if val1.arr_var: 185 | #x is an arr[var], y can be anything 186 | byte0 = pru_vars[val1.val[1]] 187 | byte1 = pru_arrs[val1.val[0]][0] 188 | byte2 |= 0b10 << 6 189 | 190 | if val2.type == 'INT': 191 | #y is a Const 192 | byte2 |= 0b00 << 4 193 | byte4 = val2.val & 0xFF 194 | byte5 = (val2.val >> 8) & 0xFF 195 | 196 | elif val2.any_var: 197 | #y is a var 198 | byte2 |= 0b01 << 4 199 | byte4 = get_var(val2) 200 | if byte4 == -1: 201 | return 0 202 | 203 | else: 204 | #y is arr[var] 205 | byte2 |= 0b10 <<4 206 | byte4 = pru_vars[val2.val[1]] #var 207 | byte5 = pru_arrs[val2.val[0]][0] #arr 208 | 209 | else: 210 | #y is arr[var], x is var/arr[const] 211 | if val1.any_var: 212 | byte2 |= 0b01 << 4 213 | 214 | if val1.type == 'INT': 215 | #error 216 | return 0 217 | 218 | if val1.arr_const: 219 | #val1 is an const indexed array 220 | byte0 = get_var(val1) 221 | else: 222 | #val1 is an VAR 223 | byte0 = pru_vars.get(val1.val, None) 224 | if byte0 == None: 225 | pru_vars[val1.val] = pru_var_count 226 | byte0 = pru_var_count 227 | pru_var_count += 1 228 | 229 | byte2 |= 0b10 << 4 230 | byte4 = pru_vars[val2.val[1]] 231 | byte5 = pru_arrs[val2.val[0]][0] 232 | 233 | return pack_byte(OPCODE, byte2, byte1, byte0), pack_byte(byte7, byte6, byte5, byte4) 234 | else: 235 | #32 bit inst SET x, y 236 | #x is var or arr[const]; occupies byte2 237 | 238 | if val1.arr_const: 239 | #val1 is an const indexed array 240 | byte2 = get_var(val1) 241 | if byte2 == -1: 242 | return 0 243 | else: 244 | #val1 is an VAR 245 | byte2 = pru_vars.get(val1.val, None) 246 | if byte2 == None: 247 | pru_vars[val1.val] = pru_var_count 248 | byte2 = pru_var_count 249 | pru_var_count += 1 250 | 251 | if val2.type == "INT": 252 | #type1 : SET x, y; y is a constant 253 | byte0 = val2.val & 0xFF #low 8 bits 254 | byte1 = (val2.val >> 8) & 0xFF #high 8 bits 255 | 256 | else: 257 | #type2 : SET x, y; y is a variable 258 | OPCODE += 1 259 | byte0 = get_var(val2) 260 | 261 | #return the byte encoded information 262 | return pack_byte(OPCODE, byte2, byte1, byte0) 263 | 264 | #redunt - could be useful for debugging 265 | byte3 = OPCODE 266 | print byte3, byte2, byte1, byte0 267 | print byte7, byte6, byte5, byte4 268 | 269 | 270 | def byte_code_dec_array(name, val): 271 | ''' 272 | declare an array : SET arr[], 5 273 | creates array arr, 6 elements in length 274 | arr[0] to arr[4] maps to arr[1] to arr[5] in the PRU 275 | arr[0] contains the len of accessible array, i.e. 5 276 | ''' 277 | #opcode 19 278 | OPCODE = 19 279 | byte2 = 0 280 | byte1 = pru_arrs[name][0] 281 | 282 | if val.type == 'INT': 283 | byte2 = 0 284 | byte0 = val.val 285 | 286 | elif val.any_var: 287 | byte2 = 1 << 7 288 | byte0 = get_var(val) 289 | if byte0 == -1: 290 | return 0 291 | 292 | else: 293 | return 0 294 | 295 | return pack_byte(OPCODE, byte2, byte1, byte0) 296 | 297 | 298 | def byte_code_single_op(cmd, val): 299 | ''' 300 | single operand instructions 301 | e.g. WAIT, GOTO, GET 302 | ''' 303 | #opcode 20-22 304 | opcode_dict = { 305 | 'WAIT' : 20, 306 | 'GOTO' : 21, 307 | 'GET' : 22 308 | } 309 | OPCODE = opcode_dict[cmd] 310 | byte2, byte1, byte0 = 0, 0, 0 311 | 312 | #incase wait or goto 313 | if OPCODE < 22 and not script_mode: 314 | return 0 #these inst only make sense in a script 315 | 316 | if val.type == 'INT': 317 | #case1 INT 318 | byte2 = 0 319 | if OPCODE == 21: 320 | #special case for goto 321 | val.val = sum(script_inst_size[:val.val]) 322 | 323 | else: 324 | byte0 = val.val & 0xFF #lower 8 bits 325 | byte1 = (val.val >> 8) & 0xFF #higher 8 bits 326 | 327 | 328 | 329 | elif val.any_var: 330 | #Var or Arr[Var] 331 | byte2 = 0b01 << 6 332 | byte0 = get_var(val) 333 | if byte0 == -1: return 0 334 | 335 | else: 336 | byte2 = 0b10 << 6 337 | byte0 = pru_vars[val.val[1]] 338 | byte1 = pru_arrs[val.val[0]][0] 339 | 340 | byte3 = OPCODE 341 | return pack_byte(OPCODE, byte2, byte1, byte0) 342 | print byte3, byte2, byte1, byte0 343 | 344 | 345 | def byte_code_if(val1, val2, cond, goto): 346 | ''' 347 | IF (val1 cond val2) GOTO goto 348 | val1, val2, goto can be any val type 349 | ''' 350 | #opcode starts with 32 351 | 352 | if not script_mode: 353 | return 0 354 | 355 | #This inst owns the (0010-XXXX) address space 356 | #0000 : == 357 | #0001 : != 358 | #0010 : >= 359 | #0011 : <= 360 | #0100 : < 361 | #0101 : > 362 | cond_code = { 363 | '==' : 0b0000, 364 | '!=' : 0b0001, 365 | '>=' : 0b0010, 366 | '<=' : 0b0011, 367 | '>' : 0b0100, 368 | '<' : 0b0101 369 | } 370 | OPCODE = 0b0010 << 4 371 | OPCODE |= cond_code[cond] 372 | 373 | byte2, byte1, byte0 = 0, 0, 0 374 | byte7, byte6, byte5, byte4 = 0, 0, 0, 0 375 | 376 | #******************val1********************** 377 | if val1.type == 'INT': 378 | #val one is a const 379 | #print "val1 : INT" 380 | byte2 |= 0b00 << 6 381 | byte0 = val1.val 382 | 383 | elif val1.any_var: 384 | #val will be a variable; either V or Arr[C] 385 | #print "val1 : VAR" 386 | byte2 |= 0b01 << 6 387 | byte0 = get_var(val1) 388 | if byte0 == -1: return 0 389 | 390 | 391 | else: 392 | #val is Ar[V] 393 | #print "val1 : VAR ARR" 394 | byte2 |= 0b10 <<6 395 | byte0 = pru_vars[val1.val[1]] 396 | byte1 = pru_arrs[val1.val[0]][0] 397 | 398 | #******************val2********************** 399 | if val2.type == 'INT': 400 | #val one is a const 401 | #print "val2 : INT" 402 | byte2 |= 0b00 << 4 403 | byte4 = val2.val 404 | 405 | elif val2.any_var: 406 | #val will be a variable; either V or Arr[C] 407 | #print "val2 : VAR" 408 | byte2 |= 0b01 << 4 409 | byte4 = get_var(val2) 410 | if byte4 == -1: return 0 411 | 412 | 413 | else: 414 | #val is Ar[V] 415 | #print "val2 : VAR ARR" 416 | byte2 |= 0b10 << 4 417 | byte4 = pru_vars[val2.val[1]] 418 | byte5 = pru_arrs[val2.val[0]][0] 419 | 420 | #******************goto********************** 421 | if goto.type == 'INT': 422 | #val one is a const 423 | #print "goto : INT" 424 | byte2 |= 0b00 << 2 425 | byte6 = goto.val 426 | 427 | elif goto.any_var: 428 | #val will be a variable; either V or Arr[C] 429 | #print "goto : VAR" 430 | byte2 |= 0b01 << 2 431 | byte6 = get_var(goto) 432 | if byte6 == -1: return 0 433 | 434 | 435 | else: 436 | #val is Ar[V] 437 | #print "goto : VAR ARR" 438 | byte2 |= 0b10 << 2 439 | byte6 = pru_vars[goto.val[1]] 440 | byte7 = pru_arrs[goto.val[0]][0] 441 | 442 | 443 | return pack_byte(OPCODE, byte2, byte1, byte0), pack_byte(byte7, byte6, byte5, byte4) 444 | 445 | #just in case - debugging 446 | byte3 = OPCODE 447 | print byte3, byte2, byte1, byte0 448 | print byte7, byte6, byte5, byte4 449 | 450 | 451 | def byte_code_arithmetic(cmd, val1, val2): 452 | ''' 453 | generates code for two operand arithmetic instructions 454 | AND, SUB, MUL, DIV, MOD 455 | BSR, BSL, AND, OR, NOT 456 | ''' 457 | #opcode starts from 48 (11-0000), ends at 79(100-1111) 458 | 459 | opcode_dict = { 460 | #These inst own the (0011-XXXX) address space 461 | 'ADD' : 48, 462 | 'SUB' : 50, 463 | 'MUL' : 52, 464 | 'DIV' : 54, 465 | 'MOD' : 56, 466 | 467 | #These inst own the (0100-XXXX) address space 468 | 'BSL' : 64, 469 | 'BSR' : 66, 470 | 'AND' : 68, 471 | 'OR' : 70, 472 | 'NOT' : 72 473 | } 474 | 475 | OPCODE = opcode_dict[cmd] 476 | #ADD x, y 477 | #x, y : INT, VAR, ARR[Var] 478 | 479 | byte3, byte2, byte1, byte0 = 0,0,0,0 480 | byte7, byte6, byte5, byte4 = 0,0,0,0 481 | 482 | if val1.arr_var or val2.arr_var: 483 | #64 bit inst 484 | OPCODE +=1 485 | 486 | if val1.arr_var: 487 | #val1 is of type Arr[var] 488 | print "val1 : ARR_VAR" 489 | byte2 |= 0b10 << 6 490 | byte0 = pru_vars[val1.val[1]] 491 | byte1 = pru_arrs[val1.val[0]][0] 492 | 493 | if val2.type == 'INT': 494 | #val2 is a const 495 | print "val2 : INT" 496 | byte2 |= 0b00 << 4 497 | byte0 = val2.val 498 | 499 | elif val2.any_var: 500 | #val will be a variable; either V or Arr[C] 501 | print "val2 : VAR" 502 | byte2 |= 0b01 << 4 503 | byte4 = get_var(val2) 504 | if byte4 == -1: return 0 505 | 506 | 507 | else : 508 | #val2 Arr[var] 509 | print "val2 : ARR_VAR" 510 | byte2 |= 0b10 << 4 511 | byte4 = pru_vars[val2.val[1]] 512 | byte5 = pru_arrs[val2.val[0]][0] 513 | 514 | else: 515 | #val1 is not arr[var]; val2 is. 516 | if val1.type == 'INT': 517 | #val one is a const 518 | print "val1 : INT" 519 | byte2 |= 0b00 << 6 520 | byte0 = val1.val 521 | 522 | else: 523 | #val is a var 524 | print "val1 : VAR" 525 | byte2 |= 0b01 <<6 526 | byte0 = get_var(val1) 527 | if byte0 == -1: return 0 528 | 529 | #val2 stuff 530 | byte2 |= 0b10 << 4 531 | byte4 = pru_vars[val2.val[1]] 532 | byte5 = pru_arrs[val2.val[0]][0] 533 | 534 | #return 64bit encoded inst 535 | return pack_byte(OPCODE, byte2, byte1, byte0), pack_byte(byte7, byte6, byte5, byte4) 536 | 537 | else: 538 | #32 bit instr 539 | #x, y : V/C 540 | 541 | #***********val1************ 542 | if val1.type == 'INT': 543 | #val one is a const 544 | #print "val1 : INT" 545 | byte2 |= 0b00 << 7 546 | byte1 = val1.val 547 | 548 | else: 549 | #val will be a variable; either V or Arr[C] 550 | #print "val1 : VAR" 551 | byte2 |= 0b01 << 7 552 | byte1 = get_var(val1) 553 | if byte1 == -1: return 0 554 | 555 | #***********val2************ 556 | if val2.type == 'INT': 557 | #val one is a const 558 | #print "val2 : INT" 559 | byte2 |= 0b00 << 6 560 | byte0 = val2.val 561 | 562 | else: 563 | #val will be a variable; either V or Arr[C] 564 | #print "val1 : VAR" 565 | byte2 |= 0b01 << 6 566 | byte0 = get_var(val2) 567 | if byte0 == -1: return 0 568 | 569 | #return 32bit encoded instruction 570 | return pack_byte(OPCODE, byte2, byte1, byte0) 571 | 572 | #debugging 573 | byte3= OPCODE 574 | print byte3, byte2, byte1, byte0 575 | print byte7, byte6, byte5, byte4 576 | 577 | #control variables (like pre processor stuff or rather compiler directives, 578 | #not to be compiled: (END)SCRIPT, RUN, ABORT, DEBUG, RESET - run by python compiler module 579 | 580 | def byte_code_ctrl(val): 581 | ''' 582 | stuff like SCRIPT, ENDSCRIPT, 583 | RUN, ABORT, DEBUG, SYSTEM etc. 584 | ''' 585 | return val 586 | 587 | """ 588 | Grammar for the parser : 589 | 590 | inst : SET val , val 591 | | GET val 592 | | IF ( val cond val ) GOTO val 593 | | WAIT val 594 | | GOTO val 595 | | ADD val , val 596 | | SUB val , val 597 | | MUL val , val 598 | | DIV val , val 599 | | MOD val, val 600 | | BSR val, val 601 | | BSL val, val 602 | | OR val, val 603 | | AND val, val 604 | | NOT val, val 605 | | LBL VAR 606 | | SCRIPT 607 | | ENDSCRIPT 608 | | RUN 609 | | HALT 610 | | DEBUG 611 | 612 | val : INT 613 | | VAR 614 | | arr 615 | 616 | arr : VAR [ INT ] 617 | | VAR [ VAR ] 618 | 619 | cond : GTE 620 | | LTE 621 | | GT 622 | | LT 623 | | EQ 624 | | NEQ 625 | """ 626 | 627 | def p_inst_SET(p): 628 | '''inst : SET val ',' val 629 | | SET VAR '[' ']' ',' val''' 630 | 631 | global pru_var_count 632 | if len(p) == 7: 633 | #array declaration case 634 | print "Array declaration" 635 | arr = p[2] 636 | size = p[6].val 637 | if arr in pru_arrs: 638 | print "Arr already defined" 639 | if (pru_var_count + size + 1) > PRU_VAR_AREA: 640 | print "No space for Arr" 641 | else : 642 | #everything is okay 643 | pru_arrs[arr] = (pru_var_count, size+1) 644 | pru_var_count += size + 1 645 | 646 | print "pru_arrs : ", pru_arrs 647 | 648 | p[0] = byte_code_dec_array(arr, p[6]) 649 | 650 | else: 651 | #print "SET command -", " val1 : ", p[2], " val2 : " , p[4] 652 | if p[2].flag: 653 | #it is of type SET DIO[x] , y 654 | p[0] = byte_code_set_r( p[2], p[4]) 655 | else : 656 | p[0] = byte_code_set(p[2], p[4]) 657 | 658 | def p_inst_LBL(p): 659 | '''inst : LBL VAR''' 660 | global pru_var_count 661 | byte2 = pru_vars.get(p[2], None) 662 | if byte2 == None: 663 | pru_vars[p[2]] = pru_var_count 664 | byte2 = pru_var_count 665 | pru_var_count += 1 666 | p[0] = pack_byte(0x10, byte2, 0, 0) 667 | 668 | def add_label(byte_code, index): 669 | return (byte_code & 0xFFFF0000) | (index & 0xFFFF) 670 | 671 | def p_inst_WAIT(p): 672 | '''inst : WAIT val''' 673 | #print "WAIT command - val :", p[2] 674 | p[0] = byte_code_single_op(p[1], p[2]) 675 | 676 | def p_inst_GOTO(p): 677 | '''inst : GOTO val''' 678 | #print "GOTO command - val :", p[2] 679 | p[0] = byte_code_single_op(p[1], p[2]) 680 | 681 | def p_inst_GET(p): 682 | '''inst : GET val''' 683 | #print "GET command - val :", p[2] 684 | p[0] = byte_code_single_op(p[1], p[2]) 685 | 686 | def p_inst_IF(p): 687 | '''inst : IF '(' val cond val ')' GOTO val''' 688 | #print "IF command - ", "val1 :", p[3], "val2 :", p[5], "cond :", p[4], "GOTO :", p[8] 689 | p[0] = byte_code_if(p[3], p[5], p[4], p[8]) 690 | 691 | def p_inst_ADD(p): 692 | '''inst : ADD val ',' val''' 693 | #print "ADD command -", " val1 : ", p[2], " val2 : " , p[4] 694 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 695 | 696 | def p_inst_SUB(p): 697 | '''inst : SUB val ',' val''' 698 | #print "SUB command -", " val1 : ", p[2], " val2 : " , p[4] 699 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 700 | 701 | def p_inst_MUL(p): 702 | '''inst : MUL val ',' val''' 703 | #print "MUL command -", " val1 : ", p[2], " val2 : " , p[4] 704 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 705 | 706 | def p_inst_DIV(p): 707 | '''inst : DIV val ',' val''' 708 | #print "DIV command -", " val1 : ", p[2], " val2 : " , p[4] 709 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 710 | 711 | def p_inst_MOD(p): 712 | '''inst : MOD val ',' val''' 713 | #print "MOD command -", " val1 : ", p[2], " val2 : " , p[4] 714 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 715 | 716 | def p_inst_AND(p): 717 | '''inst : AND val ',' val''' 718 | #print "AND command -", " val1 : ", p[2], " val2 : " , p[4] 719 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 720 | 721 | def p_inst_OR(p): 722 | '''inst : OR val ',' val''' 723 | #print "OR command -", " val1 : ", p[2], " val2 : " , p[4] 724 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 725 | 726 | def p_inst_BSR(p): 727 | '''inst : BSR val ',' val''' 728 | #print "SUB command -", " val1 : ", p[2], " val2 : " , p[4] 729 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 730 | 731 | def p_inst_BSL(p): 732 | '''inst : BSL val ',' val''' 733 | #print "SUB command -", " val1 : ", p[2], " val2 : " , p[4] 734 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 735 | 736 | def p_inst_NOT(p): 737 | '''inst : NOT val ',' val''' 738 | #print "NOT command -", " val1 : ", p[2], " val2 : " , p[4] 739 | p[0] = byte_code_arithmetic(p[1], p[2], p[4]) 740 | 741 | def p_inst_HALT(p): 742 | '''inst : HALT''' 743 | p[0] = 0x7F000000 744 | 745 | def p_val_INT(p): 746 | '''val : INT''' 747 | #print p[1] 748 | p[0] = Value('INT', p[1]) 749 | 750 | def p_val_VAR(p): 751 | '''val : VAR''' 752 | p[0] = Value('VAR', p[1]) 753 | 754 | def p_val_arr(p): 755 | '''val : arr''' 756 | p[0] = p[1] 757 | 758 | def p_arr_VAR1(p): 759 | """arr : VAR '[' INT ']' """ 760 | flag = p[1] in R_VAR 761 | #should I convert it into a var and send it from here itself? No - how to handle DIO, PWM etc? 762 | p[0] = Value("ARR", (p[1], p[3]), flag) 763 | 764 | 765 | def p_arr_VAR2(p): 766 | """arr : VAR '[' VAR ']' """ 767 | flag = p[1] in R_VAR 768 | p[0] = Value("ARR", (p[1], p[3]), flag) 769 | 770 | def p_cond_ops(p): 771 | '''cond : GTE 772 | | LTE 773 | | GT 774 | | LT 775 | | EQ 776 | | NEQ''' 777 | p[0] = p[1] 778 | 779 | 780 | #control instructions 781 | def p_inst_SCRIPT(p): 782 | '''inst : SCRIPT''' 783 | p[0] = byte_code_ctrl(p[1]) 784 | 785 | def p_inst_ENDSCRIPT(p): 786 | '''inst : ENDSCRIPT''' 787 | p[0] = byte_code_ctrl(p[1]) 788 | 789 | def p_inst_RUN(p): 790 | '''inst : RUN''' 791 | p[0] = byte_code_ctrl(p[1]) 792 | 793 | def p_inst_DEBUG(p): 794 | '''inst : DEBUG''' 795 | p[0] = byte_code_ctrl(p[1]) 796 | 797 | def p_inst_ABORT(p): 798 | '''inst : ABORT''' 799 | p[0] = byte_code_ctrl(p[1]) 800 | 801 | def p_inst_SYSTEM(p): 802 | '''inst : SYSTEM''' 803 | p[0] = byte_code_ctrl(p[1]) 804 | 805 | # Error rule for syntax errors 806 | def p_error(p): 807 | if p != None: 808 | print p 809 | print "Syntax error in input!" 810 | 811 | 812 | # Build the parser 813 | parser = yacc.yacc() 814 | 815 | if __name__ == '__main__': 816 | s = [ 817 | 'SET DIO[var2], 1', 818 | 'IF (arr1[var2] > var3) GOTO arr2[3]' , 819 | 'ADD var1, 5', 820 | 'SUB arr1[4], arr2[var3]', 821 | 'GOTO 4', 822 | 'IF ( arr1[var1] < arr1[var2] ) GOTO arr2[var3]', 823 | 'SCRIPT', 824 | 'ENDSCRIPT', 825 | 'GOTO arr1[4]' 826 | ] 827 | try : 828 | print parser.parse("SET var1, 4") 829 | #print pru_var_count 830 | print parser.parse("GET DIO[0]") 831 | #print pru_var_count 832 | print parser.parse("SET var1, DIO[0]") 833 | except Exception as e: 834 | print "some error" 835 | print e.args 836 | ''' 837 | for inst in s : 838 | print inst 839 | res = parser.parse(inst) 840 | print res 841 | print '' 842 | ''' 843 | -------------------------------------------------------------------------------- /src/userspace_lib/pru_speak/kernel_lib.py: -------------------------------------------------------------------------------- 1 | from mmap import mmap 2 | import time, struct 3 | 4 | PAGE_SIZE = 4096 5 | HOME = "/sys/class/misc/pru_speak/" 6 | INIT_FILE = HOME + "pru_speak_shm_init" 7 | EXEC_FILE = HOME + "pru_speak_execute" 8 | SINGLE_INST = HOME + "pru_speak_single_cmd" 9 | SINGLE_INST_64 = HOME + "pru_speak_single_cmd_64" 10 | ABORT = HOME + "pru_speak_abort" 11 | DEBUG = HOME + "pru_speak_debug" 12 | STATUS = HOME + "pru_speak_status" 13 | CODE_MEM_OFF = 0 14 | RET_MEM_OFF = 0 #base address for ret value shm 15 | ret_counter = 1 #like a top of stack pointer 16 | 17 | def _mem_init( ): 18 | #read the starting address (physical) of shared memory, also pass it on to the PRU (via downcall) 19 | global CODE_MEM_OFF, RET_MEM_OFF 20 | 21 | with open(INIT_FILE) as f: 22 | code, ret = f.read().split(',') 23 | CODE_MEM_OFF = int(code, 16) 24 | RET_MEM_OFF = int(ret, 16) 25 | 26 | 27 | def load(byte_code, trigger=False): 28 | ''' 29 | loads the BotSpeak *bytecode* code into memory. 30 | byte_code is list of BS *bytecode* instructions 31 | ''' 32 | #if the shared memory is not initialized 33 | if not (CODE_MEM_OFF and RET_MEM_OFF): 34 | _mem_init() 35 | 36 | #open /dev/mem and mmap it to access the physical memory through our virtual space. 37 | with open("/dev/mem", "r+b" ) as f: 38 | 39 | code_shm = mmap(f.fileno(), PAGE_SIZE, offset=CODE_MEM_OFF) 40 | #var mem contains the map if successful 41 | 42 | code_offset = 0 43 | 44 | #write every 32 bit byte-code into the shared memory 45 | for inst in byte_code: 46 | code_shm[code_offset : code_offset + 4] = struct.pack(" arr1[var3]) GOTO arr1[var3] 159 | ENDSCRIPT 160 | RUN 161 | ''' 162 | res = pruspeak.execute_instruction(["SET var1, 50","SET var2, 150","GET var1","GET var2", "GET var2", "GET var2", "GET var2"]) 163 | print res 164 | -------------------------------------------------------------------------------- /src/userspace_lib/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup 4 | 5 | setup(name='pru_speak', 6 | version='0.0', 7 | description='BotSpeak interpreter for BeagleBone Black PRU-ICSS', 8 | install_requires=['ply'], 9 | author='Deepak Karki', 10 | author_email='deepak6k@gmail.com', 11 | url='https://github.com/deepakkarki/pruspeak', 12 | packages=['pru_speak'] 13 | ) 14 | -------------------------------------------------------------------------------- /src/userspace_lib/test_funcs.py: -------------------------------------------------------------------------------- 1 | AND_SCRIPT = '''\ 2 | SCRIPT 3 | SET i, 0xAA 4 | SET j, 0xF0 5 | AND i, j 6 | GET i 7 | ENDSCRIPT 8 | RUN 9 | ''' 10 | 11 | SCRIPT = '''\ 12 | SET delay, 500 13 | SET loop, flash 14 | SCRIPT 15 | GOTO loop 16 | 17 | LBL flash 18 | SET DIO[4], 1 19 | WAIT delay 20 | SET DIO[4], 0 21 | WAIT delay 22 | GOTO 0 23 | 24 | LBL flash2 25 | SET DIO[4], 1 26 | WAIT delay 27 | SET DIO[4], 0 28 | WAIT delay 29 | SET DIO[4], 1 30 | WAIT delay 31 | SET DIO[4], 0 32 | WAIT delay 33 | WAIT delay 34 | GOTO 0 35 | 36 | ENDSCRIPT 37 | RUN 38 | ''' 39 | 40 | RUN_FLASH = '''\ 41 | SET delay, 100 42 | SET loop, flash 43 | ''' 44 | 45 | RUN_DOUBLE_FLASH = '''\ 46 | SET loop, flash2 47 | ''' 48 | 49 | from pru_speak import pru_speak 50 | import time 51 | 52 | print "Performing AND operation" 53 | ret = pru_speak.execute_instruction(AND_SCRIPT) 54 | print ret 55 | time.sleep(5) 56 | 57 | print "Starting flashing LED" 58 | ret = pru_speak.execute_instruction(SCRIPT) 59 | print ret 60 | time.sleep(5) 61 | 62 | print "Speeding up flashing LED" 63 | ret = pru_speak.execute_instruction(RUN_FLASH) 64 | print ret 65 | time.sleep(5) 66 | 67 | print "Switching to double-flash" 68 | ret = pru_speak.execute_instruction(RUN_DOUBLE_FLASH) 69 | print ret --------------------------------------------------------------------------------