diff --git a/Dockerfile b/Dockerfile index af84c4d64aab1451224c234bc01ff92bfe15fe82..370950521074232b0e8ef1c7144b64bb20b47f03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,7 @@ FROM python:3.9-alpine as sphinx-build-env RUN apk update RUN python -m pip install --upgrade pip RUN pip install -U sphinx +RUN pip install -U sphinx-design RUN pip install sphinxcontrib-svg2pdfconverter RUN apk add librsvg RUN pip install sphinx_rtd_theme diff --git a/beaglebone-cookbook/index.rst b/beaglebone-cookbook/index.rst index 6192126bff250278716438a6a608c8c192998275..f8f394aeb8c0637aba811b634770c95607c4ea28 100644 --- a/beaglebone-cookbook/index.rst +++ b/beaglebone-cookbook/index.rst @@ -1,4 +1,4 @@ -.. _beaglebone-cookbook-home: +.. _bone-cook-book-home: BeagleBone Cookbook ####################### diff --git a/conf.py b/conf.py index 9d653802b5b7cc0a8fef39fbc171748c2db6c077..b60c51e29f5b66628aa71fea34079b82e6586297 100644 --- a/conf.py +++ b/conf.py @@ -25,7 +25,7 @@ author = 'BeagleBoard.org Foundation' # -- General configuration --------------------------------------------------- extensions = [ - "sphinxcontrib.rsvgconverter", + "sphinxcontrib.rsvgconverter", "sphinx_design" ] templates_path = ['_templates'] diff --git a/index.rst b/index.rst index 8d96344e287eb13ebc8d0cdb6071eb410247f67d..3d9e4de14601ffdfb1666eef43a835d87f2830a1 100644 --- a/index.rst +++ b/index.rst @@ -40,6 +40,7 @@ Sections :caption: Books beaglebone-cookbook/index.rst + pru-cookbook/index.rst Indices and tables ############################ diff --git a/pru-cookbook/01case/case.rst b/pru-cookbook/01case/case.rst new file mode 100644 index 0000000000000000000000000000000000000000..61e21f02af4e43aa6f5691f02119de6370621fa9 --- /dev/null +++ b/pru-cookbook/01case/case.rst @@ -0,0 +1,1122 @@ +.. _pru-cookbook-case: + +Case Studies - Introduction +############################# + +It's an exciting time to be making projects that use embedded processors. +Make:'s `Makers' Guide to Boards <https://makezine.com/comparison/boards/>`_ shows +many of the options that are available and groups them into different types. +*Single board computers* (SBCs) generally run Linux on some sort of `ARM <https://www.arm.com/>`_ +processor. Examples are the BeagleBoard and the Raspberry Pi. Another type +is the *microcontroller*, of which the `Arduino <https://www.arduino.cc/>`_ is +popular. + +The SBCs are used because they have an operating system to manage files, I/O, +and schedule when things are run, all while possibly talking to the Internet. +Microcontrollers shine when things +being interfaced require careful timing and can't afford to have an OS preempt an +operation. + +But what if you have a project that needs the flexibility of an OS and the timing +of a microcontroller? This is where the BeagleBoard excels since it has both +an ARM procssor running Linux and two footnote:[Four if you are on the BeagleBone AI]; +**P**rogrammable **R**eal-Time **U**nits (PRUs). +The PRUs have 32-bit cores which run +independently of the ARM processor, therefore they can +be programmed to respond quickly to inputs and produce very precisely timed +outputs. + +There are many :ref:`Projects <pru-cookbook-projects>`_ that use the PRU. +They are able to do things that can't be done with just a SBC or just a microcontroller. +Here we present some case studies that give a high-level view of using the PRUs. In later +chapters you will see the details of how they work. + +Here we present: + +.. TODO Switch from LEDscape to FPP + +* `Robotics Control Library <http://strawsondesign.com/docs/roboticscape/>`_ +* `BeagleLogic <https://github.com/abhishek-kakkar/BeagleLogic/wiki>`_ +* `NeoPixels -- 5050 RGB LEDs with Integrated Drivers (Falcon Christmas) <http://falconchristmas.com>`_ +* `RGB LED Matrix (Falcon Christmas) <http://falconchristmas.com>`_ +* `simpPRU -- A python-like language for programming the PRUs`_ <https://github.com/VedantParanjape/simpPRU> +.. * `MachineKit <http://www.machinekit.io/>`_ +.. * `ArduPilot <http://ardupilot.org/>, <http://ardupilot.org/dev/docs/beaglepilot.html>`_ +.. * `BeagleScope <https://github.com/ZeekHuge/BeagleScope>`_ + +The following are resources used in this chapter. + +.. admonition:: Resources + + * `Pocket Beagle System Reference Manual https://github.com/beagleboard/pocketbeagle/wiki/System-Reference-Manual#673_PRUICSS_Pin_Access`_ + * `BeagleBone Black P8 Header Table https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP8HeaderTable.pdf`_ + * `BeagleBone Black P9 Header Table https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP9HeaderTable.pdf`_ + * `BeagleBone AI System Reference Manual https://github.com/beagleboard/beaglebone-ai/wiki/System-Reference-Manual`_ + + +Robotics Control Library +------------------------- + +Robotics is an embedded application that often requires both an SBC to control the +high-level tasks (such as path planning, line following, communicating with the user) +*and* a microcontroller to handle the low-level tasks (such as telling motors how fast +to turn, or how to balance in response to an IMU input). The +`EduMIP <https://www.ucsdrobotics.org/edumip>`_ balancing +`robot <https://www.hackster.io/edumip/edumip-13a29c>`_ +demonstrates that by using the PRU, the Blue can handle both the high +and low -level tasks without an additional microcontroller. The EduMIP is shown +in :ref:`<case_blue>`. + +.. _case_blue: + +Blue balancing +~~~~~~~~~~~~~~~ + +.. figure:: figures/blue.png + :align: center + :alt: Blue balancing + +The `Robotics Control Library <http://strawsondesign.com/docs/roboticscape/>`_ is a +package that is already installed on the Beagle +that contains a C library and example/testing programs. It uses the PRU to extend the +real-time hardware of the Bone by adding eight addional servo channels and one +addition real-time encoder input. + +The following examples show how easy it is to use the PRU for robotics. + +Controlling Eight Servos +************************* + +Problem +~~~~~~~~ + +You need to control eight servos, but the Bone doesn't have enough pulse width +modulation (PWM) channels +and you don't want to add hardware. + +Solution +~~~~~~~~~ + +The Robotics Control Library provides eight additional PWM channels +via the PRU that can be used out of the box. + +.. note:: + The I/O pins on the Beagles have a mutliplexer that lets you select what I/O + appears on a given pin. The Blue has the mux already configured to to run these + examples. Follow the instructions in + :ref:`../03details/details.html#details_configure_servos, Configuring Pins for Controlling Servos` + to configure the pins for the Black and the Pocket. + + +.. * TODO - verify these commands + +Just run: + +.. code-block:: bash + + bone$ sudo rc_test_servos -f 10 -p 1.5 + +The ``-f 10`` says to use a frequency of 10 Hz and the ``-p 1.5`` says to set the position to ``1.5``. The range of positions is +``-1.5`` to ``1.5``. Run ``rc_test_servos -h`` to see all the options. + +.. code-block:: bash + + bone$ rc_test_servos -h + + Options + -c {channel} Specify one channel from 1-8. + Otherwise all channels will be driven equally + -f {hz} Specify pulse frequency, otherwise 50hz is used + -p {position} Drive servo to a position between -1.5 & 1.5 + -w {width_us} Send pulse width in microseconds (us) + -s {limit} Sweep servo back/forth between +- limit + Limit can be between 0 & 1.5 + -r {ch} Use DSM radio channel {ch} to control servo + -h Print this help messege + + sample use to center servo channel 1: + rc_test_servo -c 1 -p 0.0 + +Discussion +~~~~~~~~~~~ + +The BeagleBone Blue sends these eight outputs to it's servo channels. The others use the pins shown in the +:ref:`case__register_to_pin_table`. + +.. _case__register_to_pin_table: + +PRU register to pin table +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-----------+--------+---------+----------+-------+ + |PRU pin |Blue pin|Black pin|Pocket pin|AI pin | + +===========+========+=========+==========+=======+ + |pru1_r30_8 |1 |P8_27 |P2.35 | | + +-----------+--------+---------+----------+-------+ + |pru1_r30_10|2 |P8_28 |P1.35 |P9_42 | + +-----------+--------+---------+----------+-------+ + |pru1_r30_9 |3 |P8_29 |P1.02 |P8_14 | + +-----------+--------+---------+----------+-------+ + |pru1_r30_11|4 |P8_30 |P1.04 |P9_27 | + +-----------+--------+---------+----------+-------+ + |pru1_r30_6 |5 |P8_39 | |P8_19 | + +-----------+--------+---------+----------+-------+ + |pru1_r30_7 |6 |P8_40 | |P8_13 | + +-----------+--------+---------+----------+-------+ + |pru1_r30_4 |7 |P8_41 | | | + +-----------+--------+---------+----------+-------+ + |pru1_r30_5 |8 |P8_42 | |P8_18 | + +-----------+--------+---------+----------+-------+ + + +You can find these details in the +`P8 Header Table <https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP8HeaderTable.pdf>`_, +`P9 Header Table <https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP9HeaderTable.pdf>`_, +`Pocket Beagle System Reference Manual <https://github.com/beagleboard/pocketbeagle/wiki/System-Reference-Manual#673_PRUICSS_Pin_Access>`_ +(Here is a more usable version of the `table <https://docs.google.com/spreadsheets/d/1FRGvYOyW1RiNSEVprvstfJAVeapnASgDXHtxeDOjgqw/edit?usp=sharing>`_.) +and +`BeagleBone AI System Reference Manual <https://github.com/beagleboard/beaglebone-ai/wiki/System-Reference-Manual>`_. +(Here is a more usable version of the `table <https://docs.google.com/spreadsheets/d/1dFSBVem86vAUD7MLXvqdS-N0Efi8_g_O1iTqzql8DAo/edit#gid=0>`_.) + + +Be default the PRUs are already loaded with the code needed to run the +servos. All you have to do is run the command. + +.. [/opt/source/Robotics_Cape_Installer/pru_firmware/src/pru1-servo.asm] + +Controlling Individual Servos +****************************** + +Problem +~~~~~~~~~ + +``rc_test_servos`` is nice, but I need to control the servos individually. + +Solution +~~~~~~~~~ + +You can modify ``rc_test_servos.c``. You'll find it on the bone online at +https://github.com/beagleboard/librobotcontrol/blob/master/examples/src/rc_test_servos.c. + +Just past line 250 you'll find a ``while`` loop that has calls to ``rc_servo_send_pulse_normalized(ch,servo_pos)`` and +``rc_servo_send_pulse_us(ch, width_us)``. The first call sets the pulse width relative to the pulse period; the other +sets the width to an absolute time. Use whichever works for you. + +Controlling More Than Eight Channels +************************************* + +Problem +~~~~~~~~~~ + +I need more than eight PWM channels, or I need less jitter on the off time. + +Solution +~~~~~~~~~~ + +This is a more advanced problem and required reprograming the PRUs. See +:ref:`../05blocks/blocks.html#blocks_pwm, PWM Generator` for an example. + +Reading Hardware Encoders +************************** + +Problem +~~~~~~~~~~ + +I want to use four encoders to measure four motors, but I only see hardware for three. + +Solution +~~~~~~~~~~ + +The forth encoder can be implemented on the PRU. If you run ``rc_test_encoders_eqep`` on the Blue, you will see the output of +encoders E1-E3 which are connected to the eEQP hardware. + +.. code-block:: bash + + bone$ *rc_test_encoders_eqep* + + Raw encoder positions + E1 | E2 | E3 | + 0 | 0 | 0 |^C + +You can also access these hardware encoders on the Black and Pocket using the +pins shown in :ref:`case_pin_mapping`. + +.. _case_pin_mapping: + +eQEP to pin mapping +~~~~~~~~~~~~~~~~~~~~ +.. table:: + + +----+--------+-----------+-----------+--------+--------+------------+-------------+ + |eQEP|Blue pin|Black pin A|Black pin B|AI pin A|AI pin B|Pocket pin A|Pocket pin B | + +====+========+===========+===========+========+========+============+=============+ + |0 |E1 |P9_42B |P9_27 | | |P1.31 |P2.24 | + +----+--------+-----------+-----------+--------+--------+------------+-------------+ + |1 |E2 |P8_35 |P8_33 |P8_35 |P8_33 |P2.10 | | + +----+--------+-----------+-----------+--------+--------+------------+-------------+ + |2 |E3 |P8_12 |P8_11 |P8_12 |P8_11 |P2.24 |P2.33 | + +----+--------+-----------+-----------+--------+--------+------------+-------------+ + |2 | |P8_41 |P8_42 |P9_19 |P9_41 | | | + +----+--------+-----------+-----------+--------+--------+------------+-------------+ + | |E4 |P8_16 |P8_15 | | |P2.09 |P2.18 | + +----+--------+-----------+-----------+--------+--------+------------+-------------+ + |3 | | | |P8_25 |P8_24 | | | + +----+--------+-----------+-----------+--------+--------+------------+-------------+ + |3 | | | |P9_42 |P9_27 | | | + +----+--------+-----------+-----------+--------+--------+------------+-------------+ + +.. note:: + + The I/O pins on the Beagles have a mutliplexer that lets you select what I/O + appears on a given pin. The Blue has the mux already configured to to run these + examples. Follow the instructions in + :ref:`../03details/details.html#details_configure_encoders, Configuring Pins for Controlling Encoders` + to configure the pins for the Black and the Pocket. + + +Reading PRU Encoder +********************* + +Problem +~~~~~~~~ + +I want to access the PRU encoder. + +Solution +~~~~~~~~~ + +The forth encoder is implemented on the PRU and accessed with `sudo rc_test_encoders_pru` +.. note:: + This command needs root permission, so the `sudo` is needed. + +Here's what you will see + +.. code-block:: bash + + bone$ *sudo rc_test_encoders_pru* + [sudo] password for debian: + + Raw encoder position + E4 | + 0 |^C + +.. note:: + + If you aren't running the Blue you will have to configure the pins as shown + in the note above. + + +BeagleLogic -- a 14-channel Logic Analyzer +------------------------------------------- + +Problem +******** + +I need a 100Msps, 14-channel logic analyzer + +Solution +********* + +`BeagleLogic <https://beaglelogic.readthedocs.io/en/latest/>`_ is a 100Msps, +14-channel logic analyzer that runs on the Beagle. + +.. admonition:: information + + BeagleLogic turns your BeagleBone [Black] into a 14-channel, 100Msps Logic + Analyzer. Once loaded, it presents itself as a character device node */dev/beaglelogic*. + The core of the logic analyzer is the 'beaglelogic' kernel module that + reserves memory for and drives the two Programmable Real-Time Units + (PRU) via the remoteproc interface wherein the PRU directly writes logic + samples to the System Memory (DDR RAM) at the configured sample rate + one-shot or continuously without intervention from the ARM core. + + https://github.com/abhishek-kakkar/BeagleLogic/wiki + + +The quickest solution is to get the `no-setup-required image <https://github.com/abhishek-kakkar/BeagleLogic/wiki/BeagleLogic-%22no-setup-required%22-setup:-Introducing-System-Image!>`_. It points to an older image +(beaglelogic-stretch-2017-07-13-4gb.img.xz) but should still work. + +If you want to be running a newer image, there are instructions on the site for `installing BeagleLogic <https://beaglelogic.readthedocs.io/en/latest/install.html>`_, but I had to do the additional steps in :ref:`case_installing_beaglelogic`. + +.. TODO - Recheck + +.. _case_installing_beaglelogic: + +Installing BeagleLogic +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + + bone$ *git clone https://github.com/abhishek-kakkar/BeagleLogic* + bone$ *cd BeagleLogic/kernel* + bone$ *mv beaglelogic-00A0.dts beaglelogic-00A0.dts.orig* + bone$ *wget https://gist.githubusercontent.com/abhishek-kakkar/0761ef7b10822cff4b3efd194837f49c/raw/eb2cf6cfb59ff5ccb1710dcd7d4a40cc01cfc050/beaglelogic-00A0.dts* + bone$ *make overlay* + bone$ *sudo cp beaglelogic-00A0.dtbo /lib/firmware/* + bone$ *sudo update-initramfs -u -k \`uname -r`* + bone$ *sudo reboot* + +Once the Bone has rebooted, browse to 192.168.7.2:4000 where you'll see +:ref:`case_beaglelogic_capture`. Here you can easily select the sample +rate, number of samples, and which pins to sample. +Then click *Begin Capture* to capture your data, at up to 100 MHz! + +.. _case_beaglelogic_capture: + +BeagleLogic Data Capture +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/beaglelogic_capture.png + :align: center + :alt: BeagleLogic Data Capture + + +Discussion +************ + +BeagleLogic is a complete system that includes firmware for the PRUs, +a kernel module and a web interface that create a powerful 100 MHz +logic analyzer on the Bone with no additional hardware needed. + +.. tip:: + + If you need buffered inputs, consider + http://standalone.beaglelogic.net/en/latest/[BeagleLogic Standalone], + a turnkey Logic Analyzer built on top of BeagleLogic. + + +The kernel interface makes it easy to control the PRUs through the +command line. For example + +.. code-block:: bash + + bone$ *dd if=/dev/beaglelogic of=mydump bs=1M count=1* + +will capture a binary dump from the PRUs. The sample rate and number of +bits per sample can be controlled through ``/sys/``. + +.. code-block:: bash + + bone$ *cd /sys/devices/virtual/misc/beaglelogic* + bone$ *ls* + buffers filltestpattern power state uevent + bufunitsize lasterror samplerate subsystem + dev memalloc sampleunit triggerflags + bone$ *cat samplerate* + 1000 + bone$ *cat sampleunit* + 8bit + +You can set the sample rate by simply writing to ``samplerate``. + +.. code-block:: bash + + bone$ *echo 100000000 > samplerate* + +`sysfs attributes Reference <https://beaglelogic.readthedocs.io/en/latest/sysfs_attributes.html>`_ +has more details on configuring via sysfs. + +If you run ``dmesg -Hw`` in another window you can see when a capture +is started and stopped. + +.. code-block:: bash + + bone$ *dmesg -Hw* + [Jul25 08:46] misc beaglelogic: capture started with sample rate=100000000 Hz, sampleunit=1, triggerflags=0 + [ +0.086261] misc beaglelogic: capture session ended + + +BeagleLogic uses the two PRUs to sample at 100Msps. Getting a PRU running at 200Hz to sample at 100Msps is a slick trick. +`The Embedded Kitchen <http://theembeddedkitchen.net/beaglelogic-building-a-logic-analyzer-with-the-prus-part-1/449>`_ has a nice article +explaining how the PRUs get this type of performance. + + +NeoPixels -- 5050 RGB LEDs with Integrated Drivers (Falcon Christmas) +---------------------------------------------------------------------- + +Problem +********* + +You have an `Adafruit NeoPixel LED string <http://www.adafruit.com/products/1138>`_, +`Adafruit NeoPixel LED matrix <http://www.adafruit.com/products/1487>`_ or +any other type of +`WS2812 LED <https://cdn-shop.adafruit.com/datasheets/WS2812.pdf>`_ +and want to light it up. + +.. TODO Show how to drive ws2812's with FPP. + +Solution +********* + +If you are driving just one string you can write your own code +(See :ref:`../05blocks/blocks.adoc#blocks_ws2812, WS2812 Driver`) +If you plan to drive multiple strings, then consider +Falcon Christmas (`FPP <https://falconchristmas.com/>`_). +FPP can be used to drive both LEDs with an integrated +driver (neopixels) or without an integrated driver. Here we'll show you how to +set up for the integrated drive and in the next section the no driver LEDs will be +show. + +Hardware +********* + +For this setup we'll wire a single string of NeoPixels to the Beagle. +I've attached the black wire on the string to ground on the Beagle +and the red wire to a 3.3V pin on the Beagle. +The yellow data in line is attached to P1.31 (I'm using a PocketBeagle.). + +How did I know to attach to P1.31? The FalconChristmas git repo +(https://github.com/FalconChristmas/fpp) has files that tell which pins +attach to which port. https://github.com/FalconChristmas/fpp/blob/master/capes/pb/strings/F8-B-20.json +has a list of 20 ports and where they are connected. Pin P1.31 appears on +line 27. It's the 20th entry in the list. You could pick any of the others +if you'd rather. + +Software Setup +*************** + +Assuming the PocketBeagle is attached via the USB cable, +on your host computer browse to <http://192.168.7.2/> and you will see +:ref:`case_fpp_program_control2`. + +.. _case_fpp_program_control2: + +Falcon Play Program Control +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_program_control.png + :align: center + :alt: Falcon Play Program Control + +You can test the display by first setting up the Channel Outputs and then +going to *Display Testing*. :ref:`case_channel_outputs_menu2` shows where to +select Channel Outputs and :ref:`case_channel_outputs2` shows which settings to use. + +.. _case_channel_outputs_menu2: + +Selecting Channel Outputs +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_channel_outputs_menu.png + :align: center + :alt: Selecting Channel Outputs + +.. _case_channel_outputs2: + +Channel Outputs Settings +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_channel_outputs_strings.png + :align: center + :alt: Channel Outputs Settings + +Click on the *Pixel Strings* tab. Earlier we noted that *P1.31* is attached +to port 20. Note that at the bottom of the screen, port 20 has a PIXEL COUNT +of 24. We're telling FPP our string has 24 NeoPixels and they are attached +to port 2 which in *P1.31*. + +Be sure to check the *Enable String Cape*. + +Next we need to test the display. Select **Display Testing** shown in +:ref:`case_display_testing_menu2`. + +.. _case_display_testing_menu2: + +Selecting Display Testing +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_display_testing_menu2.png + :align: center + :alt: Selecting Display Testing + +Set the *End Channel* to *72*. (72 is 3*24) +Click *Enable Test Mode* and your matrix should light up. Try the different +testing patterns shown in :ref:`case_display_testing2`. + +.. note:: + + Clicking on the *-3* will subtract three from the End Channel, which should + then display three fewer LEDs which is one NeoPixel. The last of your NeoPixels + should go black. This is an easy way to make sure you have the correct pixel + count. + +.. _case_display_testing2: + +Display Testing Options +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_display_testing2.png + :align: center + :alt: Display Testing Options + +You can control the LED string using the E1.31 protocol. +(https://www.doityourselfchristmas.com/wiki/index.php?title=E1.31_(Streaming-ACN)_Protocol) +First configure the input channels by going to Channel Inputs as shown in +:ref:`case_channel_inputs`. + +.. _case_channel_inputs: + +Going to Channel Inputs +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_channel_inputs.png + :align: center + :alt: Going to Channel Inputs + +Tell it you have 72 LEDs and enable the input as shown in :ref:`case_set_inputs`. + +.. _case_set_inputs: + +Setting Channel Inputs +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_inputs_setup2.png + :align: center + :alt: Setting Channel Inputs + +Finally go to the Status Page as shown in :ref:`case_status`. + +.. _case_status: + +Watching the status +~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_status.png + :align: center + :alt: Watching Status + +Now run a program on another computer that generated E1.31 packets. +:ref:`case_1.31_example` is an example python program. + +.. _cse_e1.31_example: + +.e1.31-test.py +~~~~~~~~~~~~~~ + +:downlod:`e1.31-test.py <code/e1.31-test.py>`- Example of generating packets to control the NeoPixels + +.. TODO document the code + +.. _case_rgb_matrix: + +RGB LED Matrix -- No Integrated Drivers (Falcon Christmas) +----------------------------------------------------------- + +Problem +************************* + +You want to use a RGB LED Matrix display that doesn't have integrated +drivers such as the +`64x32 RGB LED Matrix <https://www.adafruit.com/product/2277>`_ by Adafuit +shown in :ref:`case_adfruit_matrix`. + +.. _case_adfruit_matrix: + +Adafruit LED Matrix +~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/ledmatrix.jpg + :align: center + :alt: Adafruit LED Matrix + +Solution +************************* + +`Falcon Christmas <http://falconchristmas.com>`_ makes a software package +called +`Falcon Player <http://falconchristmas.com/forum/index.php/board,8.0.html>`_ (FPP) which can drive +such displays. + +.. admonition:: information: + + The Falcon Player (FPP) is a lightweight, optimized, feature-rich sequence player + designed to run on low-cost SBC's (Single Board Computers). + FPP is a software solution that you download and install on hardware which can be + purchased from numerous sources around the internet. + FPP aims to be controller agnostic, it can talk E1.31, DMX, Pixelnet, and + Renard to hardware from multiple hardware vendors, including controller + hardware from Falcon Christmas available via COOPs or in the store on FalconChristmas.com. + + http://www.falconchristmas.com/wiki/FPP:FAQ#What_is_FPP.3F + +Hardware +~~~~~~~~~ + +The Beagle hardware can be either a BeagleBone Black with the +`Octoscroller Cape <https://oshpark.com/shared_projects/7mSHNZcD>`_, or a +PocketBeagle with the +`PocketScroller LED Panel Cape <https://www.hackster.io/daniel-kulp/pocketscroller-led-panel-cape-for-pocketbeagle-fe12a6>`_. +(See `to purchase <https://kulplights.com/product/pocketscroller/>`_.) +`Building and Octoscroller Matrix Display <https://www.diychristmas.org/wiki/index.php?title=Building_an_Octoscroller_Matrix_Display>`_ +gives details for using the BeagleBone Black. + +:ref:`case_pocket` shows how to attach the PocketBeagle to the P5 LED matrix +and where to attach the 5V power. If you are going to turn on all the LEDs +to full white at the same time you will need at least a 4A supply. + +.. _case_pocket: + +Pocket Beagle Driving a P5 RGB LED Matrix via the PocketScroller Cape +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pocketscroller.jpg + :align: center + :alt: Pocket Beagle Driving a P5 RGB LED Matrix via the PocketScroller Cape + + +Software +~~~~~~~~~~ + +The FPP software is most easily installed by downloading the +`current FPP release <https://github.com/FalconChristmas/fpp/releases/>`_, flashing an SD card and +booting from it. + +.. tip:: + + The really brave can install it on a already running image. See details at + https://github.com/FalconChristmas/fpp/blob/master/SD/FPP_Install.sh + + +Assuming the PocketBeagle is attached via the USB cable, +on your host computer browse to http://192.168.7.2/ and you will see +:ref:`case_fpp_program_control`. + +.. _case_fpp_program_control: + +Falcon Play Program Control +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_program_control.png + :align: center + :alt: Falcon Play Program Control + +You can test the display by first setting up the Channel Outputs and then +going to *Display Testing*. :ref:`case_channel_outputs_menu` shows where to +select Channel Outputs and :ref:`case_channel_outputs` shows which settings to use. + +.. _case_channel_outputs_menu: + +Selecting Channel Outputs +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_channel_outputs_menu.png + :align: center + :alt: Selecting Channel Outputs + +.. _case_channel_outputs: + +Channel Outputs Settings +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_channel_outputs.png + :align: center + :alt: Channel Outputs Settings + +Click on the **LED Panels** tab and then the only changes I made was +to select the **Single Panel Size** to be +*64x32* and to check the **Enable LED Panel Output**. + +Next we need to test the display. Select *Display Testing* shown in +:ref:`case_display_testing_menu`. + +.. _case_display_testing_menu: + +Selecting Display Testing +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_display_testing_menu.png + :align: center + :alt: Selecting Display Testing + +Set the **End Channel** to **6144**. (6144 is 3*64*32) +Click **Enable Test Mode** and your matrix should light up. Try the different +testing patterns shown in :ref:`case_display_testing`. + +.. _case_display_testing: + +Display Testing Options +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_display_testing.png + :align: center + :alt: Display Testing Options + +xLights - Creating Content for the Display +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once you are sure your LED Matrix is working correctly you can program it +with a sequence. + + +.. admonition:: information: + + xLights is a free and open source program that enables you to design, create and play + amazing lighting displays through the use of DMX controllers, E1.31 Ethernet controllers and more. + + With it you can layout your display visually then assign effects to the various items + throughout your sequence. This can be in time to music (with beat-tracking built into xLights) + or just however you like. xLights runs on Windows, OSX and Linux + + https://xlights.org/ + + +xLights can be installed on your host computer (not the Beagle) by +following instructions at https://xlights.org/releases/. + +Run xLights and you'll see :ref:`case_xlights_setup`. + +.. code-block:: bash + + host$ *chmod +x xLights-2021.18-x86_64.AppImage* + host$ *./xLights-2021.18-x86_64.AppImage* + +.. TODO update the figures. + +.. _case_xlights_setup: + +xLights Setup +~~~~~~~~~~~~~~ + +.. figure:: figures/xlights_setup.png + :align: center + :alt: xLights Setup + +We'll walk you through a simple setup to get an animation to display on the +RGB Matrix. xLights can use a protocol called E1.31 to send information to +the display. Setup xLights by clicking on *Add Ethernet* and entering the values +shown in :ref:`case_xlights_setup_e1_31`. + +.. _case_xlights_setup_e1_31: + +Setting Up E1.31 +~~~~~~~~~~~~~~~~~ + +.. figure:: figures/xlights_setup_e1_31.png + :align: center + :alt: Setting Up E1.31 + +The **IP Address** is the Bone's address as seen from the host computer. +Each LED is one channel, so one RGB LED is three channels. The P5 board +has 3*64*32 or 6144 channels. These are grouped into universes of 512 +channels each. This gives 6144/512 = 12 universes. See the +`E.13 documentation <https://www.doityourselfchristmas.com/wiki/index.php?title=E1.31_(Streaming-ACN)_Protocol#Configuring_Sequencing_Software_to_use_E1.31_Output>`_ +for more details. + +Your setup should look like :ref:`case_xlights_setup_done`. Click the +*Save Setup* button to save. + +.. _case_xlights_setup_done: + +xLights setup for P5 display +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/xlights_setup_done.png + :align: center + :alt: xLights setup for P5 display + +Next click on the **Layout** tab. Click on the *Matrix* button as shown in +:ref:`case_xlights_matrix`, then click on the black area where you want your +matrix to appear. + +.. _case_xlights_matrix: + +Setting up the Matrix Layout +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/xlights_layout.png + :align: center + :alt: Setting up the Matrix Layout + +:ref:`case_xlights_layout_details` shows the setting to use for the P5 matrix. + +.. _case_xlights_layout_details: + +Layout details for P5 matrix +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/xlights_layout_details.png + :align: center + :alt: Layout details for P5 matrix + +All I changed was **# Strings**, **Nodes/String**, **Starting Location** and most +importantly, expand **String Properties** and select at **String Type** of +**RGB Nodes**. Above the setting you should see that **Start Chan** is 1 and +the **End Chan** is 6144, which is the total number of individual LEDs (3*63*32). +xLights now knows we are working with a P5 matrix, now on to the sequencer. + +Now click on the *Sequencer* tab and then click on the **New Sequence** button +(:ref:`case_seq_new`). + +.. _case_seq_new: + +Starting a new sequence +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/xlights_seq_new.png + :align: center + :alt: Starting a new sequence + +Then click on **Animation**, **20fps (50ms)**, and **Quick Start**. Learning how to +do sequences is beyond the scope of this cookbook, however I'll shown you how +do simple sequence just to be sure xLights is talking to the Bone. + +Setting Up E1.31 on the Bone +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First we need to setup FPP to take input from xLights. Do this by going to +the *Input/Output Setup* menu and selecting *Channel Inputs*. Then +enter *12* for *Universe Count* and click *set* and you will see +:ref:`case_inputs_setup`. + +.. _case_inputs_setup: + +E1.31 Inputs +~~~~~~~~~~~~~ + +.. figure:: figures/fpp_inputs_setup.png + :align: center + :alt: .E1.31 Inputs + +Click on the **Save** button above the table. + +Then go to the **Status/Control** menu and select **Status Page**. + +.. TODO update this + +.. _case_mode_bridge: + +Bridge Mode +~~~~~~~~~~~~~ + +.. figure:: figures/fpp_mode_bridge.png + :align: center + :alt: Bridge Mode + +Testing the xLights Connection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Bone is now listening for commands from xLights via the E1.31 protocol. +A quick way to verify everything is t o return to xLights and go to the +*Tools* menu and select **Test** (:ref:`case_xlights_test`). + +.. _case_xlights_test: + +xLights test page +~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/xlights_test.png + :align: center + :alt: xLights test page + +Click the box under **Select channels...**, click **Output to lights** and +select **Twinkle 50%**. You matrix should have a colorful twinkle pattern +(:ref:`case_xlights_twinkle`). + +.. _case_xlights_twinkle: + +xLights Twinkle test pattern +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/xlights_twinkle.jpg + :align: center + :alt: xLights Twinkle test pattern + +A Simple xLights Sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now that the xLights to FPP link is tested you can generate a sequence to +play. Close the Test window and click on the **Sequencer** tab. Then drag +an effect from the **Effects** box to the timeline that below it. Drop it to +the right of the **Matrix** label (:ref:`case_seq_drag`). The click +*Output To Lights* which is the yellow lightbulb to the right on the top +toolbar. Your matrix should now be displaying your effect. + +.. _case_seq_drag: + +Drag an effect to the timeline +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/xlights_seq_drag.png + :align: center + :alt: Drag an effect to the timeline + +The setup requires the host computer to send the animation data to the Bone. +The next section shows how to save the sequence and play it on the Bone +standalone. + +Saving a Sequence and Playing it Standalone +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In xLights save your sequence by hitting Ctrl-S and giving it a name. I called +mine *fire* since I used a fire effect. Now, switch back to FPP and select +the *Content Setup* menu and select *File Manager*. Click the black +*Select Files* button and select your sequence file that ends in *.fseq* +(:ref:`case_file_manager`). + +.. _case_file_manager: + +FPP file manager +~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_file_manager.png + :align: center + :alt: FPP file manager + +Once your sequence is uploaded, got to **Content Steup** and select **Playlists**. +Enter you playlist name (I used **fire**) and click **Add**. Then click +**Add a Sequence/Entry** and select **Sequence Only** +(:ref:`case_playlist`), then click **Add**. + +.. _case_playlist: + +Adding a new playlist to FPP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_playlist.png + :align: center + :alt: Adding a new playlist to FPP + +Be sure to click **Save Playlist** on the right. Now return to +**Status/Control** and **Status Page** and make sure **FPPD Mode:** is set +to **Standalone**. You should see your playlist. Click the **Play** +button and your sequence will play. + +.. _case_playlist_status: + +Adding a new playlist to FPP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/fpp_playlist_status.png + :align: center + :alt: Playing a playlist + +The beauty of the PRU is that the Beagle can play a detailed sequence at +20 frames per second and the ARM procossor is only 15% used. The PRUs +are doing all the work. + +simpPRU -- A python-like language for programming the PRUs +----------------------------------------------------------- + +`simpPRU <https://github.com/VedantParanjape/simpPRU>`_ is a simple, python-like +programming languge designed to make programming the PRUs easy. +It has detailed `documentation <https://simppru.readthedocs.io/en/latest/>`_ and +many `examples <https://simppru.readthedocs.io/en/latest/examples/digital_read/>`_. + +.. admonition:: information + + simpPRU is a procedural programming language that is statically typed. + Variables and functions must be assigned data types during compilation. + It is typesafe, and data types of variables are decided during compilation. + simPRU codes have a +.sim+ extension. + simpPRU provides a console app to use Remoteproc functionality. + + https://simppru.readthedocs.io/en/latest/ + +You can `build simpPRU <https://simppru.readthedocs.io/en/latest/install/build/>`_ from +source, more easily just `install it <https://simppru.readthedocs.io/en/latest/install/install/>`_. +On the Beagle run: + +.. code-block:: bash + + bone$ wget https://github.com/VedantParanjape/simpPRU/releases/download/1.4/simppru-1.4-armhf.deb + bone$ sudo dpkg -i simppru-1.4-armhf.deb + bone$ sudo apt update + bone$ sudo apt install gcc-pru + +Now, suppose you wanted to run the +`LED blink <https://simppru.readthedocs.io/en/latest/examples/led_blink/>`_ +example which is reproduced here. + +LED Blink (blink.sim) +~~~~~~~~~~~~~~~~~~~~~ + +:download:`blink.sim <code/blink.sim>` + +Just run simppru + +.. code-block:: bash + + bone$ simppru blink.sim --load + Detected TI AM335x PocketBeagle + inside while + [4] : setting P1_31 as output + + Current mode for P1_31 is: pruout + +Detected TI AM335x PocketBeagle +-------------------------------- + +The +--load+ flag caused the compiled code to be copied to +/lib/firmware+. +To start just do: + +.. code-block:: bash + + bone$ cd /dev/remoteproc/pruss-core0/ + bone$ ls + device firmware name power state subsystem uevent + bone$ echo start > state + bone$ cat state + running + +Your LED should now be blinking. + +Check out the many examples (https://simppru.readthedocs.io/en/latest/examples/led_blink/). + +simpPRU Examples +~~~~~~~~~~~~~~~~ + +.. figure:: figures/LEDblink.png + :align: center + :alt: simpPRU Examples + + +MachineKit +----------- + +`MachineKit <http://www.machinekit.io/>`_ is a platform for machine control +applications. It can control machine tools, robots, or other automated devices. It can control servo +motors, stepper motors, relays, and other devices related to machine tools. + +.. admonition:: information + + Machinekit is portable across a wide range of hardware platforms and real-time environments, + and delivers excellent performance at low cost. It is based on the HAL component architecture, + an intuitive and easy to use circuit model that includes over 150 building blocks for digital logic, + motion, control loops, signal processing, and hardware drivers. Machinekit supports local and + networked UI options, including ubiquitous platforms like phones or tablets. + + http://www.machinekit.io/about/ + +ArduPilot +---------- +`ArduPilot <http://ardupilot.org/>`_ is a open source autopilot system supporting +multi-copters, traditional helicopters, fixed wing aircraft and rovers. ArduPilot runs on a many +`hardware platforms <http://ardupilot.org/copter/docs/common-autopilots.html>`_ including the +`BeagleBone Black <http://ardupilot.org/dev/docs/building-for-beaglebone-black-on-linux.html#building-for-beaglebone-black-on-linux>`_ and the +`BeagleBone Blue <http://ardupilot.org/copter/docs/common-beagle-bone-blue.html>`_. + + + +.. admonition:: information + + Ardupilot is the most advanced, full-featured and reliable open source autopilot software available. + It has been developed over 5+ years by a team of diverse professional engineers and computer scientists. + It is the only autopilot software capable of controlling any vehicle system imaginable, from conventional + airplanes, multirotors, and helicopters, to boats and even submarines. And now being expanded to feature + support for new emerging vehicle types such as quad-planes and compound helicopters. + + Installed in over 1,000,000 vehicles world-wide, and with its advanced data-logging, analysis + and simulation tools, Ardupilot is the most tested and proven autopilot software. The open-source + code base means that it is rapidly evolving, always at the cutting edge of technology development. + With many peripheral suppliers creating interfaces, users benefit from a broad ecosystem of sensors, + companion computers and communication systems. Finally, since the source code is open, it can be + audited to ensure compliance with security and secrecy requirements. + + The software suite is installed in aircraft from many OEM UAV companies, such as 3DR, jDrones, + PrecisionHawk, AgEagle and Kespry. It is also used for testing and development by several large + institutions and corporations such as NASA, Intel and Insitu/Boeing, as well as countless + colleges and universities around the world. + + http://www.machinekit.io/about/ diff --git a/pru-cookbook/01case/code/blink.sim b/pru-cookbook/01case/code/blink.sim new file mode 100644 index 0000000000000000000000000000000000000000..212a21689e76170ad44112b926a0c4300e0c03a4 --- /dev/null +++ b/pru-cookbook/01case/code/blink.sim @@ -0,0 +1,7 @@ +/* From: https://simppru.readthedocs.io/en/latest/examples/led_blink/ */ +while : 1 == 1 { + digital_write(P1_31, true); + delay(250); /* Delay 250 ms */ + digital_write(P1_31, false); + delay(250); +} diff --git a/pru-cookbook/01case/code/circle.py b/pru-cookbook/01case/code/circle.py new file mode 100755 index 0000000000000000000000000000000000000000..1feb41cc089af343f1f2c490deef92853965bee4 --- /dev/null +++ b/pru-cookbook/01case/code/circle.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +"""A demo client for Open Pixel Control +http://github.com/zestyping/openpixelcontrol + +Runs an LED around in a circle + +""" + +import time +import opc + +ADDRESS = 'localhost:7890' + +# Create a client object +client = opc.Client(ADDRESS) + +# Test if it can connect +if client.can_connect(): + print('connected to %s' % ADDRESS) +else: + # We could exit here, but instead let's just print a warning + # and then keep trying to send pixels in case the server + # appears later + print('WARNING: could not connect to %s' % ADDRESS) + +# Send pixels forever +STR_LEN=16 +for i in range(STR_LEN): + leds = [(0, 0, 0)] * STR_LEN +leds[0] = (0, 127, 0) + +while True: + tmp = leds[0] + for i in range(STR_LEN-1): + leds[i] = leds[i+1] + leds[-1] = tmp + if client.put_pixels(leds, channel=0): + print('sent') + else: + print('not connected') + time.sleep(0.1) + diff --git a/pru-cookbook/01case/code/e1.31-test.py b/pru-cookbook/01case/code/e1.31-test.py new file mode 100755 index 0000000000000000000000000000000000000000..6016c9eb9e879a6d21f8ccf8fd20ed32bd4c45b3 --- /dev/null +++ b/pru-cookbook/01case/code/e1.31-test.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# Controls a NeoPixel (WS2812) string via E1.31 and FPP +# https://pypi.org/project/sacn/ +# https://github.com/FalconChristmas/fpp/releases +import sacn +import time + +# provide an IP-Address to bind to if you are using Windows and want to use multicast +sender = sacn.sACNsender("192.168.7.1") +sender.start() # start the sending thread +sender.activate_output(1) # start sending out data in the 1st universe +sender[1].multicast = False # set multicast to True +sender[1].destination = "192.168.7.2" # or provide unicast information. +sender.manual_flush = True # turning off the automatic sending of packets +# Keep in mind that if multicast is on, unicast is not used +LEDcount = 24 +# Have green fade is as it goes +data = [] +for i in range(LEDcount): + data.append(0) # Red + data.append(i) # Green + data.append(0) # Blue +sender[1].dmx_data = data +sender.flush() +time.sleep(0.5) + +# Turn off all LEDs +data=[] +for i in range(3*LEDcount): + data.append(0) +sender.flush() +sender[1].dmx_data = data +time.sleep(0.5) + +# Have red fade in +data = [] +for i in range(LEDcount): + data.append(i) + data.append(0) + data.append(0) +sender[1].dmx_data = data +sender.flush() +time.sleep(0.25) + +# Make LED circle 5 times +for j in range(15): + for i in range(LEDcount-1): + data[3*i+0] = 0 + data[3*i+1] = 0 + data[3*i+2] = 0 + data[3*i+3] = 0 + data[3*i+4] = 64 + data[3*i+5] = 0 + sender[1].dmx_data = data + sender.flush() + time.sleep(0.02) +# Wrap around + i = LEDcount-1 + data[0] = 0 + data[1] = 64 + data[2] = 0 + data[3*i+0] = 0 + data[3*i+1] = 0 + data[3*i+2] = 0 + sender[1].dmx_data = data + sender.flush() + time.sleep(0.02) + +time.sleep(2) # send the data for 10 seconds +sender.stop() # do not forget to stop the sender diff --git a/pru-cookbook/01case/code/encoder_setup.sh b/pru-cookbook/01case/code/encoder_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..ffc4ad68842fb6314173b523425295893cd05fc1 --- /dev/null +++ b/pru-cookbook/01case/code/encoder_setup.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Configure the pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine + +# Configure eQEP pins +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_92 P9_27 P8_35 P8_33 P8_12 P8_11 P8_41 P8_42" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P1_31 P2_34 P2_10 P2_24 P2_33" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin qep + config-pin -q $pin +done + +########################################## +# Configure PRU pins +if [ $machine = "Black" ]; then + echo " Found" + pins="P8_16 P8_15" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P2_09 P2_18" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruin + config-pin -q $pin +done diff --git a/pru-cookbook/01case/code/fire.fseq b/pru-cookbook/01case/code/fire.fseq new file mode 100644 index 0000000000000000000000000000000000000000..4bad5ae76476a87bb7bb71e853e3412b1fc63f29 Binary files /dev/null and b/pru-cookbook/01case/code/fire.fseq differ diff --git a/pru-cookbook/01case/code/logic_install.sh b/pru-cookbook/01case/code/logic_install.sh new file mode 100644 index 0000000000000000000000000000000000000000..7fb76122b55b55da9e50ea2a084b1242b8e30b78 --- /dev/null +++ b/pru-cookbook/01case/code/logic_install.sh @@ -0,0 +1,34 @@ +# Instructions for installing BeagleLogic +# https://beaglelogic.readthedocs.io/en/latest/index.html +# From: https://github.com/abhishek-kakkar/BeagleLogic/wiki + +# beaglelogic is installed on the 4.9 kernel, but not the 4.14, so +# if you are running 4.14, switch to 4.9 +sudo /opt/scripts/tools/update_kernel.sh --lts-4_9 +sudo reboot + +git clone https://github.com/abhishek-kakkar/BeagleLogic +cd BeagleLogic +sudo ./install.sh +sudo reboot + +# Now the kernel driver headers +sudo apt install linux-headers-`uname -r` + +modinfo beaglelogic +modprobe beaglelogic + +# From: https://beaglelogic.readthedocs.io/en/latest + +# Here's what works from abhishek +git clone https://github.com/abhishek-kakkar/BeagleLogic +cd BeagleLogic +# 1. Get the dts file from this gist (https://gist.github.com/abhishek-kakkar/0761ef7b10822cff4b3efd194837f49c) + +# 2. cd to 'BeagleLogic/kernel' directory. Put the dts file there. (edited) +# 3. Run 'make overlay' +# 4. Run 'sudo cp -v beaglelogic-00A0.dtbo /lib/firmware/' (edited) +# 5. Run 'sudo update-initramfs -u -k ``uname -r``' (edited) +# (single backticks only, apparently Slack treats single backtick as code) (edited) +# 6. Reboot +# 7. Browse to bone:4000 diff --git a/pru-cookbook/01case/code/main_pru1.c b/pru-cookbook/01case/code/main_pru1.c new file mode 100644 index 0000000000000000000000000000000000000000..8d751b3e65e06a8dd4e47c9ef6f28f370d60ca24 --- /dev/null +++ b/pru-cookbook/01case/code/main_pru1.c @@ -0,0 +1,53 @@ +/* + * Source Modified by Zubeen Tolani < ZeekHuge - zeekhuge@gmail.com > + * Based on the examples distributed by TI + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_pru1.h" + +// The function is defined in pru1_asm_blinky.asm in same dir +// We just need to add a declaration here, the defination can be +// seperately linked +extern void start(void); + +void main(void) +{ + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + start(); +} + diff --git a/pru-cookbook/01case/code/my-config.json b/pru-cookbook/01case/code/my-config.json new file mode 100644 index 0000000000000000000000000000000000000000..d1534cfff15f46bbabb10068c01542bb721583c4 --- /dev/null +++ b/pru-cookbook/01case/code/my-config.json @@ -0,0 +1,19 @@ +{ + "outputMode": "ws281x", + "outputMapping": "original-ledscape", + "demoMode": "fade", + "ledsPerStrip": 16, + "usedStripCount": 1, + "colorChannelOrder": "BRG", + "opcTcpPort": 7890, + "opcUdpPort": 7890, + "enableInterpolation": false, + "enableDithering": false, + "enableLookupTable": true, + "lumCurvePower": 2.0000, + "whitePoint": { + "red": 0.9000, + "green": 1.0000, + "blue": 1.0000 + } +} diff --git a/pru-cookbook/01case/code/opc.py b/pru-cookbook/01case/code/opc.py new file mode 100755 index 0000000000000000000000000000000000000000..36a3bbd6b76e7ff8e6660ea7b163da2271bbe696 --- /dev/null +++ b/pru-cookbook/01case/code/opc.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python + +"""Python Client library for Open Pixel Control +http://github.com/zestyping/openpixelcontrol + +Sends pixel values to an Open Pixel Control server to be displayed. +http://openpixelcontrol.org/ + +Recommended use: + + import opc + + # Create a client object + client = opc.Client('localhost:7890') + + # Test if it can connect (optional) + if client.can_connect(): + print('connected to %s' % ADDRESS) + else: + # We could exit here, but instead let's just print a warning + # and then keep trying to send pixels in case the server + # appears later + print('WARNING: could not connect to %s' % ADDRESS) + + # Send pixels forever at 30 frames per second + while True: + my_pixels = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] + if client.put_pixels(my_pixels, channel=0): + print('...') + else: + print('not connected') + time.sleep(1/30.0) + +""" + +import socket +import struct +import sys + +SET_PIXEL_COLOURS = 0 # "Set pixel colours" command (see openpixelcontrol.org) + + +class Client(object): + def __init__(self, server_ip_port, long_connection=True, verbose=False): + """Create an OPC client object which sends pixels to an OPC server. + + server_ip_port should be an ip:port or hostname:port as a single string. + For example: '127.0.0.1:7890' or 'localhost:7890' + + There are two connection modes: + * In long connection mode, we try to maintain a single long-lived + connection to the server. If that connection is lost we will try to + create a new one whenever put_pixels is called. This mode is best + when there's high latency or very high framerates. + * In short connection mode, we open a connection when it's needed and + close it immediately after. This means creating a connection for each + call to put_pixels. Keeping the connection usually closed makes it + possible for others to also connect to the server. + + A connection is not established during __init__. To check if a + connection will succeed, use can_connect(). + + If verbose is True, the client will print debugging info to the console. + + """ + self.verbose = verbose + + self._long_connection = long_connection + + self._ip, self._port = server_ip_port.split(':') + self._port = int(self._port) + + self._socket = None # will be None when we're not connected + + def _debug(self, m): + if self.verbose: + print(' %s' % str(m)) + + def _ensure_connected(self): + """Set up a connection if one doesn't already exist. + + Return True on success or False on failure. + + """ + if self._socket: + self._debug('_ensure_connected: already connected, doing nothing') + return True + + try: + self._debug('_ensure_connected: trying to connect...') + self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self._socket.settimeout(1) + self._socket.connect((self._ip, self._port)) + self._debug('_ensure_connected: ...success') + return True + except socket.error: + self._debug('_ensure_connected: ...failure') + self._socket = None + return False + + def disconnect(self): + """Drop the connection to the server, if there is one.""" + self._debug('disconnecting') + if self._socket: + self._socket.close() + self._socket = None + + def can_connect(self): + """Try to connect to the server. + + Return True on success or False on failure. + + If in long connection mode, this connection will be kept and re-used for + subsequent put_pixels calls. + + """ + success = self._ensure_connected() + if not self._long_connection: + self.disconnect() + return success + + def put_pixels(self, pixels, channel=0): + """Send the list of pixel colors to the OPC server on the given channel. + + channel: Which strand of lights to send the pixel colors to. + Must be an int in the range 0-255 inclusive. + 0 is a special value which means "all channels". + + pixels: A list of 3-tuples representing rgb colors. + Each value in the tuple should be in the range 0-255 inclusive. + For example: [(255, 255, 255), (0, 0, 0), (127, 0, 0)] + Floats will be rounded down to integers. + Values outside the legal range will be clamped. + + Will establish a connection to the server as needed. + + On successful transmission of pixels, return True. + On failure (bad connection), return False. + + The list of pixel colors will be applied to the LED string starting + with the first LED. It's not possible to send a color just to one + LED at a time (unless it's the first one). + + """ + self._debug('put_pixels: connecting') + is_connected = self._ensure_connected() + if not is_connected: + self._debug('put_pixels: not connected. ignoring these pixels.') + return False + + # build OPC message + command = SET_PIXEL_COLOURS + header = struct.pack('>BBH', channel, SET_PIXEL_COLOURS, len(pixels)*3) + pieces = [struct.pack( + 'BBB', + min(255, max(0, int(r))), + min(255, max(0, int(g))), + min(255, max(0, int(b))) + ) for r, g, b in pixels] + if bytes is str: + message = header + ''.join(pieces) + else: + message = header + b''.join(pieces) + + self._debug('put_pixels: sending pixels to server') + try: + self._socket.send(message) + except socket.error: + self._debug('put_pixels: connection lost. could not send pixels.') + self._socket = None + return False + + if not self._long_connection: + self._debug('put_pixels: disconnecting') + self.disconnect() + + return True diff --git a/pru-cookbook/01case/code/pru1-servo.asm b/pru-cookbook/01case/code/pru1-servo.asm new file mode 100644 index 0000000000000000000000000000000000000000..c8e66e5234214137be6c7f7a781083c21061190e --- /dev/null +++ b/pru-cookbook/01case/code/pru1-servo.asm @@ -0,0 +1,162 @@ +;* +;* Copyright (C) 2016 Zubeen Tolani <ZeekHuge - zeekhuge@gmail.com> +;* +;* This file is as an example to show how to develope +;* and compile inline assembly code for PRUs +;* +;* This program is free software; you can redistribute it and/or modify +;* it under the terms of the GNU General Public License version 2 as +;* published by the Free Software Foundation. + + + .cdecls "main_pru1.c" + +DELAY .macro time, reg + LDI32 reg, time + QBEQ $E?, reg, 0 +$M?: SUB reg, reg, 1 + QBNE $M?, reg, 0 +$E?: + .endm + + + .clink + .global start +start: + LDI R30, 0xFFFF + DELAY 10000000, r11 + LDI R30, 0x0000 + DELAY 10000000, r11 +; JMP start + +; HALT + + +; these pin definitions are specific to SD-101C Robotics Cape + .asg r30.t8, CH1BIT ; P8_27 + .asg r30.t10, CH2BIT ; P8_28 + .asg r30.t9, CH3BIT ; P8_29 + .asg r30.t11, CH4BIT ; P8_30 + .asg r30.t6, CH5BIT ; P8_39 + .asg r30.t7, CH6BIT ; P8_40 + .asg r30.t4, CH7BIT ; P8_41 + .asg r30.t5, CH8BIT ; P8_42 + + .asg C4, CONST_SYSCFG + .asg C28, CONST_PRUSHAREDRAM + + .asg 0x22000, PRU0_CTRL + .asg 0x24000, PRU1_CTRL ; page 19 + .asg 0x28, CTPPR0 ; page 75 + + .asg 0x000, OWN_RAM + .asg 0x020, OTHER_RAM + .asg 0x100, SHARED_RAM ; This is so prudebug can find it. + + LBCO &r0, CONST_SYSCFG, 4, 4 ; Enable OCP master port + CLR r0, r0, 4 ; Clear SYSCFG[STANDBY_INIT] to enable OCP master port + SBCO &r0, CONST_SYSCFG, 4, 4 + +; Configure the programmable pointer register for PRU0 by setting c28_pointer[15:0] + LDI r0, SHARED_RAM ; Set C28 to point to shared RAM + LDI32 r1, PRU1_CTRL + CTPPR0 ; Note we use beginning of shared ram unlike example which + SBBO &r0, r1, 0, 4 ; page 25 + + LDI r9, 0x0 ; erase r9 to use to use later + + LDI r0, 0x0 ; clear internal counters + LDI r1, 0x0 + LDI r2, 0x0 + LDI r3, 0x0 + LDI r4, 0x0 + LDI r5, 0x0 + LDI r6, 0x0 + LDI32 r7, 0x0 + LDI r30, 0x0 ; turn off GPIO outputs + + +; Beginning of loop, should always take 48 instructions to complete +CH1: + QBEQ CLR1, r0, 0 ; If timer is 0, jump to clear channel + SET r30, CH1BIT ; If non-zero turn on the corresponding channel + SUB r0, r0, 1 ; Subtract one from timer + CLR r9, r9.t1 ; waste a cycle for timing + SBCO &r9, CONST_PRUSHAREDRAM, 0, 4 ; write 0 to shared memory +CH2: + QBEQ CLR2, r1, 0 + SET r30, CH2BIT + SUB r1, r1, 1 + CLR r9, r9.t1 + SBCO &r9, CONST_PRUSHAREDRAM, 4, 4 +CH3: + QBEQ CLR3, r2, 0 + SET r30, CH3BIT + SUB r2, r2, 1 + CLR r9, r9.t1 + SBCO &r9, CONST_PRUSHAREDRAM, 8, 4 +CH4: + QBEQ CLR4, r3, 0 + SET r30, CH4BIT + SUB r3, r3, 1 + CLR r9, r9.t1 + SBCO &r9, CONST_PRUSHAREDRAM, 12, 4 +CH5: + QBEQ CLR5, r4, 0 + SET r30, CH5BIT + SUB r4, r4, 1 + CLR r9, r9.t1 + SBCO &r9, CONST_PRUSHAREDRAM, 16, 4 +CH6: + QBEQ CLR6, r5, 0 + SET r30, CH6BIT + SUB r5, r5, 1 + CLR r9, r9.t1 + SBCO &r9, CONST_PRUSHAREDRAM, 20, 4 +CH7: + QBEQ CLR7, r6, 0 + SET r30, CH7BIT + SUB r6, r6, 1 + CLR r9, r9.t1 + SBCO &r9, CONST_PRUSHAREDRAM, 24, 4 +CH8: + QBEQ CLR8, r7, 0 + SET r30, CH8BIT + SUB r7, r7, 1 + SBCO &r9, CONST_PRUSHAREDRAM, 28, 4 + + QBA CH1 ; return to beginning of loop + ; no need to waste a cycle for timing here because of the QBA above + + +CLR1: + CLR r30, CH1BIT ; turn off the corresponding channel + LBCO &r0, CONST_PRUSHAREDRAM, 0, 4 ; Load new timer register + QBA CH2 +CLR2: + CLR r30, CH2BIT + LBCO &r1, CONST_PRUSHAREDRAM, 4, 4 + QBA CH3 +CLR3: + CLR r30, CH3BIT + LBCO &r2, CONST_PRUSHAREDRAM, 8, 4 + QBA CH4 +CLR4: + CLR r30, CH4BIT + LBCO &r3, CONST_PRUSHAREDRAM, 12, 4 + QBA CH5 +CLR5: + CLR r30, CH5BIT + LBCO &r4, CONST_PRUSHAREDRAM, 16, 4 + QBA CH6 +CLR6: + CLR r30, CH6BIT + LBCO &r5, CONST_PRUSHAREDRAM, 20, 4 + QBA CH7 +CLR7: + CLR r30, CH7BIT + LBCO &r6, CONST_PRUSHAREDRAM, 24, 4 + QBA CH8 +CLR8: + CLR r30, CH8BIT + LBCO &r7, CONST_PRUSHAREDRAM, 28, 4 + QBA CH1 ; return to beginning of loop diff --git a/pru-cookbook/01case/code/servo-test.c b/pru-cookbook/01case/code/servo-test.c new file mode 100644 index 0000000000000000000000000000000000000000..1f94e274e573223dcf84b4bd111f9a3df16ac867 --- /dev/null +++ b/pru-cookbook/01case/code/servo-test.c @@ -0,0 +1,84 @@ +/* + * + * servo tester + * (c) Copyright 2016 + * Mark A. Yoder, 20-July-2016 + * + */ + +#include <stdio.h> +#include <fcntl.h> +#include <sys/mman.h> +#include "robotics_cape_defs.h" + +#define PRU_ADDR 0x4A300000 // Start of PRU memory Page 184 am335x TRM +#define PRU_LEN 0x80000 // Length of PRU memory +#define PRU_SHAREDMEM 0x10000 // Offset to shared memory + +unsigned int *prusharedMem_32int_ptr; // Points to the start of the shared memory + +/******************************************************************************* +* int send_servo_pulse_us(int ch, int us) +* +* Sends a single pulse of duration us (microseconds) to a single channel (ch) +*******************************************************************************/ +int send_servo_pulse_us(int ch, int us) { + // Sanity Checks + if(ch<1 || ch>SERVO_CHANNELS){ + printf("ERROR: Servo Channel must be between 1&%d\n", SERVO_CHANNELS); + return -1; + } if(prusharedMem_32int_ptr == NULL){ + printf("ERROR: PRU servo Controller not initialized\n"); + return -1; + } + // PRU runs at 200Mhz. find #loops needed + unsigned int num_loops = ((us*200.0)/PRU_SERVO_LOOP_INSTRUCTIONS); + // printf("num_loops: %d\n", num_loops); + // write to PRU shared memory + prusharedMem_32int_ptr[ch-1] = num_loops; + return 0; +} + +int main(int argc, char *argv[]) +{ + unsigned int *pru; // Points to start of PRU memory. + int fd; + printf("Servo tester\n"); + + fd = open ("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + printf ("ERROR: could not open /dev/mem.\n\n"); + return 1; + } + pru = mmap (0, PRU_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PRU_ADDR); + if (pru == MAP_FAILED) { + printf ("ERROR: could not map memory.\n\n"); + return 1; + } + close(fd); + printf ("Using /dev/mem.\n"); + + prusharedMem_32int_ptr = pru + PRU_SHAREDMEM/4; // Points to start of shared memory + + // while(1) { + // printf("value to store: "); + // scanf("%d", &value); + // printf("Storing: %d in %lx\n", value, addr); + // pru[addr/4] = value; + // } + + int i; + while(1) { + for(i=1; i<=SERVO_CHANNELS; i++) { + send_servo_pulse_us(i, 10*i); + } + usleep(200); + } + + if(munmap(pru, PRU_LEN)) { + printf("munmap failed\n"); + } else { + printf("munmap succeeded\n"); + } +} + diff --git a/pru-cookbook/01case/code/servos_setup.sh b/pru-cookbook/01case/code/servos_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..330e8f34e30d7fd97d9368861ded65817222e903 --- /dev/null +++ b/pru-cookbook/01case/code/servos_setup.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P8_27 P8_28 P8_29 P8_30 P8_39 P8_40 P8_41 P8_42" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P2_35 P1_35 P1_02 P1_04" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruout + config-pin -q $pin +done \ No newline at end of file diff --git a/pru-cookbook/01case/figures/LEDblink.png b/pru-cookbook/01case/figures/LEDblink.png new file mode 100644 index 0000000000000000000000000000000000000000..793795c761196f2d92ee22b590f81693433b5646 Binary files /dev/null and b/pru-cookbook/01case/figures/LEDblink.png differ diff --git a/pru-cookbook/01case/figures/beaglelogic_capture.png b/pru-cookbook/01case/figures/beaglelogic_capture.png new file mode 100644 index 0000000000000000000000000000000000000000..afa771caec1d7b66ba59f0bc6d649ba010fad9e8 Binary files /dev/null and b/pru-cookbook/01case/figures/beaglelogic_capture.png differ diff --git a/pru-cookbook/01case/figures/blue.png b/pru-cookbook/01case/figures/blue.png new file mode 100644 index 0000000000000000000000000000000000000000..035b5d3b9b46fc97e145c28505181de6d5f46091 Binary files /dev/null and b/pru-cookbook/01case/figures/blue.png differ diff --git a/pru-cookbook/01case/figures/fpp_channel_inputs.png b/pru-cookbook/01case/figures/fpp_channel_inputs.png new file mode 100644 index 0000000000000000000000000000000000000000..ef0c191bcc35eb63ccc868b84a7993555cc581aa Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_channel_inputs.png differ diff --git a/pru-cookbook/01case/figures/fpp_channel_outputs.png b/pru-cookbook/01case/figures/fpp_channel_outputs.png new file mode 100644 index 0000000000000000000000000000000000000000..8b2658b766080bac7457ebfd4db479f06e54a1f4 Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_channel_outputs.png differ diff --git a/pru-cookbook/01case/figures/fpp_channel_outputs_menu.png b/pru-cookbook/01case/figures/fpp_channel_outputs_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..7f3984c868401454ee98e4dccfba2244bff5971a Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_channel_outputs_menu.png differ diff --git a/pru-cookbook/01case/figures/fpp_channel_outputs_strings.png b/pru-cookbook/01case/figures/fpp_channel_outputs_strings.png new file mode 100644 index 0000000000000000000000000000000000000000..4f6ab170207cee07848cd1a3aa80a89b70d9d94f Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_channel_outputs_strings.png differ diff --git a/pru-cookbook/01case/figures/fpp_display_testing.png b/pru-cookbook/01case/figures/fpp_display_testing.png new file mode 100644 index 0000000000000000000000000000000000000000..515781eaf4dcc076ab6ab633c99629ccd42ad259 Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_display_testing.png differ diff --git a/pru-cookbook/01case/figures/fpp_display_testing2.png b/pru-cookbook/01case/figures/fpp_display_testing2.png new file mode 100644 index 0000000000000000000000000000000000000000..78a6ba07115dfe5dec7fcc9321192ba8bac63ed0 Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_display_testing2.png differ diff --git a/pru-cookbook/01case/figures/fpp_display_testing_menu.png b/pru-cookbook/01case/figures/fpp_display_testing_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..6cb7b134f663162ddac1c6f1bbd8986eab06336b Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_display_testing_menu.png differ diff --git a/pru-cookbook/01case/figures/fpp_display_testing_menu2.png b/pru-cookbook/01case/figures/fpp_display_testing_menu2.png new file mode 100644 index 0000000000000000000000000000000000000000..c5a5b33b6a003a9b10d5f3c96e84fe105679ab7a Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_display_testing_menu2.png differ diff --git a/pru-cookbook/01case/figures/fpp_file_manager.png b/pru-cookbook/01case/figures/fpp_file_manager.png new file mode 100644 index 0000000000000000000000000000000000000000..958bfab9125a87a7d546f63be35b7b98cb92be88 Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_file_manager.png differ diff --git a/pru-cookbook/01case/figures/fpp_inputs_setup.png b/pru-cookbook/01case/figures/fpp_inputs_setup.png new file mode 100644 index 0000000000000000000000000000000000000000..32046a8ff9bc41d9469ab48c8a91ffcbe010fd15 Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_inputs_setup.png differ diff --git a/pru-cookbook/01case/figures/fpp_inputs_setup2.png b/pru-cookbook/01case/figures/fpp_inputs_setup2.png new file mode 100644 index 0000000000000000000000000000000000000000..f721e6c5e15ed54e8e84db7861b3e5301fc76422 Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_inputs_setup2.png differ diff --git a/pru-cookbook/01case/figures/fpp_mode_bridge.png b/pru-cookbook/01case/figures/fpp_mode_bridge.png new file mode 100644 index 0000000000000000000000000000000000000000..9b3366565ff44237767210c9883cbce463837aaa Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_mode_bridge.png differ diff --git a/pru-cookbook/01case/figures/fpp_playlist.png b/pru-cookbook/01case/figures/fpp_playlist.png new file mode 100644 index 0000000000000000000000000000000000000000..5c8fa072db13cf23e6254ea5da9dad63eb1031d4 Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_playlist.png differ diff --git a/pru-cookbook/01case/figures/fpp_playlist_status.png b/pru-cookbook/01case/figures/fpp_playlist_status.png new file mode 100644 index 0000000000000000000000000000000000000000..1994a186874a94817094f036af3a5b8ad84ecf80 Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_playlist_status.png differ diff --git a/pru-cookbook/01case/figures/fpp_program_control.png b/pru-cookbook/01case/figures/fpp_program_control.png new file mode 100644 index 0000000000000000000000000000000000000000..b3b3662d029234f9884c08e5e71bf86792d70c6a Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_program_control.png differ diff --git a/pru-cookbook/01case/figures/fpp_status.png b/pru-cookbook/01case/figures/fpp_status.png new file mode 100644 index 0000000000000000000000000000000000000000..48748134234085f6edb3dc98693e8124307211d8 Binary files /dev/null and b/pru-cookbook/01case/figures/fpp_status.png differ diff --git a/pru-cookbook/01case/figures/ledmatrix.jpg b/pru-cookbook/01case/figures/ledmatrix.jpg new file mode 100644 index 0000000000000000000000000000000000000000..20f52dc3c56b5ab982b17a808416f5c2d2a3957c Binary files /dev/null and b/pru-cookbook/01case/figures/ledmatrix.jpg differ diff --git a/pru-cookbook/01case/figures/pocketscroller.jpg b/pru-cookbook/01case/figures/pocketscroller.jpg new file mode 100644 index 0000000000000000000000000000000000000000..972e803dde8a7f6af7f6c979b6a5ff3d31796fab Binary files /dev/null and b/pru-cookbook/01case/figures/pocketscroller.jpg differ diff --git a/pru-cookbook/01case/figures/xlights_layout.png b/pru-cookbook/01case/figures/xlights_layout.png new file mode 100644 index 0000000000000000000000000000000000000000..7a3e6930b704d791935aac4dfa5400ce3ee30638 Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_layout.png differ diff --git a/pru-cookbook/01case/figures/xlights_layout_details.png b/pru-cookbook/01case/figures/xlights_layout_details.png new file mode 100644 index 0000000000000000000000000000000000000000..393a0ead4923f018163816ad3b0819b37c1b8745 Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_layout_details.png differ diff --git a/pru-cookbook/01case/figures/xlights_seq_drag.png b/pru-cookbook/01case/figures/xlights_seq_drag.png new file mode 100644 index 0000000000000000000000000000000000000000..5dbbd14a9adce10c5b1c2f48da985659cc878520 Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_seq_drag.png differ diff --git a/pru-cookbook/01case/figures/xlights_seq_new.png b/pru-cookbook/01case/figures/xlights_seq_new.png new file mode 100644 index 0000000000000000000000000000000000000000..840d8d0021a2f695eb7190c151c69adf3aedbf62 Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_seq_new.png differ diff --git a/pru-cookbook/01case/figures/xlights_setup.png b/pru-cookbook/01case/figures/xlights_setup.png new file mode 100644 index 0000000000000000000000000000000000000000..4fd1d9a67db0c2854a5618066b7068d0c6b3cfb1 Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_setup.png differ diff --git a/pru-cookbook/01case/figures/xlights_setup_done.png b/pru-cookbook/01case/figures/xlights_setup_done.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6036f09ffcfdd0616e9cbcdd2deb9ebe860abf Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_setup_done.png differ diff --git a/pru-cookbook/01case/figures/xlights_setup_e1_31.png b/pru-cookbook/01case/figures/xlights_setup_e1_31.png new file mode 100644 index 0000000000000000000000000000000000000000..66ab80a082f756ae04dcfb9c35e57706cd7a2041 Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_setup_e1_31.png differ diff --git a/pru-cookbook/01case/figures/xlights_setup_e1_31.png.orig b/pru-cookbook/01case/figures/xlights_setup_e1_31.png.orig new file mode 100644 index 0000000000000000000000000000000000000000..40d6f0789b4b1e8eeaa7b6ba3956769612eb96ac Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_setup_e1_31.png.orig differ diff --git a/pru-cookbook/01case/figures/xlights_test.png b/pru-cookbook/01case/figures/xlights_test.png new file mode 100644 index 0000000000000000000000000000000000000000..4023a4ceb00b045c71a872252a763dbb6623eef3 Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_test.png differ diff --git a/pru-cookbook/01case/figures/xlights_twinkle.jpg b/pru-cookbook/01case/figures/xlights_twinkle.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d98d1fd7991ce1d1dea2e60c769854127c28ad8e Binary files /dev/null and b/pru-cookbook/01case/figures/xlights_twinkle.jpg differ diff --git a/pru-cookbook/02start/code/Makefile b/pru-cookbook/02start/code/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a7557fdaa22988d89cec879477ded78522d7116f --- /dev/null +++ b/pru-cookbook/02start/code/Makefile @@ -0,0 +1 @@ +include /var/lib/cloud9/common/Makefile diff --git a/pru-cookbook/02start/code/ai.notes b/pru-cookbook/02start/code/ai.notes new file mode 100644 index 0000000000000000000000000000000000000000..d11ac1d4288af4ac3f1cd5a5aa1ac6cec14cb97f --- /dev/null +++ b/pru-cookbook/02start/code/ai.notes @@ -0,0 +1,59 @@ +Here are some differences between the AI and the Black for the PRU. + +Black +/sys/devices/platform/ocp/ + 4a326004.pruss-soc-bus/ + 4a300000.pruss/ + 4a334000.pru/remoteproc/remoteproc1 + 4a338000.pru/remoteproc/remoteproc2 + + +AI +/sys/devices/platform/44000000.ocp/ + 4b226004.pruss-soc-bus/ + 4b200000.pruss/ + 4b234000.pru/remoteproc/remoteproc0 + 4b238000.pru/remoteproc/remoteproc1 + + + 4b2a6004.pruss-soc-bus/ + 4b280000.pruss/ + 4b2b4000.pru/remoteproc/remoteproc2 + 4b2b8000.pru/remoteproc/remoteproc3 + +LED addresses +https://github.com/beagleboard/BeagleBoard-DeviceTrees/blob/v4.19.x-ti/src/arm/am5729-beagleboneai.dts#L134-L171 + led0 { + label = "beaglebone:green:usr0"; + gpios = <&gpio3 17 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + + led1 { + label = "beaglebone:green:usr1"; + gpios = <&gpio5 5 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + + led2 { + label = "beaglebone:green:usr2"; + gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "cpu"; + default-state = "off"; + }; + + led3 { + label = "beaglebone:green:usr3"; + gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc1"; + default-state = "off"; + }; + + led4 { + label = "beaglebone:green:usr4"; + gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0assoc"; + +GPIO Addresses: Page 404 for TRM \ No newline at end of file diff --git a/pru-cookbook/02start/code/hello.pru0.c b/pru-cookbook/02start/code/hello.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..ab61e79eaafed3a7198532358d9ae3415559048f --- /dev/null +++ b/pru-cookbook/02start/code/hello.pru0.c @@ -0,0 +1,35 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register unsigned int __R30; +volatile register unsigned int __R31; + +void main(void) { + int i; + + uint32_t *gpio1 = (uint32_t *)GPIO1; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + for(i=0; i<10; i++) { + gpio1[GPIO_SETDATAOUT] = USR3; // The the USR3 LED on + + __delay_cycles(500000000/5); // Wait 1/2 second + + gpio1[GPIO_CLEARDATAOUT] = USR3; + + __delay_cycles(500000000/5); + + } + __halt(); +} + +// Turns off triggers +#pragma DATA_SECTION(init_pins, ".init_pins") +#pragma RETAIN(init_pins) +const char init_pins[] = + "/sys/class/leds/beaglebone:green:usr3/trigger\0none\0" \ + "\0\0"; diff --git a/pru-cookbook/02start/code/hello.pru1_1.c b/pru-cookbook/02start/code/hello.pru1_1.c new file mode 100644 index 0000000000000000000000000000000000000000..8cb8146f74c88ee890a5a251108c19642cdb0c75 --- /dev/null +++ b/pru-cookbook/02start/code/hello.pru1_1.c @@ -0,0 +1,35 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register unsigned int __R30; +volatile register unsigned int __R31; + +void main(void) { + int i; + + uint32_t *gpio3 = (uint32_t *)GPIO3; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + for(i=0; i<10; i++) { + gpio3[GPIO_SETDATAOUT] = USR3; // The the USR3 LED on + + __delay_cycles(500000000/5); // Wait 1/2 second + + gpio3[GPIO_CLEARDATAOUT] = USR3; + + __delay_cycles(500000000/5); + + } + __halt(); +} + +// Turns off triggers +#pragma DATA_SECTION(init_pins, ".init_pins") +#pragma RETAIN(init_pins) +const char init_pins[] = + "/sys/class/leds/beaglebone:green:usr3/trigger\0none\0" \ + "\0\0"; diff --git a/pru-cookbook/02start/code/hello2.pru0.c b/pru-cookbook/02start/code/hello2.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..d268d33b637cb9d51a9928589a69ce158101a4e2 --- /dev/null +++ b/pru-cookbook/02start/code/hello2.pru0.c @@ -0,0 +1,42 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register unsigned int __R30; +volatile register unsigned int __R31; + +void main(void) { + int i; + + uint32_t *gpio1 = (uint32_t *)GPIO1; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + for(i=0; i<10; i++) { + gpio1[GPIO_SETDATAOUT] = USR1; // The the USR3 LED on + gpio1[GPIO_CLEARDATAOUT] = USR2; + + // __R30 |= gpio; // Set the GPIO pin to 1 + + __delay_cycles(500000000/5); // Wait 1/2 second + + gpio1[GPIO_CLEARDATAOUT] = USR1; + gpio1[GPIO_SETDATAOUT] = USR2; + + // __R30 &= ~gpio; // Clearn the GPIO pin + + __delay_cycles(500000000/5); + + } + __halt(); +} + +// Turns off triggers +#pragma DATA_SECTION(init_pins, ".init_pins") +#pragma RETAIN(init_pins) +const char init_pins[] = + "/sys/class/leds/beaglebone:green:usr1/trigger\0none\0" \ + "/sys/class/leds/beaglebone:green:usr2/trigger\0none\0" \ + "\0\0"; diff --git a/pru-cookbook/02start/code/hello2.pru1.c b/pru-cookbook/02start/code/hello2.pru1.c new file mode 100644 index 0000000000000000000000000000000000000000..15df54495ecf681b3707a42dfaa6dfae65990559 --- /dev/null +++ b/pru-cookbook/02start/code/hello2.pru1.c @@ -0,0 +1,43 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register unsigned int __R30; +volatile register unsigned int __R31; + +void main(void) { + int i; + + uint32_t *gpio1 = (uint32_t *)GPIO1; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + for(i=0; i<10; i++) { + gpio1[GPIO_SETDATAOUT] = USR1; // The the USR3 LED on + gpio1[GPIO_CLEARDATAOUT] = USR2; + + // __R30 |= gpio; // Set the GPIO pin to 1 + + __delay_cycles(500000000/5); // Wait 1/2 second + + gpio1[GPIO_CLEARDATAOUT] = USR1; + gpio1[GPIO_SETDATAOUT] = USR2; + + // __R30 &= ~gpio; // Clearn the GPIO pin + + __delay_cycles(500000000/5); + + } + __halt(); +} + +// Turns off triggers +#pragma DATA_SECTION(init_pins, ".init_pins") +#pragma RETAIN(init_pins) +const char init_pins[] = + "/sys/class/leds/beaglebone:green:usr1/trigger\0none\0" \ + "/sys/class/leds/beaglebone:green:usr2/trigger\0none\0" \ + "\0\0"; + diff --git a/pru-cookbook/02start/code/hello2.pru1_0.c b/pru-cookbook/02start/code/hello2.pru1_0.c new file mode 100644 index 0000000000000000000000000000000000000000..564e1bc9b8c0fe7df8c21df6594f519d92470690 --- /dev/null +++ b/pru-cookbook/02start/code/hello2.pru1_0.c @@ -0,0 +1,63 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register unsigned int __R30; +volatile register unsigned int __R31; + +void main(void) { + int i; + + // uint32_t *gpio1 = (uint32_t *)GPIO1; + // uint32_t *gpio2 = (uint32_t *)GPIO2; + uint32_t *gpio3 = (uint32_t *)GPIO3; + // uint32_t *gpio4 = (uint32_t *)GPIO4; + uint32_t *gpio5 = (uint32_t *)GPIO5; + uint32_t *gpio6 = (uint32_t *)GPIO6; + // uint32_t *gpio7 = (uint32_t *)GPIO7; + uint32_t *gpio8 = (uint32_t *)GPIO8; + + // Select which pins to toggle. These are all on pru1_1 + uint32_t gpio = P9_16 | P8_15 | P8_16 | P8_26; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + for(i=0; i<100; i++) { + gpio5[GPIO_SETDATAOUT] = USR1; // Turn the USR1 LED on + gpio3[GPIO_CLEARDATAOUT] = USR2; + gpio8[GPIO_SETDATAOUT] = P8_17; + gpio6[GPIO_SETDATAOUT] = P9_25; + + __R30 |= gpio; // Set the GPIO pin to 1 + + __delay_cycles(500000000/5); // Wait 1/2 second + + gpio5[GPIO_CLEARDATAOUT] = USR1; + gpio3[GPIO_SETDATAOUT] = USR2; + gpio8[GPIO_CLEARDATAOUT] = P8_17; + gpio6[GPIO_CLEARDATAOUT] = P9_25; + + __R30 &= ~gpio; // Clear the GPIO pin + + __delay_cycles(500000000/5); + + if((__R31&P8_19) == P8_19) { + gpio3[GPIO_CLEARDATAOUT] = USR3; // Turn on LED + } else + gpio3[GPIO_SETDATAOUT] = USR3; // Turn off LED + } + __halt(); +} + +// Turns off triggers +#pragma DATA_SECTION(init_pins, ".init_pins") +#pragma RETAIN(init_pins) +const char init_pins[] = + "/sys/class/leds/beaglebone:green:usr1/trigger\0none\0" \ + "/sys/class/leds/beaglebone:green:usr2/trigger\0none\0" \ + "/sys/class/gpio/export\0 177\0" \ + "/sys/class/gpio/gpio177/direction\0out\0" \ + "\0\0"; + diff --git a/pru-cookbook/02start/code/hello2.pru1_1.c b/pru-cookbook/02start/code/hello2.pru1_1.c new file mode 100644 index 0000000000000000000000000000000000000000..564e1bc9b8c0fe7df8c21df6594f519d92470690 --- /dev/null +++ b/pru-cookbook/02start/code/hello2.pru1_1.c @@ -0,0 +1,63 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register unsigned int __R30; +volatile register unsigned int __R31; + +void main(void) { + int i; + + // uint32_t *gpio1 = (uint32_t *)GPIO1; + // uint32_t *gpio2 = (uint32_t *)GPIO2; + uint32_t *gpio3 = (uint32_t *)GPIO3; + // uint32_t *gpio4 = (uint32_t *)GPIO4; + uint32_t *gpio5 = (uint32_t *)GPIO5; + uint32_t *gpio6 = (uint32_t *)GPIO6; + // uint32_t *gpio7 = (uint32_t *)GPIO7; + uint32_t *gpio8 = (uint32_t *)GPIO8; + + // Select which pins to toggle. These are all on pru1_1 + uint32_t gpio = P9_16 | P8_15 | P8_16 | P8_26; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + for(i=0; i<100; i++) { + gpio5[GPIO_SETDATAOUT] = USR1; // Turn the USR1 LED on + gpio3[GPIO_CLEARDATAOUT] = USR2; + gpio8[GPIO_SETDATAOUT] = P8_17; + gpio6[GPIO_SETDATAOUT] = P9_25; + + __R30 |= gpio; // Set the GPIO pin to 1 + + __delay_cycles(500000000/5); // Wait 1/2 second + + gpio5[GPIO_CLEARDATAOUT] = USR1; + gpio3[GPIO_SETDATAOUT] = USR2; + gpio8[GPIO_CLEARDATAOUT] = P8_17; + gpio6[GPIO_CLEARDATAOUT] = P9_25; + + __R30 &= ~gpio; // Clear the GPIO pin + + __delay_cycles(500000000/5); + + if((__R31&P8_19) == P8_19) { + gpio3[GPIO_CLEARDATAOUT] = USR3; // Turn on LED + } else + gpio3[GPIO_SETDATAOUT] = USR3; // Turn off LED + } + __halt(); +} + +// Turns off triggers +#pragma DATA_SECTION(init_pins, ".init_pins") +#pragma RETAIN(init_pins) +const char init_pins[] = + "/sys/class/leds/beaglebone:green:usr1/trigger\0none\0" \ + "/sys/class/leds/beaglebone:green:usr2/trigger\0none\0" \ + "/sys/class/gpio/export\0 177\0" \ + "/sys/class/gpio/gpio177/direction\0out\0" \ + "\0\0"; + diff --git a/pru-cookbook/02start/code/hello2.pru2_0.c b/pru-cookbook/02start/code/hello2.pru2_0.c new file mode 100644 index 0000000000000000000000000000000000000000..564e1bc9b8c0fe7df8c21df6594f519d92470690 --- /dev/null +++ b/pru-cookbook/02start/code/hello2.pru2_0.c @@ -0,0 +1,63 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register unsigned int __R30; +volatile register unsigned int __R31; + +void main(void) { + int i; + + // uint32_t *gpio1 = (uint32_t *)GPIO1; + // uint32_t *gpio2 = (uint32_t *)GPIO2; + uint32_t *gpio3 = (uint32_t *)GPIO3; + // uint32_t *gpio4 = (uint32_t *)GPIO4; + uint32_t *gpio5 = (uint32_t *)GPIO5; + uint32_t *gpio6 = (uint32_t *)GPIO6; + // uint32_t *gpio7 = (uint32_t *)GPIO7; + uint32_t *gpio8 = (uint32_t *)GPIO8; + + // Select which pins to toggle. These are all on pru1_1 + uint32_t gpio = P9_16 | P8_15 | P8_16 | P8_26; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + for(i=0; i<100; i++) { + gpio5[GPIO_SETDATAOUT] = USR1; // Turn the USR1 LED on + gpio3[GPIO_CLEARDATAOUT] = USR2; + gpio8[GPIO_SETDATAOUT] = P8_17; + gpio6[GPIO_SETDATAOUT] = P9_25; + + __R30 |= gpio; // Set the GPIO pin to 1 + + __delay_cycles(500000000/5); // Wait 1/2 second + + gpio5[GPIO_CLEARDATAOUT] = USR1; + gpio3[GPIO_SETDATAOUT] = USR2; + gpio8[GPIO_CLEARDATAOUT] = P8_17; + gpio6[GPIO_CLEARDATAOUT] = P9_25; + + __R30 &= ~gpio; // Clear the GPIO pin + + __delay_cycles(500000000/5); + + if((__R31&P8_19) == P8_19) { + gpio3[GPIO_CLEARDATAOUT] = USR3; // Turn on LED + } else + gpio3[GPIO_SETDATAOUT] = USR3; // Turn off LED + } + __halt(); +} + +// Turns off triggers +#pragma DATA_SECTION(init_pins, ".init_pins") +#pragma RETAIN(init_pins) +const char init_pins[] = + "/sys/class/leds/beaglebone:green:usr1/trigger\0none\0" \ + "/sys/class/leds/beaglebone:green:usr2/trigger\0none\0" \ + "/sys/class/gpio/export\0 177\0" \ + "/sys/class/gpio/gpio177/direction\0out\0" \ + "\0\0"; + diff --git a/pru-cookbook/02start/code/hello2.pru2_1.c b/pru-cookbook/02start/code/hello2.pru2_1.c new file mode 100644 index 0000000000000000000000000000000000000000..564e1bc9b8c0fe7df8c21df6594f519d92470690 --- /dev/null +++ b/pru-cookbook/02start/code/hello2.pru2_1.c @@ -0,0 +1,63 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register unsigned int __R30; +volatile register unsigned int __R31; + +void main(void) { + int i; + + // uint32_t *gpio1 = (uint32_t *)GPIO1; + // uint32_t *gpio2 = (uint32_t *)GPIO2; + uint32_t *gpio3 = (uint32_t *)GPIO3; + // uint32_t *gpio4 = (uint32_t *)GPIO4; + uint32_t *gpio5 = (uint32_t *)GPIO5; + uint32_t *gpio6 = (uint32_t *)GPIO6; + // uint32_t *gpio7 = (uint32_t *)GPIO7; + uint32_t *gpio8 = (uint32_t *)GPIO8; + + // Select which pins to toggle. These are all on pru1_1 + uint32_t gpio = P9_16 | P8_15 | P8_16 | P8_26; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + for(i=0; i<100; i++) { + gpio5[GPIO_SETDATAOUT] = USR1; // Turn the USR1 LED on + gpio3[GPIO_CLEARDATAOUT] = USR2; + gpio8[GPIO_SETDATAOUT] = P8_17; + gpio6[GPIO_SETDATAOUT] = P9_25; + + __R30 |= gpio; // Set the GPIO pin to 1 + + __delay_cycles(500000000/5); // Wait 1/2 second + + gpio5[GPIO_CLEARDATAOUT] = USR1; + gpio3[GPIO_SETDATAOUT] = USR2; + gpio8[GPIO_CLEARDATAOUT] = P8_17; + gpio6[GPIO_CLEARDATAOUT] = P9_25; + + __R30 &= ~gpio; // Clear the GPIO pin + + __delay_cycles(500000000/5); + + if((__R31&P8_19) == P8_19) { + gpio3[GPIO_CLEARDATAOUT] = USR3; // Turn on LED + } else + gpio3[GPIO_SETDATAOUT] = USR3; // Turn off LED + } + __halt(); +} + +// Turns off triggers +#pragma DATA_SECTION(init_pins, ".init_pins") +#pragma RETAIN(init_pins) +const char init_pins[] = + "/sys/class/leds/beaglebone:green:usr1/trigger\0none\0" \ + "/sys/class/leds/beaglebone:green:usr2/trigger\0none\0" \ + "/sys/class/gpio/export\0 177\0" \ + "/sys/class/gpio/gpio177/direction\0out\0" \ + "\0\0"; + diff --git a/pru-cookbook/02start/code/setup.sh b/pru-cookbook/02start/code/setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..eaf9943a2c375bc9f16b158994492b1198997dda --- /dev/null +++ b/pru-cookbook/02start/code/setup.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +export TARGET=hello.pru0 + +echo TARGET=$TARGET diff --git a/pru-cookbook/02start/code/setup2.sh b/pru-cookbook/02start/code/setup2.sh new file mode 100755 index 0000000000000000000000000000000000000000..76dd6713f4f55d364403bf6a187b68e2e66172b0 --- /dev/null +++ b/pru-cookbook/02start/code/setup2.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +export TARGET=hello2.pru1 + +echo TARGET=$TARGET diff --git a/pru-cookbook/02start/figures/BB_AI_BeautyAngle_800px.jpg b/pru-cookbook/02start/figures/BB_AI_BeautyAngle_800px.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0070dd54ebd10285f016e792cdfbf862b273cf1c Binary files /dev/null and b/pru-cookbook/02start/figures/BB_AI_BeautyAngle_800px.jpg differ diff --git a/pru-cookbook/02start/figures/PocketBeagle-size-compare-small.jpg b/pru-cookbook/02start/figures/PocketBeagle-size-compare-small.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f7d440bdab452fd3251a136bcc652018cacf8357 Binary files /dev/null and b/pru-cookbook/02start/figures/PocketBeagle-size-compare-small.jpg differ diff --git a/pru-cookbook/02start/figures/beagle-blue.png b/pru-cookbook/02start/figures/beagle-blue.png new file mode 100644 index 0000000000000000000000000000000000000000..8777a254b074347d31b151f1cad690bdf71be39c Binary files /dev/null and b/pru-cookbook/02start/figures/beagle-blue.png differ diff --git a/pru-cookbook/02start/figures/c9.png b/pru-cookbook/02start/figures/c9.png new file mode 100644 index 0000000000000000000000000000000000000000..edb7a272bf57253b007ceaf931e8a6e0696a198d Binary files /dev/null and b/pru-cookbook/02start/figures/c9.png differ diff --git a/pru-cookbook/02start/figures/c9ShowHome.png b/pru-cookbook/02start/figures/c9ShowHome.png new file mode 100644 index 0000000000000000000000000000000000000000..91f268137135041853691ba981c6cfd0664108f3 Binary files /dev/null and b/pru-cookbook/02start/figures/c9ShowHome.png differ diff --git a/pru-cookbook/02start/figures/edumip.png b/pru-cookbook/02start/figures/edumip.png new file mode 100644 index 0000000000000000000000000000000000000000..e0faa0174e27f3daac479940334babd3a37c1bd6 Binary files /dev/null and b/pru-cookbook/02start/figures/edumip.png differ diff --git a/pru-cookbook/02start/figures/etcher.png b/pru-cookbook/02start/figures/etcher.png new file mode 100644 index 0000000000000000000000000000000000000000..6c7c92fc6ea019c2025ef93194d28b88ee841b1f Binary files /dev/null and b/pru-cookbook/02start/figures/etcher.png differ diff --git a/pru-cookbook/02start/figures/latest-images.png b/pru-cookbook/02start/figures/latest-images.png new file mode 100644 index 0000000000000000000000000000000000000000..c6351706e16cea91b8084121e2c393686d329344 Binary files /dev/null and b/pru-cookbook/02start/figures/latest-images.png differ diff --git a/pru-cookbook/02start/figures/product_detail_black_sm.jpg b/pru-cookbook/02start/figures/product_detail_black_sm.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e26e0c27fb7527d0c3a7ed75c818c8ae0c8dec90 Binary files /dev/null and b/pru-cookbook/02start/figures/product_detail_black_sm.jpg differ diff --git a/pru-cookbook/02start/start.rst b/pru-cookbook/02start/start.rst new file mode 100644 index 0000000000000000000000000000000000000000..dee7273df5bb6ed688a21156b65cf02433d76667 --- /dev/null +++ b/pru-cookbook/02start/start.rst @@ -0,0 +1,396 @@ +.. _pru-cookbook-start: + +Getting Started +################ + +We assume you have some experience with the Beagle and are here to learn about +the PRU. This chapter discusses what Beagles are out there, how to load the +latest software image on your beagle, how to run the Cloud9 IDE and how to +blink an LED. + +If you already have your Beagle and know your way around it, you can find the +code (and the whole book) on the PRU Cookbook github site: +https://github.com/MarkAYoder/PRUCookbook. + +Selecting a Beagle +==================== + +Problem +---------- + +Which Beagle should you use? + +Solution +---------- + +http://beagleboard.org/boards lists the many Beagles from which to choose. +Here we'll give examples for the venerable `BeagleBone Black <http://beagleboard.org/black>`_, +the robotics `BeagleBone Blue <http://beagleboard.org/blue>`_, +tiny `PockeBeagle <http://beagleboard.org/pocket>`_ and the powerful `AI <http://beagleboard.org/ai>`_. +All the examples should also run on the other Beagles too. + +Discussion +------------ + +BeagleBone Black +~~~~~~~~~~~~~~~~~ + +If you aren't sure which Beagle to use, it's hard to go wrong with the +`BeagleBone Black <http://beagleboard.org/black>`_. It's the most popular +member of the open hardware Beagle family. + +.. _start_black: + +BeagleBone Black +~~~~~~~~~~~~~~~~~ + +.. figure:: figures/product_detail_black_sm.jpg + :align: center + :alt: BeableBone Black + +The Black has: + +* AM335x 1GHz ARM® Cortex-A8 processor +* 512MB DDR3 RAM +* 4GB 8-bit eMMC on-board flash storage +* 3D graphics accelerator +* NEON floating-point accelerator +* 2x PRU 32-bit microcontrollers +* USB client for power & communications +* USB host +* Ethernet +* HDMI +* 2x 46 pin headers + +See http://beagleboard.org/black for more details. + +BeagleBone Blue +~~~~~~~~~~~~~~~~~ + +The `Blue <http://beagleboard.org/blue>`_ is a good choice if you are doing robotics. + +.. _start_blue: + +BeagleBone Blue +~~~~~~~~~~~~~~~~ + +.. figure:: figures/beagle-blue.png + :align: center + :alt: BeagleBone Blue + +The Blue has everything the Black has except it has no Ethernet or HDMI. +But it also has: + +* Wireless: 802.11bgn, Bluetooth 4.1 and BLE +* Battery support: 2-cell LiPo with balancing, LED state-of-charge monitor +* Charger input: 9-18V +* Motor control: 8 6V servo out, 4 bidirectional DC motor out, 4 quadrature encoder in +* Sensors: 9 axis IMU (accels, gyros, magnetometer), barometer, thermometer +* User interface: 11 user programmable LEDs, 2 user programmable buttons + +In addition you can mount the Blue on the +https://www.renaissancerobotics.com/eduMIP.html[EduMIP kit] as shown in +:ref:`start_edumip` to get a balancing robot. + +.. _start_edumip: + +BeagleBone Blue EduMIP Kit +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/edumip.png + :align: center + :alt: BeagleBone Blue EduMIP Kit + +https://www.hackster.io/53815/controlling-edumip-with-ni-labview-2005f8 +shows how to assemble the robot and control it from +`LabVIEW <http://www.ni.com/en-us/shop/labview.html>`_. + +PocketBeagle +~~~~~~~~~~~~~~ + +The `PocketBeagle <http://beagleboard.org/pocket>`_ is the smallest member of the +Beagle family. It is an ultra-tiny-yet-complete Beagle that is software +compatible with the other Beagles. + +.. _start_pocket: + +PocketBeagle +~~~~~~~~~~~~~ + +.. figure:: figures/PocketBeagle-size-compare-small.jpg + :align: center + :alt: PocketBeagle + +The Pocket is based on the same processor as the Black and Blue and has: + +* 8 analog inputs +* 44 digital I/Os and +* numerous digital interface peripherals + +See http://beagleboard.org/pocket for more details. + +BeagleBone AI +~~~~~~~~~~~~~~~~~ + +If you want to do deep learning, try the `BeagleBone AI <http://beagleboard.org/ai>`_. + +.. _start_ai: + +BeagleBone AI +~~~~~~~~~~~~~~ + +.. figure:: figures/BB_AI_BeautyAngle_800px.jpg + :align: center + :alt: BeableBone AI + +The AI has: + +* Dual Arm® Cortex®-A15 microprocessor subsystem +* 2 C66x floating-point VLIW DSPs +* 2.5MB of on-chip L3 RAM +* 2x dual Arm® Cortex®-M4 co-processors +* 4x Embedded Vision Engines (EVEs) +* 2x dual-core Programmable Real-Time Unit and Industrial Communication SubSystem (PRU-ICSS) +* 2D-graphics accelerator (BB2D) subsystem +* Dual-core PowerVR® SGX544â„¢ 3D GPU +* IVA-HD subsystem (4K @ 15fps encode and decode support for H.264, 1080p60 for others) +* BeagleBone Black mechanical and header compatibility +* 1GB RAM and 16GB on-board eMMC flash with high-speed interface +* USB type-C for power and superspeed dual-role controller; and USB type-A host +* Gigabit Ethernet, 2.4/5GHz WiFi, and Bluetooth +* microHDMI +* Zero-download out-of-box software experience with Debian GNU/Linux + + +Installing the Latest OS on Your Bone +====================================== + +Problem +--------- + +You want to find the lastest version of Debian that is available for your Bone. + +Solution +--------- + +On your host computer open a browser and go to +http://beagleboard.org/latest-images. + +.. TODO Update links + +This shows you two current choices of recent Debian images, +one for the BeagleBone AI +(`AM5729 Debian 10.3 2020-04-06 8GB SD IoT TIDL <https://debian.beagleboard.org/images/am57xx-debian-10.3-iot-tidl-armhf-2020-04-06-6gb.img.xz>`_) and +one for all the other Beagles ( +`AM3358 Debian 10.3 2020-04-06 4GB SD IoT <https://debian.beagleboard.org/images/bone-debian-10.3-iot-armhf-2020-04-06-4gb.img.xz>`_). +Download the one for your Beagle. + +Latest Debian images +~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/latest-images.png + :align: center + :alt: Latest Debian images + +It contains all the packages we'll need. + +Flashing a Micro SD Card +========================= + +Problem +--------- + +I've downloaded the image and need to flash my micro SD card. + +Solution +--------- + +Get a micro SD card that has at least 4GB and preferibly 8GB. + +There are many ways to flash the card, but the best seems to be Etcher by +https://www.balena.io/. Go to https://www.balena.io/etcher/ and download the version for your host +computer. Fire up Etcher, select the image you just downloaded (no need to +uncompress it, Etcher does it for you), select the SD card and hit the *Flash* +button and wait for it to finish. + +.. _start_etcher: + +Etcher +~~~~~~~~ + +.. figure:: figures/etcher.png + :align: center + :alt: Ether + +Once the SD is flashed, insert it in the Beagle and power it up. + +Cloud9 IDE +=========== + +Problem +------------ + +How do I manage and edit my files? + +Solution +------------ + +The image you downloaded includes `Cloud9 <https://aws.amazon.com/cloud9/>`_, +a web-based intergrated development environment (IDE) as shown in +:ref:`start_c9`. + +.. _start_c9: + +Cloud9 IDE +~~~~~~~~~~~~ + +.. figure:: figures/c9.png + :align: center + :alt: The Cloud9 IDE + +Just point the browswer on your host computer to http://192.168.7.2 +and start exploring. If you want the files in your home directory to appear +in the tree structure click the settings gear and select *Show Home in Favorites* +as shown in :ref:`start_c9_show_home`. + +.. _start_c9_show_home: + +Cloud9 Showing Home files +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/c9ShowHome.png + :align: center + :alt: Cloud9 showing home files + + +If you want to edit files beyond your home directory you can link to the root file system by: + +.. code-block:: bash + + bone$ *cd* + bone$ *ln -s / root* + bone$ *cd root* + bone$ *ls* + bbb-uEnv.txt boot etc ID.txt lost+found mnt opt root sbin sys usr + bin dev home lib media nfs-uEnv.txt proc run srv tmp var + +Now you can reach all the files from Cloud9. + +Getting Example Code +==================== + +Problem +--------- + +You are ready to start playing with the examples and need to find the code. + +Solution +--------- + +You can find the code (and the whole book) on the PRU Cookbook github site: +<https://github.com/MarkAYoder/PRUCookbook/tree/master/docs>. Just clone +it on your Beagle and then look in the *docs* directory. + +.. code-block::bash + + bone$ *git clone https://github.com/MarkAYoder/PRUCookbook.git* + bone$ *cd PRUCookbook/docs/* + bone$ *ls -F* + 01case/ 05blocks/ book.adoc copyright.adoc index.html projects.adoc + 02start/ 06io/ book.html hack.sh* Makefile projects.html + 03details/ 07more/ book.pdf header.adoc notes.adoc style.adoc + 04debug/ 08ai/ common/ index.adoc notes.html style.html + + +Each chapter has its own directory and within that directory is a **code** directory that has all of the code. + +.. code-block::bash + + bone$ *cd 02start/code/* + bone$ *ls* + hello.pru0.c hello.pru1_1.c Makefile setup.sh + +Go and explore. + +Blinking an LED +================= + +Problem +--------- + +You want to make sure everything is set up by blinking an LED. + +Solution +---------- + +The 'hello, world' of the embedded world is to flash an LED. :ref:`start_hello` +is some code that blinks the ``USR3`` LED ten times using the PRU. + +.. TODO The *'s and _'s in the code are messing with the formatting. + +.. _start_hello: + +hello.pru0.c +~~~~~~~~~~~~~ + +:download:`hello.pru0.c <code/hello.pru0.c>` + +Later chapters will go into details of how this code works, but if you want +to run it right now do the following. + +.. code-block:: bash + + bone$ *git clone https://github.com/MarkAYoder/PRUCookbook.git* + bone$ *cd PRUCookbook/docs/02start/code* + +.. tip:: + + If the following doesn't work see + `Compiling with clpru and lnkpru <../03details/details.html#_compiling_with_clpru_and_lnkpru>`_ + for instillation instructions. + +.. _start_running_code: + +Running Code on the Black or Pocket +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + + bone$ *make TARGET=hello.pru0* + /var/lib/cloud9/common/Makefile:28: MODEL=TI_AM335x_BeagleBone_Black,TARGET=hello.pru0,COMMON=/var/lib/cloud9/common + /var/lib/cloud9/common/Makefile:147: GEN_DIR=/tmp/cloud9-examples,CHIP=am335x,PROC=pru,PRUN=0,PRU_DIR=/sys/class/remoteproc/remoteproc1,EXE=.out + - Stopping PRU 0 + - copying firmware file /tmp/cloud9-examples/hello.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + writing "none" to "/sys/class/leds/beaglebone:green:usr3/trigger" + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /sys/class/remoteproc/remoteproc1 + + +Running Code on the AI +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + + bone$ *make TARGET=hello.pru1_1* + /var/lib/cloud9/common/Makefile:28: MODEL=BeagleBoard.org_BeagleBone_AI,TARGET=hello.pru1_1 + - Stopping PRU 1_1 + CC hello.pru1_1.c + "/var/lib/cloud9/common/prugpio.h", line 4: warning #1181-D: #warning directive: "Found AI" + LD /tmp/cloud9-examples/hello.pru1_1.o + - copying firmware file /tmp/cloud9-examples/hello.pru1_1.out to /lib/firmware/am57xx-pru1_1-fw + write_init_pins.sh + writing "none" to "/sys/class/leds/beaglebone:green:usr3/trigger" + - Starting PRU 1_1 + MODEL = BeagleBoard.org_BeagleBone_AI + PROC = pru + PRUN = 1_1 + PRU_DIR = /dev/remoteproc/pruss1-core1 + rm /tmp/cloud9-examples/hello.pru1_1.o + +Look quickly and you will see the ``USR3`` LED blinking. + +Later sections give more details on how all this works. diff --git a/pru-cookbook/03details/code/Makefile b/pru-cookbook/03details/code/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a7557fdaa22988d89cec879477ded78522d7116f --- /dev/null +++ b/pru-cookbook/03details/code/Makefile @@ -0,0 +1 @@ +include /var/lib/cloud9/common/Makefile diff --git a/pru-cookbook/03details/code/encoder_setup.sh b/pru-cookbook/03details/code/encoder_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..ffc4ad68842fb6314173b523425295893cd05fc1 --- /dev/null +++ b/pru-cookbook/03details/code/encoder_setup.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Configure the pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine + +# Configure eQEP pins +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_92 P9_27 P8_35 P8_33 P8_12 P8_11 P8_41 P8_42" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P1_31 P2_34 P2_10 P2_24 P2_33" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin qep + config-pin -q $pin +done + +########################################## +# Configure PRU pins +if [ $machine = "Black" ]; then + echo " Found" + pins="P8_16 P8_15" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P2_09 P2_18" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruin + config-pin -q $pin +done diff --git a/pru-cookbook/03details/code/gpio_setup.sh b/pru-cookbook/03details/code/gpio_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..e676ed7abe2a6beaf62d3ce6c56f5aa151d86700 --- /dev/null +++ b/pru-cookbook/03details/code/gpio_setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +export TARGET=gpio.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_11" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P2_05" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin gpio + config-pin -q $pin +done diff --git a/pru-cookbook/03details/code/servos_setup.sh b/pru-cookbook/03details/code/servos_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..330e8f34e30d7fd97d9368861ded65817222e903 --- /dev/null +++ b/pru-cookbook/03details/code/servos_setup.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P8_27 P8_28 P8_29 P8_30 P8_39 P8_40 P8_41 P8_42" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P2_35 P1_35 P1_02 P1_04" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruout + config-pin -q $pin +done \ No newline at end of file diff --git a/pru-cookbook/03details/details.rst b/pru-cookbook/03details/details.rst new file mode 100644 index 0000000000000000000000000000000000000000..379eea3edfb4f18c5fba1c3fc036e325153905b0 --- /dev/null +++ b/pru-cookbook/03details/details.rst @@ -0,0 +1,490 @@ +.. _pru-cookbook-details: + +Running a Program; Configuring Pins +#################################### + +There are a lot of details in compiling and running PRU code. +Fortunately those details are captured in a common `Makefile` that is +used througout this book. This chapter shows how to use the `Makefile` to +compile code and also start and stop the PRUs. + +The following are resources used in this chapter. + +Resources +~~~~~~~~~~ + +* `PRU Code Generation Tools - Compiler <http://software-dl.ti.com/codegen/esd/cgt_public_sw/PRU/2.1.5/ti_cgt_pru_2.1.5_armlinuxa8hf_busybox_installer.sh>`_ +* `PRU Software Support Package <http://git.ti.com/pru-software-support-package>`_ +* `PRU Optimizing C/C++ Compiler <http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf>`_ +* `PRU Assembly Language Tools <http://www.ti.com/lit/ug/spruhv6b/spruhv6b.pdf>`_ +* `AM572x Technical Reference Manual <http://www.ti.com/lit/pdf/spruhz6l>`_ (AI) +* `AM335x Technical Reference Manual <http://www.ti.com/lit/pdf/spruh73>`_ (All others) + +Getting Example Code +===================== + +Problem +--------- + +I want to get the files used in this book. + +Solution +--------- + +It's all on a GitHub repository. + +.. code-block:: bash + + bone$ git clone https://github.com/MarkAYoder/PRUCookbook.git + +Compiling with clpru and lnkpru +================================ + + +Problem +--------- + +You need details on the c compiler, linker and other tools for the PRU. + +Solution +--------- + +The PRU compiler and linker are already installed on many images. +They are called ``clpru`` and ``lnkpru``. Do the following to see if ``clpru`` is installed. + +.. code-block:: bash + + bone$ which clpru + /usr/bin/clpru + +.. tip:: + If ``clpru`` isn't installed, follow the instructions at + https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#TI_PRU_Code_Generation_Tools + to install it. + +.. code-block:: bash + + bone$ sudo apt update + bone$ sudo apt install ti-pru-cgt-installer + + +Details on each can be found here: + +* `PRU Optimizing C/C++ Compiler <http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf>`_ +* `PRU Assembly Language Tools <http://www.ti.com/lit/ug/spruhv6b/spruhv6b.pdf>`_ + +In fact there are PRU versions of many of the standard code generation tools. + +code tools +~~~~~~~~~~~ +.. code-block:: bash + + bone$ ls /usr/bin/*pru + /usr/bin/abspru /usr/bin/clistpru /usr/bin/hexpru /usr/bin/ofdpru + /usr/bin/acpiapru /usr/bin/clpru /usr/bin/ilkpru /usr/bin/optpru + /usr/bin/arpru /usr/bin/dempru /usr/bin/libinfopru /usr/bin/rc_test_encoders_pru + /usr/bin/asmpru /usr/bin/dispru /usr/bin/lnkpru /usr/bin/strippru + /usr/bin/cgpru /usr/bin/embedpru /usr/bin/nmpru /usr/bin/xrefpru + +See the `PRU Assembly Language Tools <http://www.ti.com/lit/ug/spruhv6b/spruhv6b.pdf>`_ for more details. + +Making sure the PRUs are configured +==================================== + +Problem +--------- + +When running the Makefile for the PRU you get and error about ``/dev/remoteproc`` is missing. + +Solution +--------- + +Edit ``/boot/uEnv.txt`` and enble pru_rproc by doing the following. + +.. code-block:: bash + + bone$ *sudo vi /boot/uEnv.txt* + +Around line 40 you will see: + +.. code-block:: bash + + ###pru_rproc (4.19.x-ti kernel) + uboot_overlay_pru=AM335X-PRU-RPROC-4-19-TI-00A0.dtbo + +Uncomment the ``uboot_overlay`` line as shown and then reboot. +``/dev/remoteproc`` should now be there. + +.. code-block:: bash + + bone$ sudo reboot + bone$ ls -ls /dev/remoteproc/ + total 0 + 0 lrwxrwxrwx 1 root root 33 Jul 29 16:12 pruss-core0 -> /sys/class/remoteproc/remoteproc1 + 0 lrwxrwxrwx 1 root root 33 Jul 29 16:12 pruss-core1 -> /sys/class/remoteproc/remoteproc2 + +Compiling and Running +====================== + +Problem +--------- + +I want to compile and run an example. + +Solution +--------- + +Change to the directory of the code you want to run. + +.. code-block:: bash + + bone$ cd PRUCookbook/docs/06io/code + bone$ ls + gpio.pru0.c Makefile setup.sh + +Source the setup file. + +.. code-block:: bash + + bone$ source setup.sh + TARGET=gpio.pru0 + PocketBeagle Found + P2_05 + Current mode for P2_05 is: gpio + Current mode for P2_05 is: gpio + +Now you are ready to compile and run. This is automated for you in the Makefile + +.. code-block:: bash + + bone$ make + /var/lib/cloud9/common/Makefile:28: MODEL=TI_AM335x_BeagleBone_Black,TARGET=gpio.pru0,COMMON=/var/lib/cloud9/common + /var/lib/cloud9/common/Makefile:147: GEN_DIR=/tmp/cloud9-examples,CHIP=am335x,PROC=pru,PRUN=0,PRU_DIR=/sys/class/remoteproc/remoteproc1,EXE=.out + - Stopping PRU 0 + /bin/sh: 1: echo: echo: I/O error + Cannot stop 0 + CC gpio.pru0.c + "/var/lib/cloud9/common/prugpio.h", line 53: warning #1181-D: #warning directive: "Found am335x" + LD /tmp/cloud9-examples/gpio.pru0.o + - copying firmware file /tmp/cloud9-examples/gpio.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + writing "out" to "/sys/class/gpio/gpio30/direction" + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /sys/class/remoteproc/remoteproc1 + rm /tmp/cloud9-examples/gpio.pru0.o + +Congratulations, your are now running a PRU. If you have an LED attached to +``P9_11`` on the Black, or ``P2_05`` on the Pocket, it should be blinking. + +Discussion +------------ + +The ``setup.sh`` file sets the ``TARGET`` to the file you want to compile. +Set it to the filename, without the ``.c`` extension (``gpio.pru0``). +The file extension ``.pru0`` specifies the number of the PRU you are using +(either ``1_0``, ``1_1``, ``2_0``, ``2_1`` on the AI or ``0`` or ``1`` on the others) + +You can override the ``TARGET`` on the command line. + +.. code-block:: bash + + bone$ cp gpio.pru0.c gpio.pru1.c + bone$ export TARGET=gpio.pru1 + +Notice the ``TARGET`` doesn't have the ``.c`` on the end. + +You can also specify them when running ``make``. +.. code-block:: bash + + bone$ cp gpio.pru0.c gpio.pru1.c + bone$ make TARGET=gpio.pru1 + +The setup file also contains instructions to figure out which Beagle you are running +and then configure the pins acordingly. + +setup.sh +~~~~~~~~~ + +:download:`gpio_setup.sh <code/gpio_setup.sh>` + +.. table:: + + +-----+---------------------------------------------------+ + |Line | Explanation | + +=====+===================================================+ + |2-5 | Set which PRU to use and which file to compile. | + +-----+---------------------------------------------------+ + |7 | Figure out which type of Beagle we have. | + +-----+---------------------------------------------------+ + |9-21 | Based on the type, set the `pins`. | + +-----+---------------------------------------------------+ + |23-28| Configure (set the pin mux) for each of the pins. | + +-----+---------------------------------------------------+ + +.. tip:: + + The BeagleBone AI has it's pins preconfigured at boot time, so there's no + need to use ``config-pin``. + + +The ``Makefile`` stops the PRU, compiles the file and moves it where it will +be loaded, and then restarts the PRU. + +Stopping and Starting the PRU +============================== + +Problem +--------- + +I want to stop and start the PRU. + +Solution +--------- + +It's easy, if you already have ``TARGET`` set up: + +.. code-block:: bash + + bone$ make stop + - Stopping PRU 0 + stop + bone$ make start + - Starting PRU 0 + start + +See :ref:`../04debug/debug.html#_dmesg_hw,dmesg -Hw` to see how to tell if the PRU +is stopped. + +This assumes ``TARGET`` is set to the PRU you are using. +If you want to control the other PRU use: + +.. code-block:: bash + + bone$ cp gpio.pru0.c gpio.pru1.c + bone$ make TARGET=gpio.pru1 + bone$ make TARGET=gpio.pru1 stop + bone$ make TARGET=gpio.pru1 start + + +.. _details_makefile: + +The Standard Makefile +===================== + +Problem +--------- + +There are all sorts of options that need to be set when compiling +a program. How can I be sure to get them all right? + +Solution +--------- + +The surest way to make sure everything is right is to use our +standard ``Makefile``. + +Discussion +----------- + +It's assumed you already know how Makefiles work. If not, there are +many resources online that can bring you up to speed. +Here is the local ``Makefile`` used throughout this book. + +Local Makefile +~~~~~~~~~~~~~~~ + +:download:`Makefile <code/Makefile>` + +Each of the local Makefiles refer to the same standard Makefile. The details +of how the Makefile works is beyond the scope of this cookbook. + +Fortunately you shouldn't have to modify the `Makefile`. + +.. _detail_linker: + +The Linker Command File - am335x_pru.cmd +========================================= + + +Problem +--------- + +The linker needs to be told where in memory to place the code and variables. + +Solution +--------- + +``am335x_pru.cmd`` is the standard linker command file that tells the linker +where to put what for the BeagleBone Black and Blue, and the Pocket. +The ``am57xx_pru.cmd`` does the same for the AI. +Both files can be found in ``/var/lib/cloud9/common``. + +am335x_pru.cmd +~~~~~~~~~~~~~~~~ + +:download:`am335x_pru.cmd <code/am335x_pru.cmd>` + +.. TODO does this need updating? + +The cmd file for the AI is about the same, with appropriate addresses for the AI. + +Discussion +----------- + + +The important things to notice in the file are given in the following table. + +AM335x_PRU.cmd important things +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. table:: + + +-----+-----------------------------------------------------------------------------------------+ + |Line | Explanation | + +=====+=========================================================================================+ + |16 | This is where the instructions are stored. See page 206 of the | + | | `AM335x Technical Reference Manual <https://www.ti.com/lit/ug/spruh73p/spruh73p.pdf>`_ | + | | Or see page 417 of | + | | `AM572x Technical Reference Manual <http://www.ti.com/lit/pdf/spruhz6l>`_ for the AI. | + +-----+-----------------------------------------------------------------------------------------+ + |22 | This is where PRU 0's DMEM 0 is mapped. It's also where PRU 1's | + | | DMEM 1 is mapped. | + +-----+-----------------------------------------------------------------------------------------+ + |23 | The reverse to above. PRU 0's DMEM 1 appears here and PRU 1's DMEM 0 | + | | is here. | + +-----+-----------------------------------------------------------------------------------------+ + |26 | The shared memory for both PRU's appears here. | + +-----+-----------------------------------------------------------------------------------------+ + |72 | The `.text` section is where the code goes. It's mapped to `IMEM` | + +-----+-----------------------------------------------------------------------------------------+ + |73 | The ((stack)) is then mapped to DMEM 0. Notice that DMEM 0 is one bank | + +-----+-----------------------------------------------------------------------------------------+ + | | of memory for PRU 0 and another for PRU1, so they both get their own stacks. | + +-----+-----------------------------------------------------------------------------------------+ + |74 | The `.bss` section is where the **heap** goes. | + +-----+-----------------------------------------------------------------------------------------+ + +Why is it important to understand this file? If you are going to store things +in DMEM, you need to be sure to start at address 0x0200 since the **stack** and +the **heap** are in the locations below 0x0200. + +Loading Firmware +================== + +Problem +--------- + +I have my PRU code all compiled and need to load it on the PRU. + +Solution +--------- + +It's a simple three step process. + +* Stop the PRU +* Write the ``.out`` file to the right place in ``/lib/firmware`` +* Start the PRU. + +This is all handled in the :ref:`details_makefile`. + +Discussion +----------- + + +The PRUs appear in the Linux file space at ``/dev/remoteproc/``. + +Finding the PRUs +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + + bone$ cd /dev/remoteproc/ + bone$ ls + pruss-core0 pruss-core1 + +Or if you are on the AI: + +.. code-block:: bash + + bone$ cd /dev/remoteproc/ + bone$ ls + dsp1 dsp2 ipu1 ipu2 pruss1-core0 pruss1-core1 pruss2-core0 pruss2-core1 + +You see there that the AI has two pairs of PRUs, plus a couple of DSPs and other goodies. + +Here we see PRU 0 and PRU 1 in the path. Let's follow PRU 0. + +.. code-block:: bash + + bone$ cd pruss-core0 + bone$ ls + device firmware name power state subsystem uevent + +Here we see the files that control PRU 0. ``firmware`` tells where in ``/lib/firmware`` +to look for the code to run on the PRU. + +.. code-block:: bash + + bone$ cat firmware + am335x-pru0-fw + +Therefore you copy your ``.out`` file to ``/lib/firmware/am335x-pru0-fw``. + +.. _details_configure_servos: + +Configuring Pins for Controlling Servos +======================================== + +Problem +--------- + +You want to **configure** the pins so the PRU outputs are accessable. + +Solution +--------- + +It depends on which Beagle you are running on. If you are on the AI or Blue, +everything is already configured for you. +If you are on the Black or Pocket you'll need to run the following script. + +servos_setup.sh +~~~~~~~~~~~~~~~~ + +:download:`servos_setup.sh <code/servos_setup.sh>` + +Discussion +----------- + +The first part of the code looks in ``/proc/device-tree/model`` to see which Beagle is running. Based on that it +assigns ``pins`` a list of pins to configure. Then the last part of the script loops through each of the pins and configures it. + + +.. _details_configure_encoders: + +Configuring Pins for Controlling Encoders +========================================== + +Problem +--------- + +You want to **configure** the pins so the PRU inputs are accessable. + +Solution +--------- + +It depends on which Beagle you are running on. If you are on the AI or Blue, +everything is already configured for you. +If you are on the Black or Pocket you'll need to run the following script. + +.encoder_setup.sh + +:download:`encoder_setup.sh <code/encoder_setup.sh>` + +Discussion +----------- + +This works like the servo setup except some of the pins are configured as +to the hardware eQEPs and other to the PRU inputs. + diff --git a/pru-cookbook/04debug/code/Makefile b/pru-cookbook/04debug/code/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a7557fdaa22988d89cec879477ded78522d7116f --- /dev/null +++ b/pru-cookbook/04debug/code/Makefile @@ -0,0 +1 @@ +include /var/lib/cloud9/common/Makefile diff --git a/pru-cookbook/04debug/code/copyright.c b/pru-cookbook/04debug/code/copyright.c new file mode 100644 index 0000000000000000000000000000000000000000..a34918faa44a789c3624c0e5551704e630017dae --- /dev/null +++ b/pru-cookbook/04debug/code/copyright.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff --git a/pru-cookbook/04debug/code/resource_table_empty.h b/pru-cookbook/04debug/code/resource_table_empty.h new file mode 100644 index 0000000000000000000000000000000000000000..c14bd2b222644e05a84a4a328792a4c8513ff1e8 --- /dev/null +++ b/pru-cookbook/04debug/code/resource_table_empty.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ======== resource_table_empty.h ======== + * + * Define the resource table entries for all PRU cores. This will be + * incorporated into corresponding base images, and used by the remoteproc + * on the host-side to allocated/reserve resources. Note the remoteproc + * driver requires that all PRU firmware be built with a resource table. + * + * This file contains an empty resource table. It can be used either as: + * + * 1) A template, or + * 2) As-is if a PRU application does not need to configure PRU_INTC + * or interact with the rpmsg driver + * + */ + +#ifndef _RSC_TABLE_PRU_H_ +#define _RSC_TABLE_PRU_H_ + +#include <stddef.h> +#include <rsc_types.h> + +struct my_resource_table { + struct resource_table base; + + uint32_t offset[1]; /* Should match 'num' in actual definition */ +}; + +#pragma DATA_SECTION(pru_remoteproc_ResourceTable, ".resource_table") +#pragma RETAIN(pru_remoteproc_ResourceTable) +struct my_resource_table pru_remoteproc_ResourceTable = { + 1, /* we're the first version that implements this */ + 0, /* number of entries in the table */ + 0, 0, /* reserved, must be zero */ + 0, /* offset[0] */ +}; + +#endif /* _RSC_TABLE_PRU_H_ */ + diff --git a/pru-cookbook/04debug/code/uart1.pru0.c b/pru-cookbook/04debug/code/uart1.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..e9b40d5c8c6fe6f1bda4492bb84160a1d4c08b3e --- /dev/null +++ b/pru-cookbook/04debug/code/uart1.pru0.c @@ -0,0 +1,88 @@ +// From: http://git.ti.com/pru-software-support-package/pru-software-support-package/trees/master/examples/am335x/PRU_Hardware_UART + +#include <stdint.h> +#include <pru_uart.h> +#include "resource_table_empty.h" + +/* The FIFO size on the PRU UART is 16 bytes; however, we are (arbitrarily) + * only going to send 8 at a time */ +#define FIFO_SIZE 16 +#define MAX_CHARS 8 + +void main(void) +{ + uint8_t tx; + uint8_t rx; + uint8_t cnt; + + /* hostBuffer points to the string to be printed */ + char* hostBuffer; + + /*** INITIALIZATION ***/ + + /* Set up UART to function at 115200 baud - DLL divisor is 104 at 16x oversample + * 192MHz / 104 / 16 = ~115200 */ + CT_UART.DLL = 104; + CT_UART.DLH = 0; + CT_UART.MDR = 0x0; + + /* Enable Interrupts in UART module. This allows the main thread to poll for + * Receive Data Available and Transmit Holding Register Empty */ + CT_UART.IER = 0x7; + + /* If FIFOs are to be used, select desired trigger level and enable + * FIFOs by writing to FCR. FIFOEN bit in FCR must be set first before + * other bits are configured */ + /* Enable FIFOs for now at 1-byte, and flush them */ + CT_UART.FCR = (0x8) | (0x4) | (0x2) | (0x1); + //CT_UART.FCR = (0x80) | (0x4) | (0x2) | (0x01); // 8-byte RX FIFO trigger + + /* Choose desired protocol settings by writing to LCR */ + /* 8-bit word, 1 stop bit, no parity, no break control and no divisor latch */ + CT_UART.LCR = 3; + + /* Enable loopback for test */ + CT_UART.MCR = 0x00; + + /* Choose desired response to emulation suspend events by configuring + * FREE bit and enable UART by setting UTRST and URRST in PWREMU_MGMT */ + /* Allow UART to run free, enable UART TX/RX */ + CT_UART.PWREMU_MGMT = 0x6001; + + /*** END INITIALIZATION ***/ + + /* Priming the 'hostbuffer' with a message */ + hostBuffer = "Hello! This is a long string\r\n"; + + /*** SEND SOME DATA ***/ + + /* Let's send/receive some dummy data */ + while(1) { + cnt = 0; + while(1) { + /* Load character, ensure it is not string termination */ + if ((tx = hostBuffer[cnt]) == '\0') + break; + cnt++; + CT_UART.THR = tx; + + /* Because we are doing loopback, wait until LSR.DR == 1 + * indicating there is data in the RX FIFO */ + while ((CT_UART.LSR & 0x1) == 0x0); + + /* Read the value from RBR */ + rx = CT_UART.RBR; + + /* Wait for TX FIFO to be empty */ + while (!((CT_UART.FCR & 0x2) == 0x2)); + } + } + + /*** DONE SENDING DATA ***/ + + /* Disable UART before halting */ + CT_UART.PWREMU_MGMT = 0x0; + + /* Halt PRU core */ + __halt(); +} diff --git a/pru-cookbook/04debug/code/uart1.pru1_0.c b/pru-cookbook/04debug/code/uart1.pru1_0.c new file mode 100644 index 0000000000000000000000000000000000000000..4c558bb96e6e21b9c0b05f9acee21f7d7ad3c225 --- /dev/null +++ b/pru-cookbook/04debug/code/uart1.pru1_0.c @@ -0,0 +1,90 @@ +// From: http://git.ti.com/pru-software-support-package/pru-software-support-package/trees/master/examples/am335x/PRU_Hardware_UART +// This example was converted to the am5729 by changing the names in pru_uart.h +// for the am335x to the more descriptive names for the am5729. +// For example DLL convertes to DIVISOR_REGISTER_LSB_ +#include <stdint.h> +#include <pru_uart.h> +#include "resource_table_empty.h" + +/* The FIFO size on the PRU UART is 16 bytes; however, we are (arbitrarily) + * only going to send 8 at a time */ +#define FIFO_SIZE 16 +#define MAX_CHARS 8 + +void main(void) +{ + uint8_t tx; + uint8_t rx; + uint8_t cnt; + + /* hostBuffer points to the string to be printed */ + char* hostBuffer; + + /*** INITIALIZATION ***/ + + /* Set up UART to function at 115200 baud - DLL divisor is 104 at 16x oversample + * 192MHz / 104 / 16 = ~115200 */ + CT_UART.DIVISOR_REGISTER_LSB_ = 104; + CT_UART.DIVISOR_REGISTER_MSB_ = 0; + CT_UART.MODE_DEFINITION_REGISTER = 0x0; + + /* Enable Interrupts in UART module. This allows the main thread to poll for + * Receive Data Available and Transmit Holding Register Empty */ + CT_UART.INTERRUPT_ENABLE_REGISTER = 0x7; + + /* If FIFOs are to be used, select desired trigger level and enable + * FIFOs by writing to FCR. FIFOEN bit in FCR must be set first before + * other bits are configured */ + /* Enable FIFOs for now at 1-byte, and flush them */ + CT_UART.INTERRUPT_IDENTIFICATION_REGISTER_FIFO_CONTROL_REGISTER = (0x8) | (0x4) | (0x2) | (0x1); + //CT_UART.FCR = (0x80) | (0x4) | (0x2) | (0x01); // 8-byte RX FIFO trigger + + /* Choose desired protocol settings by writing to LCR */ + /* 8-bit word, 1 stop bit, no parity, no break control and no divisor latch */ + CT_UART.LINE_CONTROL_REGISTER = 3; + + /* Enable loopback for test */ + CT_UART.MODEM_CONTROL_REGISTER = 0x00; + + /* Choose desired response to emulation suspend events by configuring + * FREE bit and enable UART by setting UTRST and URRST in PWREMU_MGMT */ + /* Allow UART to run free, enable UART TX/RX */ + CT_UART.POWERMANAGEMENT_AND_EMULATION_REGISTER = 0x6001; + + /*** END INITIALIZATION ***/ + + /* Priming the 'hostbuffer' with a message */ + hostBuffer = "Hello! This is a long string\r\n"; + + /*** SEND SOME DATA ***/ + + /* Let's send/receive some dummy data */ + while(1) { + cnt = 0; + while(1) { + /* Load character, ensure it is not string termination */ + if ((tx = hostBuffer[cnt]) == '\0') + break; + cnt++; + CT_UART.RBR_THR_REGISTERS = tx; + + /* Because we are doing loopback, wait until LSR.DR == 1 + * indicating there is data in the RX FIFO */ + while ((CT_UART.LINE_STATUS_REGISTER & 0x1) == 0x0); + + /* Read the value from RBR */ + rx = CT_UART.RBR_THR_REGISTERS; + + /* Wait for TX FIFO to be empty */ + while (!((CT_UART.INTERRUPT_IDENTIFICATION_REGISTER_FIFO_CONTROL_REGISTER & 0x2) == 0x2)); + } + } + + /*** DONE SENDING DATA ***/ + + /* Disable UART before halting */ + CT_UART.POWERMANAGEMENT_AND_EMULATION_REGISTER = 0x0; + + /* Halt PRU core */ + __halt(); +} diff --git a/pru-cookbook/04debug/code/uart2.pru0.c b/pru-cookbook/04debug/code/uart2.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..56ca985d5a45d1daeb2efd22b9576047791519bf --- /dev/null +++ b/pru-cookbook/04debug/code/uart2.pru0.c @@ -0,0 +1,126 @@ +// From: http://git.ti.com/pru-software-support-package/pru-software-support-package/trees/master/pru_cape/pru_fw/PRU_Hardware_UART + +#include <stdint.h> +#include <pru_uart.h> +#include "resource_table_empty.h" + +/* The FIFO size on the PRU UART is 16 bytes; however, we are (arbitrarily) + * only going to send 8 at a time */ +#define FIFO_SIZE 16 +#define MAX_CHARS 8 +#define BUFFER 40 + +//****************************************************************************** +// Print Message Out +// This function take in a string literal of any size and then fill the +// TX FIFO when it's empty and waits until there is info in the RX FIFO +// before returning. +//****************************************************************************** +void PrintMessageOut(volatile char* Message) +{ + uint8_t cnt, index = 0; + + while (1) { + cnt = 0; + + /* Wait until the TX FIFO and the TX SR are completely empty */ + while (!CT_UART.LSR_bit.TEMT); + + while (Message[index] != NULL && cnt < MAX_CHARS) { + CT_UART.THR = Message[index]; + index++; + cnt++; + } + if (Message[index] == NULL) + break; + } + + /* Wait until the TX FIFO and the TX SR are completely empty */ + while (!CT_UART.LSR_bit.TEMT); + +} + +//****************************************************************************** +// IEP Timer Config +// This function waits until there is info in the RX FIFO and then returns +// the first character entered. +//****************************************************************************** +char ReadMessageIn(void) +{ + while (!CT_UART.LSR_bit.DR); + + return CT_UART.RBR_bit.DATA; +} + +void main(void) +{ + uint32_t i; + volatile uint32_t not_done = 1; + + char rxBuffer[BUFFER]; + rxBuffer[BUFFER-1] = NULL; // null terminate the string + + /*** INITIALIZATION ***/ + + /* Set up UART to function at 115200 baud - DLL divisor is 104 at 16x oversample + * 192MHz / 104 / 16 = ~115200 */ + CT_UART.DLL = 104; + CT_UART.DLH = 0; + CT_UART.MDR_bit.OSM_SEL = 0x0; + + /* Enable Interrupts in UART module. This allows the main thread to poll for + * Receive Data Available and Transmit Holding Register Empty */ + CT_UART.IER = 0x7; + + /* If FIFOs are to be used, select desired trigger level and enable + * FIFOs by writing to FCR. FIFOEN bit in FCR must be set first before + * other bits are configured */ + /* Enable FIFOs for now at 1-byte, and flush them */ + CT_UART.FCR = (0x80) | (0x8) | (0x4) | (0x2) | (0x01); // 8-byte RX FIFO trigger + + /* Choose desired protocol settings by writing to LCR */ + /* 8-bit word, 1 stop bit, no parity, no break control and no divisor latch */ + CT_UART.LCR = 3; + + /* If flow control is desired write appropriate values to MCR. */ + /* No flow control for now, but enable loopback for test */ + CT_UART.MCR = 0x00; + + /* Choose desired response to emulation suspend events by configuring + * FREE bit and enable UART by setting UTRST and URRST in PWREMU_MGMT */ + /* Allow UART to run free, enable UART TX/RX */ + CT_UART.PWREMU_MGMT_bit.FREE = 0x1; + CT_UART.PWREMU_MGMT_bit.URRST = 0x1; + CT_UART.PWREMU_MGMT_bit.UTRST = 0x1; + + /* Turn off RTS and CTS functionality */ + CT_UART.MCR_bit.AFE = 0x0; + CT_UART.MCR_bit.RTS = 0x0; + + /*** END INITIALIZATION ***/ + + while(1) { + /* Print out greeting message */ + PrintMessageOut("Hello you are in the PRU UART demo test please enter some characters\r\n"); + + /* Read in characters from user, then echo them back out */ + for (i = 0; i < BUFFER-1 ; i++) { + rxBuffer[i] = ReadMessageIn(); + if(rxBuffer[i] == '\r') { // Quit early if ENTER is hit. + rxBuffer[i+1] = NULL; + break; + } + } + + PrintMessageOut("you typed:\r\n"); + PrintMessageOut(rxBuffer); + PrintMessageOut("\r\n"); + } + + /*** DONE SENDING DATA ***/ + /* Disable UART before halting */ + CT_UART.PWREMU_MGMT = 0x0; + + /* Halt PRU core */ + __halt(); +} diff --git a/pru-cookbook/04debug/code/uart2.pru1_0.c b/pru-cookbook/04debug/code/uart2.pru1_0.c new file mode 100644 index 0000000000000000000000000000000000000000..c934ef7d0bd645734aa2c181b5ab68646713755e --- /dev/null +++ b/pru-cookbook/04debug/code/uart2.pru1_0.c @@ -0,0 +1,126 @@ +// From: http://git.ti.com/pru-software-support-package/pru-software-support-package/trees/master/pru_cape/pru_fw/PRU_Hardware_UART + +#include <stdint.h> +#include <pru_uart.h> +#include "resource_table_empty.h" + +/* The FIFO size on the PRU UART is 16 bytes; however, we are (arbitrarily) + * only going to send 8 at a time */ +#define FIFO_SIZE 16 +#define MAX_CHARS 8 +#define BUFFER 40 + +//****************************************************************************** +// Print Message Out +// This function take in a string literal of any size and then fill the +// TX FIFO when it's empty and waits until there is info in the RX FIFO +// before returning. +//****************************************************************************** +void PrintMessageOut(volatile char* Message) +{ + uint8_t cnt, index = 0; + + while (1) { + cnt = 0; + + /* Wait until the TX FIFO and the TX SR are completely empty */ + while (!CT_UART.LINE_STATUS_REGISTER_bit.TEMT); + + while (Message[index] != NULL && cnt < MAX_CHARS) { + CT_UART.RBR_THR_REGISTERS = Message[index]; + index++; + cnt++; + } + if (Message[index] == NULL) + break; + } + + /* Wait until the TX FIFO and the TX SR are completely empty */ + while (!CT_UART.LINE_STATUS_REGISTER_bit.TEMT); + +} + +//****************************************************************************** +// IEP Timer Config +// This function waits until there is info in the RX FIFO and then returns +// the first character entered. +//****************************************************************************** +char ReadMessageIn(void) +{ + while (!CT_UART.LINE_STATUS_REGISTER_bit.DR); + + return CT_UART.RBR_THR_REGISTERS_bit.DATA; +} + +void main(void) +{ + uint32_t i; + volatile uint32_t not_done = 1; + + char rxBuffer[BUFFER]; + rxBuffer[BUFFER-1] = NULL; // null terminate the string + + /*** INITIALIZATION ***/ + + /* Set up UART to function at 115200 baud - DLL divisor is 104 at 16x oversample + * 192MHz / 104 / 16 = ~115200 */ + CT_UART.DIVISOR_REGISTER_LSB_ = 104; + CT_UART.DIVISOR_REGISTER_MSB_ = 0; + CT_UART.MODE_DEFINITION_REGISTER_bit.OSM_SEL = 0x0; + + /* Enable Interrupts in UART module. This allows the main thread to poll for + * Receive Data Available and Transmit Holding Register Empty */ + CT_UART.INTERRUPT_ENABLE_REGISTER = 0x7; + + /* If FIFOs are to be used, select desired trigger level and enable + * FIFOs by writing to FCR. FIFOEN bit in FCR must be set first before + * other bits are configured */ + /* Enable FIFOs for now at 1-byte, and flush them */ + CT_UART.INTERRUPT_IDENTIFICATION_REGISTER_FIFO_CONTROL_REGISTER = (0x80) | (0x8) | (0x4) | (0x2) | (0x01); // 8-byte RX FIFO trigger + + /* Choose desired protocol settings by writing to LCR */ + /* 8-bit word, 1 stop bit, no parity, no break control and no divisor latch */ + CT_UART.LINE_CONTROL_REGISTER = 3; + + /* If flow control is desired write appropriate values to MCR. */ + /* No flow control for now, but enable loopback for test */ + CT_UART.MODEM_CONTROL_REGISTER = 0x00; + + /* Choose desired response to emulation suspend events by configuring + * FREE bit and enable UART by setting UTRST and URRST in PWREMU_MGMT */ + /* Allow UART to run free, enable UART TX/RX */ + CT_UART.POWERMANAGEMENT_AND_EMULATION_REGISTER_bit.FREE = 0x1; + CT_UART.POWERMANAGEMENT_AND_EMULATION_REGISTER_bit.URRST = 0x1; + CT_UART.POWERMANAGEMENT_AND_EMULATION_REGISTER_bit.UTRST = 0x1; + + /* Turn off RTS and CTS functionality */ + CT_UART.MODEM_CONTROL_REGISTER_bit.AFE = 0x0; + CT_UART.MODEM_CONTROL_REGISTER_bit.RTS = 0x0; + + /*** END INITIALIZATION ***/ + + while(1) { + /* Print out greeting message */ + PrintMessageOut("Hello you are in the PRU UART demo test please enter some characters\r\n"); + + /* Read in characters from user, then echo them back out */ + for (i = 0; i < BUFFER-1 ; i++) { + rxBuffer[i] = ReadMessageIn(); + if(rxBuffer[i] == '\r') { // Quit early if ENTER is hit. + rxBuffer[i+1] = NULL; + break; + } + } + + PrintMessageOut("you typed:\r\n"); + PrintMessageOut(rxBuffer); + PrintMessageOut("\r\n"); + } + + /*** DONE SENDING DATA ***/ + /* Disable UART before halting */ + CT_UART.POWERMANAGEMENT_AND_EMULATION_REGISTER = 0x0; + + /* Halt PRU core */ + __halt(); +} diff --git a/pru-cookbook/04debug/code/uart_setup.sh b/pru-cookbook/04debug/code/uart_setup.sh new file mode 100644 index 0000000000000000000000000000000000000000..db11d1f4fb5226a1f66482d5262809085dfc0ea9 --- /dev/null +++ b/pru-cookbook/04debug/code/uart_setup.sh @@ -0,0 +1,28 @@ +export TARGET=uart1.pru0 +echo TARGET=$TARGET + +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + # Configure tx + config-pin P9_24 pru_uart + # Configure rx + config-pin P9_26 pru_uart +elif [ $machine = "AI" ]; then + echo " Found" + echo "See AI chapter for configuring via device tree" +elif [ $machine = "Blue" ]; then + echo " Found" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + # Configure tx + config-pin P1_06 pru_uart + config-pin P2_09 pru_uart + # Configure rx + config-pin P1_12 pru_uart + config-pin P2_11 pru_uart +else + echo " Not Found" + pins="" +fi diff --git a/pru-cookbook/04debug/debug.rst b/pru-cookbook/04debug/debug.rst new file mode 100644 index 0000000000000000000000000000000000000000..a9f0edfbd8f0a884beca0d263300cb12b1e89d6e --- /dev/null +++ b/pru-cookbook/04debug/debug.rst @@ -0,0 +1,532 @@ +.. _pru-cookbook-debug: + +Debugging and Benchmarking +########################### + +One of the challenges is getting debug +information out of the PRUs since they don't have a traditional ``printf()``. +In this chapter four different methods are presented that I've found useful in +debugging. The first is simply attaching an LED. The second is using +``dmesg`` to watch the kernel messages. ``prudebug``, a simple debugger that +allows you to inspect registers and memory of the PRUs, is then presented. +Finally, using one of the UARTS to send debugging information out a serial port +is shown. + +Debugging via an LED +===================== + +Problem +--------- + +I need a simple way to see if my program is running without slowing the real-time execution. + +Solution +--------- + +One of the simplest ways to do this is to attach an LED to the output pin and watch it +flash. :ref:`debug_LED` shows an LED attached to pin P9_29 of the BeagleBone Black. + +.. _debug_LED: + +LED used for debugging P9_29 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/LED_bb.png + :align: center + :alt: LED used for debugging P9_29 + +Make sure you have the LED in the correct way, or it won't work. + +Discussion +--------- + +If your output is changing more than a few times a second, the LED will be +blinking too fast and you'll need an oscilloscope or a logic analyzer to +see what's happening. + +Another useful tool that let's you see the contents of the registers and +RAM is discussed in :ref:`debug_prudebug`. + +dmesg Hw +========= + +Problem +--------- +I'm getting an error message +(``/sys/devices/platform/ocp/4a326000.pruss-soc-bus/4a300000.pruss/4a334000.pru0/remoteproc/remoteproc1/state: Invalid argument``) +when I load my code, but don't know what's causing it. + +Solution +--------- +The command ``dmesg`` outputs useful information when dealing with the kernel. +Simplying running ``dmesg -Hw`` can tell you a lot. The ``-H`` flag puts the +dates in the human readable form, the ``-w`` tells it to wait for more information. +Often I'll have a window open running ``dmesg -Hw``. +. + +Here's what ``dmesg`` said for the example above. + +dmesg -Hw +~~~~~~~~~~ + +.. code-block:: bash + + [ +0.000018] remoteproc remoteproc1: header-less resource table + [ +0.011879] remoteproc remoteproc1: Failed to find resource table + [ +0.008770] remoteproc remoteproc1: Boot failed: -22 + +It quickly told me I needed to add the line ``#include "resource_table_empty.h"`` +to my code. + +.. _debug_prudebug: + +prudebug - A Simple Debugger for the PRU +========================================= + +Problem +--------- + +You need to examine registers and memory on the PRUs. + +Solution +--------- + +``prudebug`` is a simple debugger for the PRUs that lets you start and stop the PRUs and +examine the registers and memory. It can be found on GitHub +https://github.com/RRvW/prudebug-rl. I have a version I updated to use byte +addressing rather than word addressing. This makes it easier to work with the +assembler output. You can find it in my GitHub BeagleBoard repo +https://github.com/MarkAYoder/BeagleBoard-exercises/tree/master/pru/prudebug. + +Just download the files and type ``make``. + +Discussion +------------ + +Once ``prudebug`` is installed is rather easy to use. + +.. note:: + + ``prudebug`` has now been ported to the AI. + +.. TODO Isn't working on Pocket at this time. + +.. code-block:: bash + + bone$ *sudo prudebug* + PRU Debugger v0.25 + (C) Copyright 2011, 2013 by Arctica Technologies. All rights reserved. + Written by Steven Anderson + + Using /dev/mem device. + Processor type AM335x + PRUSS memory address 0x4a300000 + PRUSS memory length 0x00080000 + + offsets below are in 32-bit byte addresses (not ARM byte addresses) + PRU Instruction Data Ctrl + 0 0x00034000 0x00000000 0x00022000 + 1 0x00038000 0x00002000 0x00024000 + +You get help by entering ``help``. You cal also enter ``hb`` to get a brief help. + +.. code-block:: bash + + PRU0> *hb* + Command help + + BR [breakpoint_number [address]] - View or set an instruction breakpoint + D memory_location_ba [length] - Raw dump of PRU data memory (32-bit byte offset from beginning of full PRU memory block - all PRUs) + DD memory_location_ba [length] - Dump data memory (32-bit byte offset from beginning of PRU data memory) + DI memory_location_ba [length] - Dump instruction memory (32-bit byte offset from beginning of PRU instruction memory) + DIS memory_location_ba [length] - Disassemble instruction memory (32-bit byte offset from beginning of PRU instruction memory) + G - Start processor execution of instructions (at current IP) + GSS - Start processor execution using automatic single stepping - this allows running a program with breakpoints + HALT - Halt the processor + L memory_location_iwa file_name - Load program file into instruction memory + PRU pru_number - Set the active PRU where pru_number ranges from 0 to 1 + Q - Quit the debugger and return to shell prompt. + R - Display the current PRU registers. + RESET - Reset the current PRU + SS - Single step the current instruction. + WA [watch_num [address [value]]] - Clear or set a watch point + WR memory_location_ba value1 [value2 [value3 ...]] - Write a 32-bit value to a raw (offset from beginning of full PRU memory block) + WRD memory_location_ba value1 [value2 [value3 ...]] - Write a 32-bit value to PRU data memory for current PRU + WRI memory_location_ba value1 [value2 [value3 ...]] - Write a 32-bit value to PRU instruction memory for current PRU + + +Initially you are talking to PRU 0. You can enter ``pru 1`` to talk to PRU 1. +The commands I find most useful are, ``r``, to see the registers. + +.. code-block:: bash + + PRU0> *r* + Register info for PRU0 + Control register: 0x00008003 + Reset PC:0x0000 RUNNING, FREE_RUN, COUNTER_DISABLED, NOT_SLEEPING, PROC_ENABLED + + Program counter: 0x0030 + Current instruction: ADD R0.b0, R0.b0, R0.b0 + + Rxx registers not available since PRU is RUNNING. + +Notice the PRU has to be stopped to see the register contents. + +.. code-block:: bash + + PRU0> *h* + PRU0 Halted. + PRU0> *r* + Register info for PRU0 + Control register: 0x00000001 + Reset PC:0x0000 STOPPED, FREE_RUN, COUNTER_DISABLED, NOT_SLEEPING, PROC_DISABLED + + Program counter: 0x0028 + Current instruction: LBBO R15, R15, 4, 4 + + R00: 0x00000000 R08: 0x00000000 R16: 0x00000001 R24: 0x00000002 + R01: 0x00000000 R09: 0xaf40dcf2 R17: 0x00000000 R25: 0x00000003 + R02: 0x000000dc R10: 0xd8255b1b R18: 0x00000003 R26: 0x00000003 + R03: 0x000f0000 R11: 0xc50cbefd R19: 0x00000100 R27: 0x00000002 + R04: 0x00000000 R12: 0xb037c0d7 R20: 0x00000100 R28: 0x8ca9d976 + R05: 0x00000009 R13: 0xf48bbe23 R21: 0x441fb678 R29: 0x00000002 + R06: 0x00000000 R14: 0x00000134 R22: 0xc8cc0752 R30: 0x00000000 + R07: 0x00000009 R15: 0x00000200 R23: 0xe346fee9 R31: 0x00000000 + +You can resume using ``g`` which starts right where you left off, or use ``reset`` to +restart back at the beginning. + +The ``dd`` command dumps the memory. Keep in mind the following. + +Important memory locations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-------+---------------------------------------------------------------------------+ + |Address|Contents | + +=======+===========================================================================+ + |0x00000| Start of the **stack** for PRU 0. The file **AM335x_PRU.cmd** specifies | + | | where the stack is. | + +-------+---------------------------------------------------------------------------+ + |0x00100| Start of the **heap** for PRU 0. | + +-------+---------------------------------------------------------------------------+ + |0x00200| Start of DRAM that your programs can use. The **Makefile** specifies | + +-------+---------------------------------------------------------------------------+ + | | the size of the **stack** and the **heap**. | + +-------+---------------------------------------------------------------------------+ + |0x10000| Start of the memory shared between the PRUs. | + +-------+---------------------------------------------------------------------------+ + +Using ``dd`` with no address prints the next section of memory. + +.. code-block:: bash + + PRU0> *dd* + dd + Absolute addr = 0x0000, offset = 0x0000, Len = 16 + [0x0000] 0x00000000 0x00000000 0x00000000 0x00000000 + [0x0010] 0x00000000 0x00000000 0x00000000 0x00000000 + [0x0020] 0x00000000 0x00000000 0x00000000 0x00000000 + [0x0030] 0x00000000 0x00000000 0x00000000 0x00000000 + +The stack grows from higher memory to lower memory, so you often won't see +much around address ``0x0000``. + +.. code-block:: bash + + PRU0> *dd 0x100* + dd 0x100 + Absolute addr = 0x0100, offset = 0x0000, Len = 16 + [0x0100] 0x00000001 0x00000002 0x00000003 0x00000004 + [0x0110] 0x00000004 0x00000003 0x00000002 0x00000001 + [0x0120] 0x00000001 0x00000000 0x00000000 0x00000000 + [0x0130] 0x00000000 0x00000200 0x862e5c18 0xfeb21aca + +Here we see some values on the heap. + +.. code-block:: bash + + PRU0> *dd 0x200* + dd 0x200 + Absolute addr = 0x0200, offset = 0x0000, Len = 16 + [0x0200] 0x00000001 0x00000004 0x00000002 0x00000003 + [0x0210] 0x00000003 0x00000011 0x00000004 0x00000010 + [0x0220] 0x0a4fe833 0xb222ebda 0xe5575236 0xc50cbefd + [0x0230] 0xb037c0d7 0xf48bbe23 0x88c460f0 0x011550d4 + +Data written explicity to ``0x0200`` of the DRAM. + +.. code-block:: bash + + PRU0> *dd 0x10000* + dd 0x10000 + Absolute addr = 0x10000, offset = 0x0000, Len = 16 + [0x10000] 0x8ca9d976 0xebcb119e 0x3aebce31 0x68c44d8b + [0x10010] 0xc370ba7e 0x2fea993b 0x15c67fa5 0xfbf68557 + [0x10020] 0x5ad81b4f 0x4a55071a 0x48576eb7 0x1004786b + [0x10030] 0x2265ebc6 0xa27b32a0 0x340d34dc 0xbfa02d4b + +Here's the shared memory. + +You can also use ``prudebug`` to set breakpoints and single step, +but I haven't used that feature much. + +:ref:`../05blocks/blocks.html#_memory_allocation, Memory Allocation` gives examples +of how you can control where your vaiables are stored in memory. + + +UART +====== + +Problem +--------- + +I'd like to use something like ``printf()`` to debug my code. + +.. TODO Check these on the Black and Pocket without grove + +Solution +--------- + +One simple, yet effective approach to 'printing' from the PRU is +an idea taken from the Adruino playbook; +use the UART (serial port) to output debug information. The PRU has it's +own UART that can send characters to a serial port. + +You'll need a 3.3V FTDI cable to go between your Beagle and the USB port +on your host computer as shown in :ref:`debug_ftdi`. [#debug1]_ +you can get such a cable from places such as +`Sparkfun <https://www.sparkfun.com/products/9717>`_ or +`Adafruit <https://www.adafruit.com/product/70>`_. + +.. _debug_ftdi: + +FTDI cable +~~~~~~~~~~~ + +.. figure:: figures/FTDIcable.jpg + :align: center + :alt: FTDI cable + +Discussion +--------- + +The Beagle side of the FTDI cable has a small triangle on it as shown in +:ref:`debug_ftdi_connector` which marks the ground pin, pin 1. + +.. _debug_ftdi_connector: + +FTDI connector +~~~~~~~~~~~~~~~~~ + +.. figure:: figures/FTDIconnector.jpg + :align: center + :alt: FTDI connector + +The :ref:`debug_FTDI` table shows which pins connect where and :ref:`debug_ftdi_pins` +is a wiring diagram for the BeagleBone Black. + +.. _debug_FTDI: + +Wriing for FTDI cable to Beagle +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +--------+------+---------+-------------+--------+------+---------+ + |FTDI pin|Color |Black pin|AI 1 pin |AI 2 pin|Pocket|Function | + +========+======+=========+=============+========+======+=========+ + |0 |black |P9_1 |P8_1 |P8_1 |P1_16 |ground | + +--------+------+---------+-------------+--------+------+---------+ + |4 |orange|P9_24 |P8_43 |P8_33a |P1_12 |rx | + +--------+------+---------+-------------+--------+------+---------+ + |5 |yellow|P9_26 |P8_44 |P8_31a |P1_06 |tx | + +--------+------+---------+-------------+--------+------+---------+ + +.. _debug_ftdi_pins: + +FTDI to BB Black +~~~~~~~~~~~~~~~~~ + +.. figure:: figures/FTDIhookup_bb.png + :align: center + :alt: FTDI to BB Black + +Details +~~~~~~~~ + +Two examples of using the UART are presented here. The first +(:ref:`debug_uart1`) sends a character out the serial port then +waits for a character to come in. Once the new +character arrives another character is output. + +The second example (:ref:`debug_uart2`) prints out a string and then +waits for characters to arrive. +Once an ENTER appears the string is sent back. + +.. tip:: + + On the Black, either PRU0 and PRU1 can + run this code. Both have access to the same UART. + +You need to set the pin muxes. + +config-pin +~~~~~~~~~~~ + +.. code-block:: bash + + # Configure tx Black + bone$ *config-pin P9_24 pru_uart* + # Configure rx Black + bone$ *config-pin P9_26 pru_uart* + + # Configure tx Pocket + bone$ *config-pin P1_06 pru_uart* + # Configure rx Pocket + bone$ *config-pin P1_12 pru_uart* + +.. note:: + + See :ref:`../08ai/ai.html#ai_device_tree, Configuring pins on the AI via device trees` for configuring + pins on the AI. Make sure your `rx` pins are configured as input pins in the device tree. + +For example + +.. code-block:: bash + + DRA7XX_CORE_IOPAD(0x3610, *PIN_INPUT* | MUX_MODE10) // C6: P8.33a: + +.. * TODO - Add code for Blue. + +uart1.pru1_0.c +~~~~~~~~~~~~~~~ + +Set the following variables so ``make`` will know what to compile. + +make +~~~~~ + +.. code-block:: bash + + bone$ *make TARGET=uart1.pru0* + /var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=uart1.pru0 + - Stopping PRU 0 + - copying firmware file /tmp/cloud9-examples/uart1.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /dev/remoteproc/pruss-core0 + +Now ``make`` will compile, load PRU0 and start it. +In a terminal window on your host computer run + +.. code-block:: bash + + host$ *screen /dev/ttyUSB0 115200* + +It will initially display the first charters (``H``) and then as you enter +characters on the keyboard, the rest of the message will appear. + +uart1.pru0.c output +~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/uart1.pru0.png + :align: center + :alt: uart1.pru0.c output + +Here's the code (``uart1.pru1_0.c``) that does it. + +.. _debug_uart1: + +uart1.pru1_0.c +~~~~~~~~~~~~~~~ + +:download:`uart1.pru1_0.c <code/uart1.pru1_0.c>` + +.. note:: + + I'm using the AI version of the code since + it uses variables with more desciptive names. + +The first part of the code initializes the UART. Then the line +``CT_UART.RBR_THR_REGISTERS = tx;`` takes a character in ``tx`` +and sends it to the transmit buffer on the UART. Think of +this as the UART version of the ``printf()``. + +Later the line ``while (!((CT_UART.INTERRUPT_IDENTIFICATION_REGISTER_FIFO_CONTROL_REGISTER & 0x2) == 0x2));`` +waits for the transmitter FIFO to be empty. This makes sure later characters +won't overwrite the buffer before they can be sent. The downside is, this will +cause your code to wait on the buffer and it might miss an important +real-time event. + +The line ``while ((CT_UART.LINE_STATUS_REGISTER & 0x1) == 0x0);`` waits for an input from the +UART (possibly missing something) and ``rx = CT_UART.RBR_THR_REGISTERS;`` reads from the +receive register on the UART. + +These simple lines should be enough to place in your code to print out +debugging information. + +uart2.pru0.c +~~~~~~~~~~~~ + +If you want to try ``uart2.pru0.c``, run the following: + +make +~~~~~ + +.. code-block:: bash + + bone$ *make TARGET=uart2.pru0* + /var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=uart2.pru0 + - Stopping PRU 0 + - copying firmware file /tmp/cloud9-examples/uart2.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /dev/remoteproc/pruss-core0 + +You will see: + +uart2.pru0.c output +~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/uart2.pru0.png + :align: center + :alt: uart2.pru0.c output + +Type a few characters and hit ENTER. The PRU will playback what you typed, +but it won't echo it as you type. + +``uart2.pru0.c`` defines ``PrintMessageOut()`` which is passed a string that is +sent to the UART. It takes advantage of the eight character FIFO on the UART. +Be careful using it because it also uses ``while (!CT_UART.LSR_bit.TEMT);`` to +wait for the FIFO to empty, which may cause your code to miss something. + +:ref:`debug_uart2` is the code that does it. + +.. _debug_uart2: + +uart2.pru1_0.c +~~~~~~~~~~~~~~~ + +:download:`uart2.pru1_0.c <code/uart2.pru1_0.c>` + +More complex examples can be built using the principles shown in these examples. + +Copyright +========== + +copyright.c +~~~~~~~~~~~~~ + +:download:`copyright.c <code/copyright.c>` + +.. rubric:: Footnotes + +.. [#debug1] FTDI images are from the BeagleBone Cookbook http://shop.oreilly.com/product/0636920033899.do \ No newline at end of file diff --git a/pru-cookbook/04debug/figures/FTDIcable.jpg b/pru-cookbook/04debug/figures/FTDIcable.jpg new file mode 100644 index 0000000000000000000000000000000000000000..80d8e01563cf6781849b305f7f45de40184caca3 Binary files /dev/null and b/pru-cookbook/04debug/figures/FTDIcable.jpg differ diff --git a/pru-cookbook/04debug/figures/FTDIconnector.jpg b/pru-cookbook/04debug/figures/FTDIconnector.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3517708cffa8b349f8bb6ebe06525a606d338a68 Binary files /dev/null and b/pru-cookbook/04debug/figures/FTDIconnector.jpg differ diff --git a/pru-cookbook/04debug/figures/FTDIhookup.fzz b/pru-cookbook/04debug/figures/FTDIhookup.fzz new file mode 100644 index 0000000000000000000000000000000000000000..561602594f87e6d1a778136f4fe67533bbde4316 Binary files /dev/null and b/pru-cookbook/04debug/figures/FTDIhookup.fzz differ diff --git a/pru-cookbook/04debug/figures/FTDIhookup_bb.png b/pru-cookbook/04debug/figures/FTDIhookup_bb.png new file mode 100644 index 0000000000000000000000000000000000000000..ec7b447a35ff5f1e7d6ecf5539b357833d05563a Binary files /dev/null and b/pru-cookbook/04debug/figures/FTDIhookup_bb.png differ diff --git a/pru-cookbook/04debug/figures/LED.fzz b/pru-cookbook/04debug/figures/LED.fzz new file mode 100644 index 0000000000000000000000000000000000000000..ab3d81aa9a29a2b01a4d980ca8d72a032562aa6f Binary files /dev/null and b/pru-cookbook/04debug/figures/LED.fzz differ diff --git a/pru-cookbook/04debug/figures/LED_bb.png b/pru-cookbook/04debug/figures/LED_bb.png new file mode 100644 index 0000000000000000000000000000000000000000..40533edaec88bfa756d5908aca4dddcdc8a9ca48 Binary files /dev/null and b/pru-cookbook/04debug/figures/LED_bb.png differ diff --git a/pru-cookbook/04debug/figures/uart1.pru0.png b/pru-cookbook/04debug/figures/uart1.pru0.png new file mode 100644 index 0000000000000000000000000000000000000000..beffa2c6189e7c831d0fbf8f57848bcd0995a5c7 Binary files /dev/null and b/pru-cookbook/04debug/figures/uart1.pru0.png differ diff --git a/pru-cookbook/04debug/figures/uart2.pru0.png b/pru-cookbook/04debug/figures/uart2.pru0.png new file mode 100644 index 0000000000000000000000000000000000000000..12c32441ff36ed34c811fce0ce88754103237139 Binary files /dev/null and b/pru-cookbook/04debug/figures/uart2.pru0.png differ diff --git a/pru-cookbook/05blocks/blocks.rst b/pru-cookbook/05blocks/blocks.rst new file mode 100644 index 0000000000000000000000000000000000000000..e6de06e35ef9851530791b1518ba28ef68a765c4 --- /dev/null +++ b/pru-cookbook/05blocks/blocks.rst @@ -0,0 +1,1977 @@ +.. _pru-cookbook-blocks: + +Building Blocks - Applications +############################### + +Here are some examples that use the basic PRU building blocks. + +The following are resources used in this chapter. + +Resources +~~~~~~~~~~ + +* `PRU Optimizing C/C++ Compiler, v2.2, User's Guide <http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf>`_ +* `AM572x Technical Reference Manual <http://www.ti.com/lit/pdf/spruhz6l>`_ (AI) +* `AM335x Technical Reference Manual <http://www.ti.com/lit/pdf/spruh73>`_ (All others) +* `Exploring BeagleBone by Derek Molloy <http://exploringbeaglebone.com/>`_ +* `WS2812 Data Sheet <https://cdn-shop.adafruit.com/datasheets/WS2812.pdf>`_ + +Memory Allocation +================== + + +Problem +--------- + +I want to control where my variables are stored in memory. + +.. TODO Include a section on accessing DDR. + +Solution +--------- + +Each PRU has is own 8KB of data memory (Data Mem0 and Mem1) and 12KB of +shared memory (Shared RAM) as shown in :ref:`blocks_PRU_block_diagram`. + +.. _blocks_PRU_block_diagram: + +PRU Block Diagram +~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/blockDiagram.png + :align: center + :alt: PRU Block diagram + +Each PRU accesses it's own DRAM starting at location 0x0000_0000. Each PRU +can also access the other PRU's DRAM starting at 0x0000_2000. Both PRUs +access the shared RAM at 0x0001_0000. The compiler can control where each +of these memories variables are stored. + +:ref:`blocks_shared` shows how to allocate seven variable in six different locations. + +.. _blocks_shared: + +shared.pro0.c - Examples of Using Different Memory Locations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`shared.pru0.c <code/shared.pru0.c>` + + +Discussion +----------- + +Here's the line-by-line + +Line-byline for shared.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +-------+---------------------------------------------------------------------------------------------------------+ + |Line | Explanation | + +=======+=========================================================================================================+ + |7 | `PRU_SRAM` is defined here. It will be used later to declare variables | + | | in the `Shared RAM` location of memory. Section 5.5.2 on page 75 of the | + | | `PRU Optimizing C/C++ Compiler, v2.2, User's Guide <http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf>`_ | + | | gives details of the command. The `PRU_SHAREDMEM` | + | | refers to the memory section defined in `am335x_pru.cmd` on line 26. | + +-------+---------------------------------------------------------------------------------------------------------+ + |8, 9 | These are like the previous line except for the DMEM sections. | + +-------+---------------------------------------------------------------------------------------------------------+ + |16 | Variables declared outside of `main()` are put on the heap. | + +-------+---------------------------------------------------------------------------------------------------------+ + |17 | Adding `PRU_SRAM` has the variable stored in the shared memory. | + +-------+---------------------------------------------------------------------------------------------------------+ + |18, 19 | These are stored in the PRU's local RAM. | + +-------+---------------------------------------------------------------------------------------------------------+ + |20, 21 | These lines are for storing in the `.bss` section as declared on | + | | line 74 of `am335x_pru.cmd`. | + +-------+---------------------------------------------------------------------------------------------------------+ + |28-31 | All the previous examples direct the compiler to an area in memory | + | | and the compilers figures out what to put where. With these lines we | + | | specify the exact location. Here are start with the PRU_DRAM starting | + | | address and add 0x200 to it to avoid | + | | the **stack** and the **heap**. The advantage of this technique is you can | + | | easily share these variables between the ARM and the two PRUs. | + +-------+---------------------------------------------------------------------------------------------------------+ + |36, 37 | Variable declared inside `main()` go on the stack. | + +-------+---------------------------------------------------------------------------------------------------------+ + +.. caution:: + + Using the technique of line 28-31 you can put variables anywhere, even where the + compiler has put them. Be careful, it's easy to overwrite what the compiler has done + +Compile and run the program. + +.. code-block:: bash + + bone$ *source shared_setup.sh* + TARGET=shared.pru0 + Black Found + P9_31 + Current mode for P9_31 is: pruout + Current mode for P9_31 is: pruout + P9_29 + Current mode for P9_29 is: pruout + Current mode for P9_29 is: pruout + P9_30 + Current mode for P9_30 is: pruout + Current mode for P9_30 is: pruout + P9_28 + Current mode for P9_28 is: pruout + Current mode for P9_28 is: pruout + bone$ *make* + /var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=shared.pru0 + - Stopping PRU 0 + - copying firmware file /tmp/cloud9-examples/shared.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /sys/class/remoteproc/remoteproc1 + +Now check the **symbol table** to see where things are allocated. + +.. code-block:: bash + + bone $ *grep shared /tmp/cloud9-examples/shared.pru0.map* + .... + 1 0000011c shared_0 + 2 00010000 shared_1 + 1 00000000 shared_2 + 1 00002000 shared_3 + 1 00000118 shared_4 + 1 00000120 shared_5 + +We see, ``shared_0`` had no directives and was places in the heap that is 0x100 +to 0x1ff. ``shared_1`` was directed to go to the SHAREDMEM, ``shared_2`` to +the start of the local DRAM (which is also the top of the stack). ``shared_3`` +was placed in the DRAM of PRU 1, ``shared_4`` was placed in the ``.bss`` section, +which is in the **heap**. Finally ``shared_5`` is a pointer to where the value +is stored. + +Where are ``shared_6`` and ``shared_7``? They are declared inside ``main()`` and are +therefore placed on the stack at run time. The ``shared.map`` file shows the +compile time allocations. We have to look in the memory itself to see what +happen at run time. + +Let's fire up ``prudebug`` +(:ref:`../04debug/debug.html#debug_prudebug, prudebug - A Simple Debugger for the PRU`) +to see where things are. + +.. code-block:: bash + + bone$ *sudo ./prudebug* + PRU Debugger v0.25 + (C) Copyright 2011, 2013 by Arctica Technologies. All rights reserved. + Written by Steven Anderson + + Using /dev/mem device. + Processor type AM335x + PRUSS memory address 0x4a300000 + PRUSS memory length 0x00080000 + + offsets below are in 32-bit byte addresses (not ARM byte addresses) + PRU Instruction Data Ctrl + 0 0x00034000 0x00000000 0x00022000 + 1 0x00038000 0x00002000 0x00024000 + + PRU0> *d 0* + Absolute addr = 0x0000, offset = 0x0000, Len = 16 + [0x0000] 0x0000feed 0x00000000 0x00000000 0x00000000 + [0x0010] 0x00000000 0x00000000 0x00000000 0x00000000 + [0x0020] 0x00000000 0x00000000 0x00000000 0x00000000 + [0x0030] 0x00000000 0x00000000 0x00000000 0x00000000 + +The value of ``shared_2`` is in memory location 0. + +.. code-block:: bash + + PRU0> *dd 0x100* + Absolute addr = 0x0100, offset = 0x0000, Len = 16 + [0x0100] 0x00000000 0x00000001 0x00000000 0x00000000 + [0x0110] 0x00000000 0x00000000 0x0000beed 0x0000feef + [0x0120] 0x00000200 0x3ec71de3 0x1a013e1a 0xbf2a01a0 + [0x0130] 0x111110b0 0x3f811111 0x55555555 0xbfc55555 + +There are ``shared_0`` and ``shared_4`` in the heap, but where is ``shared_6`` and +``shared_7``? They are supposed to be on the **stack** that starts at 0. + +.. code-block:: bash + + PRU0> dd *0xc0* + Absolute addr = 0x00c0, offset = 0x0000, Len = 16 + [0x00c0] 0x00000000 0x00000000 0x00000000 0x00000000 + [0x00d0] 0x00000000 0x00000000 0x00000000 0x00000000 + [0x00e0] 0x00000000 0x00000000 0x00000000 0x00000000 + [0x00f0] 0x00000000 0x00000000 0x00004321 0x00009876 + +There they are; the stack grows from the top. (The heap grows from the bottom.) + +.. code-block:: bash + + PRU0> dd *0x2000* + Absolute addr = 0x2000, offset = 0x0000, Len = 16 + [0x2000] 0x0000deed 0x00000001 0x00000000 0x557fcfb5 + [0x2010] 0xce97bd0f 0x6afb2c8f 0xc7f35df4 0x5afb6dcb + [0x2020] 0x8dec3da3 0xe39a6756 0x642cb8b8 0xcb6952c0 + [0x2030] 0x2f22ebda 0x548d97c5 0x9241786f 0x72dfeb86 + +And there is PRU 1's memory with ``shared_3``. And finally the shared memory. + +.. code-block:: bash + + PRU0> *dd 0x10000* + Absolute addr = 0x10000, offset = 0x0000, Len = 16 + [0x10000] 0xdeadbeef 0x0000feed 0x00000000 0x68c44f8b + [0x10010] 0xc372ba7e 0x2ffa993b 0x11c66da5 0xfbf6c5d7 + [0x10020] 0x5ada3fcf 0x4a5d0712 0x48576fb7 0x1004796b + [0x10030] 0x2267ebc6 0xa2793aa1 0x100d34dc 0x9ca06d4a + +The compiler offers great control over where variables are stored. Just +be sure if you are hand picking where things are put, not to put them in places +used by the compiler. + +Auto Initialization of built-in LED Triggers +============================================= + +Problem +----------- + +I see the built-in LEDs blink to their own patterns. +How do I turn this off? Can this be automated? + +Solution +--------- + +Each built-in LED has a default action (trigger) when the Bone boots up. +This is controlled by ``/sys/class/leds``. + +.. code-block:: bash + + bone$ *cd /sys/class/leds* + bone$ *ls* + beaglebone:green:usr0 beaglebone:green:usr2 + beaglebone:green:usr1 beaglebone:green:usr3 + +Here you see a directory for each of the LEDs. Let's pick USR1. + +.. code-block:: bash + + bone$ *cd beaglebone\:green\:usr1* + bone$ *ls* + brightness device max_brightness power subsystem trigger uevent + bone$ *cat trigger* + none usb-gadget usb-host rfkill-any rfkill-none kbd-scrolllock kbd-numlock + kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock + kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock *[mmc0]* timer + oneshot disk-activity disk-read disk-write ide-disk mtd nand-disk heartbeat + backlight gpio cpu cpu0 activity default-on panic netdev phy0rx phy0tx + phy0assoc phy0radio rfkill0 + +Notice ``[mmc0]`` is in brackets. This means it's the current trigger; it flashes +when the built-in flash memory is in use. You can turn this off using: + +.. code-block:: bash + + bone$ *echo none > trigger* + bone$ *cat trigger* + *[none]* usb-gadget usb-host rfkill-any rfkill-none kbd-scrolllock kbd-numlock + kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock + kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock mmc0 timer + oneshot disk-activity disk-read disk-write ide-disk mtd nand-disk heartbeat + backlight gpio cpu cpu0 activity default-on panic netdev phy0rx phy0tx + phy0assoc phy0radio rfkill0 + +Now it is no longer flashing. + +How can this be automated so when code is run that needs the trigger off, it's +turned off automatically? Here's a trick. Include the following in your code. + +.. code-block:: bash + :linenos: + + #pragma DATA_SECTION(init_pins, ".init_pins") + #pragma RETAIN(init_pins) + const char init_pins[] = + "/sys/class/leds/beaglebone:green:usr3/trigger\0none\0" \ + "\0\0"; + +Lines 3 and 4 declare the array ``init_pins`` to have an entry which is the path +to ``trigger`` and the value that should be 'echoed' into it. Both are NULL +terminated. Line 1 says to put this in a section called ``.init_pins`` and +line 2 says to ``RETAIN`` it. That is don't throw it away if it appears to be +unused. + +Discussion +----------- + +The above code stores this array in the ``.out`` file thats created, but that's not +enough. You need to run :ref:`blocks_write_init_pins` on the ``.out`` file to make +the code work. Fortunately the Makefile always runs it. + +.. _blocks_write_init_pins: + +write_init_pins.sh +~~~~~~~~~~~~~~~~~~~ + +:download:`write_init_pins.sh <code/write_init_pins.sh>` + +The ``readelf`` command extracts the path and value from the ``.out`` file. + +.. code-block:: bash + + bone$ *readelf -x .init_pins /tmp/pru0-gen/shared.out* + + Hex dump of section '.init_pins': + 0x000000c0 2f737973 2f636c61 73732f6c 6564732f /sys/class/leds/ + 0x000000d0 62656167 6c65626f 6e653a67 7265656e beaglebone:green + 0x000000e0 3a757372 332f7472 69676765 72006e6f :usr3/trigger.no + 0x000000f0 6e650000 0000 ne.... + +The rest of the command formats it. Finally line 6 echos the ``none`` into the path. + +This can be generalized to initialize other things. The point is, the ``.out`` +file contains everything needed to run the executable. + + +.. _blocks_pwm: + +PWM Generator +============== + +One of the simplest things a PRU can to is generate a simple +signal starting with a single channel PWM that has a fixed frequency and +duty cycle and ending with a multi channel PWM that the ARM can change +the frequency and duty cycle on the fly. + +Problem +--------- + +I want to generate a PWM signal that has a fixed frequency and duty cycle. + +Solution +--------- + +The solution is fairly easy, but be sure to check the *Discussion* section +for details on making it work. + +:ref:`blocks_pwm1` shows the code. + +.. warning:: + This code is for the BeagleBone Black. + See ``pwm1.pru1_1.c`` for an example + that works on the AI. + +.. _blocks_pwm1: + +pwm1.pru0.c +~~~~~~~~~~~~ + +:download:`pwm1.pru0.c <code/pwm1.pru0.c>` + +To run this code you need to configure the pin muxes to output the PRU. If you are on the Black run + +.. code-block:: bash + + bone$ config-pin P9_31 pruout + +On the Pocket run + +.. code-block:: bash + + bone$ config-pin P1_36 pruout + + +.. note:: + + See :ref:`../08ai/ai.html#ai_device_tree, Configuring pins on the AI via device trees` + for configuring pins on the AI. + +Then, tell ``Makefile`` which PRU you are compiling for and what your target file is + +.. code-block:: bash + + bone$ export TARGET=pwm1.pru0 + +Now you are ready to compile + +.. code-block:: bash + + bone$ make + /var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=pwm1.pru0 + - Stopping PRU 0 + - copying firmware file /tmp/cloud9-examples/pwm1.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /sys/class/remoteproc/remoteproc1 + +Now attach an LED (or oscilloscope) to ``P9_31`` on the Black +or ``P1.36`` on the Pocket. You should see a squarewave. + +Discussion +----------- + +Since this is our first example we'll discuss the many parts in detail. + +pwm1.pru0.c +~~~~~~~~~~~~ + +:ref:`blocks_pwm1_line_by_line` is a line-by-line expanation of the c code. + +.. _blocks_pwm1_line_by_line: + +Line-by-line of pwm1.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-----+-------------------------------------------------------------------------------------+ + |Line | Explanation | + +=====+=====================================================================================+ + |1 | Standard c-header include | + +-----+-------------------------------------------------------------------------------------+ + |2 | Include for the PRU. The compiler knows where to find this since the | + | | `Makefile` says to look for includes in `/usr/lib/ti/pru-software-support-package` | + +-----+-------------------------------------------------------------------------------------+ + |3 | The file `resource_table_empty.h` is used by the PRU loader. Generally we'll | + | | use the same file, and don't need to modify it. | + +-----+-------------------------------------------------------------------------------------+ + |4 | This include has addresses for the GPIO ports and some bit positions for | + | | some of the headers. | + +-----+-------------------------------------------------------------------------------------+ + +Here's what's in ``resource_table_empty.h`` + +resource_table_empty.c +~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`resource_table_empty.h <code/resource_table_empty.h>` + +Line-by-line (continuted) +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-----+-----------------------------------------------------------------------------------------------------------------+ + |Line | Explanation | + +=====+=================================================================================================================+ + |6-7 | `pass:[__]R30` and `pass:[__]R31` are two variables that refer to the | + | | PRU output (`pass:[__]R30`) and input (`pass:[__]R31`) registers. | + | | When you write something to `pass:[__]R30` it will show up on the | + | | corresponding output pins. When you read from `pass:[__]R31` | + | | you read the data on the input pins. | + | | NOTE: Both names begin with two underscore's. Section 5.7.2 of the | + | | http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf[PRU Optimizing C/C++ Compiler, v2.2, User's Guide] | + | | gives more details. | + +-----+-----------------------------------------------------------------------------------------------------------------+ + |11 | This line selects which GPIO pin to toggle. The table below shows which bits in `pass:[__]R30` | + | | map to which pins | + +-----+-----------------------------------------------------------------------------------------------------------------+ + |14 | `CT_CFG.SYSCFG_bit.STANDBY_INIT` is set to `0` to enable the OCP master port. More details on this | + | | and thousands of other regesters see the | + | | https://www.ti.com/lit/ug/spruh73p/spruh73p.pdf[AM335x Technical Reference Manual]. Section 4 is on the PRU | + | | and section 4.5 gives details for all the registers. | + +-----+-----------------------------------------------------------------------------------------------------------------+ + +Bit 0 is the LSB. + +.. TODO fill in Blue + +.. _blocks_mapping_bits: + +Mapping bit positions to pin names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +---+---+---------------------+-----------+ + |PRU|Bit|Black pin |Pocket pin | + +===+===+=====================+===========+ + |0 |0 |P9_31 |P1.36 | + +---+---+---------------------+-----------+ + |0 |1 |P9_29 |P1.33 | + +---+---+---------------------+-----------+ + |0 |2 |P9_30 |P2.32 | + +---+---+---------------------+-----------+ + |0 |3 |P9_28 |P2.30 | + +---+---+---------------------+-----------+ + |0 |4 |P9_42b |P1.31 | + +---+---+---------------------+-----------+ + |0 |5 |P9_27 |P2.34 | + +---+---+---------------------+-----------+ + |0 |6 |P9_41b |P2.28 | + +---+---+---------------------+-----------+ + |0 |7 |P9_25 |P1.29 | + +---+---+---------------------+-----------+ + |0 |14 |P8_12(out) P8_16(in) |P2.24 | + +---+---+---------------------+-----------+ + |0 |15 |P8_11(out) P8_15(in) |P2.33 | + +---+---+---------------------+-----------+ + | | | | | + +---+---+---------------------+-----------+ + |1 |0 |P8_45 | | + +---+---+---------------------+-----------+ + |1 |1 |P8_46 | | + +---+---+---------------------+-----------+ + |1 |2 |P8_43 | | + +---+---+---------------------+-----------+ + |1 |3 |P8_44 | | + +---+---+---------------------+-----------+ + |1 |4 |P8_41 | | + +---+---+---------------------+-----------+ + |1 |5 |P8_42 | | + +---+---+---------------------+-----------+ + |1 |6 |P8_39 | | + +---+---+---------------------+-----------+ + |1 |7 |P8_40 | | + +---+---+---------------------+-----------+ + |1 |8 |P8_27 |P2.35 | + +---+---+---------------------+-----------+ + |1 |9 |P8_29 |P2.01 | + +---+---+---------------------+-----------+ + |1 |10 |P8_28 |P1.35 | + +---+---+---------------------+-----------+ + |1 |11 |P8_30 |P1.04 | + +---+---+---------------------+-----------+ + |1 |12 |P8_21 | | + +---+---+---------------------+-----------+ + |1 |13 |P8_20 | | + +---+---+---------------------+-----------+ + |1 |14 | |P1.32 | + +---+---+---------------------+-----------+ + |1 |15 | |P1.30 | + +---+---+---------------------+-----------+ + |1 |16 |P9_26(in)| | | + +---+---+---------------------+-----------+ + +.. note:: + + See :ref:`../08ai/ai.html#ai_device_tree, Configuring pins on the AI via device trees` + for all the PRU pins on the AI. + +Since we are running on PRU 0, and we're using ``0x0001``, +that is bit 0, we'll be toggling ``P9_31``. + +Line-by-line (continued again) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-----+-----------------------------------------------------------------------+ + |Line | Explanation | + +=====+=======================================================================+ + |17 | Here is where the action is. This line reads ``pass:[__]R30`` and | + | | then ORs it with ``gpio``, setting the bits where there is | + | | a 1 in ``gpio`` and leaving the bits where there is a 0. | + | | Thus we are setting the bit we selected. Finally the new | + | | value is written back to ``pass:[__]R30``. | + +-----+-----------------------------------------------------------------------+ + |18 | ``pass:[__]delay_cycles`` is an ((instrinsic function)) that delays | + | | with number of cycles passed to it. Each cycle is 5ns, | + | | and we are delaying 100,000,000 cycles which is | + | | 500,000,000ns, or 0.5 seconds. | + +-----+-----------------------------------------------------------------------+ + |19 | This is like line 17, but ``~gpio`` inverts all the bits in ``gpio`` | + | | so that where we had a 1, there is now a 0. This 0 | + | | is then ANDed with ``pass:[__]R30`` setting the corresponding | + | | bit to 0. Thus we are clearing the bit we selected. | + +-----+-----------------------------------------------------------------------+ + + +.. tip:: + + You can read more about instrinsics in section 5.11 of the + (`PRU Optimizing C/C++ Compiler, v2.2, User's Guide <http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf>`_.) + + +When you run this code and look at the output you will see something like the following figure. + +Output of pwm1.pru0.c with 100,000,000 delays cycles giving a 1s period +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pwm1.png + :align: center + :alt: pwm1.pru0.c output + +Notice the on time (``+Width(1)``) is 500ms, just as we predicted. +The off time is 498ms, which is only 2ms off from our prediction. +The standard deviation is 0, or only 380as, which is 380 * 10^-18^!. + +You can see how fast the PRU can run by setting both of the +``pass:[__]delay_cycles`` to 0. This results in the next figure. + +Output of pwm1.pru0c with 0 delay cycles +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pwm2.png + :align: center + :alt: pwm1.pru0.c output with 0 delay + +Notice the period is 15ns which gives us a frequency of about 67MHz. At this high +frequency the breadboard that I'm using distorts the waveform so it's no longer a squarewave. +The **on** time is 5.3ns and the **off** time is 9.8ns. That means **pass:[__]R30 |= gpio** +took only one 5ns cycle and ``pass:[__]R30 &= ~gpio`` also only took one cycle, but there +is also an extra cycle needed for the loop. This means the compiler was able to implement +the ``while`` loop in just three 5ns instructions! Not bad. + +We want a square wave, so we need to add a delay to correct for the delay of looping back. + +Here's the code that does just that. + +pwm2.pru0.c +~~~~~~~~~~~~~ + +:download:`pwm2.pru0.c <code/pwm2.pru0.c>` + +The output now looks like: + +Output of pwm2.pru0.c corrected delay +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pwm3.png + :align: center + :alt: pwm2.c corrected delay + +It's not hard to adjust the two ``pass:[__]delay_cycles`` +to get the desired frequency and duty cycle. + +### Controlling the PWM Frequency +#### Problem +You would like to control the frequency and +duty cycle of the PWM without recompiling. + +#### Solution +Have the PRU read the **on** and **off** times from a shared memory location. +Each PRU has is own 8KB of data memory (DRAM) and 12KB of shared memory +(SHAREDMEM) that the ARM processor can also access. See :ref:`blocks_PRU_block_diagram`. + +The DRAM 0 address is 0x0000 for PRU 0. The same DRAM appears at address +0x4A300000 as seen from the ARM processor. + +.. tip:: + + See page + 184 of the https://www.ti.com/lit/ug/spruh73p/spruh73p.pdf[AM335x Technical Reference Manual]. + +We take the previous PRU code and add the lines + +.. code-block:: C + + #define PRU0_DRAM 0x00000 // Offset to DRAM + volatile unsigned int *pru0_dram = PRU0_DRAM; + +to define a pointer to the DRAM. + +.. note:: + + The `volatile` keyword is used here to tell the compiler the value this + points to may change, so don't make any assumptions while optimizing. + + +Later in the code we use + +.. code-block:: C + + pru0_dram[ch] = on[ch]; // Copy to DRAM0 so the ARM can change it + pru0_dram[ch+MAXCH] = off[ch]; // Copy after the on array + +to write the `on` and `off` times to the DRAM. Then inside the `while` loop we use + +.. code-block:: c + + onCount[ch] = pru0_dram[2*ch]; // Read from DRAM0 + offCount[ch]= pru0_dram[2*ch+1]; + +to read from the DRAM when reseting the counters. Now, while the PRU is running, +the ARM can write values into the DRAM and change the PWM on and off times. +:ref:`blocks_pwm4` is the whole code. + +.. _blocks_pwm4: + +pwm4.pru0.c +~~~~~~~~~~~~ + +:download:`pwm4.pru0.c <code/pwm4.pru0.c>` + +Here is code that runs on the ARM side to set the on and off time values. + +pwm-test.c +~~~~~~~~~~~~ + +:download:`pwm-test.c <code/pwm-test.c>` + +A quick check on the 'scope shows :ref:`blocks_pwm_arm_control`. + +.. _blocks_pwm_arm_control: + +Four Channel PWM with ARM control +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pwm4.png + :align: center + :alt: pwm4.png + +From the 'scope you see a 1 cycle **on** time results in a 450ns wide pulse and a +3.06us period is 326KHz, much slower than the 10ns pulse we saw before. But it +may be more than fast enough for many applications. For example, most servos run at 50Hz. + +But we can do better. + +Loop Unrolling for Better Performance +====================================== + +Problem +----------- + +The ARM controlled PRU code runs too slowly. + +Solution +----------- + +Simple loop unrolling can greatly improve the speed. ``pwm5.pru0.c`` is our unrolled +version. + +pwm5.pru0.c Unrolled +~~~~~~~~~~~~~~~~~~~~~ + +:download:`pwm5.pru0.c <code/pwm5.pru0.c>` + +The output of ``pwm5.pru0.c`` is in the figure below. + +pwm5.pru0.c Unrolled version of pwm4.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pwm5_no_loop.png + :align: center + :alt: pwm5.pru0.c Unrolled version of pwm4.pru0.c + +It's running about 6 times faster than ``pwm4.pru0.c``. + +pwm4.pru0.c vs. pwm5.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +---------+-----------------+-----------------+---------+-----------------------+---------+ + |Measure |pwm4.pru0.c time |pwm5.pru0.c time |Speedup |pwm5.pru0.c w/o UNROLL |Speedup | + +---------+-----------------+-----------------+---------+-----------------------+---------+ + |Period |3.06μs |510ns |6x |1.81μs |~1.7x | + +---------+-----------------+-----------------+---------+-----------------------+---------+ + |Width+ |450ns |70ns |~6x |1.56μs |~.3x | + +---------+-----------------+-----------------+---------+-----------------------+---------+ + +Not a bad speed up for just a couple of simple changes. + +Discussion +----------- + +Here's how it works. +First look at line 39. You see ``#pragma UNROLL(MAXCH)`` which is a ``pragma`` +that tells the compiler to unroll the loop that follows. We are unrolling it +``MAXCH`` times (four times in this example). Just removing the ``pragma`` causes +the speedup compared to the ``pwm4.pru0.c`` case to drop from 6x to only 1.7x. + +We also have our ``for`` loop inside the ``while`` loop that can be unrolled. +Unfortunately ``UNROLL()`` doesn't work on it, therefore we have to do it by +hand. We could take the loop and just copy it three times, but that would +make it harder to maintain the code. Instead I convered the loop into a +``#define`` (lines 14-24) and invoked ``update()`` as needed (lines 48-51). +This is not a function call. Whenever the preprocessor sees the ``update()`` +it copies the code an then it's compiled. + +This unrolling gets us an impressive 6x speedup. + +Making All the Pulses Start at the Same Time +============================================= + +Problem +----------- + +I have a mutlichannel PWM working, but the pulses aren't synchronized, that is +they don't all start at the same time. + +Solution +----------- + +:ref:`blocks_zoomed` is a zoomed in version of the previous figure. Notice the pulse +in each channel starts about 15ns later than the channel above it. + +.. _blocks_zoomed: + +pwm5.pru0 Zoomed In +~~~~~~~~~~~~~~~~~~~~~ +.. figure:: figures/pwm5_zoomed.png + :align: center + :alt: pwm5.pru0 zoomed.png + +The solution is to declare ``Rtmp`` (line 35) which holds the value for ``pass:[__]R30``. + +pwm6.pru0.c Sync'ed Version of pwm5.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`pwm6.pru0.c Sync'ed Version of pwm5.pru0.c <code/pwm6.pru0.c>` + +Each channel writes it's value to ``Rtmp`` (lines 17 and 20) and then after +each channel has updated, ``Rtmp`` is copied to ``pass:[__]R30`` (line 54). + +Discussion +----------- + +The following figure shows the channel are sync'ed. Though the period is slightly +longer than before. + +pwm6.pru0 Synchronized Channels +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pwm6_synced.png + :align: center + :alt: pwm6.pru0 Synchronized Channels + + +Adding More Channels via PRU 1 +================================ + +Problem +----------- + +You need more output channels, or you need to shorten the period. + +Solution +----------- + +PRU 0 can output up to eight output pins (see +:ref:`blocks_mapping_bits`). The code presented so far +can be easily extended to use the eight output pins. + +But what if you need more channels? +You can always use PRU1, it has 14 output pins. + +Or, what if four channels is enough, but you need a shorter period. Everytime +you add a channel, the overall period gets longer. Twice as many channels +means twice as long a period. If you move half the channels to PRU 1, you +will make the period half as long. + +Here's the code (``pwm7.pru0.c``) + +pwm7.pru0.c Using Both PRUs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`pwm7.pru0.c Using Both PRUs <code/pwm7.pru0.c>` + +Be sure to run ``pwm7_setup.sh`` to get the correct pins configured. + +pwm7_setup.sh +~~~~~~~~~~~~~~~ + +:download:`pw7_setup.sh <code/pwm7_setup.sh>` + +This makes sure the PRU 1 pins are properly configured. + +Here we have a second ``pwm7`` file. ``pwm7.pru1.c`` is identical to ``pwm7.pru0.c`` +except ``PRUNUM`` is set to 1, instead of 0. + +Compile and run the two files with: + +.. code-block:: bash + + bone$ *make TARGET=pwm7.pru0; make TARGET=pwm7.pru1* + /var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=pwm7.pru0 + - Stopping PRU 0 + - copying firmware file /tmp/cloud9-examples/pwm7.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /sys/class/remoteproc/remoteproc1 + /var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=pwm7.pru1 + - Stopping PRU 1 + - copying firmware file /tmp/cloud9-examples/pwm7.pru1.out to /lib/firmware/am335x-pru1-fw + write_init_pins.sh + - Starting PRU 1 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 1 + PRU_DIR = /sys/class/remoteproc/remoteproc2 + +This will first stop, compile and start PRU 0, then do the same for PRU 1. + +Moving half of the channels to PRU1 dropped the period from 510ns to 370ns, so +we gained a bit. + +Discussion +----------- + +There weren't many changes to be made. Line 15 we set MAXCH to 2. Lines 44-48 +is where the big change is. +.. code-block:: c + + pru0_dram[2*ch ] = on [ch+PRUNUN*MAXCH]; // Copy to DRAM0 so the ARM can change it + pru0_dram[2*ch+1] = off[ch+PRUNUN*MAXCH]; // Interleave the on and off values + onCount[ch] = on [ch+PRUNUN*MAXCH]; + offCount[ch]= off[ch+PRUNUN*MAXCH]; + +If we are compiling for PRU 0, ``on[ch+PRUNUN*MAXCH]`` becomes ``on[ch+0*2]`` which is +``on[ch]`` which is what we had before. But now if we are on PRU 1 it becomes +``on[ch+1*2]`` which is ``on[ch+2]``. That means we are picking up the second +half of the ``on`` and ``off`` arrays. The first half goes to PRU 0, the second to +PRU 1. So the same code can be used for both PRUs, but we get slightly different +behavior. + +Running the code you will see the next figure. + +pwm7.pru0 Two PRUs running +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pwm7_two_prus_running.png + :align: center + :alt: pwm7.pru0 Two PRUs running + +What's going on there, the first channels look fine, but the PRU 1 channels +are blurred. To see what's happening, let's stop the oscilloscope. + +pwm7.pru0 Two PRUs stopped +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pwm7_two_prus_stopped.png + :align: center + :alt: pwm7 Two PRUs stopped + +The stopped display shows that the four channels are doing what we wanted, except +The PRU 0 channels have a period of 370ns while the PRU 1 channels at 330ns. +It appears the compiler has optimied the two PRUs slightly differenty. + + +Synchronizing Two PRUs +======================= + +Problem +----------- + +I need to synchronize the two PRUs so they run together. + +Solution +----------- + +Use the Interrupt Controller (INTC). It allows one PRU to signal the other. +Page 225 of the `AM335x Technical Reference Manual <https://www.ti.com/lit/ug/spruh73p/spruh73p.pdf>`_ +has details of how it works. Here's the code for PRU 0, which at the end of the +``while`` loop signals PRU 1 to start(``pwm8.pru0.c``). + +pwm8.pru0.c PRU 0 using INTC to send a signal to PRU 1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`pwm8.pru0.c PRU 0 using INTC to send a signal to PRU 1 <code/pwm8.pru0.c>` + +PRU 2's code waits for PRU 0 before going. + +pwm8.pru1.c PRU 1 waiting for INTC from PRU 0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`pwm8.pru1.c PRU 1 waiting for INTC from PRU 0 <code/pwm8.pru1.c>` + +In ``pwm8.pru0.c`` PRU 1 waits for a signal from PRU 0, so be sure to start PRU 1 first. + +.. code-block:: bash + + bone$ *make TARGET=pwm8.pru0; make TARGET=pwm8.pru1* + +Discussion +----------- + +The figure below shows the two PRUs are synchronized, though there is some extra +overhead in the process so the period is longer. + +pwm8.pru0 PRUs sycned +~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pwm8_prus_sycned.png + :align: center + :alt: pwm8.pru0 PRUs sycned + +This isn't much different from the previous examples. + +pwm8.pru0.c changes from pwm7.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-----+-------+---------------------------------------------------------------------------------------+ + |PRU |Line |Change | + +=====+=======+=======================================================================================+ + |0 |37-45 |For PRU 0 these define ``configInitc()`` which initializes the interupts. | + | | |See page 226 of the | + | | |`AM335x Technical Reference Manual <https://www.ti.com/lit/ug/spruh73p/spruh73p.pdf>`_ | + | | |for a diagram explaining events, channels, hosts, etc. | + +-----+-------+---------------------------------------------------------------------------------------+ + |0 |55-56 |Set a configuration register and call `configInitc`. | + +-----+-------+---------------------------------------------------------------------------------------+ + |1 |59-61 |PRU 1 then waits for PRU 0 to signal it. Bit 31 of ``pass:[__]R31`` corresponds | + | | |to the Host-1 channel which ``configInitc()`` set up. We also clear event 16 so | + | | |PRU 0 can set it again. | + +-----+-------+---------------------------------------------------------------------------------------+ + |0 |74-75 |On PRU 0 this generates the interupt to send to PRU 1. I found PRU 1 was | + | | |slow to respond to the interupt, so I put this code at the end of the loop to | + | | |give time for the signal to get to PRU 1. | + +-----+-------+---------------------------------------------------------------------------------------+ + +This ends the multipart pwm example. + +Reading an Input at Regular Intervals +====================================== + +Problem +----------- + +You have an input pin that needs to be read at regular intervals. + +Solution +----------- + +You can use the ``pass:[__]R31`` register to read an input pin. Let's use the following +pins. + +.. _blocks_io_pins: + +Input/Output pins +~~~~~~~~~~~~~~~~~~ + +.. table:: + + +---------+----------+-----+----------+---------+ + |Direction|Bit number|Black|AI (ICSS2)|Pocket | + +=========+==========+=====+==========+=========+ + |out |0 |P9_31|P8_44 |P1.36 | + +---------+----------+-----+----------+---------+ + |in |7 |P9_25|P8_36 |P1.29 | + +---------+----------+-----+----------+---------+ + +These values came from :ref:`blocks_mapping_bits`. + +Configure the pins with ``input_setup.sh``. + +input_setup.sh +~~~~~~~~~~~~~~~ + +:download:`input_setup.sh <code/input_setup.sh>` + +The following code reads the input pin and writes its value to the output pin. + +input.c +~~~~~~~~~~ + +:download:`input.pru0.c <code/input.pru0.c>` + +Discussion +----------- + +Just remember that ``pass:[__]R30`` is for outputs and ``pass:[__]R31`` is for inputs. + +Analog Wave Generator +======================= + +Problem +----------- + +I want to generate an analog output, but only have GPIO pins. + +Solution +----------- + +The Beagle doesn't have a built-in analog to digital converter. You could get a +`USB Audio Dongle <https://www.amazon.com/external-Adapter-Windows-Microphone-SD-CM-UAUD/dp/B001MSS6CS/0&keywords=audio+dongle>`_ +which are under $10. But here we'll take another approach. + +Earlier we generated a PWM signal. Here we'll generate a PWM whose duty cycle +changes with time. A small duty cycle for when the output signal is small and +a large duty cycle for when it is large. + +This example was inspired by +`A PRU Sin Wave Generator <https://github.com/derekmolloy/exploringBB/tree/master/chp13/sineWave>`_ +in chapter 13 of +`Exploring BeagleBone by Derek Molloy<http://exploringbeaglebone.com/>`_. + +Here's the code. + +sine.pru0.c +~~~~~~~~~~~~~ + +:download:`sine.pru0.c <code/sine.pru0.c>` + + +Set the ``#define`` at line 7 to the number of samples in one cycle of the waveform +and set the ``#define`` at line 8 to which waveform and then run ``make``. + +Discussion +----------- + +The code has two parts. The first part (lines 21 to 39) generate the waveform +to be output. The ``#define``s let you select which waveform you want to +generate. Since the output is a percent duty cycle, the values in ``waveform[]`` +must be between 0 and 100 inclusive. The waveform is only generated once, so +this part of the code isn't time critical. + +The second part (lines 44 to 54) uses the generated data to set the +duty cycle of the PWM on a cycle-by-cycle basis. This part is time critical; +the faster we can output the values, the higher the frequency of the output +signal. + +Suppose you want to generate a sawtooth waveform like the one shown in :ref:`blocks_sawtooth`. + +.. _blocks_sawtooth: + +Continuous Sawtooth Waveform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/sawtoothsmooth.png + :align: center + :alt: Continuous Sawtooth Waveform + +You need to sample the waveform and store one cycle. :ref:`blocks_sawtoothsampled` +shows a sampled version of the sawtooth. You need to generate ``MAXT`` samples; +here we show 20 samples, which may be enough. In the code ``MAXT`` is set to 100. + +.. _blocks_sawtoothsampled: + +Sampled Sawtooth Waveform +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/sawtoothsampled.png + :align: center + :alt: Sampled Sawtooth Waveform + +There's a lot going on here; let's take it line by line. + +Line-by-line of sine.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-------+---------------------------------------------------------------------------------+ + |Line | Explanation | + +=======+=================================================================================+ + |2-5 | Standard c-header includes | + +-------+---------------------------------------------------------------------------------+ + |7 | Number for samples in one cycle of the analog waveform | + +-------+---------------------------------------------------------------------------------+ + |8 | Which waveform to use. We've defined SAWTOOTH, TRIANGLE and SINE, but | + | | you can define your own too. | + +-------+---------------------------------------------------------------------------------+ + |10-11 | Declaring registers ``pass:[__R30]`` and ``pass:[__R31]``. | + +-------+---------------------------------------------------------------------------------+ + |15-16 | ``onCount`` counts how many cycles the PWM should be 1 and ``offCount`` counts | + | | how many it should be off. | + +-------+---------------------------------------------------------------------------------+ + |18 | ``waveform[]`` stores the analog waveform being ouput. | + +-------+---------------------------------------------------------------------------------+ + |21-24 | ``SAWTOOTH`` is the simplest of the waveforms. Each sample is the duty cycle | + | | at that time and must therefore be between 0 and 100. | + +-------+---------------------------------------------------------------------------------+ + |26-31 | ``TRIANGLE`` is also a simple waveform. | + +-------+---------------------------------------------------------------------------------+ + |32-39 | ``SINE`` generates a sine wave and also introduces floating point. Yes, | + | | you can use floating point, but the PRUs don't have floating point hardware, | + | | rather, it's all done in software. This mean using floating point will make | + | | your code much bigger and slower. Slower doesn't matter in this part, and | + | | bigger isn't bigger than our instruction memory, so we're OK. | + +-------+---------------------------------------------------------------------------------+ + |47 | Here the ``for`` loop looks up each value of the generated waveform. | + +-------+---------------------------------------------------------------------------------+ + |48,49 | ``onCount`` is the number of cycles to be at 1 and ``offCount`` is the number | + | | of cycles to be 0. The two add to 100, one full cycle. | + +-------+---------------------------------------------------------------------------------+ + |50-52 | Stay on for ``onCount`` cycles. | + +-------+---------------------------------------------------------------------------------+ + |53-55 | Now turn off for ``offCount`` cycles, then loop back and look up the next | + | | cycle count. | + +-------+---------------------------------------------------------------------------------+ + +:ref:`blocks_sawunfiltered` shows the output of the code. + +.. _blocks_sawunfiltered: + +Unfiltered Sawtooth Waveform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/sawunfiltered.png + :align: center + :alt: Unfiltered Sawtooth Waveform + +It doesn't look like a sawtooth; but if you look at the left side you will +see each cycle has a longer and longer on time. The duty cycle is increasing. +Once it's almost 100% duty cycle, it switches to a very small duty cycle. +Therefore it's output what we programmed, but what we want is the average of +the signal. The left hand side has a large (and increasing) average which +would be for top of the sawtooth. The right hand side has a small average, +which is what you want for the start of the sawtooth. + +A simple low-pass filter, built with one resistor and one capacitor will do it. +:ref:`blocks_filterwiring` shows how to wire it up. + +.. _blocks_filterwiring: + +Low-Pass Filter Wiring Diagram +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/filter_bb.png + :align: center + :alt: Low-Pass Filter Wiring Diagram + +.. note:: + + I used a 10K variable resistor and a 0.022uF capacitor. + Probe the circuit between the resistor and the capacitor + and adjust the resistor until you get a good looking waveform. + +:ref:`blocks_sawscope` shows the results for filtered the SAWTOOTH. + +.. _blocks_sawscope: + +Reconstructed Sawtooth Waveform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/sawscope.png + :align: center + :alt: Reconstructed Sawtooth Waveform + +Now that looks more like a sawtooth wave. The top plot is the time-domain +plot of the output of the low-pass filter. The bottom plot is the FFT of the top +plot, therefore it's the frequency domain. We are getting a sawtooth with a +frequency of about 6.1KHz. You can see the fundamental frequency on the +bottom plot along with several harmonics. + + +The top looks like a sawtooth wave, +but there is a high freqnecy superimposed on it. We are only using a simple +first-order filter. You could lower the cutoff freqnecy by adjusting the +resistor. You'll see something like :ref:`blocks_lowercutoff`. + +.. _blocks_lowercutoff: + +Reconstructed Sawtooth Waveform with Lower Cutoff Frequency +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/sawlowercutoff.png + :align: center + :alt: Reconstructed Sawtooth Waveform with Lower Cutoff Frequency + +The high freqencies have been reduced, but the corner of the waveform has +been rounded. You can also adjust the cutoff to a higher frequency and you'll +get a sharper corner, but you'll also get more high frequencies. See +:ref:`blocks_highercutoff` + +.. _blocks_highercutoff: + +Reconstructed Sawtooth Waveform with Higher Cutoff Frequency +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/sawhighercutoff.png + :align: center + :alt: Reconstructed Sawtooth Waveform with Higher Cutoff Frequency + +Adjust to taste, though the real solution is to build a higher order filter. +Search for _second order **filter** and you'll find some nice circuits. + +You can adjust the frequency of the signal by adjusting ``MAXT``. A smaller +``MAXT`` will give a higher frequency. I've gotten good results with ``MAXT`` +as small as 20. + +You can also get a triangle waveform by setting the ``#define``. +:ref:`blocks_triangle` shows the output signal. + +.. _blocks_triangle: + +Reconstructed Triangle Waveform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/triangle.png + :align: center + :alt: Reconstructed Triangle Waveform + +And also the sine wave as shown in :ref:`blocks_sine`. + +.. _blocks_sine: + +Reconstructed Sinusoid Waveform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/sine.png + :align: center + :alt: Reconstructed Sinusoid Waveform + +Notice on the bottom plot the harmonics are much more suppressed. + +Generating the sine waveform uses **floats**. This requires much more code. +You can look in `/tmp/cloud9-examples/sine.pru0.map` to see how much memory is being used. +:ref:`blocks_sine_map` shows the first few lines for the sine wave. + +.. _blocks_sine_map: + +/tmp/cloud9-examples/sine.pru0.map for Sine Wave +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`lines=1..22 <code/sine.map>` + +Notice line 15 shows 0x18c0 bytes are being used for instructions. That's 6336 +in decimal. + +Now compile for the sawtooth and you see only 444 byes are used. Floating-point +requires over 5K more bytes. Use with care. If you are short on instruction +space, you can move the table generation to the ARM and just copy the table +to the PRU. + + +.. ToDo Ultrasonic Sensor Application + +.. _blocks_ws2812: + +WS2812 (NeoPixel) driver +========================== + +Problem +----------- + +You have an `Adafruit NeoPixel LED string <http://www.adafruit.com/products/1138>`_ +or `Adafruit NeoPixel LED matrix <http://www.adafruit.com/products/1487>`_ +and want to light it up. + +Solution +----------- + +NeoPixel is Adafruit's name for the WS2812 Intelligent control LED. Each +NeoPixel contains a Red, Green and Blue LED with a PWM controller that can +dim each one individually making a rainbow of colors possible. The +NeoPixel is driven by a single serial line. The timing on the line is very +sensesitive, which make the PRU a perfect candidate for driving it. + +Wire the input to ``P9_29`` and power to 3.3V and ground to ground as shown in +:ref:`blocks_neo_wiring`. + +.. _blocks_neo_wiring: + +.NeoPixel Wiring +.. figure:: figures/neo_bb.png + :align: center + :alt: NeoPixel Wiring + +Test your wiring with the simple code in :ref:`blocks_neo1` +which to turns all pixels white. + +.. _blocks_neo1: + +neo1.pru0.c - Code to turn all NeoPixels's white +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: bash + +:download:`neo1.pru0.c <code/neo1.pru0.c>` + +Discussion +----------- + +:ref:`blocks_sequence` (taken from `WS2812 Data Sheet <https://cdn-shop.adafruit.com/datasheets/WS2812.pdf>`_) shows the following waveforms are used to send a bit of data. + +.. _blocks_sequence: + +NeoPixel bit sequence +~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/neo_sequence.png + :align: center + :alt: NeoPixel bit sequence + +Where the times are: + +.. table:: + + +-------+-------------+ + |Label | Time in ns | + +=======+=============+ + |T0H | 350 | + +-------+-------------+ + |T0L | 800 | + +-------+-------------+ + |T1H | 700 | + +-------+-------------+ + |T1L | 600 | + +-------+-------------+ + |Treset | >50,000 | + +-------+-------------+ + +The code in :ref:`blocks_neo1` define these times in lines 7-10. +The `/5` is because +each instruction take 5ns. Lines 27-30 then set the output to 1 for +the desired time and then to 0 and keeps repeating it for the entire +string length. :ref:`blocks_zero_scope` +shows the waveform for sending a 0 value. Note the times are spot on. + +.. _blocks_zero_scope: + +NeoPixel zero timing +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/neo_scope.png + :align: center + :alt: + +Each NeoPixel listens for a RGB value. Once a value has arrived all other values +that follow are passed on to the next NeoPixel which does the same thing. +That way you can individually control all of the NeoPixels. + +Lines 38-40 send out a reset pulse. If a NeoPixel sees a reset pulse it will +grab the next value for itself and start over again. + + + +Setting NeoPixels to Different Colors +====================================== + +Problem +----------- + +I want to set the LEDs to different colors. + +Solution +----------- + +Wire your NeoPixels as shown in :ref:`blocks_neo_wiring` then run the code in +:ref:`blocks_neo2`. + +.. _blocks_neo2: + +neo2.pru0.c - Code to turn on green, red, blue +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`neo2.pru0.c <code/neo2.pru0.c>` + +This will make the first LED green, the second red and the third blue. + +Discussion +----------- + +:ref:`blocks_new_data_seq` shows the sequence of bits +used to control the green, red and blue values. + +.. _blocks_new_data_seq: + +NeoPixel data sequence +~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/neo_data_seq.png + :align: center + :alt: + +.. note:: + +The usual order for colors is RGB (red, green, blue), but the NeoPixels use GRB (green, red, blue). + +:ref:`blocks_neo2_line` is the line-by-line for ``neo2.pru0.c``. + +.. _blocks_neo2_line: + +Line-by-line for neo2.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-------+---------------------------------------------------------------------------------+ + |Line | Explanation | + |23 | Define the string of colors to be output. Here the ordering of the | + | | bits is the same as :ref:`blocks_new_data_seq`, GRB. | + +-------+---------------------------------------------------------------------------------+ + |26 | Loop for each color to output. | + +-------+---------------------------------------------------------------------------------+ + |27 | Loop for each bit in an GRB color. | + +-------+---------------------------------------------------------------------------------+ + |28 | Get the j^th^ color and mask off all but the i^th^ bit. `(0x1:ref:`i)` takes | + | | the value `0x1` and shifts it left `i` bits. When anded (&) with `color[j]` | + | | it will zero out all but the i^th^ bit. If the result of the operation is | + | | 1, the `if` is done, otherwise the `else` is done. | + +-------+---------------------------------------------------------------------------------+ + |29-32 | Send a 1. | + +-------+---------------------------------------------------------------------------------+ + |34-37 | Send a 0. | + +-------+---------------------------------------------------------------------------------+ + |42-43 | Send a reset pulse once all the colors have been sent. | + +-------+---------------------------------------------------------------------------------+ + +.. note:: + +This will only change the first ``STR_LEN`` LEDs. The LEDs that follow will not +be changed. +==== + +Controlling Arbitrary LEDs +============================ + +Problem +----------- + +I want to change the 10^th^ LED and not have to change the others. + +Solution +----------- + +You need to keep an array of colors for the whole string in the PRU. Change +the color of any pixels you want in the array and then send out the whole +string to the LEDs. :ref:`blocks_neo3` shows an example animates a red pixel +running around a ring of blue background. :ref:`blocks_neo3_video` shows +the code in action. + +.. _blocks_neo3_video: + +neo3.pru0.c - Simple animation + +:download:`ring_around.mp4 <figures/ring_around.mp4>` + +.. _blocks_neo3: + +neo3.pru0.c - Code to animate a red pixel running around a ring of blue +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`neo3.pru0.c <code/neo3.pru0.c>` + + +Discussion +----------- + +Here's the highlights. + +.. table:: + + +-----+---------------------------------+ + |Line |Explanation | + +=====|=================================+ + |32,33|Initiallize the array of colors. | + +-----+---------------------------------+ + |38-41|Update the array. | + +-----+---------------------------------+ + |44-58|Send the array to the LEDs. | + +-----+---------------------------------+ + |60-61|Send a reset. | + +-----+---------------------------------+ + |64 |Wait a bit. | + +-----+---------------------------------+ + +Controlling NeoPixels Through a Kernel Driver +====================================== + +Problem +----------- + +You want to control your NeoPixels through a kernel driver so you can control it +through a ``/dev`` interface. + +Solution +----------- + +The `rpmsg_pru <https://github.com/beagleboard/linux/raw/4.9/drivers/rpmsg/rpmsg_pru.c>`_ +driver provides a way to pass data between the ARM processor and +the PRUs. It's already included on current images. :ref:`blocks_neo4` shows +an example. + +.. _blocks_neo4: + +neo4.pru0.c - Code to talk to the PRU via rpmsg_pru +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`neo4.pru0.c <code/neo4.pru0.c>` + +Run the code as usual. + +.. code-block:: bash + + bone$ make TARGET=neo4.pru0 + /var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=neo4.pru0 + - Stopping PRU 0 + - copying firmware file /tmp/cloud9-examples/neo4.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /sys/class/remoteproc/remoteproc1 + + bone$ echo 0 0xff 0 127 > /dev/rpmsg_pru30 + bone$ echo -1 > /dev/rpmsg_pru30 + + +.. TODO get this working on the 5.10 kernel + +``/dev/rpmsg_pru30`` is a device driver that lets the ARM talk to the PRU. +The first ``echo`` says to set the 0^th^ LED to RGB value 0xff 0 127. (Note: you can +mix hex and decimal.) The second ``echo`` tells the driver to send the data to the +LEDs. Your 0^th^ LED should now be lit. + +Discussion +----------- + +There's a lot here. I'll just hit some of the highlights in :ref:`blocks_neo4_lines`. + +.. _blocks_neo4_lines: + +Line-by-line for neo4.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + +|Line |Explanation + +|30 |The `CHAN_NAME` of `rpmsg-pru` matches that `prmsg_pru` driver that is +is already installed. This connects this PRU to the driver. +|32 |The `CHAN_PORT` tells it to use port 30. That's why we use +`/dev/rpmsg_pru30` +|40 |`payload[]` is the buffer that receives the data from the ARM. +|42-48|Same as the previous NeoPixel examples. +|52 |`color[]` is the state to be sent to the LEDs. +|66-68|`color[]` is initialized. +|70-85|Here are a number of details needed to set up the channel between +the PRU and the ARM. +|88 |Here we wait until the ARM sends us some numbers. +|99 |Receive all the data from the ARM, store it in `payload[]`. +|101-111|The data sent is: index red green blue. Pull off the index. If it's +in the right range, pull off the red, green and blue values. +|113 |The NeoPixels want the data in GRB order. Shift and OR everything +together. +|116-133|If the `index` = -1, send the contents of `color` to the LEDs. This +code is same as before. +|==== + +You can now use programs running on the ARM to send colors to the PRU. + +:ref:`blocks_neo-rainbow` shows an example. + +.. _blocks_neo-rainbow: + +neo-rainbow.py - A python program using /dev/rpmsg_pru30 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`neo-rainbow.py <code/neo-rainbow.py>` + + +Line 19 writes the data to the PRU. Be sure to have a newline, or space after +the last number, or you numbers will get blurred together. + +Switching from pru0 to pru1 with rpmsg_pru +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +There are three things you need to change when switching from pru0 to pru1 +when using rpmsg_pru. + +1. The include on line 10 is switched to ``#include "resource_table_1.h"`` (0 is switched to a 1) +2. Line 17 is switched to ``#define HOST_INT ((uint32_t) 1 << 31)`` (30 is switched to 31.) +3. Lines 23 and 24 are switched to: + +.. code-block:: c + + #define TO_ARM_HOST 18 + #define FROM_ARM_HOST 19 + +These changes switch to the proper channel numbers to use pru1 instead of pru0. + +RGB LED Matrix - No Integrated Drivers +====================================== + + +Problem +----------- + +You have a RGB LED matrix +(:ref:`../01case/case.html#case_rgb_matrix, 1.4. RGB LED Matrix - No Integrated Drivers`) and want to know +at a low level how the PRU works. + +Solution +----------- + +Here is the +`datasheet <https://cdn-shop.adafruit.com/product-files/2277/MI-T35P5RGBE-AE.pdf>`_, +but the best description I've found for the RGB Matrix is from +`Adafruit <https://www.adafruit.com/>`_. I've reproduced it here, with +adjustments for the 64x32 matrix we are using. + + +.. admonition:: information + + There's zero documention out there on how these matrices work, and no public + datasheets or spec sheets so we are going to try to document how they work. + + First thing to notice is that there are 2048 RGB LEDs in a 64x32 matrix. + Like pretty much every matrix out there, you can't drive all 2048 at once. + One reason is that would require a lot of current, another reason is that + it would be really expensive to have so many pins. Instead, the matrix is + divided into 16 interleaved sections/strips. The first section is the + 1^st^ 'line' and the 17^th^ 'line' (64 x 2 RGB LEDs = 128 RGB LEDs), + the second is the 2^nd^ and 18^th^ line, etc until the last section + which is the 16^th^ and 32^nd^ line. You might be asking, why are the + lines paired this way? wouldn't it be nicer to have the first section + be the 1^st^ and 2^nd^ line, then 3^rd^ and 4^th^, until the 15^th^ and + 16^th^? The reason they do it this way is so that the lines are interleaved + and look better when refreshed, otherwise we'd see the stripes more clearly. + + So, on the PCB is 24 LED driver chips. These are like 74HC595s but they + have 16 outputs and they are constant current. 16 outputs * 24 chips = + 384 LEDs that can be controlled at once, and 128 * 3 (R G and B) = 384. + So now the design comes together: You have 384 outputs that can control + one line at a time, with each of 384 R, G and B LEDs either on or off. + The controller (say an FPGA or microcontroller) selects which section + to currently draw (using LA, LB, LC and LD address pins - 4 bits can + have 16 values). Once the address is set, the controller clocks out + 384 bits of data (48 bytes) and latches it. Then it increments the + address and clocks out another 384 bits, etc until it gets to address + #15, then it sets the address back to #0 + + https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf + +That gives a good overview, but there are a few details missing. +:ref:`blocks_rgb_python` is a functioning python program that gives a nice +high-level view of how to drive the display. + +.. TODO Test this + +.. _blocks_rgb_python: + +rgb_python.py - Python code for driving RGB LED matrix +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`rgb_python.py <code/rgb_python.py>` + +Be sure to run the :ref:`blocks_rgb_setup` script before running the python code. + +.. _blocks_rgb_setup: + +rgb_python_setup.sh +~~~~~~~~~~~~~~~~~~~~ + +:download:`rgb_python_setup.sh <code/rgb_python_setup.sh>` + +Make sure line 29 is commented out and line 30 is uncommented. +Later we'll configure for _pruout_, but for now the python code doesn't use +the PRU outs. + +.. code-block:: bash + + # config-pin $pin pruout + config-pin $pin out + +Your display should look like :ref:`blocks_rgb_python_jpg`. + +.. _blocks_rgb_python_jpg: + +Display running rgb_python.py +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/rgb_python.jpg + :align: center + :alt: Display running rgb_python.py + +So why do only two lines appear at a time? That's how the display works. +Currently lines 6 and 22 are showing, then a moment later 7 and 23 show, etc. +The display can only display two lines at a time, so it cycles through all the +lines. Unfortunately, python is too slow to make the display appear +all at once. Here's where the PRU comes in. + +:ref:``blocks_rgb1`` is the PRU code to drive the RGB LED matrix. Be sure to run +``bone$ source rgb_setup.sh`` first. + +.. _blocks_rgb1: + +PRU code for driving the RGB LED matrix +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`rgb1.pru0.c <code/rgb1.pru0.c>` + + +The results are shown in :ref:`blocks_rgb_pru`. + +.. _blocks_rgb_pru: + +Display running rgb1.c on PRU 0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/rgb_pru.jpg + :align: center + :alt: Display running rgb1.pru0.c on PRU 0 + +The PRU is fast enough to quickly write to the display so that it appears +as if all the LEDs are on at once. + +Discussion +----------- + +There are a lot of details needed to make this simple display work. Let's +go over some of them. + +First, the connector looks like :ref:`blocks_matrix_j1`. + +.. _blocks_matrix_j1: + +RGB Matrix J1 connector +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/matrix_j1.jpg + :align: center + :alt: RGB Matrix J1 connector, 200 + +Notice the labels on the connect match the labels in the code. +:ref:`blocks_pocket_scroller_pins` shows how the pins on the display are +mapped to the pins on the Pocket Beagle. + +.. ToDo Make a mapping table for the Black +.. https://github.com/FalconChristmas/fpp/blob/master/src/pru/OctoscrollerV2.hp + +.. _blocks_pocket_scroller_pins: + +PocketScroller pin table +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-----------------+---------------+------------------------+------------------+-------------------+ + |J1 Connector Pin |Pocket Headers |gpio port and bit number|Linux gpio number |PRU R30 bit number | + +=================+===============+========================+==================+===================+ + |R1 |P2_10 |1-20 |52 | | + +-----------------+---------------+------------------------+------------------+-------------------+ + |B1 |P2_06 |1-25 |57 | | + +-----------------+---------------+------------------------+------------------+-------------------+ + |R2 |P2_04 |1-26 |58 | | + +-----------------+---------------+------------------------+------------------+-------------------+ + |B2 |P2_01 |1-18 |50 | | + +-----------------+---------------+------------------------+------------------+-------------------+ + |LA |P2_32 |3-16 |112 |PRU0.2 | + +-----------------+---------------+------------------------+------------------+-------------------+ + |LC |P1_31 |3-18 |114 |PRU0.4 | + +-----------------+---------------+------------------------+------------------+-------------------+ + |CLK |P1_33 |3-15 |111 |PRU0.1 | + +-----------------+---------------+------------------------+------------------+-------------------+ + |OE |P1_29 |3-21 |117 |PRU0.7 | + +-----------------+---------------+------------------------+------------------+-------------------+ + |G1 |P2_08 |1-28 |60 | | + +-----------------+---------------+------------------------+------------------+-------------------+ + |G2 |P2_02 |1-27 |59 | | + +-----------------+---------------+------------------------+------------------+-------------------+ + |LB |P2_30 |3-17 |113 |PRU0.3 | + +-----------------+---------------+------------------------+------------------+-------------------+ + |LD |P2_34 |3-19 |115 |PRU0.5 | + +-----------------+---------------+------------------------+------------------+-------------------+ + |LAT |P1_36 |3-14 |110 |PRU0.0 | + +-----------------+---------------+------------------------+------------------+-------------------+ + +The J1 mapping to gpio port and bit number comes from +https://github.com/FalconChristmas/fpp/blob/master/capes/pb/panels/PocketScroller.json. +The gpio port and bit number mapping to Pocket Headers comes from +https://docs.google.com/spreadsheets/d/1FRGvYOyW1RiNSEVprvstfJAVeapnASgDXHtxeDOjgqw/edit#gid=0. + +:ref:`blocks_rgb_waveforms` shows four of the signal waveforms driving the RGB LED matrix. + +.. _blocks_rgb_waveforms: + +Oscilloscope display of CLK, OE, LAT and R1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/rgb_waveforms.png + :align: center + :alt: .Oscilloscope display of CLK, OE, LAT and R1 + +The top waveform is the CLK, the next is OE, followed by LAT and finally R1. +The OE (output enable) is active low, so most of the time the display is visible. +The sequence is: + +* Put data on the R1, G1, B1, R2, G2 and B2 lines +* Toggle the clock. +* Repeat the first two steps as one row of data is transfered. There are +384 LEDs (2 rows of 32 RGB LEDs times 3 LED per RGB), but we are clocking in +six bits (R1, G1, etc.) at a time, so 384/6=64 values need to be clocked in. +* Once all the values are in, disable the display (OE goes high) +* Then toggle the latch (LAT) to latch the new data. +* Turn the display back on. +* Increment the address lines (LA, LB, LC and LD) to point to the next rows. +* Keep repeating the above to keep the display lit. + +Using the PRU we are able to run the clock a about 2.9 MKHz. +:ref:`blocks_rgb_fpp` shows the optimized assembler code used by FPP clocks in +at some 6.3 MHz. So the compiler is doing a pretty good job, but you can run +some two times faster if you want to use assembly code. In fairness to FPP, +it's having to pull it's data out of RAM to display it, so isn't not a good +comparision. + +.. _blocks_rgb_fpp: + +FPP waveforms +~~~~~~~~~~~~~~ + +.. figure:: figures/rgb_fpp.png + :align: center + :alt: FPP waveforms + +Getting More Colors +~~~~~~~~~~~~~~~~~~~~~ + +The Adafruit description goes on to say: + +.. admonition:: information + + The only downside of this technique is that despite being very simple and fast, + it has no PWM control built-in! The controller can only set the LEDs on or off. + So what do you do when you want full color? You actually need to draw the entire + matrix over and over again at very high speeds to PWM the matrix manually. For + that reason, you need to have a very fast controller (50 MHz is a minimum) if + you want to do a lot of colors and motion video and have it look good. + + https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf + +This is what FPP does, but it's beyond the scope of this project. + +Compiling and Inserting rpmsg_pru +====================================== + +Problem +----------- + +Your Beagle doesn't have rpmsg_pru. + +Solution +----------- + +Do the following. + +.. code-block:: bash + + bone$ *cd 05blocks/code/module* + bone$ *sudo apt install linux-headers-\`uname -r`* + bone$ *wget https://github.com/beagleboard/linux/raw/4.9/drivers/rpmsg/rpmsg_pru.c* + bone$ *make* + make -C /lib/modules/4.9.88-ti-r111/build M=$PWD + make[1]: Entering directory '/usr/src/linux-headers-4.9.88-ti-r111' + LD /home/debian/PRUCookbook/docs/05blocks/code/module/built-in.o + CC [M] /home/debian/PRUCookbook/docs/05blocks/code/module/rpmsg_client_sample.o + CC [M] /home/debian/PRUCookbook/docs/05blocks/code/module/rpmsg_pru.o + Building modules, stage 2. + MODPOST 2 modules + CC /home/debian/PRUCookbook/docs/05blocks/code/module/rpmsg_client_sample.mod.o + LD [M] /home/debian/PRUCookbook/docs/05blocks/code/module/rpmsg_client_sample.ko + CC /home/debian/PRUCookbook/docs/05blocks/code/module/rpmsg_pru.mod.o + LD [M] /home/debian/PRUCookbook/docs/05blocks/code/module/rpmsg_pru.ko + make[1]: Leaving directory '/usr/src/linux-headers-4.9.88-ti-r111' + bone$ *sudo insmod rpmsg_pru.ko* + bone$ *lsmod | grep rpm* + rpmsg_pru 5799 2 + virtio_rpmsg_bus 13620 0 + rpmsg_core 8537 2 rpmsg_pru,virtio_rpmsg_bus + + +It's now installed and ready to go. + + +Copyright +========== + +copyright.c +~~~~~~~~~~~~~ + +:download:`copyright.c <code/copyright.c>` + diff --git a/pru-cookbook/05blocks/code/Makefile b/pru-cookbook/05blocks/code/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a7557fdaa22988d89cec879477ded78522d7116f --- /dev/null +++ b/pru-cookbook/05blocks/code/Makefile @@ -0,0 +1 @@ +include /var/lib/cloud9/common/Makefile diff --git a/pru-cookbook/05blocks/code/copyright.c b/pru-cookbook/05blocks/code/copyright.c new file mode 100644 index 0000000000000000000000000000000000000000..a34918faa44a789c3624c0e5551704e630017dae --- /dev/null +++ b/pru-cookbook/05blocks/code/copyright.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff --git a/pru-cookbook/05blocks/code/input.pru0.c b/pru-cookbook/05blocks/code/input.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..9ed5d3b759eb866fdbaa57fed9258c71ed32263e --- /dev/null +++ b/pru-cookbook/05blocks/code/input.pru0.c @@ -0,0 +1,26 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t led; + uint32_t sw; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + led = 0x1<<0; // P9_31 or P1_36 + sw = 0x1<<7; // P9_25 or P1_29 + + while (1) { + if((__R31&sw) == sw) { + __R30 |= led; // Turn on LED + } else + __R30 &= ~led; // Turn off LED + } +} + diff --git a/pru-cookbook/05blocks/code/input_setup.sh b/pru-cookbook/05blocks/code/input_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..35a0d9c3598288c14894a90907a69d62009eed1f --- /dev/null +++ b/pru-cookbook/05blocks/code/input_setup.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# +export TARGET=input.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + config-pin P9_31 pruout + config-pin -q P9_31 + config-pin P9_25 pruin + config-pin -q P9_25 +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + config-pin P1_36 pruout + config-pin -q P1_36 + config-pin P1_29 pruin + config-pin -q P1_29 +else + echo " Not Found" + pins="" +fi diff --git a/pru-cookbook/05blocks/code/module/.gitignore b/pru-cookbook/05blocks/code/module/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..9b6dfc433724ec94f8905520931dcf33d409ea87 --- /dev/null +++ b/pru-cookbook/05blocks/code/module/.gitignore @@ -0,0 +1 @@ +*.ko diff --git a/pru-cookbook/05blocks/code/module/Makefile b/pru-cookbook/05blocks/code/module/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9ca05d057c153a2d9b653fc64f5504a2d5aeea2e --- /dev/null +++ b/pru-cookbook/05blocks/code/module/Makefile @@ -0,0 +1,25 @@ +# Makefile for compiling out-of-tree +# From Free Electrons +# If on the Bone run apt install linux-headers-`uname -r` + +KDIR := /lib/modules/$(shell uname -r)/build + +obj-m += rpmsg_client_sample.o +obj-m += rpmsg_pru.o + +all: + $(MAKE) -C $(KDIR) M=$$PWD + +install: + scp hello*.ko bone:. + +print: + @echo KERNELRELEASE= $(KERNELRELEASE) + @echo CONFIG_EXAMPLES= $(CONFIG_EXAMPLES) + @echo obj-m= $(obj-m) + +clean: + rm -rf .tmp_versions *.o + rm -rf .rpmsg_client_sample* rpmsg_client_sample*.mod.c + rm -rf .rpmsg_pru* rpmsg_pru*.mod.c + rm modules.order Module.symvers .built-in.o.cmd \ No newline at end of file diff --git a/pru-cookbook/05blocks/code/module/install.sh b/pru-cookbook/05blocks/code/module/install.sh new file mode 100755 index 0000000000000000000000000000000000000000..89f497f038396b8bfaddcec73330b74255e0c5ab --- /dev/null +++ b/pru-cookbook/05blocks/code/module/install.sh @@ -0,0 +1,6 @@ +# This is a example of ARM to PRU communication from Lab 5 of +# http://processors.wiki.ti.com/index.php/PRU_Training:_Hands-on_Labs#LAB_5:_RPMsg_Communication_between_ARM_and_PRU + +sudo apt install linux-headers-`uname -r` + +wget https://github.com/beagleboard/linux/raw/4.9/drivers/rpmsg/rpmsg_pru.c diff --git a/pru-cookbook/05blocks/code/module/rpmsg_client_sample.c b/pru-cookbook/05blocks/code/module/rpmsg_client_sample.c new file mode 100644 index 0000000000000000000000000000000000000000..72b24524c626cca0291d93b5d765ecf515dac0f3 --- /dev/null +++ b/pru-cookbook/05blocks/code/module/rpmsg_client_sample.c @@ -0,0 +1,102 @@ +/* + * Remote processor messaging - sample client driver + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2011 Google, Inc. + * + * Ohad Ben-Cohen <ohad@wizery.com> + * Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/rpmsg.h> + +#define MSG "hello world!" +#define MSG_LIMIT 10 + +struct instance_data { + int rx_count; +}; + +static int rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len, + void *priv, u32 src) +{ + int ret; + struct instance_data *idata = dev_get_drvdata(&rpdev->dev); + + dev_info(&rpdev->dev, "incoming msg %d (src: 0x%x)\n", + ++idata->rx_count, src); + + print_hex_dump(KERN_DEBUG, __func__, DUMP_PREFIX_NONE, 16, 1, + data, len, true); + + /* samples should not live forever */ + if (idata->rx_count >= MSG_LIMIT) { + dev_info(&rpdev->dev, "goodbye!\n"); + return 0; + } + + /* send a new message now */ + ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG)); + if (ret) + dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret); + + return 0; +} + +static int rpmsg_sample_probe(struct rpmsg_device *rpdev) +{ + int ret; + struct instance_data *idata; + + dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n", + rpdev->src, rpdev->dst); + + idata = devm_kzalloc(&rpdev->dev, sizeof(*idata), GFP_KERNEL); + if (!idata) + return -ENOMEM; + + dev_set_drvdata(&rpdev->dev, idata); + + /* send a message to our remote processor */ + ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG)); + if (ret) { + dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret); + return ret; + } + + return 0; +} + +static void rpmsg_sample_remove(struct rpmsg_device *rpdev) +{ + dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n"); +} + +static struct rpmsg_device_id rpmsg_driver_sample_id_table[] = { + { .name = "rpmsg-client-sample" }, + { }, +}; +MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_sample_id_table); + +static struct rpmsg_driver rpmsg_sample_client = { + .drv.name = KBUILD_MODNAME, + .id_table = rpmsg_driver_sample_id_table, + .probe = rpmsg_sample_probe, + .callback = rpmsg_sample_cb, + .remove = rpmsg_sample_remove, +}; +module_rpmsg_driver(rpmsg_sample_client); + +MODULE_DESCRIPTION("Remote processor messaging sample client driver"); +MODULE_LICENSE("GPL v2"); diff --git a/pru-cookbook/05blocks/code/module/rpmsg_pru.c b/pru-cookbook/05blocks/code/module/rpmsg_pru.c new file mode 100644 index 0000000000000000000000000000000000000000..5a96b20965035e5b12139f391a41529c94ff0dbc --- /dev/null +++ b/pru-cookbook/05blocks/code/module/rpmsg_pru.c @@ -0,0 +1,359 @@ +/* + * PRU Remote Processor Messaging Driver + * + * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ + * Jason Reeder <jreeder@ti.com> + * Suman Anna <s-anna@ti.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/rpmsg.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/cdev.h> +#include <linux/module.h> +#include <linux/kfifo.h> +#include <linux/uaccess.h> +#include <linux/mutex.h> +#include <linux/poll.h> +#include <linux/rpmsg/virtio_rpmsg.h> + +#define PRU_MAX_DEVICES (8) +/* Matches the definition in virtio_rpmsg_bus.c */ +#define RPMSG_BUF_SIZE (512) +#define MAX_FIFO_MSG (32) +#define FIFO_MSG_SIZE RPMSG_BUF_SIZE + +/** + * struct rpmsg_pru_dev - Structure that contains the per-device data + * @rpdev: rpmsg channel device that is associated with this rpmsg_pru device + * @dev: device + * @cdev: character device + * @locked: boolean used to determine whether or not the device file is in use + * @devt: dev_t structure for the rpmsg_pru device + * @msg_fifo: kernel fifo used to buffer the messages between userspace and PRU + * @msg_len: array storing the lengths of each message in the kernel fifo + * @msg_idx_rd: kernel fifo read index + * @msg_idx_wr: kernel fifo write index + * @wait_list: wait queue used to implement the poll operation of the character + * device + * + * Each rpmsg_pru device provides an interface, using an rpmsg channel (rpdev), + * between a user space character device (cdev) and a PRU core. A kernel fifo + * (msg_fifo) is used to buffer the messages in the kernel that are + * being passed between the character device and the PRU. + */ +struct rpmsg_pru_dev { + struct rpmsg_device *rpdev; + struct device *dev; + struct cdev cdev; + bool locked; + dev_t devt; + struct kfifo msg_fifo; + u32 msg_len[MAX_FIFO_MSG]; + int msg_idx_rd; + int msg_idx_wr; + wait_queue_head_t wait_list; +}; + +static struct class *rpmsg_pru_class; +static dev_t rpmsg_pru_devt; +static DEFINE_MUTEX(rpmsg_pru_lock); +static DEFINE_IDR(rpmsg_pru_minors); + +static int rpmsg_pru_open(struct inode *inode, struct file *filp) +{ + struct rpmsg_pru_dev *prudev; + int ret = -EACCES; + + prudev = container_of(inode->i_cdev, struct rpmsg_pru_dev, cdev); + + mutex_lock(&rpmsg_pru_lock); + if (!prudev->locked) { + prudev->locked = true; + filp->private_data = prudev; + ret = 0; + } + mutex_unlock(&rpmsg_pru_lock); + + if (ret) + dev_err(prudev->dev, "Device already open\n"); + + return ret; +} + +static int rpmsg_pru_release(struct inode *inode, struct file *filp) +{ + struct rpmsg_pru_dev *prudev; + + prudev = container_of(inode->i_cdev, struct rpmsg_pru_dev, cdev); + mutex_lock(&rpmsg_pru_lock); + prudev->locked = false; + mutex_unlock(&rpmsg_pru_lock); + return 0; +} + +static ssize_t rpmsg_pru_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + int ret; + u32 length; + struct rpmsg_pru_dev *prudev; + + prudev = filp->private_data; + + if (kfifo_is_empty(&prudev->msg_fifo) && + (filp->f_flags & O_NONBLOCK)) + return -EAGAIN; + + ret = wait_event_interruptible(prudev->wait_list, + !kfifo_is_empty(&prudev->msg_fifo)); + if (ret) + return -EINTR; + + ret = kfifo_to_user(&prudev->msg_fifo, buf, + prudev->msg_len[prudev->msg_idx_rd], &length); + prudev->msg_idx_rd = (prudev->msg_idx_rd + 1) % MAX_FIFO_MSG; + + return ret ? ret : length; +} + +static ssize_t rpmsg_pru_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + int ret; + struct rpmsg_pru_dev *prudev; + static char rpmsg_pru_buf[RPMSG_BUF_SIZE]; + + prudev = filp->private_data; + + if (count > RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)) { + dev_err(prudev->dev, "Data too large for RPMsg Buffer\n"); + return -EINVAL; + } + + if (copy_from_user(rpmsg_pru_buf, buf, count)) { + dev_err(prudev->dev, "Error copying buffer from user space"); + return -EFAULT; + } + + ret = rpmsg_send(prudev->rpdev->ept, (void *)rpmsg_pru_buf, count); + if (ret) + dev_err(prudev->dev, "rpmsg_send failed: %d\n", ret); + + return ret ? ret : count; +} + +static unsigned int rpmsg_pru_poll(struct file *filp, + struct poll_table_struct *wait) +{ + int mask; + struct rpmsg_pru_dev *prudev; + + prudev = filp->private_data; + + poll_wait(filp, &prudev->wait_list, wait); + + mask = POLLOUT | POLLWRNORM; + + if (!kfifo_is_empty(&prudev->msg_fifo)) + mask |= POLLIN | POLLRDNORM; + + return mask; +} + +static const struct file_operations rpmsg_pru_fops = { + .owner = THIS_MODULE, + .open = rpmsg_pru_open, + .release = rpmsg_pru_release, + .read = rpmsg_pru_read, + .write = rpmsg_pru_write, + .poll = rpmsg_pru_poll, +}; + +static int rpmsg_pru_cb(struct rpmsg_device *rpdev, void *data, int len, + void *priv, u32 src) +{ + u32 length; + struct rpmsg_pru_dev *prudev; + + prudev = dev_get_drvdata(&rpdev->dev); + + if (kfifo_avail(&prudev->msg_fifo) < len) { + dev_err(&rpdev->dev, "Not enough space on the FIFO\n"); + return -ENOSPC; + } + + if ((prudev->msg_idx_wr + 1) % MAX_FIFO_MSG == + prudev->msg_idx_rd) { + dev_err(&rpdev->dev, "Message length table is full\n"); + return -ENOSPC; + } + + length = kfifo_in(&prudev->msg_fifo, data, len); + prudev->msg_len[prudev->msg_idx_wr] = length; + prudev->msg_idx_wr = (prudev->msg_idx_wr + 1) % MAX_FIFO_MSG; + + wake_up_interruptible(&prudev->wait_list); + + return 0; +} + +static int rpmsg_pru_probe(struct rpmsg_device *rpdev) +{ + int ret; + struct rpmsg_pru_dev *prudev; + int minor_got; + + prudev = devm_kzalloc(&rpdev->dev, sizeof(*prudev), GFP_KERNEL); + if (!prudev) + return -ENOMEM; + + mutex_lock(&rpmsg_pru_lock); + minor_got = idr_alloc(&rpmsg_pru_minors, prudev, 0, PRU_MAX_DEVICES, + GFP_KERNEL); + mutex_unlock(&rpmsg_pru_lock); + if (minor_got < 0) { + ret = minor_got; + dev_err(&rpdev->dev, "Failed to get a minor number for the rpmsg_pru device: %d\n", + ret); + goto fail_alloc_minor; + } + + prudev->devt = MKDEV(MAJOR(rpmsg_pru_devt), minor_got); + + cdev_init(&prudev->cdev, &rpmsg_pru_fops); + prudev->cdev.owner = THIS_MODULE; + ret = cdev_add(&prudev->cdev, prudev->devt, 1); + if (ret) { + dev_err(&rpdev->dev, "Unable to add cdev for the rpmsg_pru device\n"); + goto fail_add_cdev; + } + + prudev->dev = device_create(rpmsg_pru_class, &rpdev->dev, prudev->devt, + NULL, "rpmsg_pru%d", rpdev->dst); + if (IS_ERR(prudev->dev)) { + dev_err(&rpdev->dev, "Unable to create the rpmsg_pru device\n"); + ret = PTR_ERR(prudev->dev); + goto fail_create_device; + } + + prudev->rpdev = rpdev; + + ret = kfifo_alloc(&prudev->msg_fifo, MAX_FIFO_MSG * FIFO_MSG_SIZE, + GFP_KERNEL); + if (ret) { + dev_err(&rpdev->dev, "Unable to allocate fifo for the rpmsg_pru device\n"); + goto fail_alloc_fifo; + } + + init_waitqueue_head(&prudev->wait_list); + + dev_set_drvdata(&rpdev->dev, prudev); + + dev_info(&rpdev->dev, "new rpmsg_pru device: /dev/rpmsg_pru%d", + rpdev->dst); + + return 0; + +fail_alloc_fifo: + device_destroy(rpmsg_pru_class, prudev->devt); +fail_create_device: + cdev_del(&prudev->cdev); +fail_add_cdev: + mutex_lock(&rpmsg_pru_lock); + idr_remove(&rpmsg_pru_minors, minor_got); + mutex_unlock(&rpmsg_pru_lock); +fail_alloc_minor: + return ret; +} + +static void rpmsg_pru_remove(struct rpmsg_device *rpdev) +{ + struct rpmsg_pru_dev *prudev; + + prudev = dev_get_drvdata(&rpdev->dev); + + kfifo_free(&prudev->msg_fifo); + device_destroy(rpmsg_pru_class, prudev->devt); + cdev_del(&prudev->cdev); + mutex_lock(&rpmsg_pru_lock); + idr_remove(&rpmsg_pru_minors, MINOR(prudev->devt)); + mutex_unlock(&rpmsg_pru_lock); +} + +/* .name matches on RPMsg Channels and causes a probe */ +static const struct rpmsg_device_id rpmsg_driver_pru_id_table[] = { + { .name = "rpmsg-pru" }, + { }, +}; +MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_pru_id_table); + +static struct rpmsg_driver rpmsg_pru_driver = { + .drv.name = KBUILD_MODNAME, + .id_table = rpmsg_driver_pru_id_table, + .probe = rpmsg_pru_probe, + .callback = rpmsg_pru_cb, + .remove = rpmsg_pru_remove, +}; + +static int __init rpmsg_pru_init(void) +{ + int ret; + + rpmsg_pru_class = class_create(THIS_MODULE, "rpmsg_pru"); + if (IS_ERR(rpmsg_pru_class)) { + pr_err("Unable to create class\n"); + ret = PTR_ERR(rpmsg_pru_class); + goto fail_create_class; + } + + ret = alloc_chrdev_region(&rpmsg_pru_devt, 0, PRU_MAX_DEVICES, + "rpmsg_pru"); + if (ret) { + pr_err("Unable to allocate chrdev region\n"); + goto fail_alloc_region; + } + + ret = register_rpmsg_driver(&rpmsg_pru_driver); + if (ret) { + pr_err("Unable to register rpmsg driver"); + goto fail_register_rpmsg_driver; + } + + return 0; + +fail_register_rpmsg_driver: + unregister_chrdev_region(rpmsg_pru_devt, PRU_MAX_DEVICES); +fail_alloc_region: + class_destroy(rpmsg_pru_class); +fail_create_class: + return ret; +} + +static void __exit rpmsg_pru_exit(void) +{ + unregister_rpmsg_driver(&rpmsg_pru_driver); + idr_destroy(&rpmsg_pru_minors); + mutex_destroy(&rpmsg_pru_lock); + class_destroy(rpmsg_pru_class); + unregister_chrdev_region(rpmsg_pru_devt, PRU_MAX_DEVICES); +} + +module_init(rpmsg_pru_init); +module_exit(rpmsg_pru_exit); + +MODULE_AUTHOR("Jason Reeder <jreeder@ti.com>"); +MODULE_ALIAS("rpmsg:rpmsg-pru"); +MODULE_DESCRIPTION("PRU Remote Processor Messaging Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/pru-cookbook/05blocks/code/module/setup.sh b/pru-cookbook/05blocks/code/module/setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..3b313b366052438b0db8e7a7c0f00a04313b8687 --- /dev/null +++ b/pru-cookbook/05blocks/code/module/setup.sh @@ -0,0 +1 @@ +insmod rpmsg_pru.ko diff --git a/pru-cookbook/05blocks/code/neo-colors.py b/pru-cookbook/05blocks/code/neo-colors.py new file mode 100755 index 0000000000000000000000000000000000000000..736a47b3c7e6ae2507da296fdae5ac01be7f7a14 --- /dev/null +++ b/pru-cookbook/05blocks/code/neo-colors.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +from time import sleep +import math + +length = 24 +max = 25 + +# Open a file +fo = open("/dev/rpmsg_pru30", "wb", 0) + +colors = [[1,0,0],[1,1,0],[0,1,0],[0,1,1],[0,0,1],[1,0,1]]# colors = [[1,0,0],[1,0,0]] + +oldr=0 +oldb=0 +oldg=0 + +while True: + for color in colors: + newr = color[0] + newg = color[1] + newb = color[2] + maxtime=20 + for time in range(0, maxtime): + r = (max*oldr+(newr-oldr)*max*time/maxtime) + g = (max*oldg+(newg-oldg)*max*time/maxtime) + b = (max*oldb+(newb-oldb)*max*time/maxtime) + for i in range(0, length): + fo.write(b"%d %d %d %d\n" % (i, r, g, b)) + # print("0 0 127 %d" % (i)) + fo.write(b"-1 0 0 0\n"); # Send colors to LEDs + + # print (r,g,b) + + sleep(0.05) + + oldr=newr + oldg=newg + oldb=newb + +# Close opened file +fo.close() \ No newline at end of file diff --git a/pru-cookbook/05blocks/code/neo-rainbow.py b/pru-cookbook/05blocks/code/neo-rainbow.py new file mode 100755 index 0000000000000000000000000000000000000000..ffd706a643a9c71609e8b8893b6ff91b53cde08b --- /dev/null +++ b/pru-cookbook/05blocks/code/neo-rainbow.py @@ -0,0 +1,27 @@ +#!/usr/bin/python3 +from time import sleep +import math + +len = 24 +amp = 12 +f = 25 +shift = 3 +phase = 0 + +# Open a file +fo = open("/dev/rpmsg_pru30", "wb", 0) + +while True: + for i in range(0, len): + r = (amp * (math.sin(2*math.pi*f*(i-phase-0*shift)/len) + 1)) + 1; + g = (amp * (math.sin(2*math.pi*f*(i-phase-1*shift)/len) + 1)) + 1; + b = (amp * (math.sin(2*math.pi*f*(i-phase-2*shift)/len) + 1)) + 1; + fo.write(b"%d %d %d %d\n" % (i, r, g, b)) + # print("0 0 127 %d" % (i)) + + fo.write(b"-1 0 0 0\n"); + phase = phase + 1 + sleep(0.05) + +# Close opened file +fo.close() \ No newline at end of file diff --git a/pru-cookbook/05blocks/code/neo1.pru0.c b/pru-cookbook/05blocks/code/neo1.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..5f2ce8248d73706b8f78c7b76e5df9009ffd4b02 --- /dev/null +++ b/pru-cookbook/05blocks/code/neo1.pru0.c @@ -0,0 +1,44 @@ +// Control a ws2812 (NeoPixel) display, All on or all off +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +#define STR_LEN 24 +#define oneCyclesOn 700/5 // Stay on 700ns +#define oneCyclesOff 800/5 +#define zeroCyclesOn 350/5 +#define zeroCyclesOff 600/5 +#define resetCycles 60000/5 // Must be at least 50u, use 60u +#define gpio P9_29 // output pin + +#define ONE + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + uint32_t i; + for(i=0; i<STR_LEN*3*8; i++) { +#ifdef ONE + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(oneCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(oneCyclesOff-2); +#else + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(zeroCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(zeroCyclesOff-2); +#endif + } + // Send Reset + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(resetCycles); + + __halt(); +} diff --git a/pru-cookbook/05blocks/code/neo1.pru1_1.c b/pru-cookbook/05blocks/code/neo1.pru1_1.c new file mode 100644 index 0000000000000000000000000000000000000000..2ad8d56d1cff431ab3c006788440454083b26e96 --- /dev/null +++ b/pru-cookbook/05blocks/code/neo1.pru1_1.c @@ -0,0 +1,44 @@ +// Control a ws2812 (NeoPixel) display, All on or all off +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +#define STR_LEN 24 +#define oneCyclesOn 700/5 // Stay on 700ns +#define oneCyclesOff 800/5 +#define zeroCyclesOn 350/5 +#define zeroCyclesOff 600/5 +#define resetCycles 60000/5 // Must be at least 50u, use 60u +#define gpio P9_16 // output pin + +#define ONE + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + uint32_t i; + for(i=0; i<STR_LEN*3*8; i++) { +#ifdef ONE + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(oneCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(oneCyclesOff-2); +#else + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(zeroCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(zeroCyclesOff-2); +#endif + } + // Send Reset + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(resetCycles); + + __halt(); +} diff --git a/pru-cookbook/05blocks/code/neo2.pru0.c b/pru-cookbook/05blocks/code/neo2.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..a30077ceb090f7e3722cb0fe1a61162bdde9bb9d --- /dev/null +++ b/pru-cookbook/05blocks/code/neo2.pru0.c @@ -0,0 +1,46 @@ +// Control a ws2812 (neo pixel) display, green, red, blue, green, ... +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +#define STR_LEN 3 +#define oneCyclesOn 700/5 // Stay on 700ns +#define oneCyclesOff 800/5 +#define zeroCyclesOn 350/5 +#define zeroCyclesOff 600/5 +#define resetCycles 60000/5 // Must be at least 50u, use 60u +#define gpio P9_29 // output pin + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + uint32_t color[STR_LEN] = {0x0f0000, 0x000f00, 0x0000f}; // green, red, blue + int i, j; + + for(j=0; j<STR_LEN; j++) { + for(i=23; i>=0; i--) { + if(color[j] & (0x1<<i)) { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(oneCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(oneCyclesOff-2); + } else { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(zeroCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(zeroCyclesOff-2); + } + } + } + // Send Reset + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(resetCycles); + + __halt(); +} diff --git a/pru-cookbook/05blocks/code/neo2.pru1_1.c b/pru-cookbook/05blocks/code/neo2.pru1_1.c new file mode 100644 index 0000000000000000000000000000000000000000..6b243dcfb53c2139f44d4a2aabd113a274c331e8 --- /dev/null +++ b/pru-cookbook/05blocks/code/neo2.pru1_1.c @@ -0,0 +1,46 @@ +// Control a ws2812 (neo pixel) display, green, red, blue, green, ... +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +#define STR_LEN 3 +#define oneCyclesOn 700/5 // Stay on 700ns +#define oneCyclesOff 800/5 +#define zeroCyclesOn 350/5 +#define zeroCyclesOff 600/5 +#define resetCycles 60000/5 // Must be at least 50u, use 60u +#define gpio P9_16 // output pin + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + uint32_t color[STR_LEN] = {0x0f0000, 0x000f00, 0x0000f}; // green, red, blue + int i, j; + + for(j=0; j<STR_LEN; j++) { + for(i=23; i>=0; i--) { + if(color[j] & (0x1<<i)) { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(oneCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(oneCyclesOff-2); + } else { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(zeroCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(zeroCyclesOff-2); + } + } + } + // Send Reset + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(resetCycles); + + __halt(); +} diff --git a/pru-cookbook/05blocks/code/neo3.pru0.c b/pru-cookbook/05blocks/code/neo3.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..8c1a9f1323d564d7894b299f1bd4f8a4020bc5e8 --- /dev/null +++ b/pru-cookbook/05blocks/code/neo3.pru0.c @@ -0,0 +1,67 @@ +// Control a ws2812 (neo pixel) display, green, red, blue, green, ... +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +#define STR_LEN 24 +#define oneCyclesOn 700/5 // Stay on 700ns +#define oneCyclesOff 800/5 +#define zeroCyclesOn 350/5 +#define zeroCyclesOff 600/5 +#define resetCycles 60000/5 // Must be at least 50u, use 60u +#define gpio P9_29 // output pin + +#define SPEED 20000000/5 // Time to wait between updates + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t background = 0x00000f; + uint32_t foreground = 0x000f00; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + uint32_t color[STR_LEN]; // green, red, blue + int i, j; + int k, oldk = 0;; + // Set everything to background + for(i=0; i<STR_LEN; i++) { + color[i] = background; + } + + while(1) { + // Move forward one position + for(k=0; k<STR_LEN; k++) { + color[oldk] = background; + color[k] = foreground; + oldk=k; + + // Output the string + for(j=0; j<STR_LEN; j++) { + for(i=23; i>=0; i--) { + if(color[j] & (0x1<<i)) { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(oneCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(oneCyclesOff-2); + } else { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(zeroCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(zeroCyclesOff-2); + } + } + } + // Send Reset + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(resetCycles); + + // Wait + __delay_cycles(SPEED); + } + } +} diff --git a/pru-cookbook/05blocks/code/neo3.pru1_1.c b/pru-cookbook/05blocks/code/neo3.pru1_1.c new file mode 100644 index 0000000000000000000000000000000000000000..ee8dd63859680a930b3dca6c8c61895a87051ac9 --- /dev/null +++ b/pru-cookbook/05blocks/code/neo3.pru1_1.c @@ -0,0 +1,67 @@ +// Control a ws2812 (neo pixel) display, green, red, blue, green, ... +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +#define STR_LEN 24 +#define oneCyclesOn 700/5 // Stay on 700ns +#define oneCyclesOff 800/5 +#define zeroCyclesOn 350/5 +#define zeroCyclesOff 600/5 +#define resetCycles 60000/5 // Must be at least 50u, use 60u +#define gpio P9_16 // output pin + +#define SPEED 20000000/5 // Time to wait between updates + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t background = 0x00000f; + uint32_t foreground = 0x000f00; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + uint32_t color[STR_LEN]; // green, red, blue + int i, j; + int k, oldk = 0;; + // Set everything to background + for(i=0; i<STR_LEN; i++) { + color[i] = background; + } + + while(1) { + // Move forward one position + for(k=0; k<STR_LEN; k++) { + color[oldk] = background; + color[k] = foreground; + oldk=k; + + // Output the string + for(j=0; j<STR_LEN; j++) { + for(i=23; i>=0; i--) { + if(color[j] & (0x1<<i)) { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(oneCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(oneCyclesOff-2); + } else { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(zeroCyclesOn-1); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(zeroCyclesOff-2); + } + } + } + // Send Reset + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(resetCycles); + + // Wait + __delay_cycles(SPEED); + } + } +} diff --git a/pru-cookbook/05blocks/code/neo4.pru0.c b/pru-cookbook/05blocks/code/neo4.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..7fb5455781d8dc47cd414a433b1578ea84645ad9 --- /dev/null +++ b/pru-cookbook/05blocks/code/neo4.pru0.c @@ -0,0 +1,145 @@ +// Use rpmsg to control the NeoPixels via /dev/rpmsg_pru30 +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> // atoi +#include <string.h> +#include <pru_cfg.h> +#include <pru_intc.h> +#include <rsc_types.h> +#include <pru_rpmsg.h> +#include "resource_table_0.h" +#include "prugpio.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +/* Host-0 Interrupt sets bit 30 in register R31 */ +#define HOST_INT ((uint32_t) 1 << 30) + +/* The PRU-ICSS system events used for RPMsg are defined in the Linux device tree + * PRU0 uses system event 16 (To ARM) and 17 (From ARM) + * PRU1 uses system event 18 (To ARM) and 19 (From ARM) + */ +#define TO_ARM_HOST 16 +#define FROM_ARM_HOST 17 + +/* +* Using the name 'rpmsg-pru' will probe the rpmsg_pru driver found +* at linux-x.y.z/drivers/rpmsg/rpmsg_pru.c +*/ +#define CHAN_NAME "rpmsg-pru" +#define CHAN_DESC "Channel 30" +#define CHAN_PORT 30 + +/* + * Used to make sure the Linux drivers are ready for RPMsg communication + * Found at linux-x.y.z/include/uapi/linux/virtio_config.h + */ +#define VIRTIO_CONFIG_S_DRIVER_OK 4 + +char payload[RPMSG_BUF_SIZE]; + +#define STR_LEN 24 +#define oneCyclesOn 700/5 // Stay on for 700ns +#define oneCyclesOff 600/5 +#define zeroCyclesOn 350/5 +#define zeroCyclesOff 800/5 +#define resetCycles 51000/5 // Must be at least 50u, use 51u +#define out P9_29 // Bit number to output on + +#define SPEED 20000000/5 // Time to wait between updates + +uint32_t color[STR_LEN]; // green, red, blue + +/* + * main.c + */ +void main(void) +{ + struct pru_rpmsg_transport transport; + uint16_t src, dst, len; + volatile uint8_t *status; + + uint8_t r, g, b; + int i, j; + // Set everything to background + for(i=0; i<STR_LEN; i++) { + color[i] = 0x010000; + } + + /* Allow OCP master port access by the PRU so the PRU can read external memories */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + /* Clear the status of the PRU-ICSS system event that the ARM will use to 'kick' us */ +#ifdef CHIP_IS_am57xx + CT_INTC.SICR_bit.STATUS_CLR_INDEX = FROM_ARM_HOST; +#else + CT_INTC.SICR_bit.STS_CLR_IDX = FROM_ARM_HOST; +#endif + + /* Make sure the Linux drivers are ready for RPMsg communication */ + status = &resourceTable.rpmsg_vdev.status; + while (!(*status & VIRTIO_CONFIG_S_DRIVER_OK)); + + /* Initialize the RPMsg transport structure */ + pru_rpmsg_init(&transport, &resourceTable.rpmsg_vring0, &resourceTable.rpmsg_vring1, TO_ARM_HOST, FROM_ARM_HOST); + + /* Create the RPMsg channel between the PRU and ARM user space using the transport structure. */ + while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, CHAN_NAME, CHAN_DESC, CHAN_PORT) != PRU_RPMSG_SUCCESS); + while (1) { + /* Check bit 30 of register R31 to see if the ARM has kicked us */ + if (__R31 & HOST_INT) { + /* Clear the event status */ +#ifdef CHIP_IS_am57xx + CT_INTC.SICR_bit.STATUS_CLR_INDEX = FROM_ARM_HOST; +#else + CT_INTC.SICR_bit.STS_CLR_IDX = FROM_ARM_HOST; +#endif + /* Receive all available messages, multiple messages can be sent per kick */ + while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS) { + char *ret; // rest of payload after front character is removed + int index; // index of LED to control + // Input format is: index red green blue + index = atoi(payload); + // Update the array, but don't write it out. + if((index >=0) & (index < STR_LEN)) { + ret = strchr(payload, ' '); // Skip over index + r = strtol(&ret[1], NULL, 0); + ret = strchr(&ret[1], ' '); // Skip over r, etc. + g = strtol(&ret[1], NULL, 0); + ret = strchr(&ret[1], ' '); + b = strtol(&ret[1], NULL, 0); + + color[index] = (g<<16)|(r<<8)|b; // String wants GRB + } + // When index is -1, send the array to the LED string + if(index == -1) { + // Output the string + for(j=0; j<STR_LEN; j++) { + // Cycle through each bit + for(i=23; i>=0; i--) { + if(color[j] & (0x1<<i)) { + __R30 |= out; // Set the GPIO pin to 1 + __delay_cycles(oneCyclesOn-1); + __R30 &= ~out; // Clear the GPIO pin + __delay_cycles(oneCyclesOff-14); + } else { + __R30 |= out; // Set the GPIO pin to 1 + __delay_cycles(zeroCyclesOn-1); + __R30 &= ~(out); // Clear the GPIO pin + __delay_cycles(zeroCyclesOff-14); + } + } + } + // Send Reset + __R30 &= ~out; // Clear the GPIO pin + __delay_cycles(resetCycles); + + // Wait + __delay_cycles(SPEED); + } + + } + } + } +} diff --git a/pru-cookbook/05blocks/code/neo4.pru1_1.c b/pru-cookbook/05blocks/code/neo4.pru1_1.c new file mode 100644 index 0000000000000000000000000000000000000000..7c120937aa92b19fbc65971aa8a6ec3748c69ca4 --- /dev/null +++ b/pru-cookbook/05blocks/code/neo4.pru1_1.c @@ -0,0 +1,145 @@ +// Use rpmsg to control the NeoPixels via /dev/rpmsg_pru30 +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> // atoi +#include <string.h> +#include <pru_cfg.h> +#include <pru_intc.h> +#include <rsc_types.h> +#include <pru_rpmsg.h> +#include "resource_table_1.h" +#include "prugpio.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +/* Host-1 Interrupt sets bit 31 in register R31 */ +#define HOST_INT ((uint32_t) 1 << 31) + +/* The PRU-ICSS system events used for RPMsg are defined in the Linux device tree + * PRU0 uses system event 16 (To ARM) and 17 (From ARM) + * PRU1 uses system event 18 (To ARM) and 19 (From ARM) + */ +#define TO_ARM_HOST 18 +#define FROM_ARM_HOST 19 + +/* +* Using the name 'rpmsg-pru' will probe the rpmsg_pru driver found +* at linux-x.y.z/drivers/rpmsg/rpmsg_pru.c +*/ +#define CHAN_NAME "rpmsg-pru" +#define CHAN_DESC "Channel 31" +#define CHAN_PORT 31 + +/* + * Used to make sure the Linux drivers are ready for RPMsg communication + * Found at linux-x.y.z/include/uapi/linux/virtio_config.h + */ +#define VIRTIO_CONFIG_S_DRIVER_OK 4 + +char payload[RPMSG_BUF_SIZE]; + +#define STR_LEN 24 +#define oneCyclesOn 700/5 // Stay on for 700ns +#define oneCyclesOff 600/5 +#define zeroCyclesOn 350/5 +#define zeroCyclesOff 800/5 +#define resetCycles 51000/5 // Must be at least 50u, use 51u +#define out P9_16 // Bit number to output on + +#define SPEED 20000000/5 // Time to wait between updates + +uint32_t color[STR_LEN]; // green, red, blue + +/* + * main.c + */ +void main(void) +{ + struct pru_rpmsg_transport transport; + uint16_t src, dst, len; + volatile uint8_t *status; + + uint8_t r, g, b; + int i, j; + // Set everything to background + for(i=0; i<STR_LEN; i++) { + color[i] = 0x010000; + } + + /* Allow OCP master port access by the PRU so the PRU can read external memories */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + /* Clear the status of the PRU-ICSS system event that the ARM will use to 'kick' us */ +#ifdef CHIP_IS_am57xx + CT_INTC.SICR_bit.STATUS_CLR_INDEX = FROM_ARM_HOST; +#else + CT_INTC.SICR_bit.STS_CLR_IDX = FROM_ARM_HOST; +#endif + + /* Make sure the Linux drivers are ready for RPMsg communication */ + status = &resourceTable.rpmsg_vdev.status; + while (!(*status & VIRTIO_CONFIG_S_DRIVER_OK)); + + /* Initialize the RPMsg transport structure */ + pru_rpmsg_init(&transport, &resourceTable.rpmsg_vring0, &resourceTable.rpmsg_vring1, TO_ARM_HOST, FROM_ARM_HOST); + + /* Create the RPMsg channel between the PRU and ARM user space using the transport structure. */ + while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, CHAN_NAME, CHAN_DESC, CHAN_PORT) != PRU_RPMSG_SUCCESS); + while (1) { + /* Check bit 30 of register R31 to see if the ARM has kicked us */ + if (__R31 & HOST_INT) { + /* Clear the event status */ +#ifdef CHIP_IS_am57xx + CT_INTC.SICR_bit.STATUS_CLR_INDEX = FROM_ARM_HOST; +#else + CT_INTC.SICR_bit.STS_CLR_IDX = FROM_ARM_HOST; +#endif + /* Receive all available messages, multiple messages can be sent per kick */ + while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS) { + char *ret; // rest of payload after front character is removed + int index; // index of LED to control + // Input format is: index red green blue + index = atoi(payload); + // Update the array, but don't write it out. + if((index >=0) & (index < STR_LEN)) { + ret = strchr(payload, ' '); // Skip over index + r = strtol(&ret[1], NULL, 0); + ret = strchr(&ret[1], ' '); // Skip over r, etc. + g = strtol(&ret[1], NULL, 0); + ret = strchr(&ret[1], ' '); + b = strtol(&ret[1], NULL, 0); + + color[index] = (g<<16)|(r<<8)|b; // String wants GRB + } + // When index is -1, send the array to the LED string + if(index == -1) { + // Output the string + for(j=0; j<STR_LEN; j++) { + // Cycle through each bit + for(i=23; i>=0; i--) { + if(color[j] & (0x1<<i)) { + __R30 |= out; // Set the GPIO pin to 1 + __delay_cycles(oneCyclesOn-1); + __R30 &= ~out; // Clear the GPIO pin + __delay_cycles(oneCyclesOff-14); + } else { + __R30 |= out; // Set the GPIO pin to 1 + __delay_cycles(zeroCyclesOn-1); + __R30 &= ~(out); // Clear the GPIO pin + __delay_cycles(zeroCyclesOff-14); + } + } + } + // Send Reset + __R30 &= ~out; // Clear the GPIO pin + __delay_cycles(resetCycles); + + // Wait + __delay_cycles(SPEED); + } + + } + } + } +} diff --git a/pru-cookbook/05blocks/code/neo_setup.sh b/pru-cookbook/05blocks/code/neo_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..8f98cbb2a9ae5f915cafc47af006b958fffe44f7 --- /dev/null +++ b/pru-cookbook/05blocks/code/neo_setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +export TARGET=neo1.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_29 " +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P1_33" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruout + config-pin -q $pin +done diff --git a/pru-cookbook/05blocks/code/pwm-test.c b/pru-cookbook/05blocks/code/pwm-test.c new file mode 100644 index 0000000000000000000000000000000000000000..3bff5f71b6598b3f6ee1fd0fc04bdac16793cda8 --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm-test.c @@ -0,0 +1,74 @@ +/* + * + * pwm tester + * The on cycle and off cycles are stored in each PRU's Data memory + * + */ + +#include <stdio.h> +#include <fcntl.h> +#include <sys/mman.h> + +#define MAXCH 4 + +#define PRU_ADDR 0x4A300000 // Start of PRU memory Page 184 am335x TRM +#define PRU_LEN 0x80000 // Length of PRU memory +#define PRU0_DRAM 0x00000 // Offset to DRAM +#define PRU1_DRAM 0x02000 +#define PRU_SHAREDMEM 0x10000 // Offset to shared memory + +unsigned int *pru0DRAM_32int_ptr; // Points to the start of local DRAM +unsigned int *pru1DRAM_32int_ptr; // Points to the start of local DRAM +unsigned int *prusharedMem_32int_ptr; // Points to the start of the shared memory + +/******************************************************************************* +* int start_pwm_count(int ch, int countOn, int countOff) +* +* Starts a pwm pulse on for countOn and off for countOff to a single channel (ch) +*******************************************************************************/ +int start_pwm_count(int ch, int countOn, int countOff) { + unsigned int *pruDRAM_32int_ptr = pru0DRAM_32int_ptr; + + printf("countOn: %d, countOff: %d, count: %d\n", + countOn, countOff, countOn+countOff); + // write to PRU shared memory + pruDRAM_32int_ptr[2*(ch)+0] = countOn; // On time + pruDRAM_32int_ptr[2*(ch)+1] = countOff; // Off time + return 0; +} + +int main(int argc, char *argv[]) +{ + unsigned int *pru; // Points to start of PRU memory. + int fd; + printf("Servo tester\n"); + + fd = open ("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + printf ("ERROR: could not open /dev/mem.\n\n"); + return 1; + } + pru = mmap (0, PRU_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PRU_ADDR); + if (pru == MAP_FAILED) { + printf ("ERROR: could not map memory.\n\n"); + return 1; + } + close(fd); + printf ("Using /dev/mem.\n"); + + pru0DRAM_32int_ptr = pru + PRU0_DRAM/4 + 0x200/4; // Points to 0x200 of PRU0 memory + pru1DRAM_32int_ptr = pru + PRU1_DRAM/4 + 0x200/4; // Points to 0x200 of PRU1 memory + prusharedMem_32int_ptr = pru + PRU_SHAREDMEM/4; // Points to start of shared memory + + int i; + for(i=0; i<MAXCH; i++) { + start_pwm_count(i, i+1, 20-(i+1)); + } + + if(munmap(pru, PRU_LEN)) { + printf("munmap failed\n"); + } else { + printf("munmap succeeded\n"); + } +} + diff --git a/pru-cookbook/05blocks/code/pwm1.pru0.c b/pru-cookbook/05blocks/code/pwm1.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..2ea5caa17efd570bad1cbc658d5e2c96557b1b0f --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm1.pru0.c @@ -0,0 +1,22 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t gpio = P9_31; // Select which pin to toggle.; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + while(1) { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(100000000); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(100000000); + } +} diff --git a/pru-cookbook/05blocks/code/pwm1.pru1_1.c b/pru-cookbook/05blocks/code/pwm1.pru1_1.c new file mode 100644 index 0000000000000000000000000000000000000000..1f8b737e678691af3c4ab83cfa2d1d5bc442fe64 --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm1.pru1_1.c @@ -0,0 +1,22 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t gpio = P9_16; // Select which pin to toggle.; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + while(1) { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(100000000); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(100000000); + } +} diff --git a/pru-cookbook/05blocks/code/pwm2.pru0.c b/pru-cookbook/05blocks/code/pwm2.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..bfa0d0761411212a8a0f4469ca02dfd08f5a20bd --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm2.pru0.c @@ -0,0 +1,22 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t gpio = P9_31; // Select which pin to toggle.; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + while (1) { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(1); // Delay one cycle to correct for loop time + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(0); + } +} diff --git a/pru-cookbook/05blocks/code/pwm3.pru0.c b/pru-cookbook/05blocks/code/pwm3.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..4b2955a0573171e7e3525a9381e4a4a2acb15e36 --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm3.pru0.c @@ -0,0 +1,43 @@ +// This code does MAXCH parallel PWM channels. +// It's period is 3 us +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" + +#define MAXCH 4 // Maximum number of channels + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t ch; + uint32_t on[] = {1, 2, 3, 4}; // Number of cycles to stay on + uint32_t off[] = {4, 3, 2, 1}; // Number to stay off + uint32_t onCount[MAXCH]; // Current count + uint32_t offCount[MAXCH]; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + // Initialize the channel counters. + for(ch=0; ch<MAXCH; ch++) { + onCount[ch] = on[ch]; + offCount[ch]= off[ch]; + } + + while (1) { + for(ch=0; ch<MAXCH; ch++) { + if(onCount[ch]) { + onCount[ch]--; + __R30 |= 0x1<<ch; // Set the GPIO pin to 1 + } else if(offCount[ch]) { + offCount[ch]--; + __R30 &= ~(0x1<<ch); // Clear the GPIO pin + } else { + onCount[ch] = on[ch]; + offCount[ch]= off[ch]; + } + } + } +} diff --git a/pru-cookbook/05blocks/code/pwm4.pru0.c b/pru-cookbook/05blocks/code/pwm4.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..ee0f7ec6adf542562b8740ce410226840b01ac50 --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm4.pru0.c @@ -0,0 +1,50 @@ +// This code does MAXCH parallel PWM channels. +// It's period is 3 us +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" + +#define PRU0_DRAM 0x00000 // Offset to DRAM +// Skip the first 0x200 byte of DRAM since the Makefile allocates +// 0x100 for the STACK and 0x100 for the HEAP. +volatile unsigned int *pru0_dram = (unsigned int *) (PRU0_DRAM + 0x200); + +#define MAXCH 4 // Maximum number of channels per PRU + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t ch; + uint32_t on[] = {1, 2, 3, 4}; // Number of cycles to stay on + uint32_t off[] = {4, 3, 2, 1}; // Number to stay off + uint32_t onCount[MAXCH]; // Current count + uint32_t offCount[MAXCH]; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + // Initialize the channel counters. + for(ch=0; ch<MAXCH; ch++) { + pru0_dram[2*ch ] = on[ch]; // Copy to DRAM0 so the ARM can change it + pru0_dram[2*ch+1] = off[ch]; // Interleave the on and off values + onCount[ch] = on[ch]; + offCount[ch]= off[ch]; + } + + while (1) { + for(ch=0; ch<MAXCH; ch++) { + if(onCount[ch]) { + onCount[ch]--; + __R30 |= 0x1<<ch; // Set the GPIO pin to 1 + } else if(offCount[ch]) { + offCount[ch]--; + __R30 &= ~(0x1<<ch); // Clear the GPIO pin + } else { + onCount[ch] = pru0_dram[2*ch]; // Read from DRAM0 + offCount[ch]= pru0_dram[2*ch+1]; + } + } + } +} diff --git a/pru-cookbook/05blocks/code/pwm5.pru0.c b/pru-cookbook/05blocks/code/pwm5.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..60a97b817c32ca25fcbd9445ec6d612151ed21c6 --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm5.pru0.c @@ -0,0 +1,53 @@ +// This code does MAXCH parallel PWM channels. +// It's period is 510ns. +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" + +#define PRU0_DRAM 0x00000 // Offset to DRAM +// Skip the first 0x200 byte of DRAM since the Makefile allocates +// 0x100 for the STACK and 0x100 for the HEAP. +volatile unsigned int *pru0_dram = (unsigned int *) (PRU0_DRAM + 0x200); + +#define MAXCH 4 // Maximum number of channels per PRU + +#define update(ch) \ + if(onCount[ch]) { \ + onCount[ch]--; \ + __R30 |= 0x1<<ch; \ + } else if(offCount[ch]) { \ + offCount[ch]--; \ + __R30 &= ~(0x1<<ch); \ + } else { \ + onCount[ch] = pru0_dram[2*ch]; \ + offCount[ch]= pru0_dram[2*ch+1]; \ + } + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t ch; + uint32_t on[] = {1, 2, 3, 4}; + uint32_t off[] = {4, 3, 2, 1}; + uint32_t onCount[MAXCH], offCount[MAXCH]; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + +#pragma UNROLL(MAXCH) + for(ch=0; ch<MAXCH; ch++) { + pru0_dram[2*ch ] = on[ch]; // Copy to DRAM0 so the ARM can change it + pru0_dram[2*ch+1] = off[ch]; // Interleave the on and off values + onCount[ch] = on[ch]; + offCount[ch]= off[ch]; + } + + while (1) { + update(0) + update(1) + update(2) + update(3) + } +} diff --git a/pru-cookbook/05blocks/code/pwm6.pru0.c b/pru-cookbook/05blocks/code/pwm6.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..6df321f5f0d7094b6ec93e57cbf65a62994094a1 --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm6.pru0.c @@ -0,0 +1,56 @@ +// This code does MAXCH parallel PWM channels. +// All channels start at the same time. It's period is 510ns +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" + +#define PRU0_DRAM 0x00000 // Offset to DRAM +// Skip the first 0x200 byte of DRAM since the Makefile allocates +// 0x100 for the STACK and 0x100 for the HEAP. +volatile unsigned int *pru0_dram = (unsigned int *) (PRU0_DRAM + 0x200); + +#define MAXCH 4 // Maximum number of channels per PRU + +#define update(ch) \ + if(onCount[ch]) { \ + onCount[ch]--; \ + Rtmp |= 0x1<<ch; \ + } else if(offCount[ch]) { \ + offCount[ch]--; \ + Rtmp &= ~(0x1<<ch); \ + } else { \ + onCount[ch] = pru0_dram[2*ch]; \ + offCount[ch]= pru0_dram[2*ch+1]; \ + } + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t ch; + uint32_t on[] = {1, 2, 3, 4}; + uint32_t off[] = {4, 3, 2, 1}; + uint32_t onCount[MAXCH], offCount[MAXCH]; + register uint32_t Rtmp; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + +#pragma UNROLL(MAXCH) + for(ch=0; ch<MAXCH; ch++) { + pru0_dram[2*ch ] = on[ch]; // Copy to DRAM0 so the ARM can change it + pru0_dram[2*ch+1] = off[ch]; // Interleave the on and off values + onCount[ch] = on[ch]; + offCount[ch]= off[ch]; + } + Rtmp = __R30; + + while (1) { + update(0) + update(1) + update(2) + update(3) + __R30 = Rtmp; + } +} diff --git a/pru-cookbook/05blocks/code/pwm7-test.c b/pru-cookbook/05blocks/code/pwm7-test.c new file mode 100644 index 0000000000000000000000000000000000000000..cbb6769819050b95dec2fd402db0f69a4beaa752 --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm7-test.c @@ -0,0 +1,83 @@ +/* + * + * pwm tester + * (c) Copyright 2016 + * Mark A. Yoder, 20-July-2016 + * The channels 0-11 are on PRU1 and channels 12-17 are on PRU0 + * The period and duty cycle values are stored in each PRU's Data memory + * The enable bits are stored in the shared memory + * + */ + +#include <stdio.h> +#include <fcntl.h> +#include <sys/mman.h> + +#define MAXCH 2 + +#define PRU_ADDR 0x4A300000 // Start of PRU memory Page 184 am335x TRM +#define PRU_LEN 0x80000 // Length of PRU memory +#define PRU0_DRAM 0x00000 // Offset to DRAM +#define PRU1_DRAM 0x02000 +#define PRU_SHAREDMEM 0x10000 // Offset to shared memory + +unsigned int *pru0DRAM_32int_ptr; // Points to the start of local DRAM +unsigned int *pru1DRAM_32int_ptr; // Points to the start of local DRAM +unsigned int *prusharedMem_32int_ptr; // Points to the start of the shared memory + +/******************************************************************************* +* int start_pwm_count(int ch, int countOn, int countOff) +* +* Starts a pwm pulse on for countOn and off for countOff to a single channel (ch) +*******************************************************************************/ +int start_pwm_count(int ch, int countOn, int countOff, unsigned int *ptr) { + unsigned int *pruDRAM_32int_ptr = ptr; + + printf("countOn: %d, countOff: %d, count: %d\n", + countOn, countOff, countOn+countOff); + // write to PRU shared memory + pruDRAM_32int_ptr[2*(ch)+0] = countOn; // On time + pruDRAM_32int_ptr[2*(ch)+1] = countOff; // Off time + return 0; +} + +int main(int argc, char *argv[]) +{ + unsigned int *pru; // Points to start of PRU memory. + int fd; + printf("Servo tester\n"); + + fd = open ("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + printf ("ERROR: could not open /dev/mem.\n\n"); + return 1; + } + pru = mmap (0, PRU_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PRU_ADDR); + if (pru == MAP_FAILED) { + printf ("ERROR: could not map memory.\n\n"); + return 1; + } + close(fd); + printf ("Using /dev/mem.\n"); + + pru0DRAM_32int_ptr = pru + PRU0_DRAM/4 + 0x200/4; // Points to 0x200 of PRU0 memory + pru1DRAM_32int_ptr = pru + PRU1_DRAM/4 + 0x200/4; // Points to 0x200 of PRU1 memory + prusharedMem_32int_ptr = pru + PRU_SHAREDMEM/4; // Points to start of shared memory + + + int on[] = {1, 2, 3, 4}; + int off[] = {4, 3, 2, 1}; + + int ch; + for(ch=0; ch<MAXCH; ch++) { + start_pwm_count(ch, on[ch], off[ch], pru0DRAM_32int_ptr); + start_pwm_count(ch, on[ch+MAXCH], off[ch+MAXCH], pru1DRAM_32int_ptr); + } + + if(munmap(pru, PRU_LEN)) { + printf("munmap failed\n"); + } else { + printf("munmap succeeded\n"); + } +} + diff --git a/pru-cookbook/05blocks/code/pwm7.pru0.c b/pru-cookbook/05blocks/code/pwm7.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..b95c5caab89d3614e9dfa964d38c162921f67a4b --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm7.pru0.c @@ -0,0 +1,57 @@ +// This code does MAXCH parallel PWM channels on both PRU 0 and PRU 1 +// All channels start at the same time. But the PRU 1 ch have a difference period +// It's period is 370ns +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" + +#define PRUNUM 0 + +#define PRU0_DRAM 0x00000 // Offset to DRAM +// Skip the first 0x200 byte of DRAM since the Makefile allocates +// 0x100 for the STACK and 0x100 for the HEAP. +volatile unsigned int *pru0_dram = (unsigned int *) (PRU0_DRAM + 0x200); + +#define MAXCH 2 // Maximum number of channels per PRU + +#define update(ch) \ + if(onCount[ch]) { \ + onCount[ch]--; \ + Rtmp |= 0x1<<ch; \ + } else if(offCount[ch]) { \ + offCount[ch]--; \ + Rtmp &= ~(0x1<<ch); \ + } else { \ + onCount[ch] = pru0_dram[2*ch]; \ + offCount[ch]= pru0_dram[2*ch+1]; \ + } + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t ch; + uint32_t on[] = {1, 2, 3, 4}; + uint32_t off[] = {4, 3, 2, 1}; + uint32_t onCount[MAXCH], offCount[MAXCH]; + register uint32_t Rtmp; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + +#pragma UNROLL(MAXCH) + for(ch=0; ch<MAXCH; ch++) { + pru0_dram[2*ch ] = on [ch+PRUNUM*MAXCH]; // Copy to DRAM0 so the ARM can change it + pru0_dram[2*ch+1] = off[ch+PRUNUM*MAXCH]; // Interleave the on and off values + onCount[ch] = on [ch+PRUNUM*MAXCH]; + offCount[ch]= off[ch+PRUNUM*MAXCH]; + } + Rtmp = __R30; + + while (1) { + update(0) + update(1) + __R30 = Rtmp; + } +} diff --git a/pru-cookbook/05blocks/code/pwm7.pru1.c b/pru-cookbook/05blocks/code/pwm7.pru1.c new file mode 100644 index 0000000000000000000000000000000000000000..50d4788b8c4d07848a0f0ff651fc78a7545ff67f --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm7.pru1.c @@ -0,0 +1,57 @@ +// This code does MAXCH parallel PWM channels on both PRU 0 and PRU 1 +// All channels start at the same time. But the PRU 1 ch have a difference period +// It's period is 370ns +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" + +#define PRUNUM 1 + +#define PRU0_DRAM 0x00000 // Offset to DRAM +// Skip the first 0x200 byte of DRAM since the Makefile allocates +// 0x100 for the STACK and 0x100 for the HEAP. +volatile unsigned int *pru0_dram = (unsigned int *) (PRU0_DRAM + 0x200); + +#define MAXCH 2 // Maximum number of channels per PRU + +#define update(ch) \ + if(onCount[ch]) { \ + onCount[ch]--; \ + Rtmp |= 0x1<<ch; \ + } else if(offCount[ch]) { \ + offCount[ch]--; \ + Rtmp &= ~(0x1<<ch); \ + } else { \ + onCount[ch] = pru0_dram[2*ch]; \ + offCount[ch]= pru0_dram[2*ch+1]; \ + } + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t ch; + uint32_t on[] = {1, 2, 3, 4}; + uint32_t off[] = {4, 3, 2, 1}; + uint32_t onCount[MAXCH], offCount[MAXCH]; + register uint32_t Rtmp; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + +#pragma UNROLL(MAXCH) + for(ch=0; ch<MAXCH; ch++) { + pru0_dram[2*ch ] = on [ch+PRUNUM*MAXCH]; // Copy to DRAM0 so the ARM can change it + pru0_dram[2*ch+1] = off[ch+PRUNUM*MAXCH]; // Interleave the on and off values + onCount[ch] = on [ch+PRUNUM*MAXCH]; + offCount[ch]= off[ch+PRUNUM*MAXCH]; + } + Rtmp = __R30; + + while (1) { + update(0) + update(1) + __R30 = Rtmp; + } +} diff --git a/pru-cookbook/05blocks/code/pwm7_setup.sh b/pru-cookbook/05blocks/code/pwm7_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..aae4c778542c5209a799411b393b2d5b2130e76e --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm7_setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +export TARGET=pwm7.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_31 P9_29 P8_45 P8_46" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P1_36 P1_33" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruout + config-pin -q $pin +done diff --git a/pru-cookbook/05blocks/code/pwm8.pru0.c b/pru-cookbook/05blocks/code/pwm8.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..c566573f6f681f7642e61d5c159c8558d3895d33 --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm8.pru0.c @@ -0,0 +1,78 @@ +// This code does MAXCH parallel PWM channels on both PRU 0 and PRU 1 +// All channels start at the same time. +// It's period is 430ns +#include <stdint.h> +#include <pru_cfg.h> +#include <pru_intc.h> +#include <pru_ctrl.h> +#include "resource_table_empty.h" + +#define PRUNUM 0 + +#define PRU0_DRAM 0x00000 // Offset to DRAM +// Skip the first 0x200 byte of DRAM since the Makefile allocates +// 0x100 for the STACK and 0x100 for the HEAP. +volatile unsigned int *pru0_dram = (unsigned int *) (PRU0_DRAM + 0x200); + +#define MAXCH 2 // Maximum number of channels per PRU + +#define update(ch) \ + if(onCount[ch]) { \ + onCount[ch]--; \ + Rtmp |= 0x1<<ch; \ + } else if(offCount[ch]) { \ + offCount[ch]--; \ + Rtmp &= ~(0x1<<ch); \ + } else { \ + onCount[ch] = pru0_dram[2*ch]; \ + offCount[ch]= pru0_dram[2*ch+1]; \ + } + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +// Initialize interupts so the PRUs can be syncronized. +// PRU1 is started first and then waits for PRU0 +// PRU0 is then started and tells PRU1 when to start going +void configIntc(void) { + __R31 = 0x00000000; // Clear any pending PRU-generated events + CT_INTC.CMR4_bit.CH_MAP_16 = 1; // Map event 16 to channel 1 + CT_INTC.HMR0_bit.HINT_MAP_1 = 1; // Map channel 1 to host 1 + CT_INTC.SICR = 16; // Ensure event 16 is cleared + CT_INTC.EISR = 16; // Enable event 16 + CT_INTC.HIEISR |= (1 << 0); // Enable Host interrupt 1 + CT_INTC.GER = 1; // Globally enable host interrupts +} + +void main(void) +{ + uint32_t ch; + uint32_t on[] = {1, 2, 3, 4}; + uint32_t off[] = {4, 3, 2, 1}; + uint32_t onCount[MAXCH], offCount[MAXCH]; + register uint32_t Rtmp; + + CT_CFG.GPCFG0 = 0x0000; // Configure GPI and GPO as Mode 0 (Direct Connect) + configIntc(); // Configure INTC + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + +#pragma UNROLL(MAXCH) + for(ch=0; ch<MAXCH; ch++) { + pru0_dram[2*ch ] = on [ch+PRUNUM*MAXCH]; // Copy to DRAM0 so the ARM can change it + pru0_dram[2*ch+1] = off[ch+PRUNUM*MAXCH]; // Interleave the on and off values + onCount[ch] = on [ch+PRUNUM*MAXCH]; + offCount[ch]= off[ch+PRUNUM*MAXCH]; + } + Rtmp = __R30; + + while (1) { + __R30 = Rtmp; + update(0) + update(1) +#define PRU0_PRU1_EVT 16 + __R31 = (PRU0_PRU1_EVT-16) | (0x1<<5); //Tell PRU 1 to start + __delay_cycles(1); + } +} diff --git a/pru-cookbook/05blocks/code/pwm8.pru1.c b/pru-cookbook/05blocks/code/pwm8.pru1.c new file mode 100644 index 0000000000000000000000000000000000000000..cf5c241c99addc0d8b958724554e078f9a53412c --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm8.pru1.c @@ -0,0 +1,66 @@ +// This code does MAXCH parallel PWM channels on both PRU 0 and PRU 1 +// All channels start at the same time. +// It's period is 430ns +#include <stdint.h> +#include <pru_cfg.h> +#include <pru_intc.h> +#include <pru_ctrl.h> +#include "resource_table_empty.h" + +#define PRUNUM 1 + +#define PRU0_DRAM 0x00000 // Offset to DRAM +// Skip the first 0x200 byte of DRAM since the Makefile allocates +// 0x100 for the STACK and 0x100 for the HEAP. +volatile unsigned int *pru0_dram = (unsigned int *) (PRU0_DRAM + 0x200); + +#define MAXCH 2 // Maximum number of channels per PRU + +#define update(ch) \ + if(onCount[ch]) { \ + onCount[ch]--; \ + Rtmp |= 0x1<<ch; \ + } else if(offCount[ch]) { \ + offCount[ch]--; \ + Rtmp &= ~(0x1<<ch); \ + } else { \ + onCount[ch] = pru0_dram[2*ch]; \ + offCount[ch]= pru0_dram[2*ch+1]; \ + } + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +// Initialize interupts so the PRUs can be syncronized. +// PRU1 is started first and then waits for PRU0 +// PRU0 is then started and tells PRU1 when to start going + +void main(void) +{ + uint32_t ch; + uint32_t on[] = {1, 2, 3, 4}; + uint32_t off[] = {4, 3, 2, 1}; + uint32_t onCount[MAXCH], offCount[MAXCH]; + register uint32_t Rtmp; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + +#pragma UNROLL(MAXCH) + for(ch=0; ch<MAXCH; ch++) { + pru0_dram[2*ch ] = on [ch+PRUNUM*MAXCH]; // Copy to DRAM0 so the ARM can change it + pru0_dram[2*ch+1] = off[ch+PRUNUM*MAXCH]; // Interleave the on and off values + onCount[ch] = on [ch+PRUNUM*MAXCH]; + offCount[ch]= off[ch+PRUNUM*MAXCH]; + } + Rtmp = __R30; + + while (1) { + while((__R31 & (0x1<<31))==0) { // Wait for PRU 0 + } + CT_INTC.SICR = 16; // Clear event 16 + __R30 = Rtmp; + update(0) + update(1) + } +} diff --git a/pru-cookbook/05blocks/code/pwm_setup.sh b/pru-cookbook/05blocks/code/pwm_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..b69ed1297ab4a73d309a7f46253c3b9b5f97add1 --- /dev/null +++ b/pru-cookbook/05blocks/code/pwm_setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +export TARGET=pwm1.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_31 P9_29 P9_30 P9_28" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P1_36 P1_33 P2_32 P2_30" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruout + config-pin -q $pin +done diff --git a/pru-cookbook/05blocks/code/resource_table_empty.h b/pru-cookbook/05blocks/code/resource_table_empty.h new file mode 100644 index 0000000000000000000000000000000000000000..07e97d9b383c9d937d4b55e705024d6c28dc748a --- /dev/null +++ b/pru-cookbook/05blocks/code/resource_table_empty.h @@ -0,0 +1,39 @@ +/* + * ======== resource_table_empty.h ======== + * + * Define the resource table entries for all PRU cores. This will be + * incorporated into corresponding base images, and used by the remoteproc + * on the host-side to allocated/reserve resources. Note the remoteproc + * driver requires that all PRU firmware be built with a resource table. + * + * This file contains an empty resource table. It can be used either as: + * + * 1) A template, or + * 2) As-is if a PRU application does not need to configure PRU_INTC + * or interact with the rpmsg driver + * + */ + +#ifndef _RSC_TABLE_PRU_H_ +#define _RSC_TABLE_PRU_H_ + +#include <stddef.h> +#include <rsc_types.h> + +struct my_resource_table { + struct resource_table base; + + uint32_t offset[1]; /* Should match 'num' in actual definition */ +}; + +#pragma DATA_SECTION(pru_remoteproc_ResourceTable, ".resource_table") +#pragma RETAIN(pru_remoteproc_ResourceTable) +struct my_resource_table pru_remoteproc_ResourceTable = { + 1, /* we're the first version that implements this */ + 0, /* number of entries in the table */ + 0, 0, /* reserved, must be zero */ + 0, /* offset[0] */ +}; + +#endif /* _RSC_TABLE_PRU_H_ */ + diff --git a/pru-cookbook/05blocks/code/rgb1.pru0.c b/pru-cookbook/05blocks/code/rgb1.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..9936d627336863daf9c4c1d5e92f70afd602b3a9 --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb1.pru0.c @@ -0,0 +1,80 @@ +// This code drives the RGB LED Matrix on the 1st Connector +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" +#include "rgb_pocket.h" + +#define DELAY 10 // Number of cycles (5ns each) to wait after a write + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + // Set up the pointers to each of the GPIO ports + uint32_t *gpio[] = { + (uint32_t *) GPIO0, + (uint32_t *) GPIO1, + (uint32_t *) GPIO2, + (uint32_t *) GPIO3 + }; + + uint32_t i, row; + + while(1) { + for(row=0; row<16; row++) { + // Set the row address + // Here we take advantage of the select bits (LA,LB,LC,LD) + // being sequential in the R30 register (bits 2,3,4,5) + // We shift row over so it lines up with the select bits + // Oring (|=) with R30 sets bits to 1 and + // Anding (&=) clears bits to 0, the 0xffc mask makes sure the + // other bits aren't changed. + __R30 |= row<<pru_sel0; + __R30 &= (row<<pru_sel0)|0xffc3; + + for(i=0; i<64; i++) { + // Top row white + // Combining these to one write works because they are all in + // the same gpio port + gpio[r11_gpio][GPIO_SETDATAOUT] = r11_pin | g11_pin | b11_pin; + __delay_cycles(DELAY);; + + // Bottom row red + gpio[r12_gpio][GPIO_SETDATAOUT] = r12_pin; + __delay_cycles(DELAY); + gpio[r12_gpio][GPIO_CLEARDATAOUT] = g12_pin | b12_pin; + __delay_cycles(DELAY); + + __R30 |= pru_clock; // Toggle clock + __delay_cycles(DELAY); + __R30 &= ~pru_clock; + __delay_cycles(DELAY); + + // Top row black + gpio[r11_gpio][GPIO_CLEARDATAOUT] = r11_pin | g11_pin | b11_pin; + __delay_cycles(DELAY); + + // Bottom row green + gpio[r12_gpio][GPIO_CLEARDATAOUT] = r12_pin | b12_pin; + __delay_cycles(DELAY); + gpio[r12_gpio][GPIO_SETDATAOUT] = g12_pin; + __delay_cycles(DELAY); + + __R30 |= pru_clock; // Toggle clock + __delay_cycles(DELAY); + __R30 &= ~pru_clock; + __delay_cycles(DELAY); + } + __R30 |= pru_oe; // Disable display + __delay_cycles(DELAY); + __R30 |= pru_latch; // Toggle latch + __delay_cycles(DELAY); + __R30 &= ~pru_latch; + __delay_cycles(DELAY); + __R30 &= ~pru_oe; // Enable display + __delay_cycles(DELAY); + } + } +} diff --git a/pru-cookbook/05blocks/code/rgb2.pru0.c b/pru-cookbook/05blocks/code/rgb2.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..eb43b357bb3cdb92f6853a0d46600b1e53a7b6ac --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb2.pru0.c @@ -0,0 +1,81 @@ +// This code drives the RGB LED Matrix on J1 connector +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" +#include "rgb_pocket.h" + +#define DELAY 100 + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + // Set up the pointers to each of the GPIO ports + uint32_t *gpio[] = { + (uint32_t *) GPIO0, + (uint32_t *) GPIO1, + (uint32_t *) GPIO2, + (uint32_t *) GPIO3 + }; + + uint32_t i, row; + + while(1) { + for(row=0; row<16; row++) { + if(row&(0x1<<0)) __R30|=(0x1<<pru_sel0); else __R30&=~(0x1<<pru_sel0); + __delay_cycles(DELAY); + if(row&(0x1<<1)) __R30|=(0x1<<pru_sel1); else __R30&=~(0x1<<pru_sel1); + __delay_cycles(DELAY); + if(row&(0x1<<2)) __R30|=(0x1<<pru_sel2); else __R30&=~(0x1<<pru_sel2); + __delay_cycles(DELAY); + if(row&(0x1<<3)) __R30|=(0x1<<pru_sel3); else __R30&=~(0x1<<pru_sel3); + __delay_cycles(DELAY); + + for(i=0; i<64; i++) { + // red + gpio[r11_gpio][GPIO_SETDATAOUT] = r11_pin; + __delay_cycles(DELAY); + gpio[r11_gpio][GPIO_CLEARDATAOUT] = g11_pin | b11_pin; + __delay_cycles(DELAY); + + // green + gpio[r11_gpio][GPIO_CLEARDATAOUT] = r12_pin | b12_pin; + __delay_cycles(DELAY); + gpio[r11_gpio][GPIO_SETDATAOUT] = g12_pin; + __delay_cycles(DELAY); + + __R30 |= pru_clock; // Toggle clock + __delay_cycles(DELAY); + __R30 &= ~pru_clock; + __delay_cycles(DELAY); + + // blue + gpio[r11_gpio][GPIO_CLEARDATAOUT] = r11_pin | g11_pin; + __delay_cycles(DELAY); + gpio[r11_gpio][GPIO_SETDATAOUT] = b11_pin; + __delay_cycles(DELAY); + + //blue + gpio[r11_gpio][GPIO_CLEARDATAOUT] = r12_pin | g12_pin; + __delay_cycles(DELAY); + gpio[r11_gpio][GPIO_SETDATAOUT] = b12_pin; + __delay_cycles(DELAY); + + __R30 |= pru_clock; // Toggle clock + __delay_cycles(DELAY); + __R30 &= ~pru_clock; + __delay_cycles(DELAY); + } + __R30 |= pru_oe; // Disable display + __delay_cycles(DELAY); + __R30 |= pru_latch; // Toggle latch + __delay_cycles(DELAY); + __R30 &= ~pru_latch; + __delay_cycles(DELAY); + __R30 &= ~pru_oe; // Enable display + __delay_cycles(DELAY); + } + } +} diff --git a/pru-cookbook/05blocks/code/rgb3.pru0.c b/pru-cookbook/05blocks/code/rgb3.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..b14ad864c4de0c621561f1cb031aae0af5367dd4 --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb3.pru0.c @@ -0,0 +1,114 @@ +// This code drives the RGB LED Matrix on the 1st and 2nd Connectors +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" +#include "rgb_pocket.h" + +#define DELAY 10 // Number of cycles (5ns each) to wait after a write + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + // Set up the pointers to each of the GPIO ports + uint32_t *gpio[] = { + (uint32_t *) GPIO0, + (uint32_t *) GPIO1, + (uint32_t *) GPIO2, + (uint32_t *) GPIO3 + }; + + uint32_t i, row; + + while(1) { + for(row=0; row<16; row++) { + // Set the row address + // Here we take advantage of the select bits (LA,LB,LC,LD) + // being sequential in the R30 register (bits 2,3,4,5) + // We shift row over so it lines up with the select bits + // Oring (|=) with R30 sets bits to 1 and + // Anding (&=) clears bits to 0, the 0xffc mask makes sure the + // other bits aren't changed. + __R30 |= row<<pru_sel0; + __R30 &= (row<<pru_sel0)|0xffc3; + + for(i=0; i<64; i++) { + // Panel 1 Upper + // Top row white + // Combining these to one write works because they are all in + // the same gpio port + gpio[r11_gpio][GPIO_SETDATAOUT] = r11_pin | g11_pin | b11_pin; + __delay_cycles(DELAY); + + // Bottom row red + gpio[r12_gpio][GPIO_SETDATAOUT] = r12_pin; + // __delay_cycles(DELAY); + gpio[g12_gpio][GPIO_CLEARDATAOUT] = g12_pin | b12_pin; + __delay_cycles(DELAY); + + // Panel 2 Upper + // Top row blue + // Combining these to one write works because they are all in + // the same gpio port except b12 + gpio[r21_gpio][GPIO_CLEARDATAOUT] = r21_pin | g21_pin; + // __delay_cycles(DELAY); + gpio[b21_gpio][GPIO_SETDATAOUT] = b21_pin; + __delay_cycles(DELAY); + + // Bottom row red + gpio[r22_gpio][GPIO_SETDATAOUT] = r22_pin; + __delay_cycles(DELAY); + gpio[g22_gpio][GPIO_CLEARDATAOUT] = g22_pin; + __delay_cycles(DELAY); + gpio[b22_gpio][GPIO_CLEARDATAOUT] = b22_pin; + __delay_cycles(DELAY); + + __R30 |= pru_clock; // Toggle clock + __delay_cycles(DELAY); + __R30 &= ~pru_clock; + __delay_cycles(DELAY); + + // Panel 1 Lower + // Top row black + gpio[r11_gpio][GPIO_CLEARDATAOUT] = r11_pin | g11_pin | b11_pin; + __delay_cycles(DELAY); + + // Bottom row green + gpio[r12_gpio][GPIO_CLEARDATAOUT] = r12_pin | b12_pin; + __delay_cycles(DELAY); + gpio[g12_gpio][GPIO_SETDATAOUT] = g12_pin; + __delay_cycles(DELAY); + + // Panel 2 Lower + // Top row reg+green = yellow + gpio[r21_gpio][GPIO_SETDATAOUT] = r21_pin | g21_pin; + __delay_cycles(DELAY); + gpio[b21_gpio][GPIO_CLEARDATAOUT] = b21_pin; + __delay_cycles(DELAY); + + // Bottom row green + gpio[r22_gpio][GPIO_CLEARDATAOUT] = r22_pin; + __delay_cycles(DELAY); + gpio[b22_gpio][GPIO_CLEARDATAOUT] = b22_pin; + __delay_cycles(DELAY); + gpio[g22_gpio][GPIO_SETDATAOUT] = g22_pin; + __delay_cycles(2*DELAY); + + __R30 |= pru_clock; // Toggle clock + __delay_cycles(DELAY); + __R30 &= ~pru_clock; + __delay_cycles(DELAY); + } + __R30 |= pru_oe; // Disable display + __delay_cycles(DELAY); + __R30 |= pru_latch; // Toggle latch + __delay_cycles(DELAY); + __R30 &= ~pru_latch; + __delay_cycles(DELAY); + __R30 &= ~pru_oe; // Enable display + __delay_cycles(DELAY); + } + } +} diff --git a/pru-cookbook/05blocks/code/rgb4.pru0.c b/pru-cookbook/05blocks/code/rgb4.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..6d06f1210e18bb3bbf74bf20b9c0b0c876c365e0 --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb4.pru0.c @@ -0,0 +1,84 @@ +// This code drives the RGB LED Matrix on the 2nd Connector +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" +#include "rgb_pocket.h" + +#define DELAY 10 // Number of cycles (5ns each) to wait after a write + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + // Set up the pointers to each of the GPIO ports + uint32_t *gpio[] = { + (uint32_t *) GPIO0, + (uint32_t *) GPIO1, + (uint32_t *) GPIO2, + (uint32_t *) GPIO3 + }; + + uint32_t i, row; + + while(1) { + for(row=0; row<16; row++) { + // Set the row address + // Here we take advantage of the select bits (LA,LB,LC,LD) + // being sequential in the R30 register (bits 2,3,4,5) + // We shift row over so it lines up with the select bits + // Oring (|=) with R30 sets bits to 1 and + // Anding (&=) clears bits to 0, the 0xffc mask makes sure the + // other bits aren't changed. + __R30 |= row<<pru_sel0; + __R30 &= (row<<pru_sel0)|0xffc3; + + for(i=0; i<64; i++) { + // Top row white + // Combining these to one write works because they are all in + // the same gpio port except b12 + gpio[r21_gpio][GPIO_SETDATAOUT] = r21_pin | g21_pin; + __delay_cycles(DELAY); + gpio[b21_gpio][GPIO_SETDATAOUT] = b21_pin; + __delay_cycles(DELAY); + + // Bottom row red + gpio[r22_gpio][GPIO_SETDATAOUT] = r22_pin; + __delay_cycles(DELAY); + gpio[g22_gpio][GPIO_CLEARDATAOUT] = g22_pin | b22_pin; + __delay_cycles(2*DELAY); + + __R30 |= pru_clock; // Toggle clock + __delay_cycles(DELAY); + __R30 &= ~pru_clock; + __delay_cycles(DELAY); + + // Top row black + gpio[r21_gpio][GPIO_CLEARDATAOUT] = r21_pin | g21_pin; + __delay_cycles(DELAY); + gpio[b21_gpio][GPIO_CLEARDATAOUT] = b21_pin; + __delay_cycles(DELAY); + + // Bottom row green + gpio[r22_gpio][GPIO_CLEARDATAOUT] = r22_pin | b22_pin; + __delay_cycles(DELAY); + gpio[g22_gpio][GPIO_SETDATAOUT] = g22_pin; + __delay_cycles(2*DELAY); + + __R30 |= pru_clock; // Toggle clock + __delay_cycles(DELAY); + __R30 &= ~pru_clock; + __delay_cycles(DELAY); + } + __R30 |= pru_oe; // Disable display + __delay_cycles(DELAY); + __R30 |= pru_latch; // Toggle latch + __delay_cycles(DELAY); + __R30 &= ~pru_latch; + __delay_cycles(DELAY); + __R30 &= ~pru_oe; // Enable display + __delay_cycles(DELAY); + } + } +} diff --git a/pru-cookbook/05blocks/code/rgb_black.h b/pru-cookbook/05blocks/code/rgb_black.h new file mode 100644 index 0000000000000000000000000000000000000000..be7cf4ba8ab0da67ee7ce7301fe49a90bfad539e --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb_black.h @@ -0,0 +1,31 @@ +//Black - Not tested +// These are from https://github.com/FalconChristmas/fpp/blob/master/src/pru/PocketScrollerV1.hp +// _gpio tells which gpio port and _pin tells which bit in the port +// The first 1 in r11 is for the J1 connector +// See the githuub file for the other connectors + +#define r11_gpio 2 +#define r11_pin 9 +#define g11_gpio 2 +#define g11_pin 11 +#define b11_gpio 2 +#define b11_pin 10 + +#define r12_gpio 2 +#define r12_pin 12 +#define g12_gpio 2 +#define g12_pin 22 +#define b12_gpio 2 +#define b12_pin 23 + +#define pru_latch 1 // These are the bit positions in R30 +#define pru_oe 0 +#define pru_clock 2 + +// Control pins are all in GPIO2 +// The pocket has these on R0, the code needs to be changed for this work work +#define gpio_sel0 13 /* must be sequential with sel1 and sel2 */ +#define gpio_sel1 14 +#define gpio_sel2 15 +#define gpio_sel3 16 +#define gpio_sel4 17 diff --git a/pru-cookbook/05blocks/code/rgb_pocket.h b/pru-cookbook/05blocks/code/rgb_pocket.h new file mode 100644 index 0000000000000000000000000000000000000000..45a91118038898605939bc4493a3337cb4fd86a0 --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb_pocket.h @@ -0,0 +1,45 @@ +// Pocket +// These are from https://github.com/FalconChristmas/fpp/blob/master/src/pru/PocketScrollerV1.hp +// _gpio tells which gpio port and _pin tells which bit in the port +// The first 1 in r11 is for the J1 connector +// See the githuub file for the other connectors + +// J1 +#define r11_gpio 1 +#define r11_pin (0x1<<20) +#define g11_gpio 1 +#define g11_pin (0x1<<28) +#define b11_gpio 1 +#define b11_pin (0x1<<25) + +#define r12_gpio 1 +#define r12_pin (0x1<<26) +#define g12_gpio 1 +#define g12_pin (0x1<<27) +#define b12_gpio 1 +#define b12_pin (0x1<<18) + +// J2 +#define r21_gpio 1 +#define r21_pin (0x1<<8) +#define g21_gpio 1 +#define g21_pin (0x1<<9) +#define b21_gpio 0 +#define b21_pin (0x1<<30) + +#define r22_gpio 1 +#define r22_pin (0x1<<12) +#define g22_gpio 1 +#define g22_pin (0x1<<14) +#define b22_gpio 1 +#define b22_pin (0x1<<15) + +// All connectors +#define pru_latch (0x1<<0) // These are the bit positions in R30 +#define pru_oe (0x1<<7) +#define pru_clock (0x1<<1) + +#define pru_sel0 2 // These are called LA, LB, LC and LD in the python code +#define pru_sel1 3 // Also bit positions +#define pru_sel2 4 +#define pru_sel3 5 diff --git a/pru-cookbook/05blocks/code/rgb_python.py b/pru-cookbook/05blocks/code/rgb_python.py new file mode 100755 index 0000000000000000000000000000000000000000..25e353343f3c8f829a60376f4c3121e8ada1bbd1 --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb_python.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +import Adafruit_BBIO.GPIO as GPIO + +# Define which functions are connect to which pins +OE="P1_29" # Output Enable, active low +LAT="P1_36" # Latch, toggle after clocking in a row of pixels +CLK="P1_33" # Clock, toggle after each pixel + +# Input data pins +R1="P2_10" # R1, G1, B1 are for the top rows (1-16) of pixels +G1="P2_8" +B1="P2_6" + +R2="P2_4" # R2, G2, B2 are for the bottom rows (17-32) of pixels +G2="P2_2" +B2="P2_1" + +LA="P2_32" # Address lines for which row (1-16 or 17-32) to update +LB="P2_30" +LC="P1_31" +LD="P2_34" + +# Set everything as output ports +GPIO.setup(OE, GPIO.OUT) +GPIO.setup(LAT, GPIO.OUT) +GPIO.setup(CLK, GPIO.OUT) + +GPIO.setup(R1, GPIO.OUT) +GPIO.setup(G1, GPIO.OUT) +GPIO.setup(B1, GPIO.OUT) +GPIO.setup(R2, GPIO.OUT) +GPIO.setup(G2, GPIO.OUT) +GPIO.setup(B2, GPIO.OUT) + +GPIO.setup(LA, GPIO.OUT) +GPIO.setup(LB, GPIO.OUT) +GPIO.setup(LC, GPIO.OUT) +GPIO.setup(LD, GPIO.OUT) + +GPIO.output(OE, 0) # Enable the display +GPIO.output(LAT, 0) # Set latch to low + +while True: + for bank in range(64): + GPIO.output(LA, bank>>0&0x1) # Select rows + GPIO.output(LB, bank>>1&0x1) + GPIO.output(LC, bank>>2&0x1) + GPIO.output(LD, bank>>3&0x1) + + # Shift the colors out. Here we only have four different + # colors to keep things simple. + for i in range(16): + GPIO.output(R1, 1) # Top row, white + GPIO.output(G1, 1) + GPIO.output(B1, 1) + + GPIO.output(R2, 1) # Bottom row, red + GPIO.output(G2, 0) + GPIO.output(B2, 0) + + GPIO.output(CLK, 0) # Toggle clock + GPIO.output(CLK, 1) + + GPIO.output(R1, 0) # Top row, black + GPIO.output(G1, 0) + GPIO.output(B1, 0) + + GPIO.output(R2, 0) # Bottom row, green + GPIO.output(G2, 1) + GPIO.output(B2, 0) + + GPIO.output(CLK, 0) # Toggle clock + GPIO.output(CLK, 1) + + GPIO.output(OE, 1) # Disable display while updating + GPIO.output(LAT, 1) # Toggle latch + GPIO.output(LAT, 0) + GPIO.output(OE, 0) # Enable display diff --git a/pru-cookbook/05blocks/code/rgb_python_setup.sh b/pru-cookbook/05blocks/code/rgb_python_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..721067461771c4d0426a0646f28f748e384ec22d --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb_python_setup.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Setup for 64x32 RGB Matrix +export TARGET=rgb1.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + prupins="P2_32 P1_31 P1_33 P1_29 P2_30 P2_34 P1_36" + gpiopins="P2_10 P2_06 P2_04 P2_01 P2_08 P2_02" + # Uncomment for J2 + # gpiopins="$gpiopins P2_27 P2_25 P2_05 P2_24 P2_22 P2_18" +else + echo " Not Found" + pins="" +fi + +for pin in $prupins +do + echo $pin + # config-pin $pin pruout + config-pin $pin gpio + config-pin $pin out + config-pin -q $pin +done + +for pin in $gpiopins +do + echo $pin + config-pin $pin gpio + config-pin $pin out + config-pin -q $pin +done diff --git a/pru-cookbook/05blocks/code/rgb_setup.sh b/pru-cookbook/05blocks/code/rgb_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..fc5451444ad10b848f7ec42bb56f4b8f0ffd9195 --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb_setup.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Setup for 64x32 RGB Matrix +export TARGET=rgb1.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + prupins="P2_32 P1_31 P1_33 P1_29 P2_30 P2_34 P1_36" + gpiopins="P2_10 P2_06 P2_04 P2_01 P2_08 P2_02" + # Uncomment for J2 + # gpiopins="$gpiopins P2_27 P2_25 P2_05 P2_24 P2_22 P2_18" +else + echo " Not Found" + pins="" +fi + +for pin in $prupins +do + echo $pin + config-pin $pin pruout + # config-pin $pin gpio + # config-pin $pin out + config-pin -q $pin +done + +for pin in $gpiopins +do + echo $pin + config-pin $pin gpio + config-pin $pin out + config-pin -q $pin +done diff --git a/pru-cookbook/05blocks/code/rgb_white.pru0.c b/pru-cookbook/05blocks/code/rgb_white.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..e62d98e000c746e37a11c7a0402b13fb5f92b2df --- /dev/null +++ b/pru-cookbook/05blocks/code/rgb_white.pru0.c @@ -0,0 +1,64 @@ +// This code drives the RGB LED Matrix +// Turns all the LEDs on +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" +#include "rgb_pocket.h" + +#define DELAY 10 // Number of cycles (5ns each) to wait after a write + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + // Set up the pointers to each of the GPIO ports + uint32_t *gpio[] = { + (uint32_t *) GPIO0, + (uint32_t *) GPIO1, + (uint32_t *) GPIO2, + (uint32_t *) GPIO3 + }; + + uint32_t i, row; + + while(1) { + for(row=0; row<16; row++) { + // Set the row address + // Here we take advantage of the select bits (LA,LB,LC,LD) + // being sequential in the R30 register (bits 2,3,4,5) + // We shift row over so it lines up with the select bits + // Oring (|=) with R30 sets bits to 1 and + // Anding (&=) clears bits to 0, the 0xffc mask makes sure the + // other bits aren't changed. + __R30 |= row<<pru_sel0; + __R30 &= (row<<pru_sel0)|0xffc3; + + for(i=0; i<64; i++) { + // Top row white + // Combining these to one write works because they are all in + // the same gpio port + gpio[r11_gpio][GPIO_SETDATAOUT] = r11_pin | g11_pin | b11_pin; + __delay_cycles(DELAY);; + + // Bottom row white + gpio[r12_gpio][GPIO_SETDATAOUT] = r12_pin | g12_pin | b12_pin; + __delay_cycles(DELAY); + + __R30 |= pru_clock; // Toggle clock + __delay_cycles(DELAY); + __R30 &= ~pru_clock; + __delay_cycles(DELAY); + } + __R30 |= pru_oe; // Disable display + __delay_cycles(DELAY); + __R30 |= pru_latch; // Toggle latch + __delay_cycles(DELAY); + __R30 &= ~pru_latch; + __delay_cycles(DELAY); + __R30 &= ~pru_oe; // Enable display + __delay_cycles(DELAY); + } + } +} diff --git a/pru-cookbook/05blocks/code/shared.pru0.c b/pru-cookbook/05blocks/code/shared.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..95d87c5de147334e439c18bc6cadc68f6ebac98d --- /dev/null +++ b/pru-cookbook/05blocks/code/shared.pru0.c @@ -0,0 +1,63 @@ +// From: http://git.ti.com/pru-software-support-package/pru-software-support-package/blobs/master/examples/am335x/PRU_access_const_table/PRU_access_const_table.c +#include <stdint.h> +#include <pru_cfg.h> +#include <pru_ctrl.h> +#include "resource_table_empty.h" + +#define PRU_SRAM __far __attribute__((cregister("PRU_SHAREDMEM", near))) +#define PRU_DMEM0 __far __attribute__((cregister("PRU_DMEM_0_1", near))) +#define PRU_DMEM1 __far __attribute__((cregister("PRU_DMEM_1_0", near))) + +/* NOTE: Allocating shared_x to PRU Shared Memory means that other PRU cores on + * the same subsystem must take care not to allocate data to that memory. + * Users also cannot rely on where in shared memory these variables are placed + * so accessing them from another PRU core or from the ARM is an undefined behavior. + */ +volatile uint32_t shared_0; +PRU_SRAM volatile uint32_t shared_1; +PRU_DMEM0 volatile uint32_t shared_2; +PRU_DMEM1 volatile uint32_t shared_3; +#pragma DATA_SECTION(shared_4, ".bss") +volatile uint32_t shared_4; + +/* NOTE: Here we pick where in memory to store shared_5. The stack and + * heap take up the first 0x200 words, so we must start after that. + * Since we are hardcoding where things are stored we can share + * this between the PRUs and the ARM. +*/ +#define PRU0_DRAM 0x00000 // Offset to DRAM +// Skip the first 0x200 bytes of DRAM since the Makefile allocates +// 0x100 for the STACK and 0x100 for the HEAP. +volatile unsigned int *shared_5 = (unsigned int *) (PRU0_DRAM + 0x200); + + +int main(void) +{ + volatile uint32_t shared_6; + volatile uint32_t shared_7; + /*****************************************************************/ + /* Access PRU peripherals using Constant Table & PRU header file */ + /*****************************************************************/ + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + /*****************************************************************/ + /* Access PRU Shared RAM using Constant Table */ + /*****************************************************************/ + + /* C28 defaults to 0x00000000, we need to set bits 23:8 to 0x0100 in order to have it point to 0x00010000 */ + PRU0_CTRL.CTPPR0_bit.C28_BLK_POINTER = 0x0100; + + shared_0 = 0xfeef; + shared_1 = 0xdeadbeef; + shared_2 = shared_2 + 0xfeed; + shared_3 = 0xdeed; + shared_4 = 0xbeed; + shared_5[0] = 0x1234; + shared_6 = 0x4321; + shared_7 = 0x9876; + + /* Halt PRU core */ + __halt(); +} diff --git a/pru-cookbook/05blocks/code/shared_setup.sh b/pru-cookbook/05blocks/code/shared_setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..eefbcd553ac53d0fb0c289fefc536c5f5eb0a7f7 --- /dev/null +++ b/pru-cookbook/05blocks/code/shared_setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +export TARGET=shared.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_31 P9_29 P9_30 P9_28" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P1_36 P1_33 P2_32 P2_30" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruout + config-pin -q $pin +done diff --git a/pru-cookbook/05blocks/code/sine.map b/pru-cookbook/05blocks/code/sine.map new file mode 100644 index 0000000000000000000000000000000000000000..45872d39e001a44e2a2b38b1ed1bf38c85b8837d --- /dev/null +++ b/pru-cookbook/05blocks/code/sine.map @@ -0,0 +1,338 @@ +****************************************************************************** +PRU Linker Unix v2.1.5 +****************************************************************************** +>> Linked Fri Jun 29 13:58:08 2018 + +OUTPUT FILE NAME: </tmp/pru0-gen/sine1.out> +ENTRY POINT SYMBOL: "_c_int00_noinit_noargs_noexit" address: 00000000 + + +MEMORY CONFIGURATION + + name origin length used unused attr fill +---------------------- -------- --------- -------- -------- ---- -------- +PAGE 0: + PRU_IMEM 00000000 00002000 000018c0 00000740 RWIX + +PAGE 1: + PRU_DMEM_0_1 00000000 00002000 00000154 00001eac RWIX + PRU_DMEM_1_0 00002000 00002000 00000000 00002000 RWIX + +PAGE 2: + PRU_SHAREDMEM 00010000 00003000 00000000 00003000 RWIX + PRU_INTC 00020000 00001504 00000000 00001504 RWIX + PRU_CFG 00026000 00000044 00000044 00000000 RWIX + PRU_UART 00028000 00000038 00000000 00000038 RWIX + PRU_IEP 0002e000 0000031c 00000000 0000031c RWIX + PRU_ECAP 00030000 00000060 00000000 00000060 RWIX + RSVD27 00032000 00000100 00000000 00000100 RWIX + RSVD21 00032400 00000100 00000000 00000100 RWIX + L3OCMC 40000000 00010000 00000000 00010000 RWIX + MCASP0_DMA 46000000 00000100 00000000 00000100 RWIX + UART1 48022000 00000088 00000000 00000088 RWIX + UART2 48024000 00000088 00000000 00000088 RWIX + I2C1 4802a000 000000d8 00000000 000000d8 RWIX + MCSPI0 48030000 000001a4 00000000 000001a4 RWIX + DMTIMER2 48040000 0000005c 00000000 0000005c RWIX + MMCHS0 48060000 00000300 00000000 00000300 RWIX + MBX0 480c8000 00000140 00000000 00000140 RWIX + SPINLOCK 480ca000 00000880 00000000 00000880 RWIX + I2C2 4819c000 000000d8 00000000 000000d8 RWIX + MCSPI1 481a0000 000001a4 00000000 000001a4 RWIX + DCAN0 481cc000 000001e8 00000000 000001e8 RWIX + DCAN1 481d0000 000001e8 00000000 000001e8 RWIX + PWMSS0 48300000 000002c4 00000000 000002c4 RWIX + PWMSS1 48302000 000002c4 00000000 000002c4 RWIX + PWMSS2 48304000 000002c4 00000000 000002c4 RWIX + RSVD13 48310000 00000100 00000000 00000100 RWIX + RSVD10 48318000 00000100 00000000 00000100 RWIX + TPCC 49000000 00001098 00000000 00001098 RWIX + GEMAC 4a100000 0000128c 00000000 0000128c RWIX + DDR 80000000 00000100 00000000 00000100 RWIX + + +SECTION ALLOCATION MAP + + output attributes/ +section page origin length input sections +-------- ---- ---------- ---------- ---------------- +.text:_c_int00* +* 0 00000000 00000014 + 00000000 00000014 rtspruv3_le.lib : boot_special.obj (.text:_c_int00_noinit_noargs_noexit) + +.text 0 00000014 000018ac + 00000014 00000374 rtspruv3_le.lib : sin.obj (.text:sin) + 00000388 00000314 : frcmpyd.obj (.text:__TI_frcmpyd) + 0000069c 00000258 : frcaddd.obj (.text:__TI_frcaddd) + 000008f4 00000254 : mpyd.obj (.text:__pruabi_mpyd) + 00000b48 00000248 : addd.obj (.text:__pruabi_addd) + 00000d90 000001c8 : mpyf.obj (.text:__pruabi_mpyf) + 00000f58 00000100 : modf.obj (.text:modf) + 00001058 000000b4 : gtd.obj (.text:__pruabi_gtd) + 0000110c 000000b0 : ged.obj (.text:__pruabi_ged) + 000011bc 000000b0 : ltd.obj (.text:__pruabi_ltd) + 0000126c 000000b0 sine1.obj (.text:main) + 0000131c 000000a8 rtspruv3_le.lib : frcmpyf.obj (.text:__TI_frcmpyf) + 000013c4 000000a0 : fixdu.obj (.text:__pruabi_fixdu) + 00001464 0000009c : round.obj (.text:__pruabi_nround) + 00001500 00000090 : eqld.obj (.text:__pruabi_eqd) + 00001590 0000008c : renormd.obj (.text:__TI_renormd) + 0000161c 0000008c : fixdi.obj (.text:__pruabi_fixdi) + 000016a8 00000084 : fltid.obj (.text:__pruabi_fltid) + 0000172c 00000078 : cvtfd.obj (.text:__pruabi_cvtfd) + 000017a4 00000050 : fltuf.obj (.text:__pruabi_fltuf) + 000017f4 0000002c : asri.obj (.text:__pruabi_asri) + 00001820 0000002c : subd.obj (.text:__pruabi_subd) + 0000184c 00000024 : mpyi.obj (.text:__pruabi_mpyi) + 00001870 00000020 : negd.obj (.text:__pruabi_negd) + 00001890 00000020 : trunc.obj (.text:__pruabi_trunc) + 000018b0 00000008 : exit.obj (.text:abort) + 000018b8 00000008 : exit.obj (.text:loader_exit) + +.stack 1 00000000 00000100 UNINITIALIZED + 00000000 00000004 rtspruv3_le.lib : boot.obj (.stack) + 00000004 000000fc --HOLE-- + +.cinit 1 00000000 00000000 UNINITIALIZED + +.fardata 1 00000100 00000040 + 00000100 00000040 rtspruv3_le.lib : sin.obj (.fardata:R$1) + +.resource_table +* 1 00000140 00000014 + 00000140 00000014 sine1.obj (.resource_table:retain) + +.creg.PRU_CFG.noload.near +* 2 00026000 00000044 NOLOAD SECTION + 00026000 00000044 sine1.obj (.creg.PRU_CFG.noload.near) + +.creg.PRU_CFG.near +* 2 00026044 00000000 UNINITIALIZED + +.creg.PRU_CFG.noload.far +* 2 00026044 00000000 NOLOAD SECTION + +.creg.PRU_CFG.far +* 2 00026044 00000000 UNINITIALIZED + + +SEGMENT ATTRIBUTES + + id tag seg value + -- --- --- ----- + 0 PHA_PAGE 1 1 + 1 PHA_PAGE 2 1 + + +GLOBAL SYMBOLS: SORTED ALPHABETICALLY BY Name + +page address name +---- ------- ---- +0 000018b8 C$$EXIT +2 00026000 CT_CFG +abs 481cc000 __PRU_CREG_BASE_DCAN0 +abs 481d0000 __PRU_CREG_BASE_DCAN1 +abs 80000000 __PRU_CREG_BASE_DDR +abs 48040000 __PRU_CREG_BASE_DMTIMER2 +abs 4a100000 __PRU_CREG_BASE_GEMAC +abs 4802a000 __PRU_CREG_BASE_I2C1 +abs 4819c000 __PRU_CREG_BASE_I2C2 +abs 40000000 __PRU_CREG_BASE_L3OCMC +abs 480c8000 __PRU_CREG_BASE_MBX0 +abs 46000000 __PRU_CREG_BASE_MCASP0_DMA +abs 48030000 __PRU_CREG_BASE_MCSPI0 +abs 481a0000 __PRU_CREG_BASE_MCSPI1 +abs 48060000 __PRU_CREG_BASE_MMCHS0 +abs 00026000 __PRU_CREG_BASE_PRU_CFG +abs 00000000 __PRU_CREG_BASE_PRU_DMEM_0_1 +abs 00002000 __PRU_CREG_BASE_PRU_DMEM_1_0 +abs 00030000 __PRU_CREG_BASE_PRU_ECAP +abs 0002e000 __PRU_CREG_BASE_PRU_IEP +abs 00020000 __PRU_CREG_BASE_PRU_INTC +abs 00010000 __PRU_CREG_BASE_PRU_SHAREDMEM +abs 00028000 __PRU_CREG_BASE_PRU_UART +abs 48300000 __PRU_CREG_BASE_PWMSS0 +abs 48302000 __PRU_CREG_BASE_PWMSS1 +abs 48304000 __PRU_CREG_BASE_PWMSS2 +abs 48318000 __PRU_CREG_BASE_RSVD10 +abs 48310000 __PRU_CREG_BASE_RSVD13 +abs 00032400 __PRU_CREG_BASE_RSVD21 +abs 00032000 __PRU_CREG_BASE_RSVD27 +abs 480ca000 __PRU_CREG_BASE_SPINLOCK +abs 49000000 __PRU_CREG_BASE_TPCC +abs 48022000 __PRU_CREG_BASE_UART1 +abs 48024000 __PRU_CREG_BASE_UART2 +abs 0000000e __PRU_CREG_DCAN0 +abs 0000000f __PRU_CREG_DCAN1 +abs 0000001f __PRU_CREG_DDR +abs 00000001 __PRU_CREG_DMTIMER2 +abs 00000009 __PRU_CREG_GEMAC +abs 00000002 __PRU_CREG_I2C1 +abs 00000011 __PRU_CREG_I2C2 +abs 0000001e __PRU_CREG_L3OCMC +abs 00000016 __PRU_CREG_MBX0 +abs 00000008 __PRU_CREG_MCASP0_DMA +abs 00000006 __PRU_CREG_MCSPI0 +abs 00000010 __PRU_CREG_MCSPI1 +abs 00000005 __PRU_CREG_MMCHS0 +abs 00000004 __PRU_CREG_PRU_CFG +abs 00000018 __PRU_CREG_PRU_DMEM_0_1 +abs 00000019 __PRU_CREG_PRU_DMEM_1_0 +abs 00000003 __PRU_CREG_PRU_ECAP +abs 0000001a __PRU_CREG_PRU_IEP +abs 00000000 __PRU_CREG_PRU_INTC +abs 0000001c __PRU_CREG_PRU_SHAREDMEM +abs 00000007 __PRU_CREG_PRU_UART +abs 00000012 __PRU_CREG_PWMSS0 +abs 00000013 __PRU_CREG_PWMSS1 +abs 00000014 __PRU_CREG_PWMSS2 +abs 0000000a __PRU_CREG_RSVD10 +abs 0000000d __PRU_CREG_RSVD13 +abs 00000015 __PRU_CREG_RSVD21 +abs 0000001b __PRU_CREG_RSVD27 +abs 00000017 __PRU_CREG_SPINLOCK +abs 0000001d __PRU_CREG_TPCC +abs 0000000b __PRU_CREG_UART1 +abs 0000000c __PRU_CREG_UART2 +1 00000100 __TI_STACK_END +abs 00000100 __TI_STACK_SIZE +0 0000069c __TI_frcaddd +0 00000388 __TI_frcmpyd +0 0000131c __TI_frcmpyf +0 00001590 __TI_renormd +abs ffffffff __binit__ +abs ffffffff __c_args__ +0 00000b48 __pruabi_addd +0 000017f4 __pruabi_asri +0 0000172c __pruabi_cvtfd +0 00001500 __pruabi_eqd +0 0000161c __pruabi_fixdi +0 000013c4 __pruabi_fixdu +0 000016a8 __pruabi_fltid +0 000017a4 __pruabi_fltuf +0 0000110c __pruabi_ged +0 00001058 __pruabi_gtd +0 000011bc __pruabi_ltd +0 000008f4 __pruabi_mpyd +0 00000d90 __pruabi_mpyf +0 0000184c __pruabi_mpyi +0 00001870 __pruabi_negd +0 00001464 __pruabi_nround +0 00001820 __pruabi_subd +0 00001890 __pruabi_trunc +0 00000000 _c_int00_noinit_noargs_noexit +1 00000000 _stack +0 000018b0 abort +abs ffffffff binit +0 0000126c main +0 00000f58 modf +1 00000140 pru_remoteproc_ResourceTable +0 00000014 sin + + +GLOBAL SYMBOLS: SORTED BY Symbol Address + +page address name +---- ------- ---- +0 00000000 _c_int00_noinit_noargs_noexit +0 00000014 sin +0 00000388 __TI_frcmpyd +0 0000069c __TI_frcaddd +0 000008f4 __pruabi_mpyd +0 00000b48 __pruabi_addd +0 00000d90 __pruabi_mpyf +0 00000f58 modf +0 00001058 __pruabi_gtd +0 0000110c __pruabi_ged +0 000011bc __pruabi_ltd +0 0000126c main +0 0000131c __TI_frcmpyf +0 000013c4 __pruabi_fixdu +0 00001464 __pruabi_nround +0 00001500 __pruabi_eqd +0 00001590 __TI_renormd +0 0000161c __pruabi_fixdi +0 000016a8 __pruabi_fltid +0 0000172c __pruabi_cvtfd +0 000017a4 __pruabi_fltuf +0 000017f4 __pruabi_asri +0 00001820 __pruabi_subd +0 0000184c __pruabi_mpyi +0 00001870 __pruabi_negd +0 00001890 __pruabi_trunc +0 000018b0 abort +0 000018b8 C$$EXIT +1 00000000 _stack +1 00000100 __TI_STACK_END +1 00000140 pru_remoteproc_ResourceTable +2 00026000 CT_CFG +abs 00000000 __PRU_CREG_BASE_PRU_DMEM_0_1 +abs 00000000 __PRU_CREG_PRU_INTC +abs 00000001 __PRU_CREG_DMTIMER2 +abs 00000002 __PRU_CREG_I2C1 +abs 00000003 __PRU_CREG_PRU_ECAP +abs 00000004 __PRU_CREG_PRU_CFG +abs 00000005 __PRU_CREG_MMCHS0 +abs 00000006 __PRU_CREG_MCSPI0 +abs 00000007 __PRU_CREG_PRU_UART +abs 00000008 __PRU_CREG_MCASP0_DMA +abs 00000009 __PRU_CREG_GEMAC +abs 0000000a __PRU_CREG_RSVD10 +abs 0000000b __PRU_CREG_UART1 +abs 0000000c __PRU_CREG_UART2 +abs 0000000d __PRU_CREG_RSVD13 +abs 0000000e __PRU_CREG_DCAN0 +abs 0000000f __PRU_CREG_DCAN1 +abs 00000010 __PRU_CREG_MCSPI1 +abs 00000011 __PRU_CREG_I2C2 +abs 00000012 __PRU_CREG_PWMSS0 +abs 00000013 __PRU_CREG_PWMSS1 +abs 00000014 __PRU_CREG_PWMSS2 +abs 00000015 __PRU_CREG_RSVD21 +abs 00000016 __PRU_CREG_MBX0 +abs 00000017 __PRU_CREG_SPINLOCK +abs 00000018 __PRU_CREG_PRU_DMEM_0_1 +abs 00000019 __PRU_CREG_PRU_DMEM_1_0 +abs 0000001a __PRU_CREG_PRU_IEP +abs 0000001b __PRU_CREG_RSVD27 +abs 0000001c __PRU_CREG_PRU_SHAREDMEM +abs 0000001d __PRU_CREG_TPCC +abs 0000001e __PRU_CREG_L3OCMC +abs 0000001f __PRU_CREG_DDR +abs 00000100 __TI_STACK_SIZE +abs 00002000 __PRU_CREG_BASE_PRU_DMEM_1_0 +abs 00010000 __PRU_CREG_BASE_PRU_SHAREDMEM +abs 00020000 __PRU_CREG_BASE_PRU_INTC +abs 00026000 __PRU_CREG_BASE_PRU_CFG +abs 00028000 __PRU_CREG_BASE_PRU_UART +abs 0002e000 __PRU_CREG_BASE_PRU_IEP +abs 00030000 __PRU_CREG_BASE_PRU_ECAP +abs 00032000 __PRU_CREG_BASE_RSVD27 +abs 00032400 __PRU_CREG_BASE_RSVD21 +abs 40000000 __PRU_CREG_BASE_L3OCMC +abs 46000000 __PRU_CREG_BASE_MCASP0_DMA +abs 48022000 __PRU_CREG_BASE_UART1 +abs 48024000 __PRU_CREG_BASE_UART2 +abs 4802a000 __PRU_CREG_BASE_I2C1 +abs 48030000 __PRU_CREG_BASE_MCSPI0 +abs 48040000 __PRU_CREG_BASE_DMTIMER2 +abs 48060000 __PRU_CREG_BASE_MMCHS0 +abs 480c8000 __PRU_CREG_BASE_MBX0 +abs 480ca000 __PRU_CREG_BASE_SPINLOCK +abs 4819c000 __PRU_CREG_BASE_I2C2 +abs 481a0000 __PRU_CREG_BASE_MCSPI1 +abs 481cc000 __PRU_CREG_BASE_DCAN0 +abs 481d0000 __PRU_CREG_BASE_DCAN1 +abs 48300000 __PRU_CREG_BASE_PWMSS0 +abs 48302000 __PRU_CREG_BASE_PWMSS1 +abs 48304000 __PRU_CREG_BASE_PWMSS2 +abs 48310000 __PRU_CREG_BASE_RSVD13 +abs 48318000 __PRU_CREG_BASE_RSVD10 +abs 49000000 __PRU_CREG_BASE_TPCC +abs 4a100000 __PRU_CREG_BASE_GEMAC +abs 80000000 __PRU_CREG_BASE_DDR +abs ffffffff __binit__ +abs ffffffff __c_args__ +abs ffffffff binit + +[100 symbols] diff --git a/pru-cookbook/05blocks/code/sine.pru0.c b/pru-cookbook/05blocks/code/sine.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..ed6b5778c644f860c8fa2c0f91b7f23cf50e6df7 --- /dev/null +++ b/pru-cookbook/05blocks/code/sine.pru0.c @@ -0,0 +1,58 @@ +// Generate an analog waveform and use a filter to reconstruct it. +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include <math.h> + +#define MAXT 100 // Maximum number of time samples +#define SAWTOOTH // Pick which waveform + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t onCount; // Current count for 1 out + uint32_t offCount; // count for 0 out + uint32_t i; + uint32_t waveform[MAXT]; // Waveform to be produced + + // Generate a periodic wave in an array of MAXT values +#ifdef SAWTOOTH + for(i=0; i<MAXT; i++) { + waveform[i] = i*100/MAXT; + } +#endif +#ifdef TRIANGLE + for(i=0; i<MAXT/2; i++) { + waveform[i] = 2*i*100/MAXT; + waveform[MAXT-i-1] = 2*i*100/MAXT; + } +#endif +#ifdef SINE + float gain = 50.0f; + float bias = 50.0f; + float freq = 2.0f * 3.14159f / MAXT; + for (i=0; i<MAXT; i++){ + waveform[i] = (uint32_t)(bias+gain*sin(i*freq)); + } +#endif + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + while (1) { + // Generate a PWM signal whose duty cycle matches + // the amplitude of the signal. + for(i=0; i<MAXT; i++) { + onCount = waveform[i]; + offCount = 100 - onCount; + while(onCount--) { + __R30 |= 0x1; // Set the GPIO pin to 1 + } + while(offCount--) { + __R30 &= ~(0x1); // Clear the GPIO pin + } + } + } +} diff --git a/pru-cookbook/05blocks/code/write_init_pins.sh b/pru-cookbook/05blocks/code/write_init_pins.sh new file mode 100755 index 0000000000000000000000000000000000000000..f52082365a8b2a72a6c30d39938077bd9addf741 --- /dev/null +++ b/pru-cookbook/05blocks/code/write_init_pins.sh @@ -0,0 +1,9 @@ +#!/bin/bash +init_pins=$(readelf -x .init_pins $1 | grep 0x000 | cut -d' ' -f4-7 | xxd -r -p | tr '\0' '\n' | paste - -) +while read -a line; do + if [ ${#line[@]} == 2 ]; then + echo writing \"${line[1]}\" to \"${line[0]}\" + echo ${line[1]} > ${line[0]} + sleep 0.1 + fi +done <<< "$init_pins" diff --git a/pru-cookbook/05blocks/figures/blockDiagram.png b/pru-cookbook/05blocks/figures/blockDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..901f5b4af178dd896a3a07b5701804a0eaf17fa4 Binary files /dev/null and b/pru-cookbook/05blocks/figures/blockDiagram.png differ diff --git a/pru-cookbook/05blocks/figures/blocks_plots.asv b/pru-cookbook/05blocks/figures/blocks_plots.asv new file mode 100644 index 0000000000000000000000000000000000000000..760326592b877da906a542683a91bb8778433134 --- /dev/null +++ b/pru-cookbook/05blocks/figures/blocks_plots.asv @@ -0,0 +1,27 @@ +% Plots for PRU example +MAXT=100 +waveform = linspace(0, MAXT-1, 100); + +plot(waveform) + +%% +T = 10*(1/50); +Fs = 100; +dt = 1/Fs; +t = 0:dt:T-dt; +x = 50*sawtooth(2*pi*10*t)+50; + +stem(t,x) +title('Sawtooth Waveform') +grid on + +%% Solid sawtooth +T = 10*(1/50); +Fs = 100; +dt = 1/Fs; +t = 0:dt:T-dt; +x = 50*sawtooth(2*pi*20*t)+50; + +stem(t,x) +title('Sampled Sawtooth Waveform') +grid on diff --git a/pru-cookbook/05blocks/figures/blocks_plots.m b/pru-cookbook/05blocks/figures/blocks_plots.m new file mode 100644 index 0000000000000000000000000000000000000000..37ab48a26c799541d51ec0fa43835b9387131a7d --- /dev/null +++ b/pru-cookbook/05blocks/figures/blocks_plots.m @@ -0,0 +1,27 @@ +% Plots for PRU example +MAXT=100 +waveform = linspace(0, MAXT-1, 100); + +plot(waveform) + +%% +T = 20*(1/50); +Fs = 1000; +dt = 1/Fs; +t = 0:dt:T-dt; +x = 50*sawtooth(2*pi*10*t)+50; + +plot(t,x) +title('Sawtooth Waveform') +grid on + +%% Solid sawtooth +T = 5*(1/50); +Fs = 200; +dt = 1/Fs; +t = 0:dt:T-dt; +x = 50*sawtooth(2*pi*10*t)+50; + +stem(t,x) +title('Sampled Sawtooth Waveform') +grid on diff --git a/pru-cookbook/05blocks/figures/filter.fzz b/pru-cookbook/05blocks/figures/filter.fzz new file mode 100644 index 0000000000000000000000000000000000000000..3342d1cc50cd475f668a42b18f1900448ebb1c92 Binary files /dev/null and b/pru-cookbook/05blocks/figures/filter.fzz differ diff --git a/pru-cookbook/05blocks/figures/filter_bb.png b/pru-cookbook/05blocks/figures/filter_bb.png new file mode 100644 index 0000000000000000000000000000000000000000..3fc2955b5c48540261818efd47e01e6c1d268350 Binary files /dev/null and b/pru-cookbook/05blocks/figures/filter_bb.png differ diff --git a/pru-cookbook/05blocks/figures/matrix_j1.jpg b/pru-cookbook/05blocks/figures/matrix_j1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..711c90412e80626e916a14fe0474ca083eb3c642 Binary files /dev/null and b/pru-cookbook/05blocks/figures/matrix_j1.jpg differ diff --git a/pru-cookbook/05blocks/figures/neo.fzz b/pru-cookbook/05blocks/figures/neo.fzz new file mode 100644 index 0000000000000000000000000000000000000000..36191328e10761ac75321186fce2f2955ca8004e Binary files /dev/null and b/pru-cookbook/05blocks/figures/neo.fzz differ diff --git a/pru-cookbook/05blocks/figures/neo_bb.png b/pru-cookbook/05blocks/figures/neo_bb.png new file mode 100644 index 0000000000000000000000000000000000000000..e7cc6b2fa60b62fff23b3abddc4e2e6578408718 Binary files /dev/null and b/pru-cookbook/05blocks/figures/neo_bb.png differ diff --git a/pru-cookbook/05blocks/figures/neo_data_seq.png b/pru-cookbook/05blocks/figures/neo_data_seq.png new file mode 100644 index 0000000000000000000000000000000000000000..bef90bbeb121dee12cd393faceb17e59e2e9a985 Binary files /dev/null and b/pru-cookbook/05blocks/figures/neo_data_seq.png differ diff --git a/pru-cookbook/05blocks/figures/neo_scope.png b/pru-cookbook/05blocks/figures/neo_scope.png new file mode 100644 index 0000000000000000000000000000000000000000..919d0b8d574b64cbf237761befed37b3812f6f3c Binary files /dev/null and b/pru-cookbook/05blocks/figures/neo_scope.png differ diff --git a/pru-cookbook/05blocks/figures/neo_sequence.png b/pru-cookbook/05blocks/figures/neo_sequence.png new file mode 100644 index 0000000000000000000000000000000000000000..be8c48c18e270048b8ae6585b237e6b0973735cc Binary files /dev/null and b/pru-cookbook/05blocks/figures/neo_sequence.png differ diff --git a/pru-cookbook/05blocks/figures/pwm1.png b/pru-cookbook/05blocks/figures/pwm1.png new file mode 100644 index 0000000000000000000000000000000000000000..6b56f035350a75c7459d82d268de4cf58bba6ffd Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm1.png differ diff --git a/pru-cookbook/05blocks/figures/pwm2.png b/pru-cookbook/05blocks/figures/pwm2.png new file mode 100644 index 0000000000000000000000000000000000000000..248a142b345ccd3e425e0bfd596116df8b4ad30b Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm2.png differ diff --git a/pru-cookbook/05blocks/figures/pwm3.png b/pru-cookbook/05blocks/figures/pwm3.png new file mode 100644 index 0000000000000000000000000000000000000000..0b76c32939ab7d9143ed48815b5739caad428e0a Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm3.png differ diff --git a/pru-cookbook/05blocks/figures/pwm4.png b/pru-cookbook/05blocks/figures/pwm4.png new file mode 100644 index 0000000000000000000000000000000000000000..dfc9c75da241ba42dffc326726f143dc2a58a8d0 Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm4.png differ diff --git a/pru-cookbook/05blocks/figures/pwm5_no_loop.png b/pru-cookbook/05blocks/figures/pwm5_no_loop.png new file mode 100644 index 0000000000000000000000000000000000000000..35aff88d2bf00c727c6c6ebf0667fa0464c7c68e Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm5_no_loop.png differ diff --git a/pru-cookbook/05blocks/figures/pwm5_zoomed.png b/pru-cookbook/05blocks/figures/pwm5_zoomed.png new file mode 100644 index 0000000000000000000000000000000000000000..6802cb55ca07d815d665d7aa8f987addd4366c13 Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm5_zoomed.png differ diff --git a/pru-cookbook/05blocks/figures/pwm6_synced.png b/pru-cookbook/05blocks/figures/pwm6_synced.png new file mode 100644 index 0000000000000000000000000000000000000000..1b71ee53d8d974fd0207342ecd37fe27a34b89f5 Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm6_synced.png differ diff --git a/pru-cookbook/05blocks/figures/pwm7_two_prus_running.png b/pru-cookbook/05blocks/figures/pwm7_two_prus_running.png new file mode 100644 index 0000000000000000000000000000000000000000..662706b9203b7734ad9e3146ee7a8aa6386f39f0 Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm7_two_prus_running.png differ diff --git a/pru-cookbook/05blocks/figures/pwm7_two_prus_stopped.png b/pru-cookbook/05blocks/figures/pwm7_two_prus_stopped.png new file mode 100644 index 0000000000000000000000000000000000000000..00cfc20dc65ce2cb5b88cb34a6f60a61266e05bc Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm7_two_prus_stopped.png differ diff --git a/pru-cookbook/05blocks/figures/pwm8_prus_sycned.png b/pru-cookbook/05blocks/figures/pwm8_prus_sycned.png new file mode 100644 index 0000000000000000000000000000000000000000..f27388fa93ec02685296c3aa13ec3a7b3a182144 Binary files /dev/null and b/pru-cookbook/05blocks/figures/pwm8_prus_sycned.png differ diff --git a/pru-cookbook/05blocks/figures/rgb_fpp.png b/pru-cookbook/05blocks/figures/rgb_fpp.png new file mode 100644 index 0000000000000000000000000000000000000000..38adf5a27d49f028e09b75426211e743b35aa97b Binary files /dev/null and b/pru-cookbook/05blocks/figures/rgb_fpp.png differ diff --git a/pru-cookbook/05blocks/figures/rgb_pru.jpg b/pru-cookbook/05blocks/figures/rgb_pru.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a588b42bd7e02958c8e48142921825d79adb8b8e Binary files /dev/null and b/pru-cookbook/05blocks/figures/rgb_pru.jpg differ diff --git a/pru-cookbook/05blocks/figures/rgb_python.jpg b/pru-cookbook/05blocks/figures/rgb_python.jpg new file mode 100644 index 0000000000000000000000000000000000000000..26c83ec2d73310ea64aea2252c1c437a304530f7 Binary files /dev/null and b/pru-cookbook/05blocks/figures/rgb_python.jpg differ diff --git a/pru-cookbook/05blocks/figures/rgb_waveforms.png b/pru-cookbook/05blocks/figures/rgb_waveforms.png new file mode 100644 index 0000000000000000000000000000000000000000..df9d8cbdbe93f2b72c08945246dccec62aba3879 Binary files /dev/null and b/pru-cookbook/05blocks/figures/rgb_waveforms.png differ diff --git a/pru-cookbook/05blocks/figures/ring_around.mp4 b/pru-cookbook/05blocks/figures/ring_around.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..1695cb0532647566c09e966dca41348943962bfb Binary files /dev/null and b/pru-cookbook/05blocks/figures/ring_around.mp4 differ diff --git a/pru-cookbook/05blocks/figures/sawhighercutoff.png b/pru-cookbook/05blocks/figures/sawhighercutoff.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca0f4d4023db196b2e85b17dda9dc915e9b00c4 Binary files /dev/null and b/pru-cookbook/05blocks/figures/sawhighercutoff.png differ diff --git a/pru-cookbook/05blocks/figures/sawlowercutoff.png b/pru-cookbook/05blocks/figures/sawlowercutoff.png new file mode 100644 index 0000000000000000000000000000000000000000..933d7cc2587e9177bbc98572a302d2d6a298d5a0 Binary files /dev/null and b/pru-cookbook/05blocks/figures/sawlowercutoff.png differ diff --git a/pru-cookbook/05blocks/figures/sawscope.png b/pru-cookbook/05blocks/figures/sawscope.png new file mode 100644 index 0000000000000000000000000000000000000000..d9d191d3ebce062b6d44108a17fcf7871a39b775 Binary files /dev/null and b/pru-cookbook/05blocks/figures/sawscope.png differ diff --git a/pru-cookbook/05blocks/figures/sawtoothsampled.png b/pru-cookbook/05blocks/figures/sawtoothsampled.png new file mode 100644 index 0000000000000000000000000000000000000000..c6b09731731306d2e40695e9cc5a8bc2635bce4e Binary files /dev/null and b/pru-cookbook/05blocks/figures/sawtoothsampled.png differ diff --git a/pru-cookbook/05blocks/figures/sawtoothsmooth.png b/pru-cookbook/05blocks/figures/sawtoothsmooth.png new file mode 100644 index 0000000000000000000000000000000000000000..60296663cb33d64b76f7fc099fc5fbb0fbf86a5d Binary files /dev/null and b/pru-cookbook/05blocks/figures/sawtoothsmooth.png differ diff --git a/pru-cookbook/05blocks/figures/sawunfiltered.png b/pru-cookbook/05blocks/figures/sawunfiltered.png new file mode 100644 index 0000000000000000000000000000000000000000..9f77ac535d832cbf159b072d59cdf69819af61a4 Binary files /dev/null and b/pru-cookbook/05blocks/figures/sawunfiltered.png differ diff --git a/pru-cookbook/05blocks/figures/sine.png b/pru-cookbook/05blocks/figures/sine.png new file mode 100644 index 0000000000000000000000000000000000000000..0c6913b16be3ab3694c99fc41c4b68e969c75db6 Binary files /dev/null and b/pru-cookbook/05blocks/figures/sine.png differ diff --git a/pru-cookbook/05blocks/figures/triangle.png b/pru-cookbook/05blocks/figures/triangle.png new file mode 100644 index 0000000000000000000000000000000000000000..988a28810411074efc6de6337040dce50d558513 Binary files /dev/null and b/pru-cookbook/05blocks/figures/triangle.png differ diff --git a/pru-cookbook/06io/code/Makefile b/pru-cookbook/06io/code/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a7557fdaa22988d89cec879477ded78522d7116f --- /dev/null +++ b/pru-cookbook/06io/code/Makefile @@ -0,0 +1 @@ +include /var/lib/cloud9/common/Makefile diff --git a/pru-cookbook/06io/code/gpio.pru0.c b/pru-cookbook/06io/code/gpio.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..bcab90eff3f115577055dac3781c50bfb3e0efbf --- /dev/null +++ b/pru-cookbook/06io/code/gpio.pru0.c @@ -0,0 +1,23 @@ +// This code accesses GPIO without using R30 and R31 +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +#define P9_11 (0x1<<30) // Bit position tied to P9_11 on Black +#define P2_05 (0x1<<30) // Bit position tied to P2_05 on Pocket + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t *gpio0 = (uint32_t *)GPIO0; + + while(1) { + gpio0[GPIO_SETDATAOUT] = P9_11; + __delay_cycles(100000000); + gpio0[GPIO_CLEARDATAOUT] = P9_11; + __delay_cycles(100000000); + } +} diff --git a/pru-cookbook/06io/code/setup.sh b/pru-cookbook/06io/code/setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..e676ed7abe2a6beaf62d3ce6c56f5aa151d86700 --- /dev/null +++ b/pru-cookbook/06io/code/setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +export TARGET=gpio.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_11" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P2_05" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin gpio + config-pin -q $pin +done diff --git a/pru-cookbook/06io/figures/gpio0delay.png b/pru-cookbook/06io/figures/gpio0delay.png new file mode 100644 index 0000000000000000000000000000000000000000..ad8568542d5d6b2445cb7ba2e42792bc671e6d6b Binary files /dev/null and b/pru-cookbook/06io/figures/gpio0delay.png differ diff --git a/pru-cookbook/06io/figures/jitter.png b/pru-cookbook/06io/figures/jitter.png new file mode 100644 index 0000000000000000000000000000000000000000..e9b80b4d61809420fa6a8ee6e23cb44ee2ab9c2b Binary files /dev/null and b/pru-cookbook/06io/figures/jitter.png differ diff --git a/pru-cookbook/06io/figures/pruIntegration.png b/pru-cookbook/06io/figures/pruIntegration.png new file mode 100644 index 0000000000000000000000000000000000000000..de7ef9196b3e56e5bd1ff14a9957c2ff23d3fa41 Binary files /dev/null and b/pru-cookbook/06io/figures/pruIntegration.png differ diff --git a/pru-cookbook/06io/io.html b/pru-cookbook/06io/io.html new file mode 100644 index 0000000000000000000000000000000000000000..5bb5425db9ef3699741ac9d74701f36aac6519b4 --- /dev/null +++ b/pru-cookbook/06io/io.html @@ -0,0 +1,1003 @@ +<!DOCTYPE html> +<html lang="en"> +<head> +<meta charset="UTF-8"> +<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<meta name="generator" content="Asciidoctor 1.5.8"> +<title>Accessing More I/O</title> +<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"> +<style> +/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ +/* Uncomment @import statement below to use as custom stylesheet */ +/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ +article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} +audio,canvas,video{display:inline-block} +audio:not([controls]){display:none;height:0} +script{display:none!important} +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} +a{background:transparent} +a:focus{outline:thin dotted} +a:active,a:hover{outline:0} +h1{font-size:2em;margin:.67em 0} +abbr[title]{border-bottom:1px dotted} +b,strong{font-weight:bold} +dfn{font-style:italic} +hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} +mark{background:#ff0;color:#000} +code,kbd,pre,samp{font-family:monospace;font-size:1em} +pre{white-space:pre-wrap} +q{quotes:"\201C" "\201D" "\2018" "\2019"} +small{font-size:80%} +sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} +sup{top:-.5em} +sub{bottom:-.25em} +img{border:0} +svg:not(:root){overflow:hidden} +figure{margin:0} +fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} +legend{border:0;padding:0} +button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} +button,input{line-height:normal} +button,select{text-transform:none} +button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} +button[disabled],html input[disabled]{cursor:default} +input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} +button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} +textarea{overflow:auto;vertical-align:top} +table{border-collapse:collapse;border-spacing:0} +*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} +html,body{font-size:100%} +body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} +a:hover{cursor:pointer} +img,object,embed{max-width:100%;height:auto} +object,embed{height:100%} +img{-ms-interpolation-mode:bicubic} +.left{float:left!important} +.right{float:right!important} +.text-left{text-align:left!important} +.text-right{text-align:right!important} +.text-center{text-align:center!important} +.text-justify{text-align:justify!important} +.hide{display:none} +img,object,svg{display:inline-block;vertical-align:middle} +textarea{height:auto;min-height:50px} +select{width:100%} +.center{margin-left:auto;margin-right:auto} +.stretch{width:100%} +.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} +div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} +a{color:#2156a5;text-decoration:underline;line-height:inherit} +a:hover,a:focus{color:#1d4b8f} +a img{border:none} +p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} +p aside{font-size:.875em;line-height:1.35;font-style:italic} +h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} +h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} +h1{font-size:2.125em} +h2{font-size:1.6875em} +h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} +h4,h5{font-size:1.125em} +h6{font-size:1em} +hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} +em,i{font-style:italic;line-height:inherit} +strong,b{font-weight:bold;line-height:inherit} +small{font-size:60%;line-height:inherit} +code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} +ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} +ul,ol{margin-left:1.5em} +ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} +ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} +ul.square{list-style-type:square} +ul.circle{list-style-type:circle} +ul.disc{list-style-type:disc} +ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} +dl dt{margin-bottom:.3125em;font-weight:bold} +dl dd{margin-bottom:1.25em} +abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} +abbr{text-transform:none} +blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} +blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} +blockquote cite::before{content:"\2014 \0020"} +blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} +blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} +@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} +h1{font-size:2.75em} +h2{font-size:2.3125em} +h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} +h4{font-size:1.4375em}} +table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} +table thead,table tfoot{background:#f7f8f7} +table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} +table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} +table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} +table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} +h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} +h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} +.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table} +.clearfix::after,.float-group::after{clear:both} +*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word} +*:not(pre)>code.nobreak{word-wrap:normal} +*:not(pre)>code.nowrap{white-space:nowrap} +pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} +em em{font-style:normal} +strong strong{font-weight:400} +.keyseq{color:rgba(51,51,51,.8)} +kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} +.keyseq kbd:first-child{margin-left:0} +.keyseq kbd:last-child{margin-right:0} +.menuseq,.menuref{color:#000} +.menuseq b:not(.caret),.menuref{font-weight:inherit} +.menuseq{word-spacing:-.02em} +.menuseq b.caret{font-size:1.25em;line-height:.8} +.menuseq i.caret{font-weight:bold;text-align:center;width:.45em} +b.button::before,b.button::after{position:relative;top:-1px;font-weight:400} +b.button::before{content:"[";padding:0 3px 0 2px} +b.button::after{content:"]";padding:0 2px 0 3px} +p a>code:hover{color:rgba(0,0,0,.9)} +#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} +#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table} +#header::after,#content::after,#footnotes::after,#footer::after{clear:both} +#content{margin-top:1.25em} +#content::before{content:none} +#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} +#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf} +#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px} +#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} +#header .details span:first-child{margin-left:-.125em} +#header .details span.email a{color:rgba(0,0,0,.85)} +#header .details br{display:none} +#header .details br+span::before{content:"\00a0\2013\00a0"} +#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} +#header .details br+span#revremark::before{content:"\00a0|\00a0"} +#header #revnumber{text-transform:capitalize} +#header #revnumber::after{content:"\00a0"} +#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} +#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em} +#toc>ul{margin-left:.125em} +#toc ul.sectlevel0>li>a{font-style:italic} +#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} +#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} +#toc li{line-height:1.3334;margin-top:.3334em} +#toc a{text-decoration:none} +#toc a:active{text-decoration:underline} +#toctitle{color:#7a2518;font-size:1.2em} +@media screen and (min-width:768px){#toctitle{font-size:1.375em} +body.toc2{padding-left:15em;padding-right:0} +#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} +#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} +#toc.toc2>ul{font-size:.9em;margin-bottom:0} +#toc.toc2 ul ul{margin-left:0;padding-left:1em} +#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} +body.toc2.toc-right{padding-left:0;padding-right:15em} +body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}} +@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} +#toc.toc2{width:20em} +#toc.toc2 #toctitle{font-size:1.375em} +#toc.toc2>ul{font-size:.95em} +#toc.toc2 ul ul{padding-left:1.25em} +body.toc2.toc-right{padding-left:0;padding-right:20em}} +#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} +#content #toc>:first-child{margin-top:0} +#content #toc>:last-child{margin-bottom:0} +#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} +#footer-text{color:rgba(255,255,255,.8);line-height:1.44} +#content{margin-bottom:.625em} +.sect1{padding-bottom:.625em} +@media screen and (min-width:768px){#content{margin-bottom:1.25em} +.sect1{padding-bottom:1.25em}} +.sect1:last-child{padding-bottom:0} +.sect1+.sect1{border-top:1px solid #e7e7e9} +#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} +#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} +#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} +#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} +#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} +.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} +.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} +table.tableblock.fit-content>caption.title{white-space:nowrap;width:0} +.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)} +table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit} +.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} +.admonitionblock>table td.icon{text-align:center;width:80px} +.admonitionblock>table td.icon img{max-width:none} +.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} +.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)} +.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} +.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} +.exampleblock>.content>:first-child{margin-top:0} +.exampleblock>.content>:last-child{margin-bottom:0} +.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} +.sidebarblock>:first-child{margin-top:0} +.sidebarblock>:last-child{margin-bottom:0} +.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} +.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} +.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} +.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} +.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em} +@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}} +@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}} +.literalblock pre.nowrap,.literalblock pre.nowrap pre,.listingblock pre.nowrap,.listingblock pre.nowrap pre{white-space:pre;word-wrap:normal} +.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} +.listingblock pre.highlightjs{padding:0} +.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} +.listingblock pre.prettyprint{border-width:0} +.listingblock>.content{position:relative} +.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} +.listingblock:hover code[data-lang]::before{display:block} +.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999} +.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"} +table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} +table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} +table.pyhltable td.code{padding-left:.75em;padding-right:0} +pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #dddddf} +pre.pygments .lineno{display:inline-block;margin-right:.25em} +table.pyhltable .linenodiv{background:none!important;padding-right:0!important} +.quoteblock{margin:0 1em 1.25em 1.5em;display:table} +.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} +.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} +.quoteblock blockquote{margin:0;padding:0;border:0} +.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} +.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} +.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right} +.verseblock{margin:0 1em 1.25em} +.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} +.verseblock pre strong{font-weight:400} +.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} +.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} +.quoteblock .attribution br,.verseblock .attribution br{display:none} +.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} +.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none} +.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0} +.quoteblock.abstract{margin:0 1em 1.25em;display:block} +.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center} +.quoteblock.excerpt,.quoteblock .quoteblock{margin:0 0 1.25em;padding:0 0 .25em 1em;border-left:.25em solid #dddddf} +.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem} +.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0} +table.tableblock{max-width:100%;border-collapse:separate} +p.tableblock:last-child{margin-bottom:0} +td.tableblock>.content{margin-bottom:-1.25em} +table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} +table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0} +table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0} +table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0} +table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px} +table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0} +table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0} +table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0} +table.frame-all{border-width:1px} +table.frame-sides{border-width:0 1px} +table.frame-topbot,table.frame-ends{border-width:1px 0} +table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7} +table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none} +th.halign-left,td.halign-left{text-align:left} +th.halign-right,td.halign-right{text-align:right} +th.halign-center,td.halign-center{text-align:center} +th.valign-top,td.valign-top{vertical-align:top} +th.valign-bottom,td.valign-bottom{vertical-align:bottom} +th.valign-middle,td.valign-middle{vertical-align:middle} +table thead th,table tfoot th{font-weight:bold} +tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} +tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} +p.tableblock>code:only-child{background:none;padding:0} +p.tableblock{font-size:1em} +td>div.verse{white-space:pre} +ol{margin-left:1.75em} +ul li ol{margin-left:1.5em} +dl dd{margin-left:1.125em} +dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} +ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} +ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} +ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} +ul.unstyled,ol.unstyled{margin-left:0} +ul.checklist{margin-left:.625em} +ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} +ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em} +ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em} +ul.inline>li{margin-left:1.25em} +.unstyled dl dt{font-weight:400;font-style:normal} +ol.arabic{list-style-type:decimal} +ol.decimal{list-style-type:decimal-leading-zero} +ol.loweralpha{list-style-type:lower-alpha} +ol.upperalpha{list-style-type:upper-alpha} +ol.lowerroman{list-style-type:lower-roman} +ol.upperroman{list-style-type:upper-roman} +ol.lowergreek{list-style-type:lower-greek} +.hdlist>table,.colist>table{border:0;background:none} +.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} +td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} +td.hdlist1{font-weight:bold;padding-bottom:1.25em} +.literalblock+.colist,.listingblock+.colist{margin-top:-.5em} +.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top} +.colist td:not([class]):first-child img{max-width:none} +.colist td:not([class]):last-child{padding:.25em 0} +.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} +.imageblock.left{margin:.25em .625em 1.25em 0} +.imageblock.right{margin:.25em 0 1.25em .625em} +.imageblock>.title{margin-bottom:0} +.imageblock.thumb,.imageblock.th{border-width:6px} +.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} +.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} +.image.left{margin-right:.625em} +.image.right{margin-left:.625em} +a.image{text-decoration:none;display:inline-block} +a.image object{pointer-events:none} +sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} +sup.footnote a,sup.footnoteref a{text-decoration:none} +sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} +#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} +#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0} +#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em} +#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em} +#footnotes .footnote:last-of-type{margin-bottom:0} +#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} +.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} +.gist .file-data>table td.line-data{width:99%} +div.unbreakable{page-break-inside:avoid} +.big{font-size:larger} +.small{font-size:smaller} +.underline{text-decoration:underline} +.overline{text-decoration:overline} +.line-through{text-decoration:line-through} +.aqua{color:#00bfbf} +.aqua-background{background-color:#00fafa} +.black{color:#000} +.black-background{background-color:#000} +.blue{color:#0000bf} +.blue-background{background-color:#0000fa} +.fuchsia{color:#bf00bf} +.fuchsia-background{background-color:#fa00fa} +.gray{color:#606060} +.gray-background{background-color:#7d7d7d} +.green{color:#006000} +.green-background{background-color:#007d00} +.lime{color:#00bf00} +.lime-background{background-color:#00fa00} +.maroon{color:#600000} +.maroon-background{background-color:#7d0000} +.navy{color:#000060} +.navy-background{background-color:#00007d} +.olive{color:#606000} +.olive-background{background-color:#7d7d00} +.purple{color:#600060} +.purple-background{background-color:#7d007d} +.red{color:#bf0000} +.red-background{background-color:#fa0000} +.silver{color:#909090} +.silver-background{background-color:#bcbcbc} +.teal{color:#006060} +.teal-background{background-color:#007d7d} +.white{color:#bfbfbf} +.white-background{background-color:#fafafa} +.yellow{color:#bfbf00} +.yellow-background{background-color:#fafa00} +span.icon>.fa{cursor:default} +a span.icon>.fa{cursor:inherit} +.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} +.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c} +.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} +.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900} +.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400} +.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000} +.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} +.conum[data-value] *{color:#fff!important} +.conum[data-value]+b{display:none} +.conum[data-value]::after{content:attr(data-value)} +pre .conum[data-value]{position:relative;top:-.125em} +b.conum *{color:inherit!important} +.conum:not([data-value]):empty{display:none} +dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} +h1,h2,p,td.content,span.alt{letter-spacing:-.01em} +p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} +p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} +p{margin-bottom:1.25rem} +.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} +.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} +.print-only{display:none!important} +@page{margin:1.25cm .75cm} +@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} +html{font-size:80%} +a{color:inherit!important;text-decoration:underline!important} +a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} +a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} +abbr[title]::after{content:" (" attr(title) ")"} +pre,blockquote,tr,img,object,svg{page-break-inside:avoid} +thead{display:table-header-group} +svg{max-width:100%} +p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} +h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} +#toc,.sidebarblock,.exampleblock>.content{background:none!important} +#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important} +body.book #header{text-align:center} +body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em} +body.book #header .details{border:0!important;display:block;padding:0!important} +body.book #header .details span:first-child{margin-left:0!important} +body.book #header .details br{display:block} +body.book #header .details br+span::before{content:none!important} +body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} +body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} +.listingblock code[data-lang]::before{display:block} +#footer{padding:0 .9375em} +.hide-on-print{display:none!important} +.print-only{display:block!important} +.hide-for-print{display:none!important} +.show-for-print{display:inherit!important}} +@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem} +.sect1{padding:0!important} +.sect1+.sect1{border:0} +#footer{background:none} +#footer-text{color:rgba(0,0,0,.6);font-size:.9em}} +@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}} +</style> +<style> +/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */ +/*pre.CodeRay {background-color:#f7f7f8;}*/ +.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em} +.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)} +.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)} +table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none} +table.CodeRay td{vertical-align: top;line-height:1.45} +table.CodeRay td.line-numbers{text-align:right} +table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)} +table.CodeRay td.code{padding:0 0 0 .5em} +table.CodeRay td.code>pre{padding:0} +.CodeRay .debug{color:#fff !important;background:#000080 !important} +.CodeRay .annotation{color:#007} +.CodeRay .attribute-name{color:#000080} +.CodeRay .attribute-value{color:#700} +.CodeRay .binary{color:#509} +.CodeRay .comment{color:#998;font-style:italic} +.CodeRay .char{color:#04d} +.CodeRay .char .content{color:#04d} +.CodeRay .char .delimiter{color:#039} +.CodeRay .class{color:#458;font-weight:bold} +.CodeRay .complex{color:#a08} +.CodeRay .constant,.CodeRay .predefined-constant{color:#008080} +.CodeRay .color{color:#099} +.CodeRay .class-variable{color:#369} +.CodeRay .decorator{color:#b0b} +.CodeRay .definition{color:#099} +.CodeRay .delimiter{color:#000} +.CodeRay .doc{color:#970} +.CodeRay .doctype{color:#34b} +.CodeRay .doc-string{color:#d42} +.CodeRay .escape{color:#666} +.CodeRay .entity{color:#800} +.CodeRay .error{color:#808} +.CodeRay .exception{color:inherit} +.CodeRay .filename{color:#099} +.CodeRay .function{color:#900;font-weight:bold} +.CodeRay .global-variable{color:#008080} +.CodeRay .hex{color:#058} +.CodeRay .integer,.CodeRay .float{color:#099} +.CodeRay .include{color:#555} +.CodeRay .inline{color:#000} +.CodeRay .inline .inline{background:#ccc} +.CodeRay .inline .inline .inline{background:#bbb} +.CodeRay .inline .inline-delimiter{color:#d14} +.CodeRay .inline-delimiter{color:#d14} +.CodeRay .important{color:#555;font-weight:bold} +.CodeRay .interpreted{color:#b2b} +.CodeRay .instance-variable{color:#008080} +.CodeRay .label{color:#970} +.CodeRay .local-variable{color:#963} +.CodeRay .octal{color:#40e} +.CodeRay .predefined{color:#369} +.CodeRay .preprocessor{color:#579} +.CodeRay .pseudo-class{color:#555} +.CodeRay .directive{font-weight:bold} +.CodeRay .type{font-weight:bold} +.CodeRay .predefined-type{color:inherit} +.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold} +.CodeRay .key{color:#808} +.CodeRay .key .delimiter{color:#606} +.CodeRay .key .char{color:#80f} +.CodeRay .value{color:#088} +.CodeRay .regexp .delimiter{color:#808} +.CodeRay .regexp .content{color:#808} +.CodeRay .regexp .modifier{color:#808} +.CodeRay .regexp .char{color:#d14} +.CodeRay .regexp .function{color:#404;font-weight:bold} +.CodeRay .string{color:#d20} +.CodeRay .string .string .string{background:#ffd0d0} +.CodeRay .string .content{color:#d14} +.CodeRay .string .char{color:#d14} +.CodeRay .string .delimiter{color:#d14} +.CodeRay .shell{color:#d14} +.CodeRay .shell .delimiter{color:#d14} +.CodeRay .symbol{color:#990073} +.CodeRay .symbol .content{color:#a60} +.CodeRay .symbol .delimiter{color:#630} +.CodeRay .tag{color:#008080} +.CodeRay .tag-special{color:#d70} +.CodeRay .variable{color:#036} +.CodeRay .insert{background:#afa} +.CodeRay .delete{background:#faa} +.CodeRay .change{color:#aaf;background:#007} +.CodeRay .head{color:#f8f;background:#505} +.CodeRay .insert .insert{color:#080} +.CodeRay .delete .delete{color:#800} +.CodeRay .change .change{color:#66f} +.CodeRay .head .head{color:#f4f} +</style> +</head> +<body class="article"> +<div id="header"> +<div id="toc" class="toc"> +<div id="toctitle">Table of Contents</div> +<ul class="sectlevel1"> +<li><a href="#_accessing_more_io">1. Accessing More I/O</a> +<ul class="sectlevel2"> +<li><a href="#_editing_bootuenv_txt_to_access_the_p8_header_on_the_black">1.1. Editing /boot/uEnv.txt to Access the P8 Header on the Black</a></li> +<li><a href="#_accessing_gpio">1.2. Accessing gpio</a></li> +<li><a href="#io_uio">1.3. Configuring for UIO Instead of RemoteProc</a></li> +<li><a href="#_converting_pasm_assembly_code_to_clpru">1.4. Converting pasm Assembly Code to clpru</a></li> +</ul> +</li> +</ul> +</div> +</div> +<div id="content"> +<div class="paragraph"> +<p><a href="../index.html">Outline</a></p> +</div> +<div class="sect1"> +<h2 id="_accessing_more_io"><a class="link" href="#_accessing_more_io">1. Accessing More I/O</a></h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>So far the examples have shown how to access the GPIO pins on the BeagleBone Black’s +<code>P9</code> header and through the <code>__R30</code> register. Below shows how more GPIO pins +can be accessed.</p> +</div> +<div class="paragraph"> +<p>The following are resources used in this chapter.</p> +</div> +<div class="ulist"> +<div class="title">Resources</div> +<ul> +<li> +<p><a href="https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP8HeaderTable.pdf">P8 Header Table</a></p> +</li> +<li> +<p><a href="https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP9HeaderTable.pdf">P9 Header Table</a></p> +</li> +<li> +<p><a href="http://www.ti.com/lit/pdf/spruhz6l">AM572x Technical Reference Manual</a> (AI)</p> +</li> +<li> +<p><a href="http://www.ti.com/lit/pdf/spruh73">AM335x Technical Reference Manual</a> (All others)</p> +</li> +<li> +<p><a href="http://www.ti.com/lit/ug/spruhv6a/spruhv6a.pdf">PRU Assembly Language Tools</a></p> +</li> +</ul> +</div> +<div class="sect2"> +<h3 id="_editing_bootuenv_txt_to_access_the_p8_header_on_the_black"><a class="link" href="#_editing_bootuenv_txt_to_access_the_p8_header_on_the_black">1.1. Editing /boot/uEnv.txt to Access the P8 Header on the Black</a></h3> +<div class="sect3"> +<h4 id="_problem"><a class="link" href="#_problem">Problem</a></h4> +<div class="paragraph"> +<p>When I try to configure some pins on the <code>P8</code> header of the Black I get an error.</p> +</div> +<div class="listingblock"> +<div class="title">config-pin</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="bash">bone$ <strong>config-pin P8_28 pruout</strong> +ERROR: open() for /sys/devices/platform/ocp/ocp:P8_28_pinmux/state failed, No such file or directory</code></pre> +</div> +</div> +</div> +<div class="sect3"> +<h4 id="_solution"><a class="link" href="#_solution">Solution</a></h4> +<div class="paragraph"> +<p>On the images for the BeagleBone Black, the HDMI display driver is enabled by +default and uses many of the <code>P8</code> pins. If you are not using +HDMI video (or the HDI audio, or even the eMMC) you can disable it by editing +<code>/boot/uEnv.txt</code></p> +</div> +<div class="paragraph"> +<p>Open <code>/boot/uEnv.txt</code> and scroll down aways until you see:</p> +</div> +<div class="listingblock"> +<div class="title">/boot/uEnv.txt</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="bash">###Disable auto loading of virtual capes (emmc/video/wireless/adc) +#disable_uboot_overlay_emmc=1 +disable_uboot_overlay_video=1 +#disable_uboot_overlay_audio=1</code></pre> +</div> +</div> +<div class="paragraph"> +<p>Uncomment the lines that correspond to the devices you want to disable and +free up their pins.</p> +</div> +<div class="admonitionblock tip"> +<table> +<tr> +<td class="icon"> +<div class="title">Tip</div> +</td> +<td class="content"> +<div class="paragraph"> +<p><a href="https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP8HeaderTable.pdf">P8 Header Table</a> +shows what pins are allocated for what.</p> +</div> +</td> +</tr> +</table> +</div> +<div class="paragraph"> +<p>Save the file and reboot. You now have access to the <code>P8</code> pins.</p> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_accessing_gpio"><a class="link" href="#_accessing_gpio">1.2. Accessing gpio</a></h3> +<div class="sect3"> +<h4 id="_problem_2"><a class="link" href="#_problem_2">Problem</a></h4> +<div class="paragraph"> +<p>I’ve used up all the GPIO in <code>__R30</code>, where can I get more?</p> +</div> +</div> +<div class="sect3"> +<h4 id="_solution_2"><a class="link" href="#_solution_2">Solution</a></h4> +<div class="paragraph"> +<p>So far we have focused on using PRU 0. +<a href="../05blocks/blocks.html#blocks_mapping_bits">Mapping bit positions to pin names +PRU</a> shows +that PRU 0 can access ten GPIO pins on the BeagleBone Black. If you use +PRU 1 you can get to an additional 14 pins (if they aren’t in use for other things.)</p> +</div> +<div class="paragraph"> +<p>What if you need even more GPIO pins? You can access <em>any</em> GPIO pin by going +through the <strong>O</strong>pen-<strong>C</strong>ore <strong>P</strong>rotocol (OCP) port.</p> +</div> +<div class="paragraph"> +<div class="title">PRU Integration</div> +<p><span class="image"><img src="figures/pruIntegration.png" alt="PRU Integration"></span></p> +</div> +<div class="paragraph"> +<p>The figure above shows we’ve been using the <em>Enhanced GPIO</em> interface when using +<code>__R30</code>, but it also shows you can use the OCP. You get access to many more +GPIO pins, but it’s a slower access.</p> +</div> +<div class="listingblock"> +<div class="title">gpio.pru0.c</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="c"><table class="CodeRay"><tr> + <td class="line-numbers"><pre>1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +</pre></td> + <td class="code"><pre><span class="comment">// This code accesses GPIO without using R30 and R31</span> +<span class="preprocessor">#include</span> <span class="include"><stdint.h></span> +<span class="preprocessor">#include</span> <span class="include"><pru_cfg.h></span> +<span class="preprocessor">#include</span> <span class="include">"resource_table_empty.h"</span> +<span class="preprocessor">#include</span> <span class="include">"prugpio.h"</span> + +<span class="preprocessor">#define</span> P9_11 (<span class="hex">0x1</span><<<span class="integer">30</span>) <span class="comment">// Bit position tied to P9_11 on Black</span> +<span class="preprocessor">#define</span> P2_05 (<span class="hex">0x1</span><<<span class="integer">30</span>) <span class="comment">// Bit position tied to P2_05 on Pocket</span> + +<span class="directive">volatile</span> <span class="directive">register</span> uint32_t __R30; +<span class="directive">volatile</span> <span class="directive">register</span> uint32_t __R31; + +<span class="directive">void</span> main(<span class="directive">void</span>) +{ + uint32_t *gpio0 = (uint32_t *)GPIO0; + + <span class="keyword">while</span>(<span class="integer">1</span>) { + gpio0[GPIO_SETDATAOUT] = P9_11; + __delay_cycles(<span class="integer">100000000</span>); + gpio0[GPIO_CLEARDATAOUT] = P9_11; + __delay_cycles(<span class="integer">100000000</span>); + } +}</pre></td> +</tr></table></code></pre> +</div> +</div> +<div class="paragraph"> +<p>This code will toggle <code>P9_11</code> on and off. Here’s the setup file.</p> +</div> +<div class="listingblock"> +<div class="title">setup.sh</div> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="bash"><table class="CodeRay"><tr> + <td class="line-numbers"><pre>1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +</pre></td> + <td class="code"><pre>#!/bin/bash + +export TARGET=gpio.pru0 +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_11" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P2_05" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin gpio + config-pin -q $pin +done</pre></td> +</tr></table></code></pre> +</div> +</div> +<div class="paragraph"> +<p>Notice in the code <code>config-pin</code> set <code>P9_11</code> to <code>gpio</code>, not <code>pruout</code>. This is because +are are using the OCP interface to the pin, not the usual PRU interface.</p> +</div> +<div class="paragraph"> +<p>Set your exports and make.</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre class="CodeRay highlight"><code data-lang="bash">bone$ <strong>source setup.sh</strong> +TARGET=gpio.pru0 +... +bone$ <strong>make</strong> +/var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=gpio.pru0 +- Stopping PRU 0 +- copying firmware file /tmp/cloud9-examples/gpio.pru0.out to /lib/firmware/am335x-pru0-fw +write_init_pins.sh +- Starting PRU 0 +MODEL = TI_AM335x_BeagleBone_Black +PROC = pru +PRUN = 0 +PRU_DIR = /sys/class/remoteproc/remoteproc1</code></pre> +</div> +</div> +</div> +<div class="sect3"> +<h4 id="_discussion"><a class="link" href="#_discussion">Discussion</a></h4> +<div class="paragraph"> +<p>When you run the code you see <code>P9_11</code> toggling on and off. Let’s go through +the code line-by-line to see what’s happening.</p> +</div> +<table class="tableblock frame-all grid-all stretch"> +<caption class="title">Table 1. gpio.pru0.c line-by-line</caption> +<colgroup> +<col style="width: 10%;"> +<col style="width: 90%;"> +</colgroup> +<thead> +<tr> +<th class="tableblock halign-left valign-top">Line</th> +<th class="tableblock halign-left valign-top">Explanation</th> +</tr> +</thead> +<tbody> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">2-5</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Standard includes</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">The AM335x has four 32-bit GPIO ports. Lines 55-58 of <code>prugpio.h</code> define the addresses +for each of the ports. You can find these in Table 2-2 page 180 of the +<a href="https://www.ti.com/lit/ug/spruh73p/spruh73p.pdf">AM335x Technical Reference Manual</a>. +Look up <code>P9_11</code> in the <a href="https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP9HeaderTable.pdf">P9 Header Table</a>. +Under the <em>Mode7</em> column you see <code>gpio0[30]</code>. This means <code>P9_11</code> is bit 30 +on GPIO port 0. Therefore we will use <code>GPIO0</code> in this code.</p> +<p class="tableblock">You can also run +<code>gpioinfo</code> and look for P9_11.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Line 103 of <code>prugpio.h</code> defines the address offset from <code>GIO0</code> that will +allow us to <em>clear</em> +any (or all) bits in GPIO port 0. Other architectures require you to read a port, +then change some bit, then write it out again, three steps. Here we can do the same by writing to one location, just one step.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Line 104 of <code>prugpio.h</code> is like above, but for <em>setting</em> bits.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Using this offset of line 105 of <code>prugpio.h</code> lets us just read the bits +without changing them.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">7,8</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">This shifts <code>0x1</code> to the 30<sup>th</sup> bit position, which is the one corresponding +to <code>P9_11</code>.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">15</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Here we initialize <code>gpio0</code> to point to the start of GPIO port 0’s control +registers.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">18</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock"><code>gpio0[GPIO_SETDATAOUT]</code> refers to the <code>SETDATAOUT</code> register of port 0. +Writing to this register turns on the bits where 1’s are written, +but leaves alone the bits where 0’s are.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">19</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">Wait 100,000,000 cycles, which is 0.5 seconds.</p></td> +</tr> +<tr> +<td class="tableblock halign-left valign-top"><p class="tableblock">20</p></td> +<td class="tableblock halign-left valign-top"><p class="tableblock">This is line 18, but the output bit is set to 0 where 1’s are written.</p></td> +</tr> +</tbody> +</table> +<div class="sect4"> +<h5 id="_how_fast_can_it_go"><a class="link" href="#_how_fast_can_it_go">How fast can it go?</a></h5> +<div class="paragraph"> +<p>This approach to GPIO goes through the slower OCP interface. If you set <code>__delay_cycles(0)</code> you can see how fast it is.</p> +</div> +<div class="paragraph"> +<div class="title">gpio.pru0.c with __delay_cycles(0)</div> +<p><span class="image"><img src="figures/gpio0delay.png" alt="gpio.pru0.c with __delay_cycles(0)"></span></p> +</div> +<div class="paragraph"> +<p>The period is 80ns which is 12.MHz. That’s about one forth the speed of the +<code>__R30</code> method, but still not bad.</p> +</div> +<div class="paragraph"> +<p>If you are using an oscilloscope, look closely and you’ll see the following.</p> +</div> +<div class="paragraph"> +<div class="title">PWM with jitter</div> +<p><span class="image"><img src="figures/jitter.png" alt="PWM with jitter"></span></p> +</div> +<div class="paragraph"> +<p>The PRU is still as solid as before in it’s timing, but now it’s going through +the OCP interface. This interface is shared with other parts of the system, +therefore the sometimes the PRU must wait for the other parts to finish. +When this happens the pulse width is a bit longer than usual thus adding +jitter to the output.</p> +</div> +<div class="paragraph"> +<p>For many applications a few nanoseconds of jitter is unimportant and this +GPIO interface can be used. If your application needs better timing, +use the <code>__R30</code> interface.</p> +</div> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="io_uio"><a class="link" href="#io_uio">1.3. Configuring for UIO Instead of RemoteProc</a></h3> +<div class="sect3"> +<h4 id="_problem_3"><a class="link" href="#_problem_3">Problem</a></h4> +<div class="paragraph"> +<p>You have some legacy PRU code that uses UIO instead of remoteproc and +you want to switch to UIO.</p> +</div> +</div> +<div class="sect3"> +<h4 id="_solution_3"><a class="link" href="#_solution_3">Solution</a></h4> +<div class="paragraph"> +<p>Edit <code>/boot/uEnt.txt</code> and search for <code>uio</code>. I find</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre>###pru_uio (4.4.x-ti, 4.9.x-ti, 4.14.x-ti & mainline/bone kernel) +uboot_overlay_pru=/lib/firmware/AM335X-PRU-UIO-00A0.dtbo</pre> +</div> +</div> +<div class="paragraph"> +<p>Uncomment the <code>uboot</code> line. Look for other lines with +<code>uboot_overlay_pru=</code> and be sure they are commented out.</p> +</div> +<div class="paragraph"> +<p>Reboot your Bone.</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre>bone$ <strong>sudo reboot</strong></pre> +</div> +</div> +<div class="paragraph"> +<p>Check that UIO is running.</p> +</div> +<div class="listingblock"> +<div class="content"> +<pre>bone$ <strong>lsmod | grep uio</strong> +uio_pruss 16384 0 +uio_pdrv_genirq 16384 0 +uio 20480 2 uio_pruss,uio_pdrv_genirq</pre> +</div> +</div> +<div class="paragraph"> +<p>You are now ready to run the legacy PRU code.</p> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_converting_pasm_assembly_code_to_clpru"><a class="link" href="#_converting_pasm_assembly_code_to_clpru">1.4. Converting pasm Assembly Code to clpru</a></h3> +<div class="sect3"> +<h4 id="_problem_4"><a class="link" href="#_problem_4">Problem</a></h4> +<div class="paragraph"> +<p>You have some legacy assembly code written in pasm and it won’t assemble +with clpru.</p> +</div> +</div> +<div class="sect3"> +<h4 id="_solution_4"><a class="link" href="#_solution_4">Solution</a></h4> +<div class="paragraph"> +<p>Generally there is a simple mapping from pasm to clpru. +<a href="http://processors.wiki.ti.com/index.php/PRU_Assembly_Instructions#pasm_vs._clpru">pasm vs. clpru</a> +notes what needs to be changed. I have a less complete version on my +<a href="https://elinux.org/EBC_Exercise_30_PRU_porting_pasm_to_clpru">eLinux.org site</a>.</p> +</div> +</div> +<div class="sect3"> +<h4 id="_discussion_2"><a class="link" href="#_discussion_2">Discussion</a></h4> +<div class="paragraph"> +<p>The clpru assembly can be found in <a href="http://www.ti.com/lit/ug/spruhv6a/spruhv6a.pdf">PRU Assembly Language Tools</a>.</p> +</div> +</div> +</div> +</div> +</div> +</div> +<div id="footer"> +<div id="footer-text"> +Last updated 2021-08-04 14:38:24 -0400 +</div> +</div> +</body> +</html> \ No newline at end of file diff --git a/pru-cookbook/06io/io.rst b/pru-cookbook/06io/io.rst new file mode 100644 index 0000000000000000000000000000000000000000..3548d5e0a4330f10a7a06d4f94856bac5ba1a89c --- /dev/null +++ b/pru-cookbook/06io/io.rst @@ -0,0 +1,271 @@ +.. _pru-cookbook-io: + +Accessing More I/O +#################### + +So far the examples have shown how to access the GPIO pins on the BeagleBone Black's +``P9`` header and through the ``pass:[__]R30`` register. Below shows how more GPIO pins +can be accessed. + +The following are resources used in this chapter. + +Resources +~~~~~~~~~~ + +* `P8 Header Table <https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP8HeaderTable.pdf>`_ +* `P9 Header Table <https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP9HeaderTable.pdf>`_ +* `AM572x Technical Reference Manual<http://www.ti.com/lit/pdf/spruhz6l>`_ (AI) +* `AM335x Technical Reference Manual <http://www.ti.com/lit/pdf/spruh73>`_ (All others) +* `PRU Assembly Language Tools<http://www.ti.com/lit/ug/spruhv6a/spruhv6a.pdf>`_ + +Editing /boot/uEnv.txt to Access the P8 Header on the Black +============================================================ + +Problem +-------- + +When I try to configure some pins on the `P8` header of the Black I get an error. + +config-pin +~~~~~~~~~~~ + +.. code-block:: bash + :linenos: + + bone$ *config-pin P8_28 pruout* + ERROR: open() for /sys/devices/platform/ocp/ocp:P8_28_pinmux/state failed, No such file or directory + +Solution +-------- + +On the images for the BeagleBone Black, the HDMI display driver is enabled by default +and uses many of the ``P8`` pins. If you are not using HDMI video (or the HDI audio, +or even the eMMC) you can disable it by editing ``/boot/uEnv.txt`` + +Open ``/boot/uEnv.txt`` and scroll down aways until you see: + +/boot/uEnv.txt +~~~~~~~~~~~~~~~~ + +.. code-block:: bash + :linenos: + + ###Disable auto loading of virtual capes (emmc/video/wireless/adc) + #disable_uboot_overlay_emmc=1 + disable_uboot_overlay_video=1 + #disable_uboot_overlay_audio=1 + +Uncomment the lines that correspond to the devices you want to disable and free up their pins. + +.. tip:: + + `P8 Header Table <https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP8HeaderTable.pdf>`_ + shows what pins are allocated for what. + +Save the file and reboot. You now have access to the ``P8`` pins. + +Accessing gpio +================ + +Problem +-------- + +I've used up all the GPIO in ``pass:[__]R30``, where can I get more? + +Solution +-------- + +So far we have focused on using PRU 0. +:ref:`../05blocks/blocks.html#blocks_mapping_bits,Mapping bit positions to pin names PRU` shows +that PRU 0 can access ten GPIO pins on the BeagleBone Black. If you use +PRU 1 you can get to an additional 14 pins (if they aren't in use for other things.) + +What if you need even more GPIO pins? You can access **any** GPIO pin by going +through the **O**pen-**C**ore **P**rotocol (OCP) port. + +PRU Integration +~~~~~~~~~~~~~~~~~ + +.. figure:: figures/pruIntegration.png + :align: center + :alt: PRU Integration + +The figure above shows we've been using the _Enhanced **GPIO** interface when using +``pass:[__]R30``, but it also shows you can use the OCP. You get access to many more +GPIO pins, but it's a slower access. + +gpio.pru0.c +~~~~~~~~~~~~ + +:download:`gpio.pru0.c <code/gpio.pru0.c>` + +This code will toggle ``P9_11`` on and off. Here's the setup file. + +setup.sh +~~~~~~~~~ + +:download:`setup.sh <code/setup.sh>` + +Notice in the code ``config-pin`` set ``P9_11`` to ``gpio``, not ``pruout``. This is because +are are using the OCP interface to the pin, not the usual PRU interface. + +Set your exports and make. + +.. code-block:: bash + :linenos: + + bone$ *source setup.sh* + TARGET=gpio.pru0 + ... + bone$ *make* + /var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=gpio.pru0 + - Stopping PRU 0 + - copying firmware file /tmp/cloud9-examples/gpio.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /sys/class/remoteproc/remoteproc1 + +Discussion +----------- + +When you run the code you see ``P9_11`` toggling on and off. Let's go through +the code line-by-line to see what's happening. + +gpio.pru0.c line-by-line +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |Line | Explanation | + +=======+===============================================================================================================================================+ + |2-5 | Standard includes | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |5 | The AM335x has four 32-bit GPIO ports. Lines 55-58 of `prugpio.h` define the addresses | + | | for each of the ports. You can find these in Table 2-2 page 180 of the | + | | https://www.ti.com/lit/ug/spruh73p/spruh73p.pdf[AM335x Technical Reference Manual]. | + | | Look up `P9_11` in the https://github.com/derekmolloy/exploringBB/blob/master/chp06/docs/BeagleboneBlackP9HeaderTable.pdf[P9 Header Table]. | + | | Under the _Mode7_ column you see `gpio0[30]`. This means `P9_11` is bit 30 | + | | on GPIO port 0. Therefore we will use `GPIO0` in this code. You can also run ``gpioinfo`` and look for P9_11. | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |5 | Line 103 of `prugpio.h` defines the address offset from `GIO0` that will allow us to _clear_ any (or all) bits in GPIO port 0. | + | | Other architectures require you to read a port, then change some bit, then write it out again, three steps. Here we can do | + | | the same by writing to one location, just one step. | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |5 |Line 104 of `prugpio.h` is like above, but for _setting_ bits. | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |5 |Using this offset of line 105 of `prugpio.h` lets us just read the bits without changing them. | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |7,8 |This shifts `0x1` to the 30^th^ bit position, which is the one corresponding to `P9_11`. | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |15 |Here we initialize `gpio0` to point to the start of GPIO port 0's control registers. | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |18 |`gpio0[GPIO_SETDATAOUT]` refers to the `SETDATAOUT` register of port 0. Writing to this register turns on the bits | + | | where 1's are written, but leaves alone the bits where 0's are. | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |19 |Wait 100,000,000 cycles, which is 0.5 seconds. | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + |20 |This is line 18, but the output bit is set to 0 where 1's are written. | + +-------+-----------------------------------------------------------------------------------------------------------------------------------------------+ + +How fast can it go? +~~~~~~~~~~~~~~~~~~~~ + +This approach to GPIO goes through the slower OCP interface. If you set +``pass:[__]delay_cycles(0)`` you can see how fast it is. + +gpio.pru0.c with pass:[__]delay_cycles(0) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/gpio0delay.png + :align: center + :alt: gpio.pru0.c with pass:[__]delay_cycles(0) + +The period is 80ns which is 12.MHz. That's about one forth the speed of the +``pass:[__]R30`` method, but still not bad. + +If you are using an oscilloscope, look closely and you'll see the following. + +PWM with jitter +~~~~~~~~~~~~~~~~ + +.. figure:: figures/jitter.png + :align: center + :alt: PWM with jitter + +The PRU is still as solid as before in it's timing, but now it's going through +the OCP interface. This interface is shared with other parts of the system, +therefore the sometimes the PRU must wait for the other parts to finish. +When this happens the pulse width is a bit longer than usual thus adding +jitter to the output. + +For many applications a few nanoseconds of jitter is unimportant and this +GPIO interface can be used. If your application needs better timing, +use the ``pass:[__]R30`` interface. + + +.. _io_uio: + +Configuring for UIO Instead of RemoteProc +======================================== + +Problem +-------- + +You have some legacy PRU code that uses UIO instead of remoteproc and +you want to switch to UIO. + +Solution +-------- + +Edit ``/boot/uEnt.txt`` and search for ``uio``. I find + +.. code-block:: bash + + ###pru_uio (4.4.x-ti, 4.9.x-ti, 4.14.x-ti & mainline/bone kernel) + uboot_overlay_pru=/lib/firmware/AM335X-PRU-UIO-00A0.dtbo + +Uncomment the ``uboot`` line. Look for other lines with +``uboot_overlay_pru=`` and be sure they are commented out. + +Reboot your Bone. + +.. code-block:: bash + + bone$ sudo reboot + +Check that UIO is running. + +.. code-block:: bash + + bone$ lsmod | grep uio + uio_pruss 16384 0 + uio_pdrv_genirq 16384 0 + uio 20480 2 uio_pruss,uio_pdrv_genirq + +You are now ready to run the legacy PRU code. + +Converting pasm Assembly Code to clpru +======================================== + +Problem +-------- + +You have some legacy assembly code written in pasm and it won't assemble with clpru. + +Solution +-------- + +Generally there is a simple mapping from pasm to clpru. +`pasm vs. clpru <http://processors.wiki.ti.com/index.php/PRU_Assembly_Instructions#pasm_vs._clpru>`_ +notes what needs to be changed. I have a less complete version on my +`eLinux.org site <https://elinux.org/EBC_Exercise_30_PRU_porting_pasm_to_clpru>`_. + +Discussion +-------- + +The clpru assembly can be found in +`PRU Assembly Language Tools <http://www.ti.com/lit/ug/spruhv6a/spruhv6a.pdf>`_. diff --git a/pru-cookbook/07more/code/Makefile b/pru-cookbook/07more/code/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a7557fdaa22988d89cec879477ded78522d7116f --- /dev/null +++ b/pru-cookbook/07more/code/Makefile @@ -0,0 +1 @@ +include /var/lib/cloud9/common/Makefile diff --git a/pru-cookbook/07more/code/copyright.c b/pru-cookbook/07more/code/copyright.c new file mode 100644 index 0000000000000000000000000000000000000000..63b6a419e4ee3a2767de3fcec0c29e74e3754700 --- /dev/null +++ b/pru-cookbook/07more/code/copyright.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + \ No newline at end of file diff --git a/pru-cookbook/07more/code/cycle.pru0.c b/pru-cookbook/07more/code/cycle.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..73055d9f0662483f6e9cc03ef266b670f571e1f0 --- /dev/null +++ b/pru-cookbook/07more/code/cycle.pru0.c @@ -0,0 +1,32 @@ +// Access the CYCLE and STALL registers +#include <stdint.h> +#include <pru_cfg.h> +#include <pru_ctrl.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t gpio = P9_31; // Select which pin to toggle.; + + // These will be kept in registers and never witten to DRAM + uint32_t cycle, stall; + + // Clear SYSCFG[STANDBY_INIT] to enable OCP master port + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + PRU0_CTRL.CTRL_bit.CTR_EN = 1; // Enable cycle counter + + __R30 |= gpio; // Set the GPIO pin to 1 + // Reset cycle counter, cycle is on the right side to force the compiler + // to put it in it's own register + PRU0_CTRL.CYCLE = cycle; + __R30 &= ~gpio; // Clear the GPIO pin + cycle = PRU0_CTRL.CYCLE; // Read cycle and store in a register + stall = PRU0_CTRL.STALL; // Ditto for stall + + __halt(); +} diff --git a/pru-cookbook/07more/code/cycle.pru0.lst b/pru-cookbook/07more/code/cycle.pru0.lst new file mode 100644 index 0000000000000000000000000000000000000000..7f013a717a25159015a03849db88cf37db123d08 --- /dev/null +++ b/pru-cookbook/07more/code/cycle.pru0.lst @@ -0,0 +1,3082 @@ +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 1 + + 1;****************************************************************************** + 2;* PRU C/C++ Codegen Unix v2.1.5 * + 3;* Date/Time created: Fri Jun 5 14:14:07 2020 * + 4;****************************************************************************** + 5 .compiler_opts --abi=eabi --endian=little --hll_source=on --object_format=elf --silicon_versio + 6 + 7$C$DW$CU .dwtag DW_TAG_compile_unit + 8 .dwattr $C$DW$CU, DW_AT_name("cycle.pru0.c") + 9 .dwattr $C$DW$CU, DW_AT_producer("TI PRU C/C++ Codegen Unix v2.1.5 Copyright (c) 2012-2017 Tex + 10 .dwattr $C$DW$CU, DW_AT_TI_version(0x01) + 11 .dwattr $C$DW$CU, DW_AT_comp_dir("/home/debian/PRUCookbook/docs/07more/code") + 12 .global __PRU_CREG_PRU_CFG + 13 + 14$C$DW$1 .dwtag DW_TAG_subprogram, DW_AT_name("__halt") + 15 .dwattr $C$DW$1, DW_AT_TI_symbol_name("__halt") + 16 .dwattr $C$DW$1, DW_AT_declaration + 17 .dwattr $C$DW$1, DW_AT_external + 18 .weak ||CT_CFG|| + 19 00000000 ||CT_CFG||: .usect ".creg.PRU_CFG.noload.near",68,1 + 20$C$DW$2 .dwtag DW_TAG_variable, DW_AT_name("CT_CFG") + 21 .dwattr $C$DW$2, DW_AT_TI_symbol_name("CT_CFG") + 22 .dwattr $C$DW$2, DW_AT_location[DW_OP_addr ||CT_CFG||] + 23 .dwattr $C$DW$2, DW_AT_type(*$C$DW$T$98) + 24 .dwattr $C$DW$2, DW_AT_external + 25 .dwattr $C$DW$2, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru_ + 26 .dwattr $C$DW$2, DW_AT_decl_line(0xf2) + 27 .dwattr $C$DW$2, DW_AT_decl_column(0x17) + 28 .global ||pru_remoteproc_ResourceTable|| + 29 00000000 .sect ".resource_table:retain", RW + 30 .retain + 31 .align 1 + 32 .elfsym ||pru_remoteproc_ResourceTable||,SYM_SIZE(20) + 33 00000000 ||pru_remoteproc_ResourceTable||: + 34 00000000 00000000000001 .bits 1,32 ; pru_remoteproc_ResourceTable.base.ver @ 0 + 35 00000004 00000000000000 .bits 0,32 ; pru_remoteproc_ResourceTable.base.num @ 32 + 36 00000008 00000000000000 .bits 0,32 ; pru_remoteproc_ResourceTable.base.reserved[0] @ 64 + 37 0000000c 00000000000000 .bits 0,32 ; pru_remoteproc_ResourceTable.base.reserved[1] @ 96 + 38 00000010 00000000000000 .bits 0,32 ; pru_remoteproc_ResourceTable.offset[0] @ 128 + 39 + 40$C$DW$3 .dwtag DW_TAG_variable, DW_AT_name("pru_remoteproc_ResourceTable") + 41 .dwattr $C$DW$3, DW_AT_TI_symbol_name("pru_remoteproc_ResourceTable") + 42 .dwattr $C$DW$3, DW_AT_location[DW_OP_addr ||pru_remoteproc_ResourceTable||] + 43 .dwattr $C$DW$3, DW_AT_type(*$C$DW$T$92) + 44 .dwattr $C$DW$3, DW_AT_external + 45 .dwattr $C$DW$3, DW_AT_decl_file("/var/lib/cloud9/common/resource_table_empty.h") + 46 .dwattr $C$DW$3, DW_AT_decl_line(0x1f) + 47 .dwattr $C$DW$3, DW_AT_decl_column(0x1a) + 48; optpru /tmp/TI18yQKu8QO /tmp/TI18y6Ruqzt + 49; acpiapru -@/tmp/TI18yH9tQJL + 50 00000000 .sect ".text:main" + 51 .clink + 52 .global ||main|| + 53 + 54$C$DW$4 .dwtag DW_TAG_subprogram, DW_AT_name("main") + 55 .dwattr $C$DW$4, DW_AT_low_pc(||main||) +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 2 + + 56 .dwattr $C$DW$4, DW_AT_high_pc(0x00) + 57 .dwattr $C$DW$4, DW_AT_TI_symbol_name("main") + 58 .dwattr $C$DW$4, DW_AT_external + 59 .dwattr $C$DW$4, DW_AT_TI_begin_file("cycle.pru0.c") + 60 .dwattr $C$DW$4, DW_AT_TI_begin_line(0x0d) + 61 .dwattr $C$DW$4, DW_AT_TI_begin_column(0x06) + 62 .dwattr $C$DW$4, DW_AT_decl_file("cycle.pru0.c") + 63 .dwattr $C$DW$4, DW_AT_decl_line(0x0d) + 64 .dwattr $C$DW$4, DW_AT_decl_column(0x06) + 65 .dwattr $C$DW$4, DW_AT_TI_max_frame_size(0x00) + 66 .dwpsn file "cycle.pru0.c",line 14,column 1,is_stmt,address ||main||,isa 0 + 67 + 68 .dwfde $C$DW$CIE, ||main|| + 69;---------------------------------------------------------------------- + 70; 13 | void main(void) + 71; 15 | uint32_t gpio = P9_31; // Select which pin to toggle.; + 72; 17 | // These will be kept in registers and never witten to DRAM + 73; 18 | uint32_t cycle, stall; + 74; 20 | // Clear SYSCFG[STANDBY_INIT] to enable OCP master port + 75;---------------------------------------------------------------------- + 76 + 77;*************************************************************** + 78;* FNAME: main FR SIZE: 0 * + 79;* * + 80;* FUNCTION ENVIRONMENT * + 81;* * + 82;* FUNCTION PROPERTIES * + 83;* 0 Auto, 0 SOE * + 84;*************************************************************** + 85 + 86||main||: + 87;* --------------------------------------------------------------------------* + 88;* r0_0 assigned to $O$C1 + 89;* r14_0 assigned to cycle + 90$C$DW$5 .dwtag DW_TAG_variable, DW_AT_name("cycle") + 91 .dwattr $C$DW$5, DW_AT_TI_symbol_name("cycle") + 92 .dwattr $C$DW$5, DW_AT_type(*$C$DW$T$32) + 93 .dwattr $C$DW$5, DW_AT_location[DW_OP_regx 0x38] + 94 .dwcfi cfa_offset, 0 + 95 .dwpsn file "cycle.pru0.c",line 21,column 2,is_stmt,isa 0 + 96;---------------------------------------------------------------------- + 97; 21 | CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + 98;---------------------------------------------------------------------- + 99 00000000 00000091042080! LBCO &r0, __PRU_CREG_PRU_CFG, $CSBREL(||CT_CFG||+4), 4 ; [ALU_PRU] |21| CT_CFG + 100 00000004 0000001D04E0E0 CLR r0, r0, 0x00000004 ; [ALU_PRU] |21| + 101 00000008 00000081042080! SBCO &r0, __PRU_CREG_PRU_CFG, $CSBREL(||CT_CFG||+4), 4 ; [ALU_PRU] |21| CT_CFG + 102 .dwpsn file "cycle.pru0.c",line 23,column 2,is_stmt,isa 0 + 103;---------------------------------------------------------------------- + 104; 23 | PRU0_CTRL.CTRL_bit.CTR_EN = 1; // Enable cycle counter + 105;---------------------------------------------------------------------- + 106 0000000c 200080240002C0 LDI32 r0, 0x00022000 ; [ALU_PRU] |23| $O$C1 + 107 00000014 000000F1002081 LBBO &r1, r0, 0, 4 ; [ALU_PRU] |23| + 108 00000018 0000001F03E1E1 SET r1, r1, 0x00000003 ; [ALU_PRU] |23| + 109 0000001c 000000E1002081 SBBO &r1, r0, 0, 4 ; [ALU_PRU] |23| + 110 .dwpsn file "cycle.pru0.c",line 25,column 2,is_stmt,isa 0 +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 3 + + 111;---------------------------------------------------------------------- + 112; 25 | __R30 |= gpio; // Set the GPIO pin to 1 + 113; 26 | // Reset cycle counter, cycle is on the right side to force the compile + 114; | r + 115; 27 | // to put it in it's own register + 116;---------------------------------------------------------------------- + 117 00000020 0000001F00FEFE SET r30, r30, 0x00000000 ; [ALU_PRU] |25| + 118 .dwpsn file "cycle.pru0.c",line 28,column 2,is_stmt,isa 0 + 119;---------------------------------------------------------------------- + 120; 28 | PRU0_CTRL.CYCLE = cycle; + 121;---------------------------------------------------------------------- + 122 00000024 000000E10C208E SBBO &r14, r0, 12, 4 ; [ALU_PRU] |28| $O$C1,cycle + 123 .dwpsn file "cycle.pru0.c",line 29,column 2,is_stmt,isa 0 + 124;---------------------------------------------------------------------- + 125; 29 | __R30 &= ~gpio; // Clear the GPIO pin + 126;---------------------------------------------------------------------- + 127 00000028 0000001D00FEFE CLR r30, r30, 0x00000000 ; [ALU_PRU] |29| + 128 .dwpsn file "cycle.pru0.c",line 30,column 2,is_stmt,isa 0 + 129;---------------------------------------------------------------------- + 130; 30 | cycle = PRU0_CTRL.CYCLE; // Read cycle and store in a register + 131;---------------------------------------------------------------------- + 132 0000002c 000000F10C2081 LBBO &r1, r0, 12, 4 ; [ALU_PRU] |30| $O$C1 + 133 .dwpsn file "cycle.pru0.c",line 31,column 2,is_stmt,isa 0 + 134;---------------------------------------------------------------------- + 135; 31 | stall = PRU0_CTRL.STALL; // Ditto for stall + 136;---------------------------------------------------------------------- + 137 00000030 000000F1102080 LBBO &r0, r0, 16, 4 ; [ALU_PRU] |31| $O$C1 + 138 .dwpsn file "cycle.pru0.c",line 33,column 2,is_stmt,isa 0 + 139;---------------------------------------------------------------------- + 140; 33 | __halt(); + 141;---------------------------------------------------------------------- + 142 00000034 0000002A000000 HALT ; [ALU_PRU] |33| + 143$C$DW$6 .dwtag DW_TAG_TI_branch + 144 .dwattr $C$DW$6, DW_AT_low_pc(0x00) + 145 .dwattr $C$DW$6, DW_AT_TI_return + 146 00000038 00000020C30000 JMP r3.w2 ; [ALU_PRU] + 147 .dwattr $C$DW$4, DW_AT_TI_end_file("cycle.pru0.c") + 148 .dwattr $C$DW$4, DW_AT_TI_end_line(0x22) + 149 .dwattr $C$DW$4, DW_AT_TI_end_column(0x01) + 150 .dwendentry + 151 .dwendtag $C$DW$4 + 152 + 153 + 154;****************************************************************************** + 155;* TYPE INFORMATION * + 156;****************************************************************************** + 157 + 158$C$DW$T$19 .dwtag DW_TAG_structure_type + 159 .dwattr $C$DW$T$19, DW_AT_byte_size(0x04) + 160$C$DW$7 .dwtag DW_TAG_member + 161 .dwattr $C$DW$7, DW_AT_type(*$C$DW$T$11) + 162 .dwattr $C$DW$7, DW_AT_name("REVID") + 163 .dwattr $C$DW$7, DW_AT_TI_symbol_name("REVID") + 164 .dwattr $C$DW$7, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x20) + 165 .dwattr $C$DW$7, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 4 + + 166 .dwattr $C$DW$7, DW_AT_accessibility(DW_ACCESS_public) + 167 .dwattr $C$DW$7, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru_ + 168 .dwattr $C$DW$7, DW_AT_decl_line(0x2d) + 169 .dwattr $C$DW$7, DW_AT_decl_column(0x0d) + 170 .dwendtag $C$DW$T$19 + 171 + 172 .dwattr $C$DW$T$19, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 173 .dwattr $C$DW$T$19, DW_AT_decl_line(0x2c) + 174 .dwattr $C$DW$T$19, DW_AT_decl_column(0x13) + 175$C$DW$T$48 .dwtag DW_TAG_volatile_type + 176 .dwattr $C$DW$T$48, DW_AT_type(*$C$DW$T$19) + 177 + 178$C$DW$T$20 .dwtag DW_TAG_structure_type + 179 .dwattr $C$DW$T$20, DW_AT_byte_size(0x04) + 180$C$DW$8 .dwtag DW_TAG_member + 181 .dwattr $C$DW$8, DW_AT_type(*$C$DW$T$11) + 182 .dwattr $C$DW$8, DW_AT_name("IDLE_MODE") + 183 .dwattr $C$DW$8, DW_AT_TI_symbol_name("IDLE_MODE") + 184 .dwattr $C$DW$8, DW_AT_bit_offset(0x1e), DW_AT_bit_size(0x02) + 185 .dwattr $C$DW$8, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 186 .dwattr $C$DW$8, DW_AT_accessibility(DW_ACCESS_public) + 187 .dwattr $C$DW$8, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru_ + 188 .dwattr $C$DW$8, DW_AT_decl_line(0x37) + 189 .dwattr $C$DW$8, DW_AT_decl_column(0x0d) + 190$C$DW$9 .dwtag DW_TAG_member + 191 .dwattr $C$DW$9, DW_AT_type(*$C$DW$T$11) + 192 .dwattr $C$DW$9, DW_AT_name("STANDBY_MODE") + 193 .dwattr $C$DW$9, DW_AT_TI_symbol_name("STANDBY_MODE") + 194 .dwattr $C$DW$9, DW_AT_bit_offset(0x1c), DW_AT_bit_size(0x02) + 195 .dwattr $C$DW$9, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 196 .dwattr $C$DW$9, DW_AT_accessibility(DW_ACCESS_public) + 197 .dwattr $C$DW$9, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru_ + 198 .dwattr $C$DW$9, DW_AT_decl_line(0x38) + 199 .dwattr $C$DW$9, DW_AT_decl_column(0x0d) + 200$C$DW$10 .dwtag DW_TAG_member + 201 .dwattr $C$DW$10, DW_AT_type(*$C$DW$T$11) + 202 .dwattr $C$DW$10, DW_AT_name("STANDBY_INIT") + 203 .dwattr $C$DW$10, DW_AT_TI_symbol_name("STANDBY_INIT") + 204 .dwattr $C$DW$10, DW_AT_bit_offset(0x1b), DW_AT_bit_size(0x01) + 205 .dwattr $C$DW$10, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 206 .dwattr $C$DW$10, DW_AT_accessibility(DW_ACCESS_public) + 207 .dwattr $C$DW$10, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 208 .dwattr $C$DW$10, DW_AT_decl_line(0x39) + 209 .dwattr $C$DW$10, DW_AT_decl_column(0x0d) + 210$C$DW$11 .dwtag DW_TAG_member + 211 .dwattr $C$DW$11, DW_AT_type(*$C$DW$T$11) + 212 .dwattr $C$DW$11, DW_AT_name("SUB_MWAIT") + 213 .dwattr $C$DW$11, DW_AT_TI_symbol_name("SUB_MWAIT") + 214 .dwattr $C$DW$11, DW_AT_bit_offset(0x1a), DW_AT_bit_size(0x01) + 215 .dwattr $C$DW$11, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 216 .dwattr $C$DW$11, DW_AT_accessibility(DW_ACCESS_public) + 217 .dwattr $C$DW$11, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 218 .dwattr $C$DW$11, DW_AT_decl_line(0x3a) + 219 .dwattr $C$DW$11, DW_AT_decl_column(0x0d) + 220$C$DW$12 .dwtag DW_TAG_member +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 5 + + 221 .dwattr $C$DW$12, DW_AT_type(*$C$DW$T$11) + 222 .dwattr $C$DW$12, DW_AT_name("rsvd6") + 223 .dwattr $C$DW$12, DW_AT_TI_symbol_name("rsvd6") + 224 .dwattr $C$DW$12, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x1a) + 225 .dwattr $C$DW$12, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 226 .dwattr $C$DW$12, DW_AT_accessibility(DW_ACCESS_public) + 227 .dwattr $C$DW$12, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 228 .dwattr $C$DW$12, DW_AT_decl_line(0x3b) + 229 .dwattr $C$DW$12, DW_AT_decl_column(0x0d) + 230 .dwendtag $C$DW$T$20 + 231 + 232 .dwattr $C$DW$T$20, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 233 .dwattr $C$DW$T$20, DW_AT_decl_line(0x36) + 234 .dwattr $C$DW$T$20, DW_AT_decl_column(0x13) + 235$C$DW$T$50 .dwtag DW_TAG_volatile_type + 236 .dwattr $C$DW$T$50, DW_AT_type(*$C$DW$T$20) + 237 + 238$C$DW$T$21 .dwtag DW_TAG_structure_type + 239 .dwattr $C$DW$T$21, DW_AT_byte_size(0x04) + 240$C$DW$13 .dwtag DW_TAG_member + 241 .dwattr $C$DW$13, DW_AT_type(*$C$DW$T$11) + 242 .dwattr $C$DW$13, DW_AT_name("PRU0_GPI_MODE") + 243 .dwattr $C$DW$13, DW_AT_TI_symbol_name("PRU0_GPI_MODE") + 244 .dwattr $C$DW$13, DW_AT_bit_offset(0x1e), DW_AT_bit_size(0x02) + 245 .dwattr $C$DW$13, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 246 .dwattr $C$DW$13, DW_AT_accessibility(DW_ACCESS_public) + 247 .dwattr $C$DW$13, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 248 .dwattr $C$DW$13, DW_AT_decl_line(0x45) + 249 .dwattr $C$DW$13, DW_AT_decl_column(0x0d) + 250$C$DW$14 .dwtag DW_TAG_member + 251 .dwattr $C$DW$14, DW_AT_type(*$C$DW$T$11) + 252 .dwattr $C$DW$14, DW_AT_name("PRU0_GPI_CLK_MODE") + 253 .dwattr $C$DW$14, DW_AT_TI_symbol_name("PRU0_GPI_CLK_MODE") + 254 .dwattr $C$DW$14, DW_AT_bit_offset(0x1d), DW_AT_bit_size(0x01) + 255 .dwattr $C$DW$14, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 256 .dwattr $C$DW$14, DW_AT_accessibility(DW_ACCESS_public) + 257 .dwattr $C$DW$14, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 258 .dwattr $C$DW$14, DW_AT_decl_line(0x46) + 259 .dwattr $C$DW$14, DW_AT_decl_column(0x0d) + 260$C$DW$15 .dwtag DW_TAG_member + 261 .dwattr $C$DW$15, DW_AT_type(*$C$DW$T$11) + 262 .dwattr $C$DW$15, DW_AT_name("PRU0_GPI_DIV0") + 263 .dwattr $C$DW$15, DW_AT_TI_symbol_name("PRU0_GPI_DIV0") + 264 .dwattr $C$DW$15, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x05) + 265 .dwattr $C$DW$15, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 266 .dwattr $C$DW$15, DW_AT_accessibility(DW_ACCESS_public) + 267 .dwattr $C$DW$15, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 268 .dwattr $C$DW$15, DW_AT_decl_line(0x47) + 269 .dwattr $C$DW$15, DW_AT_decl_column(0x0d) + 270$C$DW$16 .dwtag DW_TAG_member + 271 .dwattr $C$DW$16, DW_AT_type(*$C$DW$T$11) + 272 .dwattr $C$DW$16, DW_AT_name("PRU0_GPI_DIV1") + 273 .dwattr $C$DW$16, DW_AT_TI_symbol_name("PRU0_GPI_DIV1") + 274 .dwattr $C$DW$16, DW_AT_bit_offset(0x13), DW_AT_bit_size(0x05) + 275 .dwattr $C$DW$16, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 6 + + 276 .dwattr $C$DW$16, DW_AT_accessibility(DW_ACCESS_public) + 277 .dwattr $C$DW$16, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 278 .dwattr $C$DW$16, DW_AT_decl_line(0x48) + 279 .dwattr $C$DW$16, DW_AT_decl_column(0x0d) + 280$C$DW$17 .dwtag DW_TAG_member + 281 .dwattr $C$DW$17, DW_AT_type(*$C$DW$T$11) + 282 .dwattr $C$DW$17, DW_AT_name("PRU0_GPI_SB") + 283 .dwattr $C$DW$17, DW_AT_TI_symbol_name("PRU0_GPI_SB") + 284 .dwattr $C$DW$17, DW_AT_bit_offset(0x12), DW_AT_bit_size(0x01) + 285 .dwattr $C$DW$17, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 286 .dwattr $C$DW$17, DW_AT_accessibility(DW_ACCESS_public) + 287 .dwattr $C$DW$17, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 288 .dwattr $C$DW$17, DW_AT_decl_line(0x49) + 289 .dwattr $C$DW$17, DW_AT_decl_column(0x0d) + 290$C$DW$18 .dwtag DW_TAG_member + 291 .dwattr $C$DW$18, DW_AT_type(*$C$DW$T$11) + 292 .dwattr $C$DW$18, DW_AT_name("PRU0_GPO_MODE") + 293 .dwattr $C$DW$18, DW_AT_TI_symbol_name("PRU0_GPO_MODE") + 294 .dwattr $C$DW$18, DW_AT_bit_offset(0x11), DW_AT_bit_size(0x01) + 295 .dwattr $C$DW$18, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 296 .dwattr $C$DW$18, DW_AT_accessibility(DW_ACCESS_public) + 297 .dwattr $C$DW$18, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 298 .dwattr $C$DW$18, DW_AT_decl_line(0x4a) + 299 .dwattr $C$DW$18, DW_AT_decl_column(0x0d) + 300$C$DW$19 .dwtag DW_TAG_member + 301 .dwattr $C$DW$19, DW_AT_type(*$C$DW$T$11) + 302 .dwattr $C$DW$19, DW_AT_name("PRU0_GPO_DIV0") + 303 .dwattr $C$DW$19, DW_AT_TI_symbol_name("PRU0_GPO_DIV0") + 304 .dwattr $C$DW$19, DW_AT_bit_offset(0x0c), DW_AT_bit_size(0x05) + 305 .dwattr $C$DW$19, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 306 .dwattr $C$DW$19, DW_AT_accessibility(DW_ACCESS_public) + 307 .dwattr $C$DW$19, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 308 .dwattr $C$DW$19, DW_AT_decl_line(0x4b) + 309 .dwattr $C$DW$19, DW_AT_decl_column(0x0d) + 310$C$DW$20 .dwtag DW_TAG_member + 311 .dwattr $C$DW$20, DW_AT_type(*$C$DW$T$11) + 312 .dwattr $C$DW$20, DW_AT_name("PRU0_GPO_DIV1") + 313 .dwattr $C$DW$20, DW_AT_TI_symbol_name("PRU0_GPO_DIV1") + 314 .dwattr $C$DW$20, DW_AT_bit_offset(0x07), DW_AT_bit_size(0x05) + 315 .dwattr $C$DW$20, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 316 .dwattr $C$DW$20, DW_AT_accessibility(DW_ACCESS_public) + 317 .dwattr $C$DW$20, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 318 .dwattr $C$DW$20, DW_AT_decl_line(0x4c) + 319 .dwattr $C$DW$20, DW_AT_decl_column(0x0d) + 320$C$DW$21 .dwtag DW_TAG_member + 321 .dwattr $C$DW$21, DW_AT_type(*$C$DW$T$11) + 322 .dwattr $C$DW$21, DW_AT_name("PRU0_GPO_SH_SEL") + 323 .dwattr $C$DW$21, DW_AT_TI_symbol_name("PRU0_GPO_SH_SEL") + 324 .dwattr $C$DW$21, DW_AT_bit_offset(0x06), DW_AT_bit_size(0x01) + 325 .dwattr $C$DW$21, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 326 .dwattr $C$DW$21, DW_AT_accessibility(DW_ACCESS_public) + 327 .dwattr $C$DW$21, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 328 .dwattr $C$DW$21, DW_AT_decl_line(0x4d) + 329 .dwattr $C$DW$21, DW_AT_decl_column(0x0d) + 330$C$DW$22 .dwtag DW_TAG_member +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 7 + + 331 .dwattr $C$DW$22, DW_AT_type(*$C$DW$T$11) + 332 .dwattr $C$DW$22, DW_AT_name("rsvd26") + 333 .dwattr $C$DW$22, DW_AT_TI_symbol_name("rsvd26") + 334 .dwattr $C$DW$22, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x06) + 335 .dwattr $C$DW$22, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 336 .dwattr $C$DW$22, DW_AT_accessibility(DW_ACCESS_public) + 337 .dwattr $C$DW$22, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 338 .dwattr $C$DW$22, DW_AT_decl_line(0x4e) + 339 .dwattr $C$DW$22, DW_AT_decl_column(0x0d) + 340 .dwendtag $C$DW$T$21 + 341 + 342 .dwattr $C$DW$T$21, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 343 .dwattr $C$DW$T$21, DW_AT_decl_line(0x44) + 344 .dwattr $C$DW$T$21, DW_AT_decl_column(0x13) + 345$C$DW$T$52 .dwtag DW_TAG_volatile_type + 346 .dwattr $C$DW$T$52, DW_AT_type(*$C$DW$T$21) + 347 + 348$C$DW$T$22 .dwtag DW_TAG_structure_type + 349 .dwattr $C$DW$T$22, DW_AT_byte_size(0x04) + 350$C$DW$23 .dwtag DW_TAG_member + 351 .dwattr $C$DW$23, DW_AT_type(*$C$DW$T$11) + 352 .dwattr $C$DW$23, DW_AT_name("PRU1_GPI_MODE") + 353 .dwattr $C$DW$23, DW_AT_TI_symbol_name("PRU1_GPI_MODE") + 354 .dwattr $C$DW$23, DW_AT_bit_offset(0x1e), DW_AT_bit_size(0x02) + 355 .dwattr $C$DW$23, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 356 .dwattr $C$DW$23, DW_AT_accessibility(DW_ACCESS_public) + 357 .dwattr $C$DW$23, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 358 .dwattr $C$DW$23, DW_AT_decl_line(0x58) + 359 .dwattr $C$DW$23, DW_AT_decl_column(0x0d) + 360$C$DW$24 .dwtag DW_TAG_member + 361 .dwattr $C$DW$24, DW_AT_type(*$C$DW$T$11) + 362 .dwattr $C$DW$24, DW_AT_name("PRU1_GPI_CLK_MODE") + 363 .dwattr $C$DW$24, DW_AT_TI_symbol_name("PRU1_GPI_CLK_MODE") + 364 .dwattr $C$DW$24, DW_AT_bit_offset(0x1d), DW_AT_bit_size(0x01) + 365 .dwattr $C$DW$24, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 366 .dwattr $C$DW$24, DW_AT_accessibility(DW_ACCESS_public) + 367 .dwattr $C$DW$24, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 368 .dwattr $C$DW$24, DW_AT_decl_line(0x59) + 369 .dwattr $C$DW$24, DW_AT_decl_column(0x0d) + 370$C$DW$25 .dwtag DW_TAG_member + 371 .dwattr $C$DW$25, DW_AT_type(*$C$DW$T$11) + 372 .dwattr $C$DW$25, DW_AT_name("PRU1_GPI_DIV0") + 373 .dwattr $C$DW$25, DW_AT_TI_symbol_name("PRU1_GPI_DIV0") + 374 .dwattr $C$DW$25, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x05) + 375 .dwattr $C$DW$25, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 376 .dwattr $C$DW$25, DW_AT_accessibility(DW_ACCESS_public) + 377 .dwattr $C$DW$25, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 378 .dwattr $C$DW$25, DW_AT_decl_line(0x5a) + 379 .dwattr $C$DW$25, DW_AT_decl_column(0x0d) + 380$C$DW$26 .dwtag DW_TAG_member + 381 .dwattr $C$DW$26, DW_AT_type(*$C$DW$T$11) + 382 .dwattr $C$DW$26, DW_AT_name("PRU1_GPI_DIV1") + 383 .dwattr $C$DW$26, DW_AT_TI_symbol_name("PRU1_GPI_DIV1") + 384 .dwattr $C$DW$26, DW_AT_bit_offset(0x13), DW_AT_bit_size(0x05) + 385 .dwattr $C$DW$26, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 8 + + 386 .dwattr $C$DW$26, DW_AT_accessibility(DW_ACCESS_public) + 387 .dwattr $C$DW$26, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 388 .dwattr $C$DW$26, DW_AT_decl_line(0x5b) + 389 .dwattr $C$DW$26, DW_AT_decl_column(0x0d) + 390$C$DW$27 .dwtag DW_TAG_member + 391 .dwattr $C$DW$27, DW_AT_type(*$C$DW$T$11) + 392 .dwattr $C$DW$27, DW_AT_name("PRU1_GPI_SB") + 393 .dwattr $C$DW$27, DW_AT_TI_symbol_name("PRU1_GPI_SB") + 394 .dwattr $C$DW$27, DW_AT_bit_offset(0x12), DW_AT_bit_size(0x01) + 395 .dwattr $C$DW$27, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 396 .dwattr $C$DW$27, DW_AT_accessibility(DW_ACCESS_public) + 397 .dwattr $C$DW$27, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 398 .dwattr $C$DW$27, DW_AT_decl_line(0x5c) + 399 .dwattr $C$DW$27, DW_AT_decl_column(0x0d) + 400$C$DW$28 .dwtag DW_TAG_member + 401 .dwattr $C$DW$28, DW_AT_type(*$C$DW$T$11) + 402 .dwattr $C$DW$28, DW_AT_name("PRU1_GPO_MODE") + 403 .dwattr $C$DW$28, DW_AT_TI_symbol_name("PRU1_GPO_MODE") + 404 .dwattr $C$DW$28, DW_AT_bit_offset(0x11), DW_AT_bit_size(0x01) + 405 .dwattr $C$DW$28, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 406 .dwattr $C$DW$28, DW_AT_accessibility(DW_ACCESS_public) + 407 .dwattr $C$DW$28, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 408 .dwattr $C$DW$28, DW_AT_decl_line(0x5d) + 409 .dwattr $C$DW$28, DW_AT_decl_column(0x0d) + 410$C$DW$29 .dwtag DW_TAG_member + 411 .dwattr $C$DW$29, DW_AT_type(*$C$DW$T$11) + 412 .dwattr $C$DW$29, DW_AT_name("PRU1_GPO_DIV0") + 413 .dwattr $C$DW$29, DW_AT_TI_symbol_name("PRU1_GPO_DIV0") + 414 .dwattr $C$DW$29, DW_AT_bit_offset(0x0c), DW_AT_bit_size(0x05) + 415 .dwattr $C$DW$29, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 416 .dwattr $C$DW$29, DW_AT_accessibility(DW_ACCESS_public) + 417 .dwattr $C$DW$29, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 418 .dwattr $C$DW$29, DW_AT_decl_line(0x5e) + 419 .dwattr $C$DW$29, DW_AT_decl_column(0x0d) + 420$C$DW$30 .dwtag DW_TAG_member + 421 .dwattr $C$DW$30, DW_AT_type(*$C$DW$T$11) + 422 .dwattr $C$DW$30, DW_AT_name("PRU1_GPO_DIV1") + 423 .dwattr $C$DW$30, DW_AT_TI_symbol_name("PRU1_GPO_DIV1") + 424 .dwattr $C$DW$30, DW_AT_bit_offset(0x07), DW_AT_bit_size(0x05) + 425 .dwattr $C$DW$30, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 426 .dwattr $C$DW$30, DW_AT_accessibility(DW_ACCESS_public) + 427 .dwattr $C$DW$30, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 428 .dwattr $C$DW$30, DW_AT_decl_line(0x5f) + 429 .dwattr $C$DW$30, DW_AT_decl_column(0x0d) + 430$C$DW$31 .dwtag DW_TAG_member + 431 .dwattr $C$DW$31, DW_AT_type(*$C$DW$T$11) + 432 .dwattr $C$DW$31, DW_AT_name("PRU1_GPO_SH_SEL") + 433 .dwattr $C$DW$31, DW_AT_TI_symbol_name("PRU1_GPO_SH_SEL") + 434 .dwattr $C$DW$31, DW_AT_bit_offset(0x06), DW_AT_bit_size(0x01) + 435 .dwattr $C$DW$31, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 436 .dwattr $C$DW$31, DW_AT_accessibility(DW_ACCESS_public) + 437 .dwattr $C$DW$31, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 438 .dwattr $C$DW$31, DW_AT_decl_line(0x60) + 439 .dwattr $C$DW$31, DW_AT_decl_column(0x0d) + 440$C$DW$32 .dwtag DW_TAG_member +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 9 + + 441 .dwattr $C$DW$32, DW_AT_type(*$C$DW$T$11) + 442 .dwattr $C$DW$32, DW_AT_name("rsvd26") + 443 .dwattr $C$DW$32, DW_AT_TI_symbol_name("rsvd26") + 444 .dwattr $C$DW$32, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x06) + 445 .dwattr $C$DW$32, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 446 .dwattr $C$DW$32, DW_AT_accessibility(DW_ACCESS_public) + 447 .dwattr $C$DW$32, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 448 .dwattr $C$DW$32, DW_AT_decl_line(0x61) + 449 .dwattr $C$DW$32, DW_AT_decl_column(0x0d) + 450 .dwendtag $C$DW$T$22 + 451 + 452 .dwattr $C$DW$T$22, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 453 .dwattr $C$DW$T$22, DW_AT_decl_line(0x57) + 454 .dwattr $C$DW$T$22, DW_AT_decl_column(0x13) + 455$C$DW$T$54 .dwtag DW_TAG_volatile_type + 456 .dwattr $C$DW$T$54, DW_AT_type(*$C$DW$T$22) + 457 + 458$C$DW$T$23 .dwtag DW_TAG_structure_type + 459 .dwattr $C$DW$T$23, DW_AT_byte_size(0x04) + 460$C$DW$33 .dwtag DW_TAG_member + 461 .dwattr $C$DW$33, DW_AT_type(*$C$DW$T$11) + 462 .dwattr $C$DW$33, DW_AT_name("PRU0_CLK_STOP_REQ") + 463 .dwattr $C$DW$33, DW_AT_TI_symbol_name("PRU0_CLK_STOP_REQ") + 464 .dwattr $C$DW$33, DW_AT_bit_offset(0x1f), DW_AT_bit_size(0x01) + 465 .dwattr $C$DW$33, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 466 .dwattr $C$DW$33, DW_AT_accessibility(DW_ACCESS_public) + 467 .dwattr $C$DW$33, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 468 .dwattr $C$DW$33, DW_AT_decl_line(0x6b) + 469 .dwattr $C$DW$33, DW_AT_decl_column(0x0d) + 470$C$DW$34 .dwtag DW_TAG_member + 471 .dwattr $C$DW$34, DW_AT_type(*$C$DW$T$11) + 472 .dwattr $C$DW$34, DW_AT_name("PRU0_CLK_STOP_ACK") + 473 .dwattr $C$DW$34, DW_AT_TI_symbol_name("PRU0_CLK_STOP_ACK") + 474 .dwattr $C$DW$34, DW_AT_bit_offset(0x1e), DW_AT_bit_size(0x01) + 475 .dwattr $C$DW$34, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 476 .dwattr $C$DW$34, DW_AT_accessibility(DW_ACCESS_public) + 477 .dwattr $C$DW$34, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 478 .dwattr $C$DW$34, DW_AT_decl_line(0x6c) + 479 .dwattr $C$DW$34, DW_AT_decl_column(0x0d) + 480$C$DW$35 .dwtag DW_TAG_member + 481 .dwattr $C$DW$35, DW_AT_type(*$C$DW$T$11) + 482 .dwattr $C$DW$35, DW_AT_name("PRU0_CLK_EN") + 483 .dwattr $C$DW$35, DW_AT_TI_symbol_name("PRU0_CLK_EN") + 484 .dwattr $C$DW$35, DW_AT_bit_offset(0x1d), DW_AT_bit_size(0x01) + 485 .dwattr $C$DW$35, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 486 .dwattr $C$DW$35, DW_AT_accessibility(DW_ACCESS_public) + 487 .dwattr $C$DW$35, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 488 .dwattr $C$DW$35, DW_AT_decl_line(0x6d) + 489 .dwattr $C$DW$35, DW_AT_decl_column(0x0d) + 490$C$DW$36 .dwtag DW_TAG_member + 491 .dwattr $C$DW$36, DW_AT_type(*$C$DW$T$11) + 492 .dwattr $C$DW$36, DW_AT_name("PRU1_CLK_STOP_REQ") + 493 .dwattr $C$DW$36, DW_AT_TI_symbol_name("PRU1_CLK_STOP_REQ") + 494 .dwattr $C$DW$36, DW_AT_bit_offset(0x1c), DW_AT_bit_size(0x01) + 495 .dwattr $C$DW$36, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 10 + + 496 .dwattr $C$DW$36, DW_AT_accessibility(DW_ACCESS_public) + 497 .dwattr $C$DW$36, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 498 .dwattr $C$DW$36, DW_AT_decl_line(0x6e) + 499 .dwattr $C$DW$36, DW_AT_decl_column(0x0d) + 500$C$DW$37 .dwtag DW_TAG_member + 501 .dwattr $C$DW$37, DW_AT_type(*$C$DW$T$11) + 502 .dwattr $C$DW$37, DW_AT_name("PRU1_CLK_STOP_ACK") + 503 .dwattr $C$DW$37, DW_AT_TI_symbol_name("PRU1_CLK_STOP_ACK") + 504 .dwattr $C$DW$37, DW_AT_bit_offset(0x1b), DW_AT_bit_size(0x01) + 505 .dwattr $C$DW$37, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 506 .dwattr $C$DW$37, DW_AT_accessibility(DW_ACCESS_public) + 507 .dwattr $C$DW$37, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 508 .dwattr $C$DW$37, DW_AT_decl_line(0x6f) + 509 .dwattr $C$DW$37, DW_AT_decl_column(0x0d) + 510$C$DW$38 .dwtag DW_TAG_member + 511 .dwattr $C$DW$38, DW_AT_type(*$C$DW$T$11) + 512 .dwattr $C$DW$38, DW_AT_name("PRU1_CLK_EN") + 513 .dwattr $C$DW$38, DW_AT_TI_symbol_name("PRU1_CLK_EN") + 514 .dwattr $C$DW$38, DW_AT_bit_offset(0x1a), DW_AT_bit_size(0x01) + 515 .dwattr $C$DW$38, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 516 .dwattr $C$DW$38, DW_AT_accessibility(DW_ACCESS_public) + 517 .dwattr $C$DW$38, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 518 .dwattr $C$DW$38, DW_AT_decl_line(0x70) + 519 .dwattr $C$DW$38, DW_AT_decl_column(0x0d) + 520$C$DW$39 .dwtag DW_TAG_member + 521 .dwattr $C$DW$39, DW_AT_type(*$C$DW$T$11) + 522 .dwattr $C$DW$39, DW_AT_name("INTC_CLK_STOP_REQ") + 523 .dwattr $C$DW$39, DW_AT_TI_symbol_name("INTC_CLK_STOP_REQ") + 524 .dwattr $C$DW$39, DW_AT_bit_offset(0x19), DW_AT_bit_size(0x01) + 525 .dwattr $C$DW$39, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 526 .dwattr $C$DW$39, DW_AT_accessibility(DW_ACCESS_public) + 527 .dwattr $C$DW$39, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 528 .dwattr $C$DW$39, DW_AT_decl_line(0x71) + 529 .dwattr $C$DW$39, DW_AT_decl_column(0x0d) + 530$C$DW$40 .dwtag DW_TAG_member + 531 .dwattr $C$DW$40, DW_AT_type(*$C$DW$T$11) + 532 .dwattr $C$DW$40, DW_AT_name("INTC_CLK_STOP_ACK") + 533 .dwattr $C$DW$40, DW_AT_TI_symbol_name("INTC_CLK_STOP_ACK") + 534 .dwattr $C$DW$40, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x01) + 535 .dwattr $C$DW$40, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 536 .dwattr $C$DW$40, DW_AT_accessibility(DW_ACCESS_public) + 537 .dwattr $C$DW$40, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 538 .dwattr $C$DW$40, DW_AT_decl_line(0x72) + 539 .dwattr $C$DW$40, DW_AT_decl_column(0x0d) + 540$C$DW$41 .dwtag DW_TAG_member + 541 .dwattr $C$DW$41, DW_AT_type(*$C$DW$T$11) + 542 .dwattr $C$DW$41, DW_AT_name("INTC_CLK_EN") + 543 .dwattr $C$DW$41, DW_AT_TI_symbol_name("INTC_CLK_EN") + 544 .dwattr $C$DW$41, DW_AT_bit_offset(0x17), DW_AT_bit_size(0x01) + 545 .dwattr $C$DW$41, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 546 .dwattr $C$DW$41, DW_AT_accessibility(DW_ACCESS_public) + 547 .dwattr $C$DW$41, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 548 .dwattr $C$DW$41, DW_AT_decl_line(0x73) + 549 .dwattr $C$DW$41, DW_AT_decl_column(0x0d) + 550$C$DW$42 .dwtag DW_TAG_member +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 11 + + 551 .dwattr $C$DW$42, DW_AT_type(*$C$DW$T$11) + 552 .dwattr $C$DW$42, DW_AT_name("UART_CLK_STOP_REQ") + 553 .dwattr $C$DW$42, DW_AT_TI_symbol_name("UART_CLK_STOP_REQ") + 554 .dwattr $C$DW$42, DW_AT_bit_offset(0x16), DW_AT_bit_size(0x01) + 555 .dwattr $C$DW$42, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 556 .dwattr $C$DW$42, DW_AT_accessibility(DW_ACCESS_public) + 557 .dwattr $C$DW$42, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 558 .dwattr $C$DW$42, DW_AT_decl_line(0x74) + 559 .dwattr $C$DW$42, DW_AT_decl_column(0x0d) + 560$C$DW$43 .dwtag DW_TAG_member + 561 .dwattr $C$DW$43, DW_AT_type(*$C$DW$T$11) + 562 .dwattr $C$DW$43, DW_AT_name("UART_CLK_STOP_ACK") + 563 .dwattr $C$DW$43, DW_AT_TI_symbol_name("UART_CLK_STOP_ACK") + 564 .dwattr $C$DW$43, DW_AT_bit_offset(0x15), DW_AT_bit_size(0x01) + 565 .dwattr $C$DW$43, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 566 .dwattr $C$DW$43, DW_AT_accessibility(DW_ACCESS_public) + 567 .dwattr $C$DW$43, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 568 .dwattr $C$DW$43, DW_AT_decl_line(0x75) + 569 .dwattr $C$DW$43, DW_AT_decl_column(0x0d) + 570$C$DW$44 .dwtag DW_TAG_member + 571 .dwattr $C$DW$44, DW_AT_type(*$C$DW$T$11) + 572 .dwattr $C$DW$44, DW_AT_name("UART_CLK_EN") + 573 .dwattr $C$DW$44, DW_AT_TI_symbol_name("UART_CLK_EN") + 574 .dwattr $C$DW$44, DW_AT_bit_offset(0x14), DW_AT_bit_size(0x01) + 575 .dwattr $C$DW$44, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 576 .dwattr $C$DW$44, DW_AT_accessibility(DW_ACCESS_public) + 577 .dwattr $C$DW$44, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 578 .dwattr $C$DW$44, DW_AT_decl_line(0x76) + 579 .dwattr $C$DW$44, DW_AT_decl_column(0x0d) + 580$C$DW$45 .dwtag DW_TAG_member + 581 .dwattr $C$DW$45, DW_AT_type(*$C$DW$T$11) + 582 .dwattr $C$DW$45, DW_AT_name("ECAP_CLK_STOP_REQ") + 583 .dwattr $C$DW$45, DW_AT_TI_symbol_name("ECAP_CLK_STOP_REQ") + 584 .dwattr $C$DW$45, DW_AT_bit_offset(0x13), DW_AT_bit_size(0x01) + 585 .dwattr $C$DW$45, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 586 .dwattr $C$DW$45, DW_AT_accessibility(DW_ACCESS_public) + 587 .dwattr $C$DW$45, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 588 .dwattr $C$DW$45, DW_AT_decl_line(0x77) + 589 .dwattr $C$DW$45, DW_AT_decl_column(0x0d) + 590$C$DW$46 .dwtag DW_TAG_member + 591 .dwattr $C$DW$46, DW_AT_type(*$C$DW$T$11) + 592 .dwattr $C$DW$46, DW_AT_name("ECAP_CLK_STOP_ACK") + 593 .dwattr $C$DW$46, DW_AT_TI_symbol_name("ECAP_CLK_STOP_ACK") + 594 .dwattr $C$DW$46, DW_AT_bit_offset(0x12), DW_AT_bit_size(0x01) + 595 .dwattr $C$DW$46, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 596 .dwattr $C$DW$46, DW_AT_accessibility(DW_ACCESS_public) + 597 .dwattr $C$DW$46, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 598 .dwattr $C$DW$46, DW_AT_decl_line(0x78) + 599 .dwattr $C$DW$46, DW_AT_decl_column(0x0d) + 600$C$DW$47 .dwtag DW_TAG_member + 601 .dwattr $C$DW$47, DW_AT_type(*$C$DW$T$11) + 602 .dwattr $C$DW$47, DW_AT_name("ECAP_CLK_EN") + 603 .dwattr $C$DW$47, DW_AT_TI_symbol_name("ECAP_CLK_EN") + 604 .dwattr $C$DW$47, DW_AT_bit_offset(0x11), DW_AT_bit_size(0x01) + 605 .dwattr $C$DW$47, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 12 + + 606 .dwattr $C$DW$47, DW_AT_accessibility(DW_ACCESS_public) + 607 .dwattr $C$DW$47, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 608 .dwattr $C$DW$47, DW_AT_decl_line(0x79) + 609 .dwattr $C$DW$47, DW_AT_decl_column(0x0d) + 610$C$DW$48 .dwtag DW_TAG_member + 611 .dwattr $C$DW$48, DW_AT_type(*$C$DW$T$11) + 612 .dwattr $C$DW$48, DW_AT_name("IEP_CLK_STOP_REQ") + 613 .dwattr $C$DW$48, DW_AT_TI_symbol_name("IEP_CLK_STOP_REQ") + 614 .dwattr $C$DW$48, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x01) + 615 .dwattr $C$DW$48, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 616 .dwattr $C$DW$48, DW_AT_accessibility(DW_ACCESS_public) + 617 .dwattr $C$DW$48, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 618 .dwattr $C$DW$48, DW_AT_decl_line(0x7a) + 619 .dwattr $C$DW$48, DW_AT_decl_column(0x0d) + 620$C$DW$49 .dwtag DW_TAG_member + 621 .dwattr $C$DW$49, DW_AT_type(*$C$DW$T$11) + 622 .dwattr $C$DW$49, DW_AT_name("IEP_CLK_STOP_ACK") + 623 .dwattr $C$DW$49, DW_AT_TI_symbol_name("IEP_CLK_STOP_ACK") + 624 .dwattr $C$DW$49, DW_AT_bit_offset(0x0f), DW_AT_bit_size(0x01) + 625 .dwattr $C$DW$49, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 626 .dwattr $C$DW$49, DW_AT_accessibility(DW_ACCESS_public) + 627 .dwattr $C$DW$49, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 628 .dwattr $C$DW$49, DW_AT_decl_line(0x7b) + 629 .dwattr $C$DW$49, DW_AT_decl_column(0x0d) + 630$C$DW$50 .dwtag DW_TAG_member + 631 .dwattr $C$DW$50, DW_AT_type(*$C$DW$T$11) + 632 .dwattr $C$DW$50, DW_AT_name("IEP_CLK_EN") + 633 .dwattr $C$DW$50, DW_AT_TI_symbol_name("IEP_CLK_EN") + 634 .dwattr $C$DW$50, DW_AT_bit_offset(0x0e), DW_AT_bit_size(0x01) + 635 .dwattr $C$DW$50, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 636 .dwattr $C$DW$50, DW_AT_accessibility(DW_ACCESS_public) + 637 .dwattr $C$DW$50, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 638 .dwattr $C$DW$50, DW_AT_decl_line(0x7c) + 639 .dwattr $C$DW$50, DW_AT_decl_column(0x0d) + 640$C$DW$51 .dwtag DW_TAG_member + 641 .dwattr $C$DW$51, DW_AT_type(*$C$DW$T$11) + 642 .dwattr $C$DW$51, DW_AT_name("rsvd18") + 643 .dwattr $C$DW$51, DW_AT_TI_symbol_name("rsvd18") + 644 .dwattr $C$DW$51, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x0e) + 645 .dwattr $C$DW$51, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 646 .dwattr $C$DW$51, DW_AT_accessibility(DW_ACCESS_public) + 647 .dwattr $C$DW$51, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 648 .dwattr $C$DW$51, DW_AT_decl_line(0x7d) + 649 .dwattr $C$DW$51, DW_AT_decl_column(0x0d) + 650 .dwendtag $C$DW$T$23 + 651 + 652 .dwattr $C$DW$T$23, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 653 .dwattr $C$DW$T$23, DW_AT_decl_line(0x6a) + 654 .dwattr $C$DW$T$23, DW_AT_decl_column(0x13) + 655$C$DW$T$56 .dwtag DW_TAG_volatile_type + 656 .dwattr $C$DW$T$56, DW_AT_type(*$C$DW$T$23) + 657 + 658$C$DW$T$24 .dwtag DW_TAG_structure_type + 659 .dwattr $C$DW$T$24, DW_AT_byte_size(0x04) + 660$C$DW$52 .dwtag DW_TAG_member +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 13 + + 661 .dwattr $C$DW$52, DW_AT_type(*$C$DW$T$11) + 662 .dwattr $C$DW$52, DW_AT_name("PRU0_IMEM_PE_RAW") + 663 .dwattr $C$DW$52, DW_AT_TI_symbol_name("PRU0_IMEM_PE_RAW") + 664 .dwattr $C$DW$52, DW_AT_bit_offset(0x1c), DW_AT_bit_size(0x04) + 665 .dwattr $C$DW$52, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 666 .dwattr $C$DW$52, DW_AT_accessibility(DW_ACCESS_public) + 667 .dwattr $C$DW$52, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 668 .dwattr $C$DW$52, DW_AT_decl_line(0x87) + 669 .dwattr $C$DW$52, DW_AT_decl_column(0x0d) + 670$C$DW$53 .dwtag DW_TAG_member + 671 .dwattr $C$DW$53, DW_AT_type(*$C$DW$T$11) + 672 .dwattr $C$DW$53, DW_AT_name("PRU0_DMEM_PE_RAW") + 673 .dwattr $C$DW$53, DW_AT_TI_symbol_name("PRU0_DMEM_PE_RAW") + 674 .dwattr $C$DW$53, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x04) + 675 .dwattr $C$DW$53, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 676 .dwattr $C$DW$53, DW_AT_accessibility(DW_ACCESS_public) + 677 .dwattr $C$DW$53, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 678 .dwattr $C$DW$53, DW_AT_decl_line(0x88) + 679 .dwattr $C$DW$53, DW_AT_decl_column(0x0d) + 680$C$DW$54 .dwtag DW_TAG_member + 681 .dwattr $C$DW$54, DW_AT_type(*$C$DW$T$11) + 682 .dwattr $C$DW$54, DW_AT_name("PRU1_IMEM_PE_RAW") + 683 .dwattr $C$DW$54, DW_AT_TI_symbol_name("PRU1_IMEM_PE_RAW") + 684 .dwattr $C$DW$54, DW_AT_bit_offset(0x14), DW_AT_bit_size(0x04) + 685 .dwattr $C$DW$54, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 686 .dwattr $C$DW$54, DW_AT_accessibility(DW_ACCESS_public) + 687 .dwattr $C$DW$54, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 688 .dwattr $C$DW$54, DW_AT_decl_line(0x89) + 689 .dwattr $C$DW$54, DW_AT_decl_column(0x0d) + 690$C$DW$55 .dwtag DW_TAG_member + 691 .dwattr $C$DW$55, DW_AT_type(*$C$DW$T$11) + 692 .dwattr $C$DW$55, DW_AT_name("PRU1_DMEM_PE_RAW") + 693 .dwattr $C$DW$55, DW_AT_TI_symbol_name("PRU1_DMEM_PE_RAW") + 694 .dwattr $C$DW$55, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x04) + 695 .dwattr $C$DW$55, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 696 .dwattr $C$DW$55, DW_AT_accessibility(DW_ACCESS_public) + 697 .dwattr $C$DW$55, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 698 .dwattr $C$DW$55, DW_AT_decl_line(0x8a) + 699 .dwattr $C$DW$55, DW_AT_decl_column(0x0d) + 700$C$DW$56 .dwtag DW_TAG_member + 701 .dwattr $C$DW$56, DW_AT_type(*$C$DW$T$11) + 702 .dwattr $C$DW$56, DW_AT_name("RAM_PE_RAW") + 703 .dwattr $C$DW$56, DW_AT_TI_symbol_name("RAM_PE_RAW") + 704 .dwattr $C$DW$56, DW_AT_bit_offset(0x0c), DW_AT_bit_size(0x04) + 705 .dwattr $C$DW$56, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 706 .dwattr $C$DW$56, DW_AT_accessibility(DW_ACCESS_public) + 707 .dwattr $C$DW$56, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 708 .dwattr $C$DW$56, DW_AT_decl_line(0x8b) + 709 .dwattr $C$DW$56, DW_AT_decl_column(0x0d) + 710$C$DW$57 .dwtag DW_TAG_member + 711 .dwattr $C$DW$57, DW_AT_type(*$C$DW$T$11) + 712 .dwattr $C$DW$57, DW_AT_name("rsvd20") + 713 .dwattr $C$DW$57, DW_AT_TI_symbol_name("rsvd20") + 714 .dwattr $C$DW$57, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x0c) + 715 .dwattr $C$DW$57, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 14 + + 716 .dwattr $C$DW$57, DW_AT_accessibility(DW_ACCESS_public) + 717 .dwattr $C$DW$57, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 718 .dwattr $C$DW$57, DW_AT_decl_line(0x8c) + 719 .dwattr $C$DW$57, DW_AT_decl_column(0x0d) + 720 .dwendtag $C$DW$T$24 + 721 + 722 .dwattr $C$DW$T$24, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 723 .dwattr $C$DW$T$24, DW_AT_decl_line(0x86) + 724 .dwattr $C$DW$T$24, DW_AT_decl_column(0x14) + 725$C$DW$T$58 .dwtag DW_TAG_volatile_type + 726 .dwattr $C$DW$T$58, DW_AT_type(*$C$DW$T$24) + 727 + 728$C$DW$T$25 .dwtag DW_TAG_structure_type + 729 .dwattr $C$DW$T$25, DW_AT_byte_size(0x04) + 730$C$DW$58 .dwtag DW_TAG_member + 731 .dwattr $C$DW$58, DW_AT_type(*$C$DW$T$11) + 732 .dwattr $C$DW$58, DW_AT_name("PRU0_IMEM_PE") + 733 .dwattr $C$DW$58, DW_AT_TI_symbol_name("PRU0_IMEM_PE") + 734 .dwattr $C$DW$58, DW_AT_bit_offset(0x1c), DW_AT_bit_size(0x04) + 735 .dwattr $C$DW$58, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 736 .dwattr $C$DW$58, DW_AT_accessibility(DW_ACCESS_public) + 737 .dwattr $C$DW$58, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 738 .dwattr $C$DW$58, DW_AT_decl_line(0x96) + 739 .dwattr $C$DW$58, DW_AT_decl_column(0x0d) + 740$C$DW$59 .dwtag DW_TAG_member + 741 .dwattr $C$DW$59, DW_AT_type(*$C$DW$T$11) + 742 .dwattr $C$DW$59, DW_AT_name("PRU0_DMEM_PE") + 743 .dwattr $C$DW$59, DW_AT_TI_symbol_name("PRU0_DMEM_PE") + 744 .dwattr $C$DW$59, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x04) + 745 .dwattr $C$DW$59, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 746 .dwattr $C$DW$59, DW_AT_accessibility(DW_ACCESS_public) + 747 .dwattr $C$DW$59, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 748 .dwattr $C$DW$59, DW_AT_decl_line(0x97) + 749 .dwattr $C$DW$59, DW_AT_decl_column(0x0d) + 750$C$DW$60 .dwtag DW_TAG_member + 751 .dwattr $C$DW$60, DW_AT_type(*$C$DW$T$11) + 752 .dwattr $C$DW$60, DW_AT_name("PRU1_IMEM_PE") + 753 .dwattr $C$DW$60, DW_AT_TI_symbol_name("PRU1_IMEM_PE") + 754 .dwattr $C$DW$60, DW_AT_bit_offset(0x14), DW_AT_bit_size(0x04) + 755 .dwattr $C$DW$60, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 756 .dwattr $C$DW$60, DW_AT_accessibility(DW_ACCESS_public) + 757 .dwattr $C$DW$60, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 758 .dwattr $C$DW$60, DW_AT_decl_line(0x98) + 759 .dwattr $C$DW$60, DW_AT_decl_column(0x0d) + 760$C$DW$61 .dwtag DW_TAG_member + 761 .dwattr $C$DW$61, DW_AT_type(*$C$DW$T$11) + 762 .dwattr $C$DW$61, DW_AT_name("PRU1_DMEM_PE") + 763 .dwattr $C$DW$61, DW_AT_TI_symbol_name("PRU1_DMEM_PE") + 764 .dwattr $C$DW$61, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x04) + 765 .dwattr $C$DW$61, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 766 .dwattr $C$DW$61, DW_AT_accessibility(DW_ACCESS_public) + 767 .dwattr $C$DW$61, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 768 .dwattr $C$DW$61, DW_AT_decl_line(0x99) + 769 .dwattr $C$DW$61, DW_AT_decl_column(0x0d) + 770$C$DW$62 .dwtag DW_TAG_member +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 15 + + 771 .dwattr $C$DW$62, DW_AT_type(*$C$DW$T$11) + 772 .dwattr $C$DW$62, DW_AT_name("RAM_PE") + 773 .dwattr $C$DW$62, DW_AT_TI_symbol_name("RAM_PE") + 774 .dwattr $C$DW$62, DW_AT_bit_offset(0x0c), DW_AT_bit_size(0x04) + 775 .dwattr $C$DW$62, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 776 .dwattr $C$DW$62, DW_AT_accessibility(DW_ACCESS_public) + 777 .dwattr $C$DW$62, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 778 .dwattr $C$DW$62, DW_AT_decl_line(0x9a) + 779 .dwattr $C$DW$62, DW_AT_decl_column(0x0d) + 780$C$DW$63 .dwtag DW_TAG_member + 781 .dwattr $C$DW$63, DW_AT_type(*$C$DW$T$11) + 782 .dwattr $C$DW$63, DW_AT_name("rsvd20") + 783 .dwattr $C$DW$63, DW_AT_TI_symbol_name("rsvd20") + 784 .dwattr $C$DW$63, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x0c) + 785 .dwattr $C$DW$63, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 786 .dwattr $C$DW$63, DW_AT_accessibility(DW_ACCESS_public) + 787 .dwattr $C$DW$63, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 788 .dwattr $C$DW$63, DW_AT_decl_line(0x9b) + 789 .dwattr $C$DW$63, DW_AT_decl_column(0x0d) + 790 .dwendtag $C$DW$T$25 + 791 + 792 .dwattr $C$DW$T$25, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 793 .dwattr $C$DW$T$25, DW_AT_decl_line(0x95) + 794 .dwattr $C$DW$T$25, DW_AT_decl_column(0x14) + 795$C$DW$T$60 .dwtag DW_TAG_volatile_type + 796 .dwattr $C$DW$T$60, DW_AT_type(*$C$DW$T$25) + 797 + 798$C$DW$T$26 .dwtag DW_TAG_structure_type + 799 .dwattr $C$DW$T$26, DW_AT_byte_size(0x04) + 800$C$DW$64 .dwtag DW_TAG_member + 801 .dwattr $C$DW$64, DW_AT_type(*$C$DW$T$11) + 802 .dwattr $C$DW$64, DW_AT_name("PRU0_IMEM_PE_SET") + 803 .dwattr $C$DW$64, DW_AT_TI_symbol_name("PRU0_IMEM_PE_SET") + 804 .dwattr $C$DW$64, DW_AT_bit_offset(0x1c), DW_AT_bit_size(0x04) + 805 .dwattr $C$DW$64, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 806 .dwattr $C$DW$64, DW_AT_accessibility(DW_ACCESS_public) + 807 .dwattr $C$DW$64, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 808 .dwattr $C$DW$64, DW_AT_decl_line(0xa4) + 809 .dwattr $C$DW$64, DW_AT_decl_column(0x0d) + 810$C$DW$65 .dwtag DW_TAG_member + 811 .dwattr $C$DW$65, DW_AT_type(*$C$DW$T$11) + 812 .dwattr $C$DW$65, DW_AT_name("PRU0_DMEM_PE_SET") + 813 .dwattr $C$DW$65, DW_AT_TI_symbol_name("PRU0_DMEM_PE_SET") + 814 .dwattr $C$DW$65, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x04) + 815 .dwattr $C$DW$65, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 816 .dwattr $C$DW$65, DW_AT_accessibility(DW_ACCESS_public) + 817 .dwattr $C$DW$65, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 818 .dwattr $C$DW$65, DW_AT_decl_line(0xa5) + 819 .dwattr $C$DW$65, DW_AT_decl_column(0x0d) + 820$C$DW$66 .dwtag DW_TAG_member + 821 .dwattr $C$DW$66, DW_AT_type(*$C$DW$T$11) + 822 .dwattr $C$DW$66, DW_AT_name("PRU1_IMEM_PE_SET") + 823 .dwattr $C$DW$66, DW_AT_TI_symbol_name("PRU1_IMEM_PE_SET") + 824 .dwattr $C$DW$66, DW_AT_bit_offset(0x14), DW_AT_bit_size(0x04) + 825 .dwattr $C$DW$66, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 16 + + 826 .dwattr $C$DW$66, DW_AT_accessibility(DW_ACCESS_public) + 827 .dwattr $C$DW$66, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 828 .dwattr $C$DW$66, DW_AT_decl_line(0xa6) + 829 .dwattr $C$DW$66, DW_AT_decl_column(0x0d) + 830$C$DW$67 .dwtag DW_TAG_member + 831 .dwattr $C$DW$67, DW_AT_type(*$C$DW$T$11) + 832 .dwattr $C$DW$67, DW_AT_name("PRU1_DMEM_PE_SET") + 833 .dwattr $C$DW$67, DW_AT_TI_symbol_name("PRU1_DMEM_PE_SET") + 834 .dwattr $C$DW$67, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x04) + 835 .dwattr $C$DW$67, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 836 .dwattr $C$DW$67, DW_AT_accessibility(DW_ACCESS_public) + 837 .dwattr $C$DW$67, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 838 .dwattr $C$DW$67, DW_AT_decl_line(0xa7) + 839 .dwattr $C$DW$67, DW_AT_decl_column(0x0d) + 840$C$DW$68 .dwtag DW_TAG_member + 841 .dwattr $C$DW$68, DW_AT_type(*$C$DW$T$11) + 842 .dwattr $C$DW$68, DW_AT_name("RAM_PE_SET") + 843 .dwattr $C$DW$68, DW_AT_TI_symbol_name("RAM_PE_SET") + 844 .dwattr $C$DW$68, DW_AT_bit_offset(0x0c), DW_AT_bit_size(0x04) + 845 .dwattr $C$DW$68, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 846 .dwattr $C$DW$68, DW_AT_accessibility(DW_ACCESS_public) + 847 .dwattr $C$DW$68, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 848 .dwattr $C$DW$68, DW_AT_decl_line(0xa8) + 849 .dwattr $C$DW$68, DW_AT_decl_column(0x0d) + 850$C$DW$69 .dwtag DW_TAG_member + 851 .dwattr $C$DW$69, DW_AT_type(*$C$DW$T$11) + 852 .dwattr $C$DW$69, DW_AT_name("rsvd20") + 853 .dwattr $C$DW$69, DW_AT_TI_symbol_name("rsvd20") + 854 .dwattr $C$DW$69, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x0c) + 855 .dwattr $C$DW$69, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 856 .dwattr $C$DW$69, DW_AT_accessibility(DW_ACCESS_public) + 857 .dwattr $C$DW$69, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 858 .dwattr $C$DW$69, DW_AT_decl_line(0xa9) + 859 .dwattr $C$DW$69, DW_AT_decl_column(0x0d) + 860 .dwendtag $C$DW$T$26 + 861 + 862 .dwattr $C$DW$T$26, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 863 .dwattr $C$DW$T$26, DW_AT_decl_line(0xa3) + 864 .dwattr $C$DW$T$26, DW_AT_decl_column(0x13) + 865$C$DW$T$62 .dwtag DW_TAG_volatile_type + 866 .dwattr $C$DW$T$62, DW_AT_type(*$C$DW$T$26) + 867 + 868$C$DW$T$27 .dwtag DW_TAG_structure_type + 869 .dwattr $C$DW$T$27, DW_AT_byte_size(0x04) + 870$C$DW$70 .dwtag DW_TAG_member + 871 .dwattr $C$DW$70, DW_AT_type(*$C$DW$T$11) + 872 .dwattr $C$DW$70, DW_AT_name("PRU0_IMEM_PE_CLR") + 873 .dwattr $C$DW$70, DW_AT_TI_symbol_name("PRU0_IMEM_PE_CLR") + 874 .dwattr $C$DW$70, DW_AT_bit_offset(0x1c), DW_AT_bit_size(0x04) + 875 .dwattr $C$DW$70, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 876 .dwattr $C$DW$70, DW_AT_accessibility(DW_ACCESS_public) + 877 .dwattr $C$DW$70, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 878 .dwattr $C$DW$70, DW_AT_decl_line(0xb3) + 879 .dwattr $C$DW$70, DW_AT_decl_column(0x0d) + 880$C$DW$71 .dwtag DW_TAG_member +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 17 + + 881 .dwattr $C$DW$71, DW_AT_type(*$C$DW$T$11) + 882 .dwattr $C$DW$71, DW_AT_name("PRU0_DMEM_PE_CLR") + 883 .dwattr $C$DW$71, DW_AT_TI_symbol_name("PRU0_DMEM_PE_CLR") + 884 .dwattr $C$DW$71, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x04) + 885 .dwattr $C$DW$71, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 886 .dwattr $C$DW$71, DW_AT_accessibility(DW_ACCESS_public) + 887 .dwattr $C$DW$71, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 888 .dwattr $C$DW$71, DW_AT_decl_line(0xb4) + 889 .dwattr $C$DW$71, DW_AT_decl_column(0x0d) + 890$C$DW$72 .dwtag DW_TAG_member + 891 .dwattr $C$DW$72, DW_AT_type(*$C$DW$T$11) + 892 .dwattr $C$DW$72, DW_AT_name("PRU1_IMEM_PE_CLR") + 893 .dwattr $C$DW$72, DW_AT_TI_symbol_name("PRU1_IMEM_PE_CLR") + 894 .dwattr $C$DW$72, DW_AT_bit_offset(0x14), DW_AT_bit_size(0x04) + 895 .dwattr $C$DW$72, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 896 .dwattr $C$DW$72, DW_AT_accessibility(DW_ACCESS_public) + 897 .dwattr $C$DW$72, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 898 .dwattr $C$DW$72, DW_AT_decl_line(0xb5) + 899 .dwattr $C$DW$72, DW_AT_decl_column(0x0d) + 900$C$DW$73 .dwtag DW_TAG_member + 901 .dwattr $C$DW$73, DW_AT_type(*$C$DW$T$11) + 902 .dwattr $C$DW$73, DW_AT_name("PRU1_DMEM_PE_CLR") + 903 .dwattr $C$DW$73, DW_AT_TI_symbol_name("PRU1_DMEM_PE_CLR") + 904 .dwattr $C$DW$73, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x04) + 905 .dwattr $C$DW$73, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 906 .dwattr $C$DW$73, DW_AT_accessibility(DW_ACCESS_public) + 907 .dwattr $C$DW$73, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 908 .dwattr $C$DW$73, DW_AT_decl_line(0xb6) + 909 .dwattr $C$DW$73, DW_AT_decl_column(0x0d) + 910$C$DW$74 .dwtag DW_TAG_member + 911 .dwattr $C$DW$74, DW_AT_type(*$C$DW$T$11) + 912 .dwattr $C$DW$74, DW_AT_name("rsvd16") + 913 .dwattr $C$DW$74, DW_AT_TI_symbol_name("rsvd16") + 914 .dwattr $C$DW$74, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x10) + 915 .dwattr $C$DW$74, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 916 .dwattr $C$DW$74, DW_AT_accessibility(DW_ACCESS_public) + 917 .dwattr $C$DW$74, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 918 .dwattr $C$DW$74, DW_AT_decl_line(0xb7) + 919 .dwattr $C$DW$74, DW_AT_decl_column(0x0d) + 920 .dwendtag $C$DW$T$27 + 921 + 922 .dwattr $C$DW$T$27, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 923 .dwattr $C$DW$T$27, DW_AT_decl_line(0xb2) + 924 .dwattr $C$DW$T$27, DW_AT_decl_column(0x13) + 925$C$DW$T$64 .dwtag DW_TAG_volatile_type + 926 .dwattr $C$DW$T$64, DW_AT_type(*$C$DW$T$27) + 927 + 928$C$DW$T$28 .dwtag DW_TAG_structure_type + 929 .dwattr $C$DW$T$28, DW_AT_byte_size(0x04) + 930$C$DW$75 .dwtag DW_TAG_member + 931 .dwattr $C$DW$75, DW_AT_type(*$C$DW$T$11) + 932 .dwattr $C$DW$75, DW_AT_name("PMAO_PRU0") + 933 .dwattr $C$DW$75, DW_AT_TI_symbol_name("PMAO_PRU0") + 934 .dwattr $C$DW$75, DW_AT_bit_offset(0x1f), DW_AT_bit_size(0x01) + 935 .dwattr $C$DW$75, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 18 + + 936 .dwattr $C$DW$75, DW_AT_accessibility(DW_ACCESS_public) + 937 .dwattr $C$DW$75, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 938 .dwattr $C$DW$75, DW_AT_decl_line(0xc4) + 939 .dwattr $C$DW$75, DW_AT_decl_column(0x0d) + 940$C$DW$76 .dwtag DW_TAG_member + 941 .dwattr $C$DW$76, DW_AT_type(*$C$DW$T$11) + 942 .dwattr $C$DW$76, DW_AT_name("PMAO_PRU1") + 943 .dwattr $C$DW$76, DW_AT_TI_symbol_name("PMAO_PRU1") + 944 .dwattr $C$DW$76, DW_AT_bit_offset(0x1e), DW_AT_bit_size(0x01) + 945 .dwattr $C$DW$76, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 946 .dwattr $C$DW$76, DW_AT_accessibility(DW_ACCESS_public) + 947 .dwattr $C$DW$76, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 948 .dwattr $C$DW$76, DW_AT_decl_line(0xc5) + 949 .dwattr $C$DW$76, DW_AT_decl_column(0x0d) + 950$C$DW$77 .dwtag DW_TAG_member + 951 .dwattr $C$DW$77, DW_AT_type(*$C$DW$T$11) + 952 .dwattr $C$DW$77, DW_AT_name("rsvd2") + 953 .dwattr $C$DW$77, DW_AT_TI_symbol_name("rsvd2") + 954 .dwattr $C$DW$77, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x1e) + 955 .dwattr $C$DW$77, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 956 .dwattr $C$DW$77, DW_AT_accessibility(DW_ACCESS_public) + 957 .dwattr $C$DW$77, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 958 .dwattr $C$DW$77, DW_AT_decl_line(0xc6) + 959 .dwattr $C$DW$77, DW_AT_decl_column(0x0d) + 960 .dwendtag $C$DW$T$28 + 961 + 962 .dwattr $C$DW$T$28, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 963 .dwattr $C$DW$T$28, DW_AT_decl_line(0xc3) + 964 .dwattr $C$DW$T$28, DW_AT_decl_column(0x13) + 965$C$DW$T$66 .dwtag DW_TAG_volatile_type + 966 .dwattr $C$DW$T$66, DW_AT_type(*$C$DW$T$28) + 967 + 968$C$DW$T$29 .dwtag DW_TAG_structure_type + 969 .dwattr $C$DW$T$29, DW_AT_byte_size(0x04) + 970$C$DW$78 .dwtag DW_TAG_member + 971 .dwattr $C$DW$78, DW_AT_type(*$C$DW$T$11) + 972 .dwattr $C$DW$78, DW_AT_name("OCP_EN") + 973 .dwattr $C$DW$78, DW_AT_TI_symbol_name("OCP_EN") + 974 .dwattr $C$DW$78, DW_AT_bit_offset(0x1f), DW_AT_bit_size(0x01) + 975 .dwattr $C$DW$78, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 976 .dwattr $C$DW$78, DW_AT_accessibility(DW_ACCESS_public) + 977 .dwattr $C$DW$78, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 978 .dwattr $C$DW$78, DW_AT_decl_line(0xd3) + 979 .dwattr $C$DW$78, DW_AT_decl_column(0x0d) + 980$C$DW$79 .dwtag DW_TAG_member + 981 .dwattr $C$DW$79, DW_AT_type(*$C$DW$T$11) + 982 .dwattr $C$DW$79, DW_AT_name("rsvd1") + 983 .dwattr $C$DW$79, DW_AT_TI_symbol_name("rsvd1") + 984 .dwattr $C$DW$79, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x1f) + 985 .dwattr $C$DW$79, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 986 .dwattr $C$DW$79, DW_AT_accessibility(DW_ACCESS_public) + 987 .dwattr $C$DW$79, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 988 .dwattr $C$DW$79, DW_AT_decl_line(0xd4) + 989 .dwattr $C$DW$79, DW_AT_decl_column(0x0d) + 990 .dwendtag $C$DW$T$29 +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 19 + + 991 + 992 .dwattr $C$DW$T$29, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 993 .dwattr $C$DW$T$29, DW_AT_decl_line(0xd2) + 994 .dwattr $C$DW$T$29, DW_AT_decl_column(0x13) + 995$C$DW$T$68 .dwtag DW_TAG_volatile_type + 996 .dwattr $C$DW$T$68, DW_AT_type(*$C$DW$T$29) + 997 + 998$C$DW$T$30 .dwtag DW_TAG_structure_type + 999 .dwattr $C$DW$T$30, DW_AT_byte_size(0x04) + 1000$C$DW$80 .dwtag DW_TAG_member + 1001 .dwattr $C$DW$80, DW_AT_type(*$C$DW$T$11) + 1002 .dwattr $C$DW$80, DW_AT_name("PRU1_PAD_HP_EN") + 1003 .dwattr $C$DW$80, DW_AT_TI_symbol_name("PRU1_PAD_HP_EN") + 1004 .dwattr $C$DW$80, DW_AT_bit_offset(0x1f), DW_AT_bit_size(0x01) + 1005 .dwattr $C$DW$80, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1006 .dwattr $C$DW$80, DW_AT_accessibility(DW_ACCESS_public) + 1007 .dwattr $C$DW$80, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1008 .dwattr $C$DW$80, DW_AT_decl_line(0xde) + 1009 .dwattr $C$DW$80, DW_AT_decl_column(0x0d) + 1010$C$DW$81 .dwtag DW_TAG_member + 1011 .dwattr $C$DW$81, DW_AT_type(*$C$DW$T$11) + 1012 .dwattr $C$DW$81, DW_AT_name("XFR_SHIFT_EN") + 1013 .dwattr $C$DW$81, DW_AT_TI_symbol_name("XFR_SHIFT_EN") + 1014 .dwattr $C$DW$81, DW_AT_bit_offset(0x1e), DW_AT_bit_size(0x01) + 1015 .dwattr $C$DW$81, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1016 .dwattr $C$DW$81, DW_AT_accessibility(DW_ACCESS_public) + 1017 .dwattr $C$DW$81, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1018 .dwattr $C$DW$81, DW_AT_decl_line(0xdf) + 1019 .dwattr $C$DW$81, DW_AT_decl_column(0x0d) + 1020$C$DW$82 .dwtag DW_TAG_member + 1021 .dwattr $C$DW$82, DW_AT_type(*$C$DW$T$11) + 1022 .dwattr $C$DW$82, DW_AT_name("rsvd2") + 1023 .dwattr $C$DW$82, DW_AT_TI_symbol_name("rsvd2") + 1024 .dwattr $C$DW$82, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x1e) + 1025 .dwattr $C$DW$82, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1026 .dwattr $C$DW$82, DW_AT_accessibility(DW_ACCESS_public) + 1027 .dwattr $C$DW$82, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1028 .dwattr $C$DW$82, DW_AT_decl_line(0xe0) + 1029 .dwattr $C$DW$82, DW_AT_decl_column(0x0d) + 1030 .dwendtag $C$DW$T$30 + 1031 + 1032 .dwattr $C$DW$T$30, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1033 .dwattr $C$DW$T$30, DW_AT_decl_line(0xdd) + 1034 .dwattr $C$DW$T$30, DW_AT_decl_column(0x13) + 1035$C$DW$T$70 .dwtag DW_TAG_volatile_type + 1036 .dwattr $C$DW$T$70, DW_AT_type(*$C$DW$T$30) + 1037 + 1038$C$DW$T$31 .dwtag DW_TAG_structure_type + 1039 .dwattr $C$DW$T$31, DW_AT_byte_size(0x04) + 1040$C$DW$83 .dwtag DW_TAG_member + 1041 .dwattr $C$DW$83, DW_AT_type(*$C$DW$T$11) + 1042 .dwattr $C$DW$83, DW_AT_name("PIN_MUX_SEL") + 1043 .dwattr $C$DW$83, DW_AT_TI_symbol_name("PIN_MUX_SEL") + 1044 .dwattr $C$DW$83, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x08) + 1045 .dwattr $C$DW$83, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 20 + + 1046 .dwattr $C$DW$83, DW_AT_accessibility(DW_ACCESS_public) + 1047 .dwattr $C$DW$83, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1048 .dwattr $C$DW$83, DW_AT_decl_line(0xec) + 1049 .dwattr $C$DW$83, DW_AT_decl_column(0x0d) + 1050$C$DW$84 .dwtag DW_TAG_member + 1051 .dwattr $C$DW$84, DW_AT_type(*$C$DW$T$11) + 1052 .dwattr $C$DW$84, DW_AT_name("rsvd2") + 1053 .dwattr $C$DW$84, DW_AT_TI_symbol_name("rsvd2") + 1054 .dwattr $C$DW$84, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x18) + 1055 .dwattr $C$DW$84, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1056 .dwattr $C$DW$84, DW_AT_accessibility(DW_ACCESS_public) + 1057 .dwattr $C$DW$84, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1058 .dwattr $C$DW$84, DW_AT_decl_line(0xed) + 1059 .dwattr $C$DW$84, DW_AT_decl_column(0x0d) + 1060 .dwendtag $C$DW$T$31 + 1061 + 1062 .dwattr $C$DW$T$31, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1063 .dwattr $C$DW$T$31, DW_AT_decl_line(0xeb) + 1064 .dwattr $C$DW$T$31, DW_AT_decl_column(0x13) + 1065$C$DW$T$72 .dwtag DW_TAG_volatile_type + 1066 .dwattr $C$DW$T$72, DW_AT_type(*$C$DW$T$31) + 1067 + 1068$C$DW$T$35 .dwtag DW_TAG_structure_type + 1069 .dwattr $C$DW$T$35, DW_AT_byte_size(0x44) + 1070$C$DW$85 .dwtag DW_TAG_member + 1071 .dwattr $C$DW$85, DW_AT_type(*$C$DW$T$49) + 1072 .dwattr $C$DW$85, DW_AT_name("$P$T0") + 1073 .dwattr $C$DW$85, DW_AT_TI_symbol_name("$P$T0") + 1074 .dwattr $C$DW$85, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1075 .dwattr $C$DW$85, DW_AT_accessibility(DW_ACCESS_public) + 1076 .dwattr $C$DW$85, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1077 .dwattr $C$DW$85, DW_AT_decl_line(0x29) + 1078 .dwattr $C$DW$85, DW_AT_decl_column(0x02) + 1079$C$DW$86 .dwtag DW_TAG_member + 1080 .dwattr $C$DW$86, DW_AT_type(*$C$DW$T$51) + 1081 .dwattr $C$DW$86, DW_AT_name("$P$T1") + 1082 .dwattr $C$DW$86, DW_AT_TI_symbol_name("$P$T1") + 1083 .dwattr $C$DW$86, DW_AT_data_member_location[DW_OP_plus_uconst 0x4] + 1084 .dwattr $C$DW$86, DW_AT_accessibility(DW_ACCESS_public) + 1085 .dwattr $C$DW$86, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1086 .dwattr $C$DW$86, DW_AT_decl_line(0x33) + 1087 .dwattr $C$DW$86, DW_AT_decl_column(0x02) + 1088$C$DW$87 .dwtag DW_TAG_member + 1089 .dwattr $C$DW$87, DW_AT_type(*$C$DW$T$53) + 1090 .dwattr $C$DW$87, DW_AT_name("$P$T2") + 1091 .dwattr $C$DW$87, DW_AT_TI_symbol_name("$P$T2") + 1092 .dwattr $C$DW$87, DW_AT_data_member_location[DW_OP_plus_uconst 0x8] + 1093 .dwattr $C$DW$87, DW_AT_accessibility(DW_ACCESS_public) + 1094 .dwattr $C$DW$87, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1095 .dwattr $C$DW$87, DW_AT_decl_line(0x41) + 1096 .dwattr $C$DW$87, DW_AT_decl_column(0x02) + 1097$C$DW$88 .dwtag DW_TAG_member + 1098 .dwattr $C$DW$88, DW_AT_type(*$C$DW$T$55) + 1099 .dwattr $C$DW$88, DW_AT_name("$P$T3") + 1100 .dwattr $C$DW$88, DW_AT_TI_symbol_name("$P$T3") +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 21 + + 1101 .dwattr $C$DW$88, DW_AT_data_member_location[DW_OP_plus_uconst 0xc] + 1102 .dwattr $C$DW$88, DW_AT_accessibility(DW_ACCESS_public) + 1103 .dwattr $C$DW$88, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1104 .dwattr $C$DW$88, DW_AT_decl_line(0x54) + 1105 .dwattr $C$DW$88, DW_AT_decl_column(0x02) + 1106$C$DW$89 .dwtag DW_TAG_member + 1107 .dwattr $C$DW$89, DW_AT_type(*$C$DW$T$57) + 1108 .dwattr $C$DW$89, DW_AT_name("$P$T4") + 1109 .dwattr $C$DW$89, DW_AT_TI_symbol_name("$P$T4") + 1110 .dwattr $C$DW$89, DW_AT_data_member_location[DW_OP_plus_uconst 0x10] + 1111 .dwattr $C$DW$89, DW_AT_accessibility(DW_ACCESS_public) + 1112 .dwattr $C$DW$89, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1113 .dwattr $C$DW$89, DW_AT_decl_line(0x67) + 1114 .dwattr $C$DW$89, DW_AT_decl_column(0x02) + 1115$C$DW$90 .dwtag DW_TAG_member + 1116 .dwattr $C$DW$90, DW_AT_type(*$C$DW$T$59) + 1117 .dwattr $C$DW$90, DW_AT_name("$P$T5") + 1118 .dwattr $C$DW$90, DW_AT_TI_symbol_name("$P$T5") + 1119 .dwattr $C$DW$90, DW_AT_data_member_location[DW_OP_plus_uconst 0x14] + 1120 .dwattr $C$DW$90, DW_AT_accessibility(DW_ACCESS_public) + 1121 .dwattr $C$DW$90, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1122 .dwattr $C$DW$90, DW_AT_decl_line(0x83) + 1123 .dwattr $C$DW$90, DW_AT_decl_column(0x02) + 1124$C$DW$91 .dwtag DW_TAG_member + 1125 .dwattr $C$DW$91, DW_AT_type(*$C$DW$T$61) + 1126 .dwattr $C$DW$91, DW_AT_name("$P$T6") + 1127 .dwattr $C$DW$91, DW_AT_TI_symbol_name("$P$T6") + 1128 .dwattr $C$DW$91, DW_AT_data_member_location[DW_OP_plus_uconst 0x18] + 1129 .dwattr $C$DW$91, DW_AT_accessibility(DW_ACCESS_public) + 1130 .dwattr $C$DW$91, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1131 .dwattr $C$DW$91, DW_AT_decl_line(0x92) + 1132 .dwattr $C$DW$91, DW_AT_decl_column(0x02) + 1133$C$DW$92 .dwtag DW_TAG_member + 1134 .dwattr $C$DW$92, DW_AT_type(*$C$DW$T$63) + 1135 .dwattr $C$DW$92, DW_AT_name("$P$T7") + 1136 .dwattr $C$DW$92, DW_AT_TI_symbol_name("$P$T7") + 1137 .dwattr $C$DW$92, DW_AT_data_member_location[DW_OP_plus_uconst 0x1c] + 1138 .dwattr $C$DW$92, DW_AT_accessibility(DW_ACCESS_public) + 1139 .dwattr $C$DW$92, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1140 .dwattr $C$DW$92, DW_AT_decl_line(0xa0) + 1141 .dwattr $C$DW$92, DW_AT_decl_column(0x02) + 1142$C$DW$93 .dwtag DW_TAG_member + 1143 .dwattr $C$DW$93, DW_AT_type(*$C$DW$T$65) + 1144 .dwattr $C$DW$93, DW_AT_name("$P$T8") + 1145 .dwattr $C$DW$93, DW_AT_TI_symbol_name("$P$T8") + 1146 .dwattr $C$DW$93, DW_AT_data_member_location[DW_OP_plus_uconst 0x20] + 1147 .dwattr $C$DW$93, DW_AT_accessibility(DW_ACCESS_public) + 1148 .dwattr $C$DW$93, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1149 .dwattr $C$DW$93, DW_AT_decl_line(0xaf) + 1150 .dwattr $C$DW$93, DW_AT_decl_column(0x02) + 1151$C$DW$94 .dwtag DW_TAG_member + 1152 .dwattr $C$DW$94, DW_AT_type(*$C$DW$T$32) + 1153 .dwattr $C$DW$94, DW_AT_name("rsvd24") + 1154 .dwattr $C$DW$94, DW_AT_TI_symbol_name("rsvd24") + 1155 .dwattr $C$DW$94, DW_AT_data_member_location[DW_OP_plus_uconst 0x24] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 22 + + 1156 .dwattr $C$DW$94, DW_AT_accessibility(DW_ACCESS_public) + 1157 .dwattr $C$DW$94, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1158 .dwattr $C$DW$94, DW_AT_decl_line(0xbc) + 1159 .dwattr $C$DW$94, DW_AT_decl_column(0x0b) + 1160$C$DW$95 .dwtag DW_TAG_member + 1161 .dwattr $C$DW$95, DW_AT_type(*$C$DW$T$67) + 1162 .dwattr $C$DW$95, DW_AT_name("$P$T9") + 1163 .dwattr $C$DW$95, DW_AT_TI_symbol_name("$P$T9") + 1164 .dwattr $C$DW$95, DW_AT_data_member_location[DW_OP_plus_uconst 0x28] + 1165 .dwattr $C$DW$95, DW_AT_accessibility(DW_ACCESS_public) + 1166 .dwattr $C$DW$95, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1167 .dwattr $C$DW$95, DW_AT_decl_line(0xc0) + 1168 .dwattr $C$DW$95, DW_AT_decl_column(0x02) + 1169$C$DW$96 .dwtag DW_TAG_member + 1170 .dwattr $C$DW$96, DW_AT_type(*$C$DW$T$33) + 1171 .dwattr $C$DW$96, DW_AT_name("rsvd2c") + 1172 .dwattr $C$DW$96, DW_AT_TI_symbol_name("rsvd2c") + 1173 .dwattr $C$DW$96, DW_AT_data_member_location[DW_OP_plus_uconst 0x2c] + 1174 .dwattr $C$DW$96, DW_AT_accessibility(DW_ACCESS_public) + 1175 .dwattr $C$DW$96, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1176 .dwattr $C$DW$96, DW_AT_decl_line(0xcb) + 1177 .dwattr $C$DW$96, DW_AT_decl_column(0x0b) + 1178$C$DW$97 .dwtag DW_TAG_member + 1179 .dwattr $C$DW$97, DW_AT_type(*$C$DW$T$69) + 1180 .dwattr $C$DW$97, DW_AT_name("$P$T10") + 1181 .dwattr $C$DW$97, DW_AT_TI_symbol_name("$P$T10") + 1182 .dwattr $C$DW$97, DW_AT_data_member_location[DW_OP_plus_uconst 0x30] + 1183 .dwattr $C$DW$97, DW_AT_accessibility(DW_ACCESS_public) + 1184 .dwattr $C$DW$97, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1185 .dwattr $C$DW$97, DW_AT_decl_line(0xcf) + 1186 .dwattr $C$DW$97, DW_AT_decl_column(0x02) + 1187$C$DW$98 .dwtag DW_TAG_member + 1188 .dwattr $C$DW$98, DW_AT_type(*$C$DW$T$71) + 1189 .dwattr $C$DW$98, DW_AT_name("$P$T11") + 1190 .dwattr $C$DW$98, DW_AT_TI_symbol_name("$P$T11") + 1191 .dwattr $C$DW$98, DW_AT_data_member_location[DW_OP_plus_uconst 0x34] + 1192 .dwattr $C$DW$98, DW_AT_accessibility(DW_ACCESS_public) + 1193 .dwattr $C$DW$98, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1194 .dwattr $C$DW$98, DW_AT_decl_line(0xda) + 1195 .dwattr $C$DW$98, DW_AT_decl_column(0x02) + 1196$C$DW$99 .dwtag DW_TAG_member + 1197 .dwattr $C$DW$99, DW_AT_type(*$C$DW$T$34) + 1198 .dwattr $C$DW$99, DW_AT_name("rsvd38") + 1199 .dwattr $C$DW$99, DW_AT_TI_symbol_name("rsvd38") + 1200 .dwattr $C$DW$99, DW_AT_data_member_location[DW_OP_plus_uconst 0x38] + 1201 .dwattr $C$DW$99, DW_AT_accessibility(DW_ACCESS_public) + 1202 .dwattr $C$DW$99, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pru + 1203 .dwattr $C$DW$99, DW_AT_decl_line(0xe5) + 1204 .dwattr $C$DW$99, DW_AT_decl_column(0x0b) + 1205$C$DW$100 .dwtag DW_TAG_member + 1206 .dwattr $C$DW$100, DW_AT_type(*$C$DW$T$73) + 1207 .dwattr $C$DW$100, DW_AT_name("$P$T12") + 1208 .dwattr $C$DW$100, DW_AT_TI_symbol_name("$P$T12") + 1209 .dwattr $C$DW$100, DW_AT_data_member_location[DW_OP_plus_uconst 0x40] + 1210 .dwattr $C$DW$100, DW_AT_accessibility(DW_ACCESS_public) +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 23 + + 1211 .dwattr $C$DW$100, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1212 .dwattr $C$DW$100, DW_AT_decl_line(0xe8) + 1213 .dwattr $C$DW$100, DW_AT_decl_column(0x02) + 1214 .dwendtag $C$DW$T$35 + 1215 + 1216 .dwattr $C$DW$T$35, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1217 .dwattr $C$DW$T$35, DW_AT_decl_line(0x26) + 1218 .dwattr $C$DW$T$35, DW_AT_decl_column(0x10) + 1219$C$DW$T$97 .dwtag DW_TAG_typedef, DW_AT_name("pruCfg") + 1220 .dwattr $C$DW$T$97, DW_AT_type(*$C$DW$T$35) + 1221 .dwattr $C$DW$T$97, DW_AT_language(DW_LANG_C) + 1222 .dwattr $C$DW$T$97, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1223 .dwattr $C$DW$T$97, DW_AT_decl_line(0xf0) + 1224 .dwattr $C$DW$T$97, DW_AT_decl_column(0x03) + 1225$C$DW$T$98 .dwtag DW_TAG_volatile_type + 1226 .dwattr $C$DW$T$98, DW_AT_type(*$C$DW$T$97) + 1227 + 1228$C$DW$T$36 .dwtag DW_TAG_structure_type + 1229 .dwattr $C$DW$T$36, DW_AT_byte_size(0x04) + 1230$C$DW$101 .dwtag DW_TAG_member + 1231 .dwattr $C$DW$101, DW_AT_type(*$C$DW$T$11) + 1232 .dwattr $C$DW$101, DW_AT_name("SOFT_RST_N") + 1233 .dwattr $C$DW$101, DW_AT_TI_symbol_name("SOFT_RST_N") + 1234 .dwattr $C$DW$101, DW_AT_bit_offset(0x1f), DW_AT_bit_size(0x01) + 1235 .dwattr $C$DW$101, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1236 .dwattr $C$DW$101, DW_AT_accessibility(DW_ACCESS_public) + 1237 .dwattr $C$DW$101, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1238 .dwattr $C$DW$101, DW_AT_decl_line(0x2d) + 1239 .dwattr $C$DW$101, DW_AT_decl_column(0x0d) + 1240$C$DW$102 .dwtag DW_TAG_member + 1241 .dwattr $C$DW$102, DW_AT_type(*$C$DW$T$11) + 1242 .dwattr $C$DW$102, DW_AT_name("EN") + 1243 .dwattr $C$DW$102, DW_AT_TI_symbol_name("EN") + 1244 .dwattr $C$DW$102, DW_AT_bit_offset(0x1e), DW_AT_bit_size(0x01) + 1245 .dwattr $C$DW$102, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1246 .dwattr $C$DW$102, DW_AT_accessibility(DW_ACCESS_public) + 1247 .dwattr $C$DW$102, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1248 .dwattr $C$DW$102, DW_AT_decl_line(0x2e) + 1249 .dwattr $C$DW$102, DW_AT_decl_column(0x0d) + 1250$C$DW$103 .dwtag DW_TAG_member + 1251 .dwattr $C$DW$103, DW_AT_type(*$C$DW$T$11) + 1252 .dwattr $C$DW$103, DW_AT_name("SLEEPING") + 1253 .dwattr $C$DW$103, DW_AT_TI_symbol_name("SLEEPING") + 1254 .dwattr $C$DW$103, DW_AT_bit_offset(0x1d), DW_AT_bit_size(0x01) + 1255 .dwattr $C$DW$103, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1256 .dwattr $C$DW$103, DW_AT_accessibility(DW_ACCESS_public) + 1257 .dwattr $C$DW$103, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1258 .dwattr $C$DW$103, DW_AT_decl_line(0x2f) + 1259 .dwattr $C$DW$103, DW_AT_decl_column(0x0d) + 1260$C$DW$104 .dwtag DW_TAG_member + 1261 .dwattr $C$DW$104, DW_AT_type(*$C$DW$T$11) + 1262 .dwattr $C$DW$104, DW_AT_name("CTR_EN") + 1263 .dwattr $C$DW$104, DW_AT_TI_symbol_name("CTR_EN") + 1264 .dwattr $C$DW$104, DW_AT_bit_offset(0x1c), DW_AT_bit_size(0x01) + 1265 .dwattr $C$DW$104, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 24 + + 1266 .dwattr $C$DW$104, DW_AT_accessibility(DW_ACCESS_public) + 1267 .dwattr $C$DW$104, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1268 .dwattr $C$DW$104, DW_AT_decl_line(0x30) + 1269 .dwattr $C$DW$104, DW_AT_decl_column(0x0d) + 1270$C$DW$105 .dwtag DW_TAG_member + 1271 .dwattr $C$DW$105, DW_AT_type(*$C$DW$T$11) + 1272 .dwattr $C$DW$105, DW_AT_name("rsvd4") + 1273 .dwattr $C$DW$105, DW_AT_TI_symbol_name("rsvd4") + 1274 .dwattr $C$DW$105, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x04) + 1275 .dwattr $C$DW$105, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1276 .dwattr $C$DW$105, DW_AT_accessibility(DW_ACCESS_public) + 1277 .dwattr $C$DW$105, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1278 .dwattr $C$DW$105, DW_AT_decl_line(0x31) + 1279 .dwattr $C$DW$105, DW_AT_decl_column(0x0d) + 1280$C$DW$106 .dwtag DW_TAG_member + 1281 .dwattr $C$DW$106, DW_AT_type(*$C$DW$T$11) + 1282 .dwattr $C$DW$106, DW_AT_name("SINGLE_STEP") + 1283 .dwattr $C$DW$106, DW_AT_TI_symbol_name("SINGLE_STEP") + 1284 .dwattr $C$DW$106, DW_AT_bit_offset(0x17), DW_AT_bit_size(0x01) + 1285 .dwattr $C$DW$106, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1286 .dwattr $C$DW$106, DW_AT_accessibility(DW_ACCESS_public) + 1287 .dwattr $C$DW$106, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1288 .dwattr $C$DW$106, DW_AT_decl_line(0x32) + 1289 .dwattr $C$DW$106, DW_AT_decl_column(0x0d) + 1290$C$DW$107 .dwtag DW_TAG_member + 1291 .dwattr $C$DW$107, DW_AT_type(*$C$DW$T$11) + 1292 .dwattr $C$DW$107, DW_AT_name("rsvd9") + 1293 .dwattr $C$DW$107, DW_AT_TI_symbol_name("rsvd9") + 1294 .dwattr $C$DW$107, DW_AT_bit_offset(0x11), DW_AT_bit_size(0x06) + 1295 .dwattr $C$DW$107, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1296 .dwattr $C$DW$107, DW_AT_accessibility(DW_ACCESS_public) + 1297 .dwattr $C$DW$107, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1298 .dwattr $C$DW$107, DW_AT_decl_line(0x33) + 1299 .dwattr $C$DW$107, DW_AT_decl_column(0x0d) + 1300$C$DW$108 .dwtag DW_TAG_member + 1301 .dwattr $C$DW$108, DW_AT_type(*$C$DW$T$11) + 1302 .dwattr $C$DW$108, DW_AT_name("RUNSTATE") + 1303 .dwattr $C$DW$108, DW_AT_TI_symbol_name("RUNSTATE") + 1304 .dwattr $C$DW$108, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x01) + 1305 .dwattr $C$DW$108, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1306 .dwattr $C$DW$108, DW_AT_accessibility(DW_ACCESS_public) + 1307 .dwattr $C$DW$108, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1308 .dwattr $C$DW$108, DW_AT_decl_line(0x34) + 1309 .dwattr $C$DW$108, DW_AT_decl_column(0x0d) + 1310$C$DW$109 .dwtag DW_TAG_member + 1311 .dwattr $C$DW$109, DW_AT_type(*$C$DW$T$11) + 1312 .dwattr $C$DW$109, DW_AT_name("PCTR_RST_VAL") + 1313 .dwattr $C$DW$109, DW_AT_TI_symbol_name("PCTR_RST_VAL") + 1314 .dwattr $C$DW$109, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x10) + 1315 .dwattr $C$DW$109, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1316 .dwattr $C$DW$109, DW_AT_accessibility(DW_ACCESS_public) + 1317 .dwattr $C$DW$109, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1318 .dwattr $C$DW$109, DW_AT_decl_line(0x35) + 1319 .dwattr $C$DW$109, DW_AT_decl_column(0x0d) + 1320 .dwendtag $C$DW$T$36 +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 25 + + 1321 + 1322 .dwattr $C$DW$T$36, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1323 .dwattr $C$DW$T$36, DW_AT_decl_line(0x2c) + 1324 .dwattr $C$DW$T$36, DW_AT_decl_column(0x13) + 1325$C$DW$T$74 .dwtag DW_TAG_volatile_type + 1326 .dwattr $C$DW$T$74, DW_AT_type(*$C$DW$T$36) + 1327 + 1328$C$DW$T$37 .dwtag DW_TAG_structure_type + 1329 .dwattr $C$DW$T$37, DW_AT_byte_size(0x04) + 1330$C$DW$110 .dwtag DW_TAG_member + 1331 .dwattr $C$DW$110, DW_AT_type(*$C$DW$T$11) + 1332 .dwattr $C$DW$110, DW_AT_name("PCTR") + 1333 .dwattr $C$DW$110, DW_AT_TI_symbol_name("PCTR") + 1334 .dwattr $C$DW$110, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x10) + 1335 .dwattr $C$DW$110, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1336 .dwattr $C$DW$110, DW_AT_accessibility(DW_ACCESS_public) + 1337 .dwattr $C$DW$110, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1338 .dwattr $C$DW$110, DW_AT_decl_line(0x3f) + 1339 .dwattr $C$DW$110, DW_AT_decl_column(0x0d) + 1340$C$DW$111 .dwtag DW_TAG_member + 1341 .dwattr $C$DW$111, DW_AT_type(*$C$DW$T$11) + 1342 .dwattr $C$DW$111, DW_AT_name("rsvd16") + 1343 .dwattr $C$DW$111, DW_AT_TI_symbol_name("rsvd16") + 1344 .dwattr $C$DW$111, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x10) + 1345 .dwattr $C$DW$111, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1346 .dwattr $C$DW$111, DW_AT_accessibility(DW_ACCESS_public) + 1347 .dwattr $C$DW$111, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1348 .dwattr $C$DW$111, DW_AT_decl_line(0x40) + 1349 .dwattr $C$DW$111, DW_AT_decl_column(0x0d) + 1350 .dwendtag $C$DW$T$37 + 1351 + 1352 .dwattr $C$DW$T$37, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1353 .dwattr $C$DW$T$37, DW_AT_decl_line(0x3e) + 1354 .dwattr $C$DW$T$37, DW_AT_decl_column(0x13) + 1355$C$DW$T$76 .dwtag DW_TAG_volatile_type + 1356 .dwattr $C$DW$T$76, DW_AT_type(*$C$DW$T$37) + 1357 + 1358$C$DW$T$38 .dwtag DW_TAG_structure_type + 1359 .dwattr $C$DW$T$38, DW_AT_byte_size(0x04) + 1360$C$DW$112 .dwtag DW_TAG_member + 1361 .dwattr $C$DW$112, DW_AT_type(*$C$DW$T$11) + 1362 .dwattr $C$DW$112, DW_AT_name("BITWISE_ENS") + 1363 .dwattr $C$DW$112, DW_AT_TI_symbol_name("BITWISE_ENS") + 1364 .dwattr $C$DW$112, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x20) + 1365 .dwattr $C$DW$112, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1366 .dwattr $C$DW$112, DW_AT_accessibility(DW_ACCESS_public) + 1367 .dwattr $C$DW$112, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1368 .dwattr $C$DW$112, DW_AT_decl_line(0x4a) + 1369 .dwattr $C$DW$112, DW_AT_decl_column(0x0d) + 1370 .dwendtag $C$DW$T$38 + 1371 + 1372 .dwattr $C$DW$T$38, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1373 .dwattr $C$DW$T$38, DW_AT_decl_line(0x49) + 1374 .dwattr $C$DW$T$38, DW_AT_decl_column(0x13) + 1375$C$DW$T$78 .dwtag DW_TAG_volatile_type +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 26 + + 1376 .dwattr $C$DW$T$78, DW_AT_type(*$C$DW$T$38) + 1377 + 1378$C$DW$T$39 .dwtag DW_TAG_structure_type + 1379 .dwattr $C$DW$T$39, DW_AT_byte_size(0x04) + 1380$C$DW$113 .dwtag DW_TAG_member + 1381 .dwattr $C$DW$113, DW_AT_type(*$C$DW$T$11) + 1382 .dwattr $C$DW$113, DW_AT_name("CYCLECOUNT") + 1383 .dwattr $C$DW$113, DW_AT_TI_symbol_name("CYCLECOUNT") + 1384 .dwattr $C$DW$113, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x20) + 1385 .dwattr $C$DW$113, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1386 .dwattr $C$DW$113, DW_AT_accessibility(DW_ACCESS_public) + 1387 .dwattr $C$DW$113, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1388 .dwattr $C$DW$113, DW_AT_decl_line(0x54) + 1389 .dwattr $C$DW$113, DW_AT_decl_column(0x0d) + 1390 .dwendtag $C$DW$T$39 + 1391 + 1392 .dwattr $C$DW$T$39, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1393 .dwattr $C$DW$T$39, DW_AT_decl_line(0x53) + 1394 .dwattr $C$DW$T$39, DW_AT_decl_column(0x13) + 1395$C$DW$T$80 .dwtag DW_TAG_volatile_type + 1396 .dwattr $C$DW$T$80, DW_AT_type(*$C$DW$T$39) + 1397 + 1398$C$DW$T$40 .dwtag DW_TAG_structure_type + 1399 .dwattr $C$DW$T$40, DW_AT_byte_size(0x04) + 1400$C$DW$114 .dwtag DW_TAG_member + 1401 .dwattr $C$DW$114, DW_AT_type(*$C$DW$T$11) + 1402 .dwattr $C$DW$114, DW_AT_name("STALLCOUNT") + 1403 .dwattr $C$DW$114, DW_AT_TI_symbol_name("STALLCOUNT") + 1404 .dwattr $C$DW$114, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x20) + 1405 .dwattr $C$DW$114, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1406 .dwattr $C$DW$114, DW_AT_accessibility(DW_ACCESS_public) + 1407 .dwattr $C$DW$114, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1408 .dwattr $C$DW$114, DW_AT_decl_line(0x5e) + 1409 .dwattr $C$DW$114, DW_AT_decl_column(0x0d) + 1410 .dwendtag $C$DW$T$40 + 1411 + 1412 .dwattr $C$DW$T$40, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1413 .dwattr $C$DW$T$40, DW_AT_decl_line(0x5d) + 1414 .dwattr $C$DW$T$40, DW_AT_decl_column(0x14) + 1415$C$DW$T$82 .dwtag DW_TAG_volatile_type + 1416 .dwattr $C$DW$T$82, DW_AT_type(*$C$DW$T$40) + 1417 + 1418$C$DW$T$41 .dwtag DW_TAG_structure_type + 1419 .dwattr $C$DW$T$41, DW_AT_byte_size(0x04) + 1420$C$DW$115 .dwtag DW_TAG_member + 1421 .dwattr $C$DW$115, DW_AT_type(*$C$DW$T$11) + 1422 .dwattr $C$DW$115, DW_AT_name("C24_BLK_IDX") + 1423 .dwattr $C$DW$115, DW_AT_TI_symbol_name("C24_BLK_IDX") + 1424 .dwattr $C$DW$115, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x08) + 1425 .dwattr $C$DW$115, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1426 .dwattr $C$DW$115, DW_AT_accessibility(DW_ACCESS_public) + 1427 .dwattr $C$DW$115, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1428 .dwattr $C$DW$115, DW_AT_decl_line(0x6b) + 1429 .dwattr $C$DW$115, DW_AT_decl_column(0x0d) + 1430$C$DW$116 .dwtag DW_TAG_member +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 27 + + 1431 .dwattr $C$DW$116, DW_AT_type(*$C$DW$T$11) + 1432 .dwattr $C$DW$116, DW_AT_name("rsvd8") + 1433 .dwattr $C$DW$116, DW_AT_TI_symbol_name("rsvd8") + 1434 .dwattr $C$DW$116, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x08) + 1435 .dwattr $C$DW$116, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1436 .dwattr $C$DW$116, DW_AT_accessibility(DW_ACCESS_public) + 1437 .dwattr $C$DW$116, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1438 .dwattr $C$DW$116, DW_AT_decl_line(0x6c) + 1439 .dwattr $C$DW$116, DW_AT_decl_column(0x0d) + 1440$C$DW$117 .dwtag DW_TAG_member + 1441 .dwattr $C$DW$117, DW_AT_type(*$C$DW$T$11) + 1442 .dwattr $C$DW$117, DW_AT_name("C25_BLK_IDX") + 1443 .dwattr $C$DW$117, DW_AT_TI_symbol_name("C25_BLK_IDX") + 1444 .dwattr $C$DW$117, DW_AT_bit_offset(0x08), DW_AT_bit_size(0x08) + 1445 .dwattr $C$DW$117, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1446 .dwattr $C$DW$117, DW_AT_accessibility(DW_ACCESS_public) + 1447 .dwattr $C$DW$117, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1448 .dwattr $C$DW$117, DW_AT_decl_line(0x6d) + 1449 .dwattr $C$DW$117, DW_AT_decl_column(0x0d) + 1450$C$DW$118 .dwtag DW_TAG_member + 1451 .dwattr $C$DW$118, DW_AT_type(*$C$DW$T$11) + 1452 .dwattr $C$DW$118, DW_AT_name("rsvd24") + 1453 .dwattr $C$DW$118, DW_AT_TI_symbol_name("rsvd24") + 1454 .dwattr $C$DW$118, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x08) + 1455 .dwattr $C$DW$118, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1456 .dwattr $C$DW$118, DW_AT_accessibility(DW_ACCESS_public) + 1457 .dwattr $C$DW$118, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1458 .dwattr $C$DW$118, DW_AT_decl_line(0x6e) + 1459 .dwattr $C$DW$118, DW_AT_decl_column(0x0d) + 1460 .dwendtag $C$DW$T$41 + 1461 + 1462 .dwattr $C$DW$T$41, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1463 .dwattr $C$DW$T$41, DW_AT_decl_line(0x6a) + 1464 .dwattr $C$DW$T$41, DW_AT_decl_column(0x13) + 1465$C$DW$T$84 .dwtag DW_TAG_volatile_type + 1466 .dwattr $C$DW$T$84, DW_AT_type(*$C$DW$T$41) + 1467 + 1468$C$DW$T$42 .dwtag DW_TAG_structure_type + 1469 .dwattr $C$DW$T$42, DW_AT_byte_size(0x04) + 1470$C$DW$119 .dwtag DW_TAG_member + 1471 .dwattr $C$DW$119, DW_AT_type(*$C$DW$T$11) + 1472 .dwattr $C$DW$119, DW_AT_name("C26_BLK_IDX") + 1473 .dwattr $C$DW$119, DW_AT_TI_symbol_name("C26_BLK_IDX") + 1474 .dwattr $C$DW$119, DW_AT_bit_offset(0x18), DW_AT_bit_size(0x08) + 1475 .dwattr $C$DW$119, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1476 .dwattr $C$DW$119, DW_AT_accessibility(DW_ACCESS_public) + 1477 .dwattr $C$DW$119, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1478 .dwattr $C$DW$119, DW_AT_decl_line(0x78) + 1479 .dwattr $C$DW$119, DW_AT_decl_column(0x0d) + 1480$C$DW$120 .dwtag DW_TAG_member + 1481 .dwattr $C$DW$120, DW_AT_type(*$C$DW$T$11) + 1482 .dwattr $C$DW$120, DW_AT_name("rsvd8") + 1483 .dwattr $C$DW$120, DW_AT_TI_symbol_name("rsvd8") + 1484 .dwattr $C$DW$120, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x08) + 1485 .dwattr $C$DW$120, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 28 + + 1486 .dwattr $C$DW$120, DW_AT_accessibility(DW_ACCESS_public) + 1487 .dwattr $C$DW$120, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1488 .dwattr $C$DW$120, DW_AT_decl_line(0x79) + 1489 .dwattr $C$DW$120, DW_AT_decl_column(0x0d) + 1490$C$DW$121 .dwtag DW_TAG_member + 1491 .dwattr $C$DW$121, DW_AT_type(*$C$DW$T$11) + 1492 .dwattr $C$DW$121, DW_AT_name("C27_BLK_IDX") + 1493 .dwattr $C$DW$121, DW_AT_TI_symbol_name("C27_BLK_IDX") + 1494 .dwattr $C$DW$121, DW_AT_bit_offset(0x08), DW_AT_bit_size(0x08) + 1495 .dwattr $C$DW$121, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1496 .dwattr $C$DW$121, DW_AT_accessibility(DW_ACCESS_public) + 1497 .dwattr $C$DW$121, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1498 .dwattr $C$DW$121, DW_AT_decl_line(0x7a) + 1499 .dwattr $C$DW$121, DW_AT_decl_column(0x0d) + 1500$C$DW$122 .dwtag DW_TAG_member + 1501 .dwattr $C$DW$122, DW_AT_type(*$C$DW$T$11) + 1502 .dwattr $C$DW$122, DW_AT_name("rsvd24") + 1503 .dwattr $C$DW$122, DW_AT_TI_symbol_name("rsvd24") + 1504 .dwattr $C$DW$122, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x08) + 1505 .dwattr $C$DW$122, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1506 .dwattr $C$DW$122, DW_AT_accessibility(DW_ACCESS_public) + 1507 .dwattr $C$DW$122, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1508 .dwattr $C$DW$122, DW_AT_decl_line(0x7b) + 1509 .dwattr $C$DW$122, DW_AT_decl_column(0x0d) + 1510 .dwendtag $C$DW$T$42 + 1511 + 1512 .dwattr $C$DW$T$42, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1513 .dwattr $C$DW$T$42, DW_AT_decl_line(0x77) + 1514 .dwattr $C$DW$T$42, DW_AT_decl_column(0x13) + 1515$C$DW$T$86 .dwtag DW_TAG_volatile_type + 1516 .dwattr $C$DW$T$86, DW_AT_type(*$C$DW$T$42) + 1517 + 1518$C$DW$T$43 .dwtag DW_TAG_structure_type + 1519 .dwattr $C$DW$T$43, DW_AT_byte_size(0x04) + 1520$C$DW$123 .dwtag DW_TAG_member + 1521 .dwattr $C$DW$123, DW_AT_type(*$C$DW$T$11) + 1522 .dwattr $C$DW$123, DW_AT_name("C28_BLK_POINTER") + 1523 .dwattr $C$DW$123, DW_AT_TI_symbol_name("C28_BLK_POINTER") + 1524 .dwattr $C$DW$123, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x10) + 1525 .dwattr $C$DW$123, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1526 .dwattr $C$DW$123, DW_AT_accessibility(DW_ACCESS_public) + 1527 .dwattr $C$DW$123, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1528 .dwattr $C$DW$123, DW_AT_decl_line(0x85) + 1529 .dwattr $C$DW$123, DW_AT_decl_column(0x0d) + 1530$C$DW$124 .dwtag DW_TAG_member + 1531 .dwattr $C$DW$124, DW_AT_type(*$C$DW$T$11) + 1532 .dwattr $C$DW$124, DW_AT_name("C29_BLK_POINTER") + 1533 .dwattr $C$DW$124, DW_AT_TI_symbol_name("C29_BLK_POINTER") + 1534 .dwattr $C$DW$124, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x10) + 1535 .dwattr $C$DW$124, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1536 .dwattr $C$DW$124, DW_AT_accessibility(DW_ACCESS_public) + 1537 .dwattr $C$DW$124, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1538 .dwattr $C$DW$124, DW_AT_decl_line(0x86) + 1539 .dwattr $C$DW$124, DW_AT_decl_column(0x0d) + 1540 .dwendtag $C$DW$T$43 +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 29 + + 1541 + 1542 .dwattr $C$DW$T$43, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1543 .dwattr $C$DW$T$43, DW_AT_decl_line(0x84) + 1544 .dwattr $C$DW$T$43, DW_AT_decl_column(0x13) + 1545$C$DW$T$88 .dwtag DW_TAG_volatile_type + 1546 .dwattr $C$DW$T$88, DW_AT_type(*$C$DW$T$43) + 1547 + 1548$C$DW$T$44 .dwtag DW_TAG_structure_type + 1549 .dwattr $C$DW$T$44, DW_AT_byte_size(0x04) + 1550$C$DW$125 .dwtag DW_TAG_member + 1551 .dwattr $C$DW$125, DW_AT_type(*$C$DW$T$11) + 1552 .dwattr $C$DW$125, DW_AT_name("C30_BLK_POINTER") + 1553 .dwattr $C$DW$125, DW_AT_TI_symbol_name("C30_BLK_POINTER") + 1554 .dwattr $C$DW$125, DW_AT_bit_offset(0x10), DW_AT_bit_size(0x10) + 1555 .dwattr $C$DW$125, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1556 .dwattr $C$DW$125, DW_AT_accessibility(DW_ACCESS_public) + 1557 .dwattr $C$DW$125, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1558 .dwattr $C$DW$125, DW_AT_decl_line(0x90) + 1559 .dwattr $C$DW$125, DW_AT_decl_column(0x0d) + 1560$C$DW$126 .dwtag DW_TAG_member + 1561 .dwattr $C$DW$126, DW_AT_type(*$C$DW$T$11) + 1562 .dwattr $C$DW$126, DW_AT_name("C31_BLK_POINTER") + 1563 .dwattr $C$DW$126, DW_AT_TI_symbol_name("C31_BLK_POINTER") + 1564 .dwattr $C$DW$126, DW_AT_bit_offset(0x00), DW_AT_bit_size(0x10) + 1565 .dwattr $C$DW$126, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1566 .dwattr $C$DW$126, DW_AT_accessibility(DW_ACCESS_public) + 1567 .dwattr $C$DW$126, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1568 .dwattr $C$DW$126, DW_AT_decl_line(0x91) + 1569 .dwattr $C$DW$126, DW_AT_decl_column(0x0d) + 1570 .dwendtag $C$DW$T$44 + 1571 + 1572 .dwattr $C$DW$T$44, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1573 .dwattr $C$DW$T$44, DW_AT_decl_line(0x8f) + 1574 .dwattr $C$DW$T$44, DW_AT_decl_column(0x13) + 1575$C$DW$T$90 .dwtag DW_TAG_volatile_type + 1576 .dwattr $C$DW$T$90, DW_AT_type(*$C$DW$T$44) + 1577 + 1578$C$DW$T$46 .dwtag DW_TAG_structure_type + 1579 .dwattr $C$DW$T$46, DW_AT_byte_size(0x30) + 1580$C$DW$127 .dwtag DW_TAG_member + 1581 .dwattr $C$DW$127, DW_AT_type(*$C$DW$T$75) + 1582 .dwattr $C$DW$127, DW_AT_name("$P$T13") + 1583 .dwattr $C$DW$127, DW_AT_TI_symbol_name("$P$T13") + 1584 .dwattr $C$DW$127, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1585 .dwattr $C$DW$127, DW_AT_accessibility(DW_ACCESS_public) + 1586 .dwattr $C$DW$127, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1587 .dwattr $C$DW$127, DW_AT_decl_line(0x29) + 1588 .dwattr $C$DW$127, DW_AT_decl_column(0x02) + 1589$C$DW$128 .dwtag DW_TAG_member + 1590 .dwattr $C$DW$128, DW_AT_type(*$C$DW$T$77) + 1591 .dwattr $C$DW$128, DW_AT_name("$P$T14") + 1592 .dwattr $C$DW$128, DW_AT_TI_symbol_name("$P$T14") + 1593 .dwattr $C$DW$128, DW_AT_data_member_location[DW_OP_plus_uconst 0x4] + 1594 .dwattr $C$DW$128, DW_AT_accessibility(DW_ACCESS_public) + 1595 .dwattr $C$DW$128, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 30 + + 1596 .dwattr $C$DW$128, DW_AT_decl_line(0x3b) + 1597 .dwattr $C$DW$128, DW_AT_decl_column(0x02) + 1598$C$DW$129 .dwtag DW_TAG_member + 1599 .dwattr $C$DW$129, DW_AT_type(*$C$DW$T$79) + 1600 .dwattr $C$DW$129, DW_AT_name("$P$T15") + 1601 .dwattr $C$DW$129, DW_AT_TI_symbol_name("$P$T15") + 1602 .dwattr $C$DW$129, DW_AT_data_member_location[DW_OP_plus_uconst 0x8] + 1603 .dwattr $C$DW$129, DW_AT_accessibility(DW_ACCESS_public) + 1604 .dwattr $C$DW$129, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1605 .dwattr $C$DW$129, DW_AT_decl_line(0x46) + 1606 .dwattr $C$DW$129, DW_AT_decl_column(0x02) + 1607$C$DW$130 .dwtag DW_TAG_member + 1608 .dwattr $C$DW$130, DW_AT_type(*$C$DW$T$81) + 1609 .dwattr $C$DW$130, DW_AT_name("$P$T16") + 1610 .dwattr $C$DW$130, DW_AT_TI_symbol_name("$P$T16") + 1611 .dwattr $C$DW$130, DW_AT_data_member_location[DW_OP_plus_uconst 0xc] + 1612 .dwattr $C$DW$130, DW_AT_accessibility(DW_ACCESS_public) + 1613 .dwattr $C$DW$130, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1614 .dwattr $C$DW$130, DW_AT_decl_line(0x50) + 1615 .dwattr $C$DW$130, DW_AT_decl_column(0x02) + 1616$C$DW$131 .dwtag DW_TAG_member + 1617 .dwattr $C$DW$131, DW_AT_type(*$C$DW$T$83) + 1618 .dwattr $C$DW$131, DW_AT_name("$P$T17") + 1619 .dwattr $C$DW$131, DW_AT_TI_symbol_name("$P$T17") + 1620 .dwattr $C$DW$131, DW_AT_data_member_location[DW_OP_plus_uconst 0x10] + 1621 .dwattr $C$DW$131, DW_AT_accessibility(DW_ACCESS_public) + 1622 .dwattr $C$DW$131, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1623 .dwattr $C$DW$131, DW_AT_decl_line(0x5a) + 1624 .dwattr $C$DW$131, DW_AT_decl_column(0x02) + 1625$C$DW$132 .dwtag DW_TAG_member + 1626 .dwattr $C$DW$132, DW_AT_type(*$C$DW$T$45) + 1627 .dwattr $C$DW$132, DW_AT_name("rsvd14") + 1628 .dwattr $C$DW$132, DW_AT_TI_symbol_name("rsvd14") + 1629 .dwattr $C$DW$132, DW_AT_data_member_location[DW_OP_plus_uconst 0x14] + 1630 .dwattr $C$DW$132, DW_AT_accessibility(DW_ACCESS_public) + 1631 .dwattr $C$DW$132, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1632 .dwattr $C$DW$132, DW_AT_decl_line(0x63) + 1633 .dwattr $C$DW$132, DW_AT_decl_column(0x0b) + 1634$C$DW$133 .dwtag DW_TAG_member + 1635 .dwattr $C$DW$133, DW_AT_type(*$C$DW$T$85) + 1636 .dwattr $C$DW$133, DW_AT_name("$P$T18") + 1637 .dwattr $C$DW$133, DW_AT_TI_symbol_name("$P$T18") + 1638 .dwattr $C$DW$133, DW_AT_data_member_location[DW_OP_plus_uconst 0x20] + 1639 .dwattr $C$DW$133, DW_AT_accessibility(DW_ACCESS_public) + 1640 .dwattr $C$DW$133, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1641 .dwattr $C$DW$133, DW_AT_decl_line(0x67) + 1642 .dwattr $C$DW$133, DW_AT_decl_column(0x02) + 1643$C$DW$134 .dwtag DW_TAG_member + 1644 .dwattr $C$DW$134, DW_AT_type(*$C$DW$T$87) + 1645 .dwattr $C$DW$134, DW_AT_name("$P$T19") + 1646 .dwattr $C$DW$134, DW_AT_TI_symbol_name("$P$T19") + 1647 .dwattr $C$DW$134, DW_AT_data_member_location[DW_OP_plus_uconst 0x24] + 1648 .dwattr $C$DW$134, DW_AT_accessibility(DW_ACCESS_public) + 1649 .dwattr $C$DW$134, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1650 .dwattr $C$DW$134, DW_AT_decl_line(0x74) +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 31 + + 1651 .dwattr $C$DW$134, DW_AT_decl_column(0x02) + 1652$C$DW$135 .dwtag DW_TAG_member + 1653 .dwattr $C$DW$135, DW_AT_type(*$C$DW$T$89) + 1654 .dwattr $C$DW$135, DW_AT_name("$P$T20") + 1655 .dwattr $C$DW$135, DW_AT_TI_symbol_name("$P$T20") + 1656 .dwattr $C$DW$135, DW_AT_data_member_location[DW_OP_plus_uconst 0x28] + 1657 .dwattr $C$DW$135, DW_AT_accessibility(DW_ACCESS_public) + 1658 .dwattr $C$DW$135, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1659 .dwattr $C$DW$135, DW_AT_decl_line(0x81) + 1660 .dwattr $C$DW$135, DW_AT_decl_column(0x02) + 1661$C$DW$136 .dwtag DW_TAG_member + 1662 .dwattr $C$DW$136, DW_AT_type(*$C$DW$T$91) + 1663 .dwattr $C$DW$136, DW_AT_name("$P$T21") + 1664 .dwattr $C$DW$136, DW_AT_TI_symbol_name("$P$T21") + 1665 .dwattr $C$DW$136, DW_AT_data_member_location[DW_OP_plus_uconst 0x2c] + 1666 .dwattr $C$DW$136, DW_AT_accessibility(DW_ACCESS_public) + 1667 .dwattr $C$DW$136, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1668 .dwattr $C$DW$136, DW_AT_decl_line(0x8c) + 1669 .dwattr $C$DW$136, DW_AT_decl_column(0x02) + 1670 .dwendtag $C$DW$T$46 + 1671 + 1672 .dwattr $C$DW$T$46, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1673 .dwattr $C$DW$T$46, DW_AT_decl_line(0x26) + 1674 .dwattr $C$DW$T$46, DW_AT_decl_column(0x10) + 1675$C$DW$T$102 .dwtag DW_TAG_typedef, DW_AT_name("pruCtrl") + 1676 .dwattr $C$DW$T$102, DW_AT_type(*$C$DW$T$46) + 1677 .dwattr $C$DW$T$102, DW_AT_language(DW_LANG_C) + 1678 .dwattr $C$DW$T$102, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/ + 1679 .dwattr $C$DW$T$102, DW_AT_decl_line(0x95) + 1680 .dwattr $C$DW$T$102, DW_AT_decl_column(0x03) + 1681 + 1682$C$DW$T$49 .dwtag DW_TAG_union_type + 1683 .dwattr $C$DW$T$49, DW_AT_byte_size(0x04) + 1684$C$DW$137 .dwtag DW_TAG_member + 1685 .dwattr $C$DW$137, DW_AT_type(*$C$DW$T$47) + 1686 .dwattr $C$DW$137, DW_AT_name("REVID") + 1687 .dwattr $C$DW$137, DW_AT_TI_symbol_name("REVID") + 1688 .dwattr $C$DW$137, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1689 .dwattr $C$DW$137, DW_AT_accessibility(DW_ACCESS_public) + 1690 .dwattr $C$DW$137, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1691 .dwattr $C$DW$137, DW_AT_decl_line(0x2a) + 1692 .dwattr $C$DW$137, DW_AT_decl_column(0x15) + 1693$C$DW$138 .dwtag DW_TAG_member + 1694 .dwattr $C$DW$138, DW_AT_type(*$C$DW$T$48) + 1695 .dwattr $C$DW$138, DW_AT_name("REVID_bit") + 1696 .dwattr $C$DW$138, DW_AT_TI_symbol_name("REVID_bit") + 1697 .dwattr $C$DW$138, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1698 .dwattr $C$DW$138, DW_AT_accessibility(DW_ACCESS_public) + 1699 .dwattr $C$DW$138, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1700 .dwattr $C$DW$138, DW_AT_decl_line(0x2e) + 1701 .dwattr $C$DW$138, DW_AT_decl_column(0x05) + 1702 .dwendtag $C$DW$T$49 + 1703 + 1704 .dwattr $C$DW$T$49, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1705 .dwattr $C$DW$T$49, DW_AT_decl_line(0x29) +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 32 + + 1706 .dwattr $C$DW$T$49, DW_AT_decl_column(0x08) + 1707 + 1708$C$DW$T$51 .dwtag DW_TAG_union_type + 1709 .dwattr $C$DW$T$51, DW_AT_byte_size(0x04) + 1710$C$DW$139 .dwtag DW_TAG_member + 1711 .dwattr $C$DW$139, DW_AT_type(*$C$DW$T$47) + 1712 .dwattr $C$DW$139, DW_AT_name("SYSCFG") + 1713 .dwattr $C$DW$139, DW_AT_TI_symbol_name("SYSCFG") + 1714 .dwattr $C$DW$139, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1715 .dwattr $C$DW$139, DW_AT_accessibility(DW_ACCESS_public) + 1716 .dwattr $C$DW$139, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1717 .dwattr $C$DW$139, DW_AT_decl_line(0x34) + 1718 .dwattr $C$DW$139, DW_AT_decl_column(0x15) + 1719$C$DW$140 .dwtag DW_TAG_member + 1720 .dwattr $C$DW$140, DW_AT_type(*$C$DW$T$50) + 1721 .dwattr $C$DW$140, DW_AT_name("SYSCFG_bit") + 1722 .dwattr $C$DW$140, DW_AT_TI_symbol_name("SYSCFG_bit") + 1723 .dwattr $C$DW$140, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1724 .dwattr $C$DW$140, DW_AT_accessibility(DW_ACCESS_public) + 1725 .dwattr $C$DW$140, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1726 .dwattr $C$DW$140, DW_AT_decl_line(0x3c) + 1727 .dwattr $C$DW$140, DW_AT_decl_column(0x05) + 1728 .dwendtag $C$DW$T$51 + 1729 + 1730 .dwattr $C$DW$T$51, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1731 .dwattr $C$DW$T$51, DW_AT_decl_line(0x33) + 1732 .dwattr $C$DW$T$51, DW_AT_decl_column(0x08) + 1733 + 1734$C$DW$T$53 .dwtag DW_TAG_union_type + 1735 .dwattr $C$DW$T$53, DW_AT_byte_size(0x04) + 1736$C$DW$141 .dwtag DW_TAG_member + 1737 .dwattr $C$DW$141, DW_AT_type(*$C$DW$T$47) + 1738 .dwattr $C$DW$141, DW_AT_name("GPCFG0") + 1739 .dwattr $C$DW$141, DW_AT_TI_symbol_name("GPCFG0") + 1740 .dwattr $C$DW$141, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1741 .dwattr $C$DW$141, DW_AT_accessibility(DW_ACCESS_public) + 1742 .dwattr $C$DW$141, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1743 .dwattr $C$DW$141, DW_AT_decl_line(0x42) + 1744 .dwattr $C$DW$141, DW_AT_decl_column(0x15) + 1745$C$DW$142 .dwtag DW_TAG_member + 1746 .dwattr $C$DW$142, DW_AT_type(*$C$DW$T$52) + 1747 .dwattr $C$DW$142, DW_AT_name("GPCFG0_bit") + 1748 .dwattr $C$DW$142, DW_AT_TI_symbol_name("GPCFG0_bit") + 1749 .dwattr $C$DW$142, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1750 .dwattr $C$DW$142, DW_AT_accessibility(DW_ACCESS_public) + 1751 .dwattr $C$DW$142, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1752 .dwattr $C$DW$142, DW_AT_decl_line(0x4f) + 1753 .dwattr $C$DW$142, DW_AT_decl_column(0x05) + 1754 .dwendtag $C$DW$T$53 + 1755 + 1756 .dwattr $C$DW$T$53, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1757 .dwattr $C$DW$T$53, DW_AT_decl_line(0x41) + 1758 .dwattr $C$DW$T$53, DW_AT_decl_column(0x08) + 1759 + 1760$C$DW$T$55 .dwtag DW_TAG_union_type +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 33 + + 1761 .dwattr $C$DW$T$55, DW_AT_byte_size(0x04) + 1762$C$DW$143 .dwtag DW_TAG_member + 1763 .dwattr $C$DW$143, DW_AT_type(*$C$DW$T$47) + 1764 .dwattr $C$DW$143, DW_AT_name("GPCFG1") + 1765 .dwattr $C$DW$143, DW_AT_TI_symbol_name("GPCFG1") + 1766 .dwattr $C$DW$143, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1767 .dwattr $C$DW$143, DW_AT_accessibility(DW_ACCESS_public) + 1768 .dwattr $C$DW$143, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1769 .dwattr $C$DW$143, DW_AT_decl_line(0x55) + 1770 .dwattr $C$DW$143, DW_AT_decl_column(0x15) + 1771$C$DW$144 .dwtag DW_TAG_member + 1772 .dwattr $C$DW$144, DW_AT_type(*$C$DW$T$54) + 1773 .dwattr $C$DW$144, DW_AT_name("GPCFG1_bit") + 1774 .dwattr $C$DW$144, DW_AT_TI_symbol_name("GPCFG1_bit") + 1775 .dwattr $C$DW$144, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1776 .dwattr $C$DW$144, DW_AT_accessibility(DW_ACCESS_public) + 1777 .dwattr $C$DW$144, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1778 .dwattr $C$DW$144, DW_AT_decl_line(0x62) + 1779 .dwattr $C$DW$144, DW_AT_decl_column(0x05) + 1780 .dwendtag $C$DW$T$55 + 1781 + 1782 .dwattr $C$DW$T$55, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1783 .dwattr $C$DW$T$55, DW_AT_decl_line(0x54) + 1784 .dwattr $C$DW$T$55, DW_AT_decl_column(0x08) + 1785 + 1786$C$DW$T$57 .dwtag DW_TAG_union_type + 1787 .dwattr $C$DW$T$57, DW_AT_byte_size(0x04) + 1788$C$DW$145 .dwtag DW_TAG_member + 1789 .dwattr $C$DW$145, DW_AT_type(*$C$DW$T$47) + 1790 .dwattr $C$DW$145, DW_AT_name("CGR") + 1791 .dwattr $C$DW$145, DW_AT_TI_symbol_name("CGR") + 1792 .dwattr $C$DW$145, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1793 .dwattr $C$DW$145, DW_AT_accessibility(DW_ACCESS_public) + 1794 .dwattr $C$DW$145, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1795 .dwattr $C$DW$145, DW_AT_decl_line(0x68) + 1796 .dwattr $C$DW$145, DW_AT_decl_column(0x15) + 1797$C$DW$146 .dwtag DW_TAG_member + 1798 .dwattr $C$DW$146, DW_AT_type(*$C$DW$T$56) + 1799 .dwattr $C$DW$146, DW_AT_name("CGR_bit") + 1800 .dwattr $C$DW$146, DW_AT_TI_symbol_name("CGR_bit") + 1801 .dwattr $C$DW$146, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1802 .dwattr $C$DW$146, DW_AT_accessibility(DW_ACCESS_public) + 1803 .dwattr $C$DW$146, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1804 .dwattr $C$DW$146, DW_AT_decl_line(0x7e) + 1805 .dwattr $C$DW$146, DW_AT_decl_column(0x05) + 1806 .dwendtag $C$DW$T$57 + 1807 + 1808 .dwattr $C$DW$T$57, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1809 .dwattr $C$DW$T$57, DW_AT_decl_line(0x67) + 1810 .dwattr $C$DW$T$57, DW_AT_decl_column(0x08) + 1811 + 1812$C$DW$T$59 .dwtag DW_TAG_union_type + 1813 .dwattr $C$DW$T$59, DW_AT_byte_size(0x04) + 1814$C$DW$147 .dwtag DW_TAG_member + 1815 .dwattr $C$DW$147, DW_AT_type(*$C$DW$T$47) +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 34 + + 1816 .dwattr $C$DW$147, DW_AT_name("ISRP") + 1817 .dwattr $C$DW$147, DW_AT_TI_symbol_name("ISRP") + 1818 .dwattr $C$DW$147, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1819 .dwattr $C$DW$147, DW_AT_accessibility(DW_ACCESS_public) + 1820 .dwattr $C$DW$147, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1821 .dwattr $C$DW$147, DW_AT_decl_line(0x84) + 1822 .dwattr $C$DW$147, DW_AT_decl_column(0x15) + 1823$C$DW$148 .dwtag DW_TAG_member + 1824 .dwattr $C$DW$148, DW_AT_type(*$C$DW$T$58) + 1825 .dwattr $C$DW$148, DW_AT_name("ISRP_bit") + 1826 .dwattr $C$DW$148, DW_AT_TI_symbol_name("ISRP_bit") + 1827 .dwattr $C$DW$148, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1828 .dwattr $C$DW$148, DW_AT_accessibility(DW_ACCESS_public) + 1829 .dwattr $C$DW$148, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1830 .dwattr $C$DW$148, DW_AT_decl_line(0x8d) + 1831 .dwattr $C$DW$148, DW_AT_decl_column(0x05) + 1832 .dwendtag $C$DW$T$59 + 1833 + 1834 .dwattr $C$DW$T$59, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1835 .dwattr $C$DW$T$59, DW_AT_decl_line(0x83) + 1836 .dwattr $C$DW$T$59, DW_AT_decl_column(0x08) + 1837 + 1838$C$DW$T$61 .dwtag DW_TAG_union_type + 1839 .dwattr $C$DW$T$61, DW_AT_byte_size(0x04) + 1840$C$DW$149 .dwtag DW_TAG_member + 1841 .dwattr $C$DW$149, DW_AT_type(*$C$DW$T$47) + 1842 .dwattr $C$DW$149, DW_AT_name("ISP") + 1843 .dwattr $C$DW$149, DW_AT_TI_symbol_name("ISP") + 1844 .dwattr $C$DW$149, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1845 .dwattr $C$DW$149, DW_AT_accessibility(DW_ACCESS_public) + 1846 .dwattr $C$DW$149, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1847 .dwattr $C$DW$149, DW_AT_decl_line(0x93) + 1848 .dwattr $C$DW$149, DW_AT_decl_column(0x15) + 1849$C$DW$150 .dwtag DW_TAG_member + 1850 .dwattr $C$DW$150, DW_AT_type(*$C$DW$T$60) + 1851 .dwattr $C$DW$150, DW_AT_name("ISP_bit") + 1852 .dwattr $C$DW$150, DW_AT_TI_symbol_name("ISP_bit") + 1853 .dwattr $C$DW$150, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1854 .dwattr $C$DW$150, DW_AT_accessibility(DW_ACCESS_public) + 1855 .dwattr $C$DW$150, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1856 .dwattr $C$DW$150, DW_AT_decl_line(0x9c) + 1857 .dwattr $C$DW$150, DW_AT_decl_column(0x05) + 1858 .dwendtag $C$DW$T$61 + 1859 + 1860 .dwattr $C$DW$T$61, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1861 .dwattr $C$DW$T$61, DW_AT_decl_line(0x92) + 1862 .dwattr $C$DW$T$61, DW_AT_decl_column(0x08) + 1863 + 1864$C$DW$T$63 .dwtag DW_TAG_union_type + 1865 .dwattr $C$DW$T$63, DW_AT_byte_size(0x04) + 1866$C$DW$151 .dwtag DW_TAG_member + 1867 .dwattr $C$DW$151, DW_AT_type(*$C$DW$T$47) + 1868 .dwattr $C$DW$151, DW_AT_name("IESP") + 1869 .dwattr $C$DW$151, DW_AT_TI_symbol_name("IESP") + 1870 .dwattr $C$DW$151, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 35 + + 1871 .dwattr $C$DW$151, DW_AT_accessibility(DW_ACCESS_public) + 1872 .dwattr $C$DW$151, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1873 .dwattr $C$DW$151, DW_AT_decl_line(0xa1) + 1874 .dwattr $C$DW$151, DW_AT_decl_column(0x15) + 1875$C$DW$152 .dwtag DW_TAG_member + 1876 .dwattr $C$DW$152, DW_AT_type(*$C$DW$T$62) + 1877 .dwattr $C$DW$152, DW_AT_name("IESP_bit") + 1878 .dwattr $C$DW$152, DW_AT_TI_symbol_name("IESP_bit") + 1879 .dwattr $C$DW$152, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1880 .dwattr $C$DW$152, DW_AT_accessibility(DW_ACCESS_public) + 1881 .dwattr $C$DW$152, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1882 .dwattr $C$DW$152, DW_AT_decl_line(0xaa) + 1883 .dwattr $C$DW$152, DW_AT_decl_column(0x05) + 1884 .dwendtag $C$DW$T$63 + 1885 + 1886 .dwattr $C$DW$T$63, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1887 .dwattr $C$DW$T$63, DW_AT_decl_line(0xa0) + 1888 .dwattr $C$DW$T$63, DW_AT_decl_column(0x08) + 1889 + 1890$C$DW$T$65 .dwtag DW_TAG_union_type + 1891 .dwattr $C$DW$T$65, DW_AT_byte_size(0x04) + 1892$C$DW$153 .dwtag DW_TAG_member + 1893 .dwattr $C$DW$153, DW_AT_type(*$C$DW$T$47) + 1894 .dwattr $C$DW$153, DW_AT_name("IECP") + 1895 .dwattr $C$DW$153, DW_AT_TI_symbol_name("IECP") + 1896 .dwattr $C$DW$153, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1897 .dwattr $C$DW$153, DW_AT_accessibility(DW_ACCESS_public) + 1898 .dwattr $C$DW$153, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1899 .dwattr $C$DW$153, DW_AT_decl_line(0xb0) + 1900 .dwattr $C$DW$153, DW_AT_decl_column(0x15) + 1901$C$DW$154 .dwtag DW_TAG_member + 1902 .dwattr $C$DW$154, DW_AT_type(*$C$DW$T$64) + 1903 .dwattr $C$DW$154, DW_AT_name("IECP_bit") + 1904 .dwattr $C$DW$154, DW_AT_TI_symbol_name("IECP_bit") + 1905 .dwattr $C$DW$154, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1906 .dwattr $C$DW$154, DW_AT_accessibility(DW_ACCESS_public) + 1907 .dwattr $C$DW$154, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1908 .dwattr $C$DW$154, DW_AT_decl_line(0xb8) + 1909 .dwattr $C$DW$154, DW_AT_decl_column(0x05) + 1910 .dwendtag $C$DW$T$65 + 1911 + 1912 .dwattr $C$DW$T$65, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1913 .dwattr $C$DW$T$65, DW_AT_decl_line(0xaf) + 1914 .dwattr $C$DW$T$65, DW_AT_decl_column(0x08) + 1915 + 1916$C$DW$T$67 .dwtag DW_TAG_union_type + 1917 .dwattr $C$DW$T$67, DW_AT_byte_size(0x04) + 1918$C$DW$155 .dwtag DW_TAG_member + 1919 .dwattr $C$DW$155, DW_AT_type(*$C$DW$T$47) + 1920 .dwattr $C$DW$155, DW_AT_name("PMAO") + 1921 .dwattr $C$DW$155, DW_AT_TI_symbol_name("PMAO") + 1922 .dwattr $C$DW$155, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1923 .dwattr $C$DW$155, DW_AT_accessibility(DW_ACCESS_public) + 1924 .dwattr $C$DW$155, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1925 .dwattr $C$DW$155, DW_AT_decl_line(0xc1) +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 36 + + 1926 .dwattr $C$DW$155, DW_AT_decl_column(0x15) + 1927$C$DW$156 .dwtag DW_TAG_member + 1928 .dwattr $C$DW$156, DW_AT_type(*$C$DW$T$66) + 1929 .dwattr $C$DW$156, DW_AT_name("PMAO_bit") + 1930 .dwattr $C$DW$156, DW_AT_TI_symbol_name("PMAO_bit") + 1931 .dwattr $C$DW$156, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1932 .dwattr $C$DW$156, DW_AT_accessibility(DW_ACCESS_public) + 1933 .dwattr $C$DW$156, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1934 .dwattr $C$DW$156, DW_AT_decl_line(0xc7) + 1935 .dwattr $C$DW$156, DW_AT_decl_column(0x05) + 1936 .dwendtag $C$DW$T$67 + 1937 + 1938 .dwattr $C$DW$T$67, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1939 .dwattr $C$DW$T$67, DW_AT_decl_line(0xc0) + 1940 .dwattr $C$DW$T$67, DW_AT_decl_column(0x08) + 1941 + 1942$C$DW$T$69 .dwtag DW_TAG_union_type + 1943 .dwattr $C$DW$T$69, DW_AT_byte_size(0x04) + 1944$C$DW$157 .dwtag DW_TAG_member + 1945 .dwattr $C$DW$157, DW_AT_type(*$C$DW$T$47) + 1946 .dwattr $C$DW$157, DW_AT_name("IEPCLK") + 1947 .dwattr $C$DW$157, DW_AT_TI_symbol_name("IEPCLK") + 1948 .dwattr $C$DW$157, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1949 .dwattr $C$DW$157, DW_AT_accessibility(DW_ACCESS_public) + 1950 .dwattr $C$DW$157, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1951 .dwattr $C$DW$157, DW_AT_decl_line(0xd0) + 1952 .dwattr $C$DW$157, DW_AT_decl_column(0x15) + 1953$C$DW$158 .dwtag DW_TAG_member + 1954 .dwattr $C$DW$158, DW_AT_type(*$C$DW$T$68) + 1955 .dwattr $C$DW$158, DW_AT_name("IEPCLK_bit") + 1956 .dwattr $C$DW$158, DW_AT_TI_symbol_name("IEPCLK_bit") + 1957 .dwattr $C$DW$158, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1958 .dwattr $C$DW$158, DW_AT_accessibility(DW_ACCESS_public) + 1959 .dwattr $C$DW$158, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1960 .dwattr $C$DW$158, DW_AT_decl_line(0xd5) + 1961 .dwattr $C$DW$158, DW_AT_decl_column(0x05) + 1962 .dwendtag $C$DW$T$69 + 1963 + 1964 .dwattr $C$DW$T$69, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1965 .dwattr $C$DW$T$69, DW_AT_decl_line(0xcf) + 1966 .dwattr $C$DW$T$69, DW_AT_decl_column(0x08) + 1967 + 1968$C$DW$T$71 .dwtag DW_TAG_union_type + 1969 .dwattr $C$DW$T$71, DW_AT_byte_size(0x04) + 1970$C$DW$159 .dwtag DW_TAG_member + 1971 .dwattr $C$DW$159, DW_AT_type(*$C$DW$T$47) + 1972 .dwattr $C$DW$159, DW_AT_name("SPP") + 1973 .dwattr $C$DW$159, DW_AT_TI_symbol_name("SPP") + 1974 .dwattr $C$DW$159, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1975 .dwattr $C$DW$159, DW_AT_accessibility(DW_ACCESS_public) + 1976 .dwattr $C$DW$159, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1977 .dwattr $C$DW$159, DW_AT_decl_line(0xdb) + 1978 .dwattr $C$DW$159, DW_AT_decl_column(0x15) + 1979$C$DW$160 .dwtag DW_TAG_member + 1980 .dwattr $C$DW$160, DW_AT_type(*$C$DW$T$70) +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 37 + + 1981 .dwattr $C$DW$160, DW_AT_name("SPP_bit") + 1982 .dwattr $C$DW$160, DW_AT_TI_symbol_name("SPP_bit") + 1983 .dwattr $C$DW$160, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 1984 .dwattr $C$DW$160, DW_AT_accessibility(DW_ACCESS_public) + 1985 .dwattr $C$DW$160, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 1986 .dwattr $C$DW$160, DW_AT_decl_line(0xe1) + 1987 .dwattr $C$DW$160, DW_AT_decl_column(0x05) + 1988 .dwendtag $C$DW$T$71 + 1989 + 1990 .dwattr $C$DW$T$71, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 1991 .dwattr $C$DW$T$71, DW_AT_decl_line(0xda) + 1992 .dwattr $C$DW$T$71, DW_AT_decl_column(0x08) + 1993 + 1994$C$DW$T$73 .dwtag DW_TAG_union_type + 1995 .dwattr $C$DW$T$73, DW_AT_byte_size(0x04) + 1996$C$DW$161 .dwtag DW_TAG_member + 1997 .dwattr $C$DW$161, DW_AT_type(*$C$DW$T$47) + 1998 .dwattr $C$DW$161, DW_AT_name("PIN_MX") + 1999 .dwattr $C$DW$161, DW_AT_TI_symbol_name("PIN_MX") + 2000 .dwattr $C$DW$161, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2001 .dwattr $C$DW$161, DW_AT_accessibility(DW_ACCESS_public) + 2002 .dwattr $C$DW$161, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2003 .dwattr $C$DW$161, DW_AT_decl_line(0xe9) + 2004 .dwattr $C$DW$161, DW_AT_decl_column(0x15) + 2005$C$DW$162 .dwtag DW_TAG_member + 2006 .dwattr $C$DW$162, DW_AT_type(*$C$DW$T$72) + 2007 .dwattr $C$DW$162, DW_AT_name("PIN_MX_bit") + 2008 .dwattr $C$DW$162, DW_AT_TI_symbol_name("PIN_MX_bit") + 2009 .dwattr $C$DW$162, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2010 .dwattr $C$DW$162, DW_AT_accessibility(DW_ACCESS_public) + 2011 .dwattr $C$DW$162, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2012 .dwattr $C$DW$162, DW_AT_decl_line(0xee) + 2013 .dwattr $C$DW$162, DW_AT_decl_column(0x05) + 2014 .dwendtag $C$DW$T$73 + 2015 + 2016 .dwattr $C$DW$T$73, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2017 .dwattr $C$DW$T$73, DW_AT_decl_line(0xe8) + 2018 .dwattr $C$DW$T$73, DW_AT_decl_column(0x08) + 2019 + 2020$C$DW$T$75 .dwtag DW_TAG_union_type + 2021 .dwattr $C$DW$T$75, DW_AT_byte_size(0x04) + 2022$C$DW$163 .dwtag DW_TAG_member + 2023 .dwattr $C$DW$163, DW_AT_type(*$C$DW$T$47) + 2024 .dwattr $C$DW$163, DW_AT_name("CTRL") + 2025 .dwattr $C$DW$163, DW_AT_TI_symbol_name("CTRL") + 2026 .dwattr $C$DW$163, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2027 .dwattr $C$DW$163, DW_AT_accessibility(DW_ACCESS_public) + 2028 .dwattr $C$DW$163, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2029 .dwattr $C$DW$163, DW_AT_decl_line(0x2a) + 2030 .dwattr $C$DW$163, DW_AT_decl_column(0x15) + 2031$C$DW$164 .dwtag DW_TAG_member + 2032 .dwattr $C$DW$164, DW_AT_type(*$C$DW$T$74) + 2033 .dwattr $C$DW$164, DW_AT_name("CTRL_bit") + 2034 .dwattr $C$DW$164, DW_AT_TI_symbol_name("CTRL_bit") + 2035 .dwattr $C$DW$164, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 38 + + 2036 .dwattr $C$DW$164, DW_AT_accessibility(DW_ACCESS_public) + 2037 .dwattr $C$DW$164, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2038 .dwattr $C$DW$164, DW_AT_decl_line(0x36) + 2039 .dwattr $C$DW$164, DW_AT_decl_column(0x05) + 2040 .dwendtag $C$DW$T$75 + 2041 + 2042 .dwattr $C$DW$T$75, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2043 .dwattr $C$DW$T$75, DW_AT_decl_line(0x29) + 2044 .dwattr $C$DW$T$75, DW_AT_decl_column(0x08) + 2045 + 2046$C$DW$T$77 .dwtag DW_TAG_union_type + 2047 .dwattr $C$DW$T$77, DW_AT_byte_size(0x04) + 2048$C$DW$165 .dwtag DW_TAG_member + 2049 .dwattr $C$DW$165, DW_AT_type(*$C$DW$T$47) + 2050 .dwattr $C$DW$165, DW_AT_name("STS") + 2051 .dwattr $C$DW$165, DW_AT_TI_symbol_name("STS") + 2052 .dwattr $C$DW$165, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2053 .dwattr $C$DW$165, DW_AT_accessibility(DW_ACCESS_public) + 2054 .dwattr $C$DW$165, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2055 .dwattr $C$DW$165, DW_AT_decl_line(0x3c) + 2056 .dwattr $C$DW$165, DW_AT_decl_column(0x15) + 2057$C$DW$166 .dwtag DW_TAG_member + 2058 .dwattr $C$DW$166, DW_AT_type(*$C$DW$T$76) + 2059 .dwattr $C$DW$166, DW_AT_name("STS_bit") + 2060 .dwattr $C$DW$166, DW_AT_TI_symbol_name("STS_bit") + 2061 .dwattr $C$DW$166, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2062 .dwattr $C$DW$166, DW_AT_accessibility(DW_ACCESS_public) + 2063 .dwattr $C$DW$166, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2064 .dwattr $C$DW$166, DW_AT_decl_line(0x41) + 2065 .dwattr $C$DW$166, DW_AT_decl_column(0x05) + 2066 .dwendtag $C$DW$T$77 + 2067 + 2068 .dwattr $C$DW$T$77, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2069 .dwattr $C$DW$T$77, DW_AT_decl_line(0x3b) + 2070 .dwattr $C$DW$T$77, DW_AT_decl_column(0x08) + 2071 + 2072$C$DW$T$79 .dwtag DW_TAG_union_type + 2073 .dwattr $C$DW$T$79, DW_AT_byte_size(0x04) + 2074$C$DW$167 .dwtag DW_TAG_member + 2075 .dwattr $C$DW$167, DW_AT_type(*$C$DW$T$47) + 2076 .dwattr $C$DW$167, DW_AT_name("WAKEUP_EN") + 2077 .dwattr $C$DW$167, DW_AT_TI_symbol_name("WAKEUP_EN") + 2078 .dwattr $C$DW$167, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2079 .dwattr $C$DW$167, DW_AT_accessibility(DW_ACCESS_public) + 2080 .dwattr $C$DW$167, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2081 .dwattr $C$DW$167, DW_AT_decl_line(0x47) + 2082 .dwattr $C$DW$167, DW_AT_decl_column(0x15) + 2083$C$DW$168 .dwtag DW_TAG_member + 2084 .dwattr $C$DW$168, DW_AT_type(*$C$DW$T$78) + 2085 .dwattr $C$DW$168, DW_AT_name("WAKEUP_EN_bit") + 2086 .dwattr $C$DW$168, DW_AT_TI_symbol_name("WAKEUP_EN_bit") + 2087 .dwattr $C$DW$168, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2088 .dwattr $C$DW$168, DW_AT_accessibility(DW_ACCESS_public) + 2089 .dwattr $C$DW$168, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2090 .dwattr $C$DW$168, DW_AT_decl_line(0x4b) +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 39 + + 2091 .dwattr $C$DW$168, DW_AT_decl_column(0x05) + 2092 .dwendtag $C$DW$T$79 + 2093 + 2094 .dwattr $C$DW$T$79, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2095 .dwattr $C$DW$T$79, DW_AT_decl_line(0x46) + 2096 .dwattr $C$DW$T$79, DW_AT_decl_column(0x08) + 2097 + 2098$C$DW$T$81 .dwtag DW_TAG_union_type + 2099 .dwattr $C$DW$T$81, DW_AT_byte_size(0x04) + 2100$C$DW$169 .dwtag DW_TAG_member + 2101 .dwattr $C$DW$169, DW_AT_type(*$C$DW$T$47) + 2102 .dwattr $C$DW$169, DW_AT_name("CYCLE") + 2103 .dwattr $C$DW$169, DW_AT_TI_symbol_name("CYCLE") + 2104 .dwattr $C$DW$169, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2105 .dwattr $C$DW$169, DW_AT_accessibility(DW_ACCESS_public) + 2106 .dwattr $C$DW$169, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2107 .dwattr $C$DW$169, DW_AT_decl_line(0x51) + 2108 .dwattr $C$DW$169, DW_AT_decl_column(0x15) + 2109$C$DW$170 .dwtag DW_TAG_member + 2110 .dwattr $C$DW$170, DW_AT_type(*$C$DW$T$80) + 2111 .dwattr $C$DW$170, DW_AT_name("CYCLE_bit") + 2112 .dwattr $C$DW$170, DW_AT_TI_symbol_name("CYCLE_bit") + 2113 .dwattr $C$DW$170, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2114 .dwattr $C$DW$170, DW_AT_accessibility(DW_ACCESS_public) + 2115 .dwattr $C$DW$170, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2116 .dwattr $C$DW$170, DW_AT_decl_line(0x55) + 2117 .dwattr $C$DW$170, DW_AT_decl_column(0x05) + 2118 .dwendtag $C$DW$T$81 + 2119 + 2120 .dwattr $C$DW$T$81, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2121 .dwattr $C$DW$T$81, DW_AT_decl_line(0x50) + 2122 .dwattr $C$DW$T$81, DW_AT_decl_column(0x08) + 2123 + 2124$C$DW$T$83 .dwtag DW_TAG_union_type + 2125 .dwattr $C$DW$T$83, DW_AT_byte_size(0x04) + 2126$C$DW$171 .dwtag DW_TAG_member + 2127 .dwattr $C$DW$171, DW_AT_type(*$C$DW$T$47) + 2128 .dwattr $C$DW$171, DW_AT_name("STALL") + 2129 .dwattr $C$DW$171, DW_AT_TI_symbol_name("STALL") + 2130 .dwattr $C$DW$171, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2131 .dwattr $C$DW$171, DW_AT_accessibility(DW_ACCESS_public) + 2132 .dwattr $C$DW$171, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2133 .dwattr $C$DW$171, DW_AT_decl_line(0x5b) + 2134 .dwattr $C$DW$171, DW_AT_decl_column(0x15) + 2135$C$DW$172 .dwtag DW_TAG_member + 2136 .dwattr $C$DW$172, DW_AT_type(*$C$DW$T$82) + 2137 .dwattr $C$DW$172, DW_AT_name("STALL_bit") + 2138 .dwattr $C$DW$172, DW_AT_TI_symbol_name("STALL_bit") + 2139 .dwattr $C$DW$172, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2140 .dwattr $C$DW$172, DW_AT_accessibility(DW_ACCESS_public) + 2141 .dwattr $C$DW$172, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2142 .dwattr $C$DW$172, DW_AT_decl_line(0x5f) + 2143 .dwattr $C$DW$172, DW_AT_decl_column(0x05) + 2144 .dwendtag $C$DW$T$83 + 2145 +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 40 + + 2146 .dwattr $C$DW$T$83, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2147 .dwattr $C$DW$T$83, DW_AT_decl_line(0x5a) + 2148 .dwattr $C$DW$T$83, DW_AT_decl_column(0x08) + 2149 + 2150$C$DW$T$85 .dwtag DW_TAG_union_type + 2151 .dwattr $C$DW$T$85, DW_AT_byte_size(0x04) + 2152$C$DW$173 .dwtag DW_TAG_member + 2153 .dwattr $C$DW$173, DW_AT_type(*$C$DW$T$47) + 2154 .dwattr $C$DW$173, DW_AT_name("CTBIR0") + 2155 .dwattr $C$DW$173, DW_AT_TI_symbol_name("CTBIR0") + 2156 .dwattr $C$DW$173, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2157 .dwattr $C$DW$173, DW_AT_accessibility(DW_ACCESS_public) + 2158 .dwattr $C$DW$173, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2159 .dwattr $C$DW$173, DW_AT_decl_line(0x68) + 2160 .dwattr $C$DW$173, DW_AT_decl_column(0x15) + 2161$C$DW$174 .dwtag DW_TAG_member + 2162 .dwattr $C$DW$174, DW_AT_type(*$C$DW$T$84) + 2163 .dwattr $C$DW$174, DW_AT_name("CTBIR0_bit") + 2164 .dwattr $C$DW$174, DW_AT_TI_symbol_name("CTBIR0_bit") + 2165 .dwattr $C$DW$174, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2166 .dwattr $C$DW$174, DW_AT_accessibility(DW_ACCESS_public) + 2167 .dwattr $C$DW$174, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2168 .dwattr $C$DW$174, DW_AT_decl_line(0x6f) + 2169 .dwattr $C$DW$174, DW_AT_decl_column(0x05) + 2170 .dwendtag $C$DW$T$85 + 2171 + 2172 .dwattr $C$DW$T$85, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2173 .dwattr $C$DW$T$85, DW_AT_decl_line(0x67) + 2174 .dwattr $C$DW$T$85, DW_AT_decl_column(0x08) + 2175 + 2176$C$DW$T$87 .dwtag DW_TAG_union_type + 2177 .dwattr $C$DW$T$87, DW_AT_byte_size(0x04) + 2178$C$DW$175 .dwtag DW_TAG_member + 2179 .dwattr $C$DW$175, DW_AT_type(*$C$DW$T$47) + 2180 .dwattr $C$DW$175, DW_AT_name("CTBIR1") + 2181 .dwattr $C$DW$175, DW_AT_TI_symbol_name("CTBIR1") + 2182 .dwattr $C$DW$175, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2183 .dwattr $C$DW$175, DW_AT_accessibility(DW_ACCESS_public) + 2184 .dwattr $C$DW$175, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2185 .dwattr $C$DW$175, DW_AT_decl_line(0x75) + 2186 .dwattr $C$DW$175, DW_AT_decl_column(0x15) + 2187$C$DW$176 .dwtag DW_TAG_member + 2188 .dwattr $C$DW$176, DW_AT_type(*$C$DW$T$86) + 2189 .dwattr $C$DW$176, DW_AT_name("CTBIR1_bit") + 2190 .dwattr $C$DW$176, DW_AT_TI_symbol_name("CTBIR1_bit") + 2191 .dwattr $C$DW$176, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2192 .dwattr $C$DW$176, DW_AT_accessibility(DW_ACCESS_public) + 2193 .dwattr $C$DW$176, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2194 .dwattr $C$DW$176, DW_AT_decl_line(0x7c) + 2195 .dwattr $C$DW$176, DW_AT_decl_column(0x05) + 2196 .dwendtag $C$DW$T$87 + 2197 + 2198 .dwattr $C$DW$T$87, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2199 .dwattr $C$DW$T$87, DW_AT_decl_line(0x74) + 2200 .dwattr $C$DW$T$87, DW_AT_decl_column(0x08) +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 41 + + 2201 + 2202$C$DW$T$89 .dwtag DW_TAG_union_type + 2203 .dwattr $C$DW$T$89, DW_AT_byte_size(0x04) + 2204$C$DW$177 .dwtag DW_TAG_member + 2205 .dwattr $C$DW$177, DW_AT_type(*$C$DW$T$47) + 2206 .dwattr $C$DW$177, DW_AT_name("CTPPR0") + 2207 .dwattr $C$DW$177, DW_AT_TI_symbol_name("CTPPR0") + 2208 .dwattr $C$DW$177, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2209 .dwattr $C$DW$177, DW_AT_accessibility(DW_ACCESS_public) + 2210 .dwattr $C$DW$177, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2211 .dwattr $C$DW$177, DW_AT_decl_line(0x82) + 2212 .dwattr $C$DW$177, DW_AT_decl_column(0x15) + 2213$C$DW$178 .dwtag DW_TAG_member + 2214 .dwattr $C$DW$178, DW_AT_type(*$C$DW$T$88) + 2215 .dwattr $C$DW$178, DW_AT_name("CTPPR0_bit") + 2216 .dwattr $C$DW$178, DW_AT_TI_symbol_name("CTPPR0_bit") + 2217 .dwattr $C$DW$178, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2218 .dwattr $C$DW$178, DW_AT_accessibility(DW_ACCESS_public) + 2219 .dwattr $C$DW$178, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2220 .dwattr $C$DW$178, DW_AT_decl_line(0x87) + 2221 .dwattr $C$DW$178, DW_AT_decl_column(0x05) + 2222 .dwendtag $C$DW$T$89 + 2223 + 2224 .dwattr $C$DW$T$89, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2225 .dwattr $C$DW$T$89, DW_AT_decl_line(0x81) + 2226 .dwattr $C$DW$T$89, DW_AT_decl_column(0x08) + 2227 + 2228$C$DW$T$91 .dwtag DW_TAG_union_type + 2229 .dwattr $C$DW$T$91, DW_AT_byte_size(0x04) + 2230$C$DW$179 .dwtag DW_TAG_member + 2231 .dwattr $C$DW$179, DW_AT_type(*$C$DW$T$47) + 2232 .dwattr $C$DW$179, DW_AT_name("CTPPR1") + 2233 .dwattr $C$DW$179, DW_AT_TI_symbol_name("CTPPR1") + 2234 .dwattr $C$DW$179, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2235 .dwattr $C$DW$179, DW_AT_accessibility(DW_ACCESS_public) + 2236 .dwattr $C$DW$179, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2237 .dwattr $C$DW$179, DW_AT_decl_line(0x8d) + 2238 .dwattr $C$DW$179, DW_AT_decl_column(0x15) + 2239$C$DW$180 .dwtag DW_TAG_member + 2240 .dwattr $C$DW$180, DW_AT_type(*$C$DW$T$90) + 2241 .dwattr $C$DW$180, DW_AT_name("CTPPR1_bit") + 2242 .dwattr $C$DW$180, DW_AT_TI_symbol_name("CTPPR1_bit") + 2243 .dwattr $C$DW$180, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2244 .dwattr $C$DW$180, DW_AT_accessibility(DW_ACCESS_public) + 2245 .dwattr $C$DW$180, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/pr + 2246 .dwattr $C$DW$180, DW_AT_decl_line(0x92) + 2247 .dwattr $C$DW$180, DW_AT_decl_column(0x05) + 2248 .dwendtag $C$DW$T$91 + 2249 + 2250 .dwattr $C$DW$T$91, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/am335x/p + 2251 .dwattr $C$DW$T$91, DW_AT_decl_line(0x8c) + 2252 .dwattr $C$DW$T$91, DW_AT_decl_column(0x08) + 2253$C$DW$T$2 .dwtag DW_TAG_unspecified_type + 2254 .dwattr $C$DW$T$2, DW_AT_name("void") + 2255$C$DW$T$4 .dwtag DW_TAG_base_type +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 42 + + 2256 .dwattr $C$DW$T$4, DW_AT_encoding(DW_ATE_boolean) + 2257 .dwattr $C$DW$T$4, DW_AT_name("bool") + 2258 .dwattr $C$DW$T$4, DW_AT_byte_size(0x01) + 2259$C$DW$T$5 .dwtag DW_TAG_base_type + 2260 .dwattr $C$DW$T$5, DW_AT_encoding(DW_ATE_signed_char) + 2261 .dwattr $C$DW$T$5, DW_AT_name("signed char") + 2262 .dwattr $C$DW$T$5, DW_AT_byte_size(0x01) + 2263$C$DW$T$6 .dwtag DW_TAG_base_type + 2264 .dwattr $C$DW$T$6, DW_AT_encoding(DW_ATE_unsigned_char) + 2265 .dwattr $C$DW$T$6, DW_AT_name("unsigned char") + 2266 .dwattr $C$DW$T$6, DW_AT_byte_size(0x01) + 2267$C$DW$T$7 .dwtag DW_TAG_base_type + 2268 .dwattr $C$DW$T$7, DW_AT_encoding(DW_ATE_signed_char) + 2269 .dwattr $C$DW$T$7, DW_AT_name("wchar_t") + 2270 .dwattr $C$DW$T$7, DW_AT_byte_size(0x04) + 2271$C$DW$T$8 .dwtag DW_TAG_base_type + 2272 .dwattr $C$DW$T$8, DW_AT_encoding(DW_ATE_signed) + 2273 .dwattr $C$DW$T$8, DW_AT_name("short") + 2274 .dwattr $C$DW$T$8, DW_AT_byte_size(0x02) + 2275$C$DW$T$9 .dwtag DW_TAG_base_type + 2276 .dwattr $C$DW$T$9, DW_AT_encoding(DW_ATE_unsigned) + 2277 .dwattr $C$DW$T$9, DW_AT_name("unsigned short") + 2278 .dwattr $C$DW$T$9, DW_AT_byte_size(0x02) + 2279$C$DW$T$10 .dwtag DW_TAG_base_type + 2280 .dwattr $C$DW$T$10, DW_AT_encoding(DW_ATE_signed) + 2281 .dwattr $C$DW$T$10, DW_AT_name("int") + 2282 .dwattr $C$DW$T$10, DW_AT_byte_size(0x04) + 2283$C$DW$T$11 .dwtag DW_TAG_base_type + 2284 .dwattr $C$DW$T$11, DW_AT_encoding(DW_ATE_unsigned) + 2285 .dwattr $C$DW$T$11, DW_AT_name("unsigned int") + 2286 .dwattr $C$DW$T$11, DW_AT_byte_size(0x04) + 2287$C$DW$T$32 .dwtag DW_TAG_typedef, DW_AT_name("uint32_t") + 2288 .dwattr $C$DW$T$32, DW_AT_type(*$C$DW$T$11) + 2289 .dwattr $C$DW$T$32, DW_AT_language(DW_LANG_C) + 2290 .dwattr $C$DW$T$32, DW_AT_decl_file("/usr/share/ti/cgt-pru/include/stdint.h") + 2291 .dwattr $C$DW$T$32, DW_AT_decl_line(0x2f) + 2292 .dwattr $C$DW$T$32, DW_AT_decl_column(0x1c) + 2293 + 2294$C$DW$T$33 .dwtag DW_TAG_array_type + 2295 .dwattr $C$DW$T$33, DW_AT_type(*$C$DW$T$32) + 2296 .dwattr $C$DW$T$33, DW_AT_language(DW_LANG_C) + 2297 .dwattr $C$DW$T$33, DW_AT_byte_size(0x04) + 2298$C$DW$181 .dwtag DW_TAG_subrange_type + 2299 .dwattr $C$DW$181, DW_AT_upper_bound(0x00) + 2300 .dwendtag $C$DW$T$33 + 2301 + 2302 + 2303$C$DW$T$34 .dwtag DW_TAG_array_type + 2304 .dwattr $C$DW$T$34, DW_AT_type(*$C$DW$T$32) + 2305 .dwattr $C$DW$T$34, DW_AT_language(DW_LANG_C) + 2306 .dwattr $C$DW$T$34, DW_AT_byte_size(0x08) + 2307$C$DW$182 .dwtag DW_TAG_subrange_type + 2308 .dwattr $C$DW$182, DW_AT_upper_bound(0x01) + 2309 .dwendtag $C$DW$T$34 + 2310 +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 43 + + 2311 + 2312$C$DW$T$45 .dwtag DW_TAG_array_type + 2313 .dwattr $C$DW$T$45, DW_AT_type(*$C$DW$T$32) + 2314 .dwattr $C$DW$T$45, DW_AT_language(DW_LANG_C) + 2315 .dwattr $C$DW$T$45, DW_AT_byte_size(0x0c) + 2316$C$DW$183 .dwtag DW_TAG_subrange_type + 2317 .dwattr $C$DW$183, DW_AT_upper_bound(0x02) + 2318 .dwendtag $C$DW$T$45 + 2319 + 2320$C$DW$T$47 .dwtag DW_TAG_volatile_type + 2321 .dwattr $C$DW$T$47, DW_AT_type(*$C$DW$T$32) + 2322$C$DW$T$12 .dwtag DW_TAG_base_type + 2323 .dwattr $C$DW$T$12, DW_AT_encoding(DW_ATE_signed) + 2324 .dwattr $C$DW$T$12, DW_AT_name("long") + 2325 .dwattr $C$DW$T$12, DW_AT_byte_size(0x04) + 2326$C$DW$T$13 .dwtag DW_TAG_base_type + 2327 .dwattr $C$DW$T$13, DW_AT_encoding(DW_ATE_unsigned) + 2328 .dwattr $C$DW$T$13, DW_AT_name("unsigned long") + 2329 .dwattr $C$DW$T$13, DW_AT_byte_size(0x04) + 2330$C$DW$T$14 .dwtag DW_TAG_base_type + 2331 .dwattr $C$DW$T$14, DW_AT_encoding(DW_ATE_signed) + 2332 .dwattr $C$DW$T$14, DW_AT_name("long long") + 2333 .dwattr $C$DW$T$14, DW_AT_byte_size(0x08) + 2334$C$DW$T$15 .dwtag DW_TAG_base_type + 2335 .dwattr $C$DW$T$15, DW_AT_encoding(DW_ATE_unsigned) + 2336 .dwattr $C$DW$T$15, DW_AT_name("unsigned long long") + 2337 .dwattr $C$DW$T$15, DW_AT_byte_size(0x08) + 2338$C$DW$T$16 .dwtag DW_TAG_base_type + 2339 .dwattr $C$DW$T$16, DW_AT_encoding(DW_ATE_float) + 2340 .dwattr $C$DW$T$16, DW_AT_name("float") + 2341 .dwattr $C$DW$T$16, DW_AT_byte_size(0x04) + 2342$C$DW$T$17 .dwtag DW_TAG_base_type + 2343 .dwattr $C$DW$T$17, DW_AT_encoding(DW_ATE_float) + 2344 .dwattr $C$DW$T$17, DW_AT_name("double") + 2345 .dwattr $C$DW$T$17, DW_AT_byte_size(0x08) + 2346$C$DW$T$18 .dwtag DW_TAG_base_type + 2347 .dwattr $C$DW$T$18, DW_AT_encoding(DW_ATE_float) + 2348 .dwattr $C$DW$T$18, DW_AT_name("long double") + 2349 .dwattr $C$DW$T$18, DW_AT_byte_size(0x08) + 2350 + 2351$C$DW$T$92 .dwtag DW_TAG_structure_type + 2352 .dwattr $C$DW$T$92, DW_AT_name("my_resource_table") + 2353 .dwattr $C$DW$T$92, DW_AT_byte_size(0x14) + 2354$C$DW$184 .dwtag DW_TAG_member + 2355 .dwattr $C$DW$184, DW_AT_type(*$C$DW$T$93) + 2356 .dwattr $C$DW$184, DW_AT_name("base") + 2357 .dwattr $C$DW$184, DW_AT_TI_symbol_name("base") + 2358 .dwattr $C$DW$184, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2359 .dwattr $C$DW$184, DW_AT_accessibility(DW_ACCESS_public) + 2360 .dwattr $C$DW$184, DW_AT_decl_file("/var/lib/cloud9/common/resource_table_empty.h") + 2361 .dwattr $C$DW$184, DW_AT_decl_line(0x18) + 2362 .dwattr $C$DW$184, DW_AT_decl_column(0x18) + 2363$C$DW$185 .dwtag DW_TAG_member + 2364 .dwattr $C$DW$185, DW_AT_type(*$C$DW$T$33) + 2365 .dwattr $C$DW$185, DW_AT_name("offset") +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 44 + + 2366 .dwattr $C$DW$185, DW_AT_TI_symbol_name("offset") + 2367 .dwattr $C$DW$185, DW_AT_data_member_location[DW_OP_plus_uconst 0x10] + 2368 .dwattr $C$DW$185, DW_AT_accessibility(DW_ACCESS_public) + 2369 .dwattr $C$DW$185, DW_AT_decl_file("/var/lib/cloud9/common/resource_table_empty.h") + 2370 .dwattr $C$DW$185, DW_AT_decl_line(0x1a) + 2371 .dwattr $C$DW$185, DW_AT_decl_column(0x0b) + 2372 .dwendtag $C$DW$T$92 + 2373 + 2374 .dwattr $C$DW$T$92, DW_AT_decl_file("/var/lib/cloud9/common/resource_table_empty.h") + 2375 .dwattr $C$DW$T$92, DW_AT_decl_line(0x17) + 2376 .dwattr $C$DW$T$92, DW_AT_decl_column(0x08) + 2377 + 2378$C$DW$T$93 .dwtag DW_TAG_structure_type + 2379 .dwattr $C$DW$T$93, DW_AT_name("resource_table") + 2380 .dwattr $C$DW$T$93, DW_AT_byte_size(0x10) + 2381$C$DW$186 .dwtag DW_TAG_member + 2382 .dwattr $C$DW$186, DW_AT_type(*$C$DW$T$32) + 2383 .dwattr $C$DW$186, DW_AT_name("ver") + 2384 .dwattr $C$DW$186, DW_AT_TI_symbol_name("ver") + 2385 .dwattr $C$DW$186, DW_AT_data_member_location[DW_OP_plus_uconst 0x0] + 2386 .dwattr $C$DW$186, DW_AT_accessibility(DW_ACCESS_public) + 2387 .dwattr $C$DW$186, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/rsc_types + 2388 .dwattr $C$DW$186, DW_AT_decl_line(0x59) + 2389 .dwattr $C$DW$186, DW_AT_decl_column(0x0b) + 2390$C$DW$187 .dwtag DW_TAG_member + 2391 .dwattr $C$DW$187, DW_AT_type(*$C$DW$T$32) + 2392 .dwattr $C$DW$187, DW_AT_name("num") + 2393 .dwattr $C$DW$187, DW_AT_TI_symbol_name("num") + 2394 .dwattr $C$DW$187, DW_AT_data_member_location[DW_OP_plus_uconst 0x4] + 2395 .dwattr $C$DW$187, DW_AT_accessibility(DW_ACCESS_public) + 2396 .dwattr $C$DW$187, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/rsc_types + 2397 .dwattr $C$DW$187, DW_AT_decl_line(0x5a) + 2398 .dwattr $C$DW$187, DW_AT_decl_column(0x0b) + 2399$C$DW$188 .dwtag DW_TAG_member + 2400 .dwattr $C$DW$188, DW_AT_type(*$C$DW$T$34) + 2401 .dwattr $C$DW$188, DW_AT_name("reserved") + 2402 .dwattr $C$DW$188, DW_AT_TI_symbol_name("reserved") + 2403 .dwattr $C$DW$188, DW_AT_data_member_location[DW_OP_plus_uconst 0x8] + 2404 .dwattr $C$DW$188, DW_AT_accessibility(DW_ACCESS_public) + 2405 .dwattr $C$DW$188, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/rsc_types + 2406 .dwattr $C$DW$188, DW_AT_decl_line(0x5b) + 2407 .dwattr $C$DW$188, DW_AT_decl_column(0x0b) + 2408 .dwendtag $C$DW$T$93 + 2409 + 2410 .dwattr $C$DW$T$93, DW_AT_decl_file("/usr/lib/ti/pru-software-support-package/include/rsc_type + 2411 .dwattr $C$DW$T$93, DW_AT_decl_line(0x58) + 2412 .dwattr $C$DW$T$93, DW_AT_decl_column(0x08) + 2413 .dwattr $C$DW$CU, DW_AT_language(DW_LANG_C) + 2414 + 2415;*************************************************************** + 2416;* DWARF CIE ENTRIES * + 2417;*************************************************************** + 2418 + 2419$C$DW$CIE .dwcie 14 + 2420 .dwcfi cfa_register, 8 +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 45 + + 2421 .dwcfi cfa_offset, 0 + 2422 .dwcfi undefined, 0 + 2423 .dwcfi undefined, 1 + 2424 .dwcfi undefined, 2 + 2425 .dwcfi undefined, 3 + 2426 .dwcfi undefined, 4 + 2427 .dwcfi undefined, 5 + 2428 .dwcfi undefined, 6 + 2429 .dwcfi undefined, 7 + 2430 .dwcfi same_value, 8 + 2431 .dwcfi same_value, 9 + 2432 .dwcfi same_value, 10 + 2433 .dwcfi same_value, 11 + 2434 .dwcfi undefined, 12 + 2435 .dwcfi undefined, 13 + 2436 .dwcfi undefined, 14 + 2437 .dwcfi undefined, 15 + 2438 .dwcfi same_value, 16 + 2439 .dwcfi same_value, 17 + 2440 .dwcfi same_value, 18 + 2441 .dwcfi same_value, 19 + 2442 .dwcfi same_value, 20 + 2443 .dwcfi same_value, 21 + 2444 .dwcfi same_value, 22 + 2445 .dwcfi same_value, 23 + 2446 .dwcfi same_value, 24 + 2447 .dwcfi same_value, 25 + 2448 .dwcfi same_value, 26 + 2449 .dwcfi same_value, 27 + 2450 .dwcfi same_value, 28 + 2451 .dwcfi same_value, 29 + 2452 .dwcfi same_value, 30 + 2453 .dwcfi same_value, 31 + 2454 .dwcfi same_value, 32 + 2455 .dwcfi same_value, 33 + 2456 .dwcfi same_value, 34 + 2457 .dwcfi same_value, 35 + 2458 .dwcfi same_value, 36 + 2459 .dwcfi same_value, 37 + 2460 .dwcfi same_value, 38 + 2461 .dwcfi same_value, 39 + 2462 .dwcfi same_value, 40 + 2463 .dwcfi same_value, 41 + 2464 .dwcfi same_value, 42 + 2465 .dwcfi same_value, 43 + 2466 .dwcfi same_value, 44 + 2467 .dwcfi same_value, 45 + 2468 .dwcfi same_value, 46 + 2469 .dwcfi same_value, 47 + 2470 .dwcfi same_value, 48 + 2471 .dwcfi same_value, 49 + 2472 .dwcfi same_value, 50 + 2473 .dwcfi same_value, 51 + 2474 .dwcfi same_value, 52 + 2475 .dwcfi same_value, 53 +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 46 + + 2476 .dwcfi same_value, 54 + 2477 .dwcfi same_value, 55 + 2478 .dwcfi undefined, 56 + 2479 .dwcfi undefined, 57 + 2480 .dwcfi undefined, 58 + 2481 .dwcfi undefined, 59 + 2482 .dwcfi undefined, 60 + 2483 .dwcfi undefined, 61 + 2484 .dwcfi undefined, 62 + 2485 .dwcfi undefined, 63 + 2486 .dwcfi undefined, 64 + 2487 .dwcfi undefined, 65 + 2488 .dwcfi undefined, 66 + 2489 .dwcfi undefined, 67 + 2490 .dwcfi undefined, 68 + 2491 .dwcfi undefined, 69 + 2492 .dwcfi undefined, 70 + 2493 .dwcfi undefined, 71 + 2494 .dwcfi undefined, 72 + 2495 .dwcfi undefined, 73 + 2496 .dwcfi undefined, 74 + 2497 .dwcfi undefined, 75 + 2498 .dwcfi undefined, 76 + 2499 .dwcfi undefined, 77 + 2500 .dwcfi undefined, 78 + 2501 .dwcfi undefined, 79 + 2502 .dwcfi undefined, 80 + 2503 .dwcfi undefined, 81 + 2504 .dwcfi undefined, 82 + 2505 .dwcfi undefined, 83 + 2506 .dwcfi undefined, 84 + 2507 .dwcfi undefined, 85 + 2508 .dwcfi undefined, 86 + 2509 .dwcfi undefined, 87 + 2510 .dwcfi undefined, 88 + 2511 .dwcfi undefined, 89 + 2512 .dwcfi undefined, 90 + 2513 .dwcfi undefined, 91 + 2514 .dwcfi undefined, 92 + 2515 .dwcfi undefined, 93 + 2516 .dwcfi undefined, 94 + 2517 .dwcfi undefined, 95 + 2518 .dwcfi undefined, 96 + 2519 .dwcfi undefined, 97 + 2520 .dwcfi undefined, 98 + 2521 .dwcfi undefined, 99 + 2522 .dwcfi undefined, 100 + 2523 .dwcfi undefined, 101 + 2524 .dwcfi undefined, 102 + 2525 .dwcfi undefined, 103 + 2526 .dwcfi undefined, 104 + 2527 .dwcfi undefined, 105 + 2528 .dwcfi undefined, 106 + 2529 .dwcfi undefined, 107 + 2530 .dwcfi undefined, 108 +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 47 + + 2531 .dwcfi undefined, 109 + 2532 .dwcfi undefined, 110 + 2533 .dwcfi undefined, 111 + 2534 .dwcfi undefined, 112 + 2535 .dwcfi undefined, 113 + 2536 .dwcfi undefined, 114 + 2537 .dwcfi undefined, 115 + 2538 .dwcfi undefined, 116 + 2539 .dwcfi undefined, 117 + 2540 .dwcfi undefined, 118 + 2541 .dwcfi undefined, 119 + 2542 .dwcfi undefined, 120 + 2543 .dwcfi undefined, 121 + 2544 .dwcfi undefined, 122 + 2545 .dwcfi undefined, 123 + 2546 .dwcfi undefined, 124 + 2547 .dwcfi undefined, 125 + 2548 .dwcfi undefined, 126 + 2549 .dwcfi undefined, 127 + 2550 .dwcfi undefined, 128 + 2551 .dwcfi undefined, 129 + 2552 .dwcfi undefined, 130 + 2553 .dwcfi undefined, 131 + 2554 .dwcfi undefined, 132 + 2555 .dwcfi undefined, 133 + 2556 .dwcfi undefined, 134 + 2557 .dwendentry + 2558 + 2559;*************************************************************** + 2560;* DWARF REGISTER MAP * + 2561;*************************************************************** + 2562 + 2563$C$DW$189 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R0_b0") + 2564 .dwattr $C$DW$189, DW_AT_location[DW_OP_reg0] + 2565$C$DW$190 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R0_b1") + 2566 .dwattr $C$DW$190, DW_AT_location[DW_OP_reg1] + 2567$C$DW$191 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R0_b2") + 2568 .dwattr $C$DW$191, DW_AT_location[DW_OP_reg2] + 2569$C$DW$192 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R0_b3") + 2570 .dwattr $C$DW$192, DW_AT_location[DW_OP_reg3] + 2571$C$DW$193 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R1_b0") + 2572 .dwattr $C$DW$193, DW_AT_location[DW_OP_reg4] + 2573$C$DW$194 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R1_b1") + 2574 .dwattr $C$DW$194, DW_AT_location[DW_OP_reg5] + 2575$C$DW$195 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R1_b2") + 2576 .dwattr $C$DW$195, DW_AT_location[DW_OP_reg6] + 2577$C$DW$196 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R1_b3") + 2578 .dwattr $C$DW$196, DW_AT_location[DW_OP_reg7] + 2579$C$DW$197 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R2_b0") + 2580 .dwattr $C$DW$197, DW_AT_location[DW_OP_reg8] + 2581$C$DW$198 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R2_b1") + 2582 .dwattr $C$DW$198, DW_AT_location[DW_OP_reg9] + 2583$C$DW$199 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R2_b2") + 2584 .dwattr $C$DW$199, DW_AT_location[DW_OP_reg10] + 2585$C$DW$200 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R2_b3") +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 48 + + 2586 .dwattr $C$DW$200, DW_AT_location[DW_OP_reg11] + 2587$C$DW$201 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R3_b0") + 2588 .dwattr $C$DW$201, DW_AT_location[DW_OP_reg12] + 2589$C$DW$202 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R3_b1") + 2590 .dwattr $C$DW$202, DW_AT_location[DW_OP_reg13] + 2591$C$DW$203 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R3_b2") + 2592 .dwattr $C$DW$203, DW_AT_location[DW_OP_reg14] + 2593$C$DW$204 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R3_b3") + 2594 .dwattr $C$DW$204, DW_AT_location[DW_OP_reg15] + 2595$C$DW$205 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R4_b0") + 2596 .dwattr $C$DW$205, DW_AT_location[DW_OP_reg16] + 2597$C$DW$206 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R4_b1") + 2598 .dwattr $C$DW$206, DW_AT_location[DW_OP_reg17] + 2599$C$DW$207 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R4_b2") + 2600 .dwattr $C$DW$207, DW_AT_location[DW_OP_reg18] + 2601$C$DW$208 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R4_b3") + 2602 .dwattr $C$DW$208, DW_AT_location[DW_OP_reg19] + 2603$C$DW$209 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R5_b0") + 2604 .dwattr $C$DW$209, DW_AT_location[DW_OP_reg20] + 2605$C$DW$210 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R5_b1") + 2606 .dwattr $C$DW$210, DW_AT_location[DW_OP_reg21] + 2607$C$DW$211 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R5_b2") + 2608 .dwattr $C$DW$211, DW_AT_location[DW_OP_reg22] + 2609$C$DW$212 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R5_b3") + 2610 .dwattr $C$DW$212, DW_AT_location[DW_OP_reg23] + 2611$C$DW$213 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R6_b0") + 2612 .dwattr $C$DW$213, DW_AT_location[DW_OP_reg24] + 2613$C$DW$214 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R6_b1") + 2614 .dwattr $C$DW$214, DW_AT_location[DW_OP_reg25] + 2615$C$DW$215 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R6_b2") + 2616 .dwattr $C$DW$215, DW_AT_location[DW_OP_reg26] + 2617$C$DW$216 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R6_b3") + 2618 .dwattr $C$DW$216, DW_AT_location[DW_OP_reg27] + 2619$C$DW$217 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R7_b0") + 2620 .dwattr $C$DW$217, DW_AT_location[DW_OP_reg28] + 2621$C$DW$218 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R7_b1") + 2622 .dwattr $C$DW$218, DW_AT_location[DW_OP_reg29] + 2623$C$DW$219 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R7_b2") + 2624 .dwattr $C$DW$219, DW_AT_location[DW_OP_reg30] + 2625$C$DW$220 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R7_b3") + 2626 .dwattr $C$DW$220, DW_AT_location[DW_OP_reg31] + 2627$C$DW$221 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R8_b0") + 2628 .dwattr $C$DW$221, DW_AT_location[DW_OP_regx 0x20] + 2629$C$DW$222 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R8_b1") + 2630 .dwattr $C$DW$222, DW_AT_location[DW_OP_regx 0x21] + 2631$C$DW$223 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R8_b2") + 2632 .dwattr $C$DW$223, DW_AT_location[DW_OP_regx 0x22] + 2633$C$DW$224 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R8_b3") + 2634 .dwattr $C$DW$224, DW_AT_location[DW_OP_regx 0x23] + 2635$C$DW$225 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R9_b0") + 2636 .dwattr $C$DW$225, DW_AT_location[DW_OP_regx 0x24] + 2637$C$DW$226 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R9_b1") + 2638 .dwattr $C$DW$226, DW_AT_location[DW_OP_regx 0x25] + 2639$C$DW$227 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R9_b2") + 2640 .dwattr $C$DW$227, DW_AT_location[DW_OP_regx 0x26] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 49 + + 2641$C$DW$228 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R9_b3") + 2642 .dwattr $C$DW$228, DW_AT_location[DW_OP_regx 0x27] + 2643$C$DW$229 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R10_b0") + 2644 .dwattr $C$DW$229, DW_AT_location[DW_OP_regx 0x28] + 2645$C$DW$230 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R10_b1") + 2646 .dwattr $C$DW$230, DW_AT_location[DW_OP_regx 0x29] + 2647$C$DW$231 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R10_b2") + 2648 .dwattr $C$DW$231, DW_AT_location[DW_OP_regx 0x2a] + 2649$C$DW$232 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R10_b3") + 2650 .dwattr $C$DW$232, DW_AT_location[DW_OP_regx 0x2b] + 2651$C$DW$233 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R11_b0") + 2652 .dwattr $C$DW$233, DW_AT_location[DW_OP_regx 0x2c] + 2653$C$DW$234 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R11_b1") + 2654 .dwattr $C$DW$234, DW_AT_location[DW_OP_regx 0x2d] + 2655$C$DW$235 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R11_b2") + 2656 .dwattr $C$DW$235, DW_AT_location[DW_OP_regx 0x2e] + 2657$C$DW$236 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R11_b3") + 2658 .dwattr $C$DW$236, DW_AT_location[DW_OP_regx 0x2f] + 2659$C$DW$237 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R12_b0") + 2660 .dwattr $C$DW$237, DW_AT_location[DW_OP_regx 0x30] + 2661$C$DW$238 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R12_b1") + 2662 .dwattr $C$DW$238, DW_AT_location[DW_OP_regx 0x31] + 2663$C$DW$239 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R12_b2") + 2664 .dwattr $C$DW$239, DW_AT_location[DW_OP_regx 0x32] + 2665$C$DW$240 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R12_b3") + 2666 .dwattr $C$DW$240, DW_AT_location[DW_OP_regx 0x33] + 2667$C$DW$241 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R13_b0") + 2668 .dwattr $C$DW$241, DW_AT_location[DW_OP_regx 0x34] + 2669$C$DW$242 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R13_b1") + 2670 .dwattr $C$DW$242, DW_AT_location[DW_OP_regx 0x35] + 2671$C$DW$243 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R13_b2") + 2672 .dwattr $C$DW$243, DW_AT_location[DW_OP_regx 0x36] + 2673$C$DW$244 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R13_b3") + 2674 .dwattr $C$DW$244, DW_AT_location[DW_OP_regx 0x37] + 2675$C$DW$245 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R14_b0") + 2676 .dwattr $C$DW$245, DW_AT_location[DW_OP_regx 0x38] + 2677$C$DW$246 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R14_b1") + 2678 .dwattr $C$DW$246, DW_AT_location[DW_OP_regx 0x39] + 2679$C$DW$247 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R14_b2") + 2680 .dwattr $C$DW$247, DW_AT_location[DW_OP_regx 0x3a] + 2681$C$DW$248 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R14_b3") + 2682 .dwattr $C$DW$248, DW_AT_location[DW_OP_regx 0x3b] + 2683$C$DW$249 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R15_b0") + 2684 .dwattr $C$DW$249, DW_AT_location[DW_OP_regx 0x3c] + 2685$C$DW$250 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R15_b1") + 2686 .dwattr $C$DW$250, DW_AT_location[DW_OP_regx 0x3d] + 2687$C$DW$251 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R15_b2") + 2688 .dwattr $C$DW$251, DW_AT_location[DW_OP_regx 0x3e] + 2689$C$DW$252 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R15_b3") + 2690 .dwattr $C$DW$252, DW_AT_location[DW_OP_regx 0x3f] + 2691$C$DW$253 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R16_b0") + 2692 .dwattr $C$DW$253, DW_AT_location[DW_OP_regx 0x40] + 2693$C$DW$254 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R16_b1") + 2694 .dwattr $C$DW$254, DW_AT_location[DW_OP_regx 0x41] + 2695$C$DW$255 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R16_b2") +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 50 + + 2696 .dwattr $C$DW$255, DW_AT_location[DW_OP_regx 0x42] + 2697$C$DW$256 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R16_b3") + 2698 .dwattr $C$DW$256, DW_AT_location[DW_OP_regx 0x43] + 2699$C$DW$257 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R17_b0") + 2700 .dwattr $C$DW$257, DW_AT_location[DW_OP_regx 0x44] + 2701$C$DW$258 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R17_b1") + 2702 .dwattr $C$DW$258, DW_AT_location[DW_OP_regx 0x45] + 2703$C$DW$259 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R17_b2") + 2704 .dwattr $C$DW$259, DW_AT_location[DW_OP_regx 0x46] + 2705$C$DW$260 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R17_b3") + 2706 .dwattr $C$DW$260, DW_AT_location[DW_OP_regx 0x47] + 2707$C$DW$261 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R18_b0") + 2708 .dwattr $C$DW$261, DW_AT_location[DW_OP_regx 0x48] + 2709$C$DW$262 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R18_b1") + 2710 .dwattr $C$DW$262, DW_AT_location[DW_OP_regx 0x49] + 2711$C$DW$263 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R18_b2") + 2712 .dwattr $C$DW$263, DW_AT_location[DW_OP_regx 0x4a] + 2713$C$DW$264 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R18_b3") + 2714 .dwattr $C$DW$264, DW_AT_location[DW_OP_regx 0x4b] + 2715$C$DW$265 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R19_b0") + 2716 .dwattr $C$DW$265, DW_AT_location[DW_OP_regx 0x4c] + 2717$C$DW$266 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R19_b1") + 2718 .dwattr $C$DW$266, DW_AT_location[DW_OP_regx 0x4d] + 2719$C$DW$267 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R19_b2") + 2720 .dwattr $C$DW$267, DW_AT_location[DW_OP_regx 0x4e] + 2721$C$DW$268 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R19_b3") + 2722 .dwattr $C$DW$268, DW_AT_location[DW_OP_regx 0x4f] + 2723$C$DW$269 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R20_b0") + 2724 .dwattr $C$DW$269, DW_AT_location[DW_OP_regx 0x50] + 2725$C$DW$270 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R20_b1") + 2726 .dwattr $C$DW$270, DW_AT_location[DW_OP_regx 0x51] + 2727$C$DW$271 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R20_b2") + 2728 .dwattr $C$DW$271, DW_AT_location[DW_OP_regx 0x52] + 2729$C$DW$272 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R20_b3") + 2730 .dwattr $C$DW$272, DW_AT_location[DW_OP_regx 0x53] + 2731$C$DW$273 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R21_b0") + 2732 .dwattr $C$DW$273, DW_AT_location[DW_OP_regx 0x54] + 2733$C$DW$274 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R21_b1") + 2734 .dwattr $C$DW$274, DW_AT_location[DW_OP_regx 0x55] + 2735$C$DW$275 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R21_b2") + 2736 .dwattr $C$DW$275, DW_AT_location[DW_OP_regx 0x56] + 2737$C$DW$276 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R21_b3") + 2738 .dwattr $C$DW$276, DW_AT_location[DW_OP_regx 0x57] + 2739$C$DW$277 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R22_b0") + 2740 .dwattr $C$DW$277, DW_AT_location[DW_OP_regx 0x58] + 2741$C$DW$278 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R22_b1") + 2742 .dwattr $C$DW$278, DW_AT_location[DW_OP_regx 0x59] + 2743$C$DW$279 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R22_b2") + 2744 .dwattr $C$DW$279, DW_AT_location[DW_OP_regx 0x5a] + 2745$C$DW$280 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R22_b3") + 2746 .dwattr $C$DW$280, DW_AT_location[DW_OP_regx 0x5b] + 2747$C$DW$281 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R23_b0") + 2748 .dwattr $C$DW$281, DW_AT_location[DW_OP_regx 0x5c] + 2749$C$DW$282 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R23_b1") + 2750 .dwattr $C$DW$282, DW_AT_location[DW_OP_regx 0x5d] +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 51 + + 2751$C$DW$283 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R23_b2") + 2752 .dwattr $C$DW$283, DW_AT_location[DW_OP_regx 0x5e] + 2753$C$DW$284 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R23_b3") + 2754 .dwattr $C$DW$284, DW_AT_location[DW_OP_regx 0x5f] + 2755$C$DW$285 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R24_b0") + 2756 .dwattr $C$DW$285, DW_AT_location[DW_OP_regx 0x60] + 2757$C$DW$286 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R24_b1") + 2758 .dwattr $C$DW$286, DW_AT_location[DW_OP_regx 0x61] + 2759$C$DW$287 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R24_b2") + 2760 .dwattr $C$DW$287, DW_AT_location[DW_OP_regx 0x62] + 2761$C$DW$288 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R24_b3") + 2762 .dwattr $C$DW$288, DW_AT_location[DW_OP_regx 0x63] + 2763$C$DW$289 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R25_b0") + 2764 .dwattr $C$DW$289, DW_AT_location[DW_OP_regx 0x64] + 2765$C$DW$290 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R25_b1") + 2766 .dwattr $C$DW$290, DW_AT_location[DW_OP_regx 0x65] + 2767$C$DW$291 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R25_b2") + 2768 .dwattr $C$DW$291, DW_AT_location[DW_OP_regx 0x66] + 2769$C$DW$292 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R25_b3") + 2770 .dwattr $C$DW$292, DW_AT_location[DW_OP_regx 0x67] + 2771$C$DW$293 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R26_b0") + 2772 .dwattr $C$DW$293, DW_AT_location[DW_OP_regx 0x68] + 2773$C$DW$294 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R26_b1") + 2774 .dwattr $C$DW$294, DW_AT_location[DW_OP_regx 0x69] + 2775$C$DW$295 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R26_b2") + 2776 .dwattr $C$DW$295, DW_AT_location[DW_OP_regx 0x6a] + 2777$C$DW$296 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R26_b3") + 2778 .dwattr $C$DW$296, DW_AT_location[DW_OP_regx 0x6b] + 2779$C$DW$297 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R27_b0") + 2780 .dwattr $C$DW$297, DW_AT_location[DW_OP_regx 0x6c] + 2781$C$DW$298 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R27_b1") + 2782 .dwattr $C$DW$298, DW_AT_location[DW_OP_regx 0x6d] + 2783$C$DW$299 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R27_b2") + 2784 .dwattr $C$DW$299, DW_AT_location[DW_OP_regx 0x6e] + 2785$C$DW$300 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R27_b3") + 2786 .dwattr $C$DW$300, DW_AT_location[DW_OP_regx 0x6f] + 2787$C$DW$301 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R28_b0") + 2788 .dwattr $C$DW$301, DW_AT_location[DW_OP_regx 0x70] + 2789$C$DW$302 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R28_b1") + 2790 .dwattr $C$DW$302, DW_AT_location[DW_OP_regx 0x71] + 2791$C$DW$303 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R28_b2") + 2792 .dwattr $C$DW$303, DW_AT_location[DW_OP_regx 0x72] + 2793$C$DW$304 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R28_b3") + 2794 .dwattr $C$DW$304, DW_AT_location[DW_OP_regx 0x73] + 2795$C$DW$305 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R29_b0") + 2796 .dwattr $C$DW$305, DW_AT_location[DW_OP_regx 0x74] + 2797$C$DW$306 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R29_b1") + 2798 .dwattr $C$DW$306, DW_AT_location[DW_OP_regx 0x75] + 2799$C$DW$307 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R29_b2") + 2800 .dwattr $C$DW$307, DW_AT_location[DW_OP_regx 0x76] + 2801$C$DW$308 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R29_b3") + 2802 .dwattr $C$DW$308, DW_AT_location[DW_OP_regx 0x77] + 2803$C$DW$309 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R30_b0") + 2804 .dwattr $C$DW$309, DW_AT_location[DW_OP_regx 0x78] + 2805$C$DW$310 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R30_b1") +PRU Assembler Unix v2.1.5 Fri Jun 5 14:14:07 2020 + +Tools Copyright (c) 2012-2017 Texas Instruments Incorporated +/tmp/cloud9-examples/cycle.pru0.asm PAGE 52 + + 2806 .dwattr $C$DW$310, DW_AT_location[DW_OP_regx 0x79] + 2807$C$DW$311 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R30_b2") + 2808 .dwattr $C$DW$311, DW_AT_location[DW_OP_regx 0x7a] + 2809$C$DW$312 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R30_b3") + 2810 .dwattr $C$DW$312, DW_AT_location[DW_OP_regx 0x7b] + 2811$C$DW$313 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R31_b0") + 2812 .dwattr $C$DW$313, DW_AT_location[DW_OP_regx 0x7c] + 2813$C$DW$314 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R31_b1") + 2814 .dwattr $C$DW$314, DW_AT_location[DW_OP_regx 0x7d] + 2815$C$DW$315 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R31_b2") + 2816 .dwattr $C$DW$315, DW_AT_location[DW_OP_regx 0x7e] + 2817$C$DW$316 .dwtag DW_TAG_TI_assign_register, DW_AT_name("R31_b3") + 2818 .dwattr $C$DW$316, DW_AT_location[DW_OP_regx 0x7f] + 2819 .dwendtag $C$DW$CU + 2820 + +No Assembly Errors, No Assembly Warnings diff --git a/pru-cookbook/07more/code/delay-test.pru0.c b/pru-cookbook/07more/code/delay-test.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..337ecbb23cb0920a687b30b3e50dcdbf5ae86f86 --- /dev/null +++ b/pru-cookbook/07more/code/delay-test.pru0.c @@ -0,0 +1,28 @@ +// Shows how to call an assembly routine with one parameter +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +// The function is defined in delay.asm in same dir +// We just need to add a declaration here, the defination can be +// seperately linked +extern void my_delay_cycles(uint32_t); + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t gpio = P9_31; // Select which pin to toggle.; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + while(1) { + __R30 |= gpio; // Set the GPIO pin to 1 + my_delay_cycles(1); + __R30 &= ~gpio; // Clear the GPIO pin + my_delay_cycles(1); + } +} diff --git a/pru-cookbook/07more/code/delay-test2.pru0.c b/pru-cookbook/07more/code/delay-test2.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..763b3a7d7b0452139cb817b0d56bf5e13688e0f6 --- /dev/null +++ b/pru-cookbook/07more/code/delay-test2.pru0.c @@ -0,0 +1,32 @@ +// Shows how to call an assembly routine with a return value +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +#define TEST 100 + +// The function is defined in delay.asm in same dir +// We just need to add a declaration here, the defination can be +// seperately linked +extern uint32_t my_delay_cycles(uint32_t); + +uint32_t ret; + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t gpio = P9_31; // Select which pin to toggle.; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + while(1) { + __R30 |= gpio; // Set the GPIO pin to 1 + ret = my_delay_cycles(1); + __R30 &= ~gpio; // Clear the GPIO pin + ret = my_delay_cycles(1); + } +} diff --git a/pru-cookbook/07more/code/delay.pru0.asm b/pru-cookbook/07more/code/delay.pru0.asm new file mode 100644 index 0000000000000000000000000000000000000000..1c1cce7d1d986e55bc3bc3f8bf3cc3e3d783fc21 --- /dev/null +++ b/pru-cookbook/07more/code/delay.pru0.asm @@ -0,0 +1,9 @@ +; This is an example of how to call an assembly routine from C. +; Mark A. Yoder, 9-July-2018 + .global my_delay_cycles +my_delay_cycles: +delay: + sub r14, r14, 1 ; The first argument is passed in r14 + qbne delay, r14, 0 + + jmp r3.w2 ; r3 contains the return address \ No newline at end of file diff --git a/pru-cookbook/07more/code/delay2.pru0.asm b/pru-cookbook/07more/code/delay2.pru0.asm new file mode 100644 index 0000000000000000000000000000000000000000..e1f1da03d37ece54ca7c577b4244bd8abbbc921f --- /dev/null +++ b/pru-cookbook/07more/code/delay2.pru0.asm @@ -0,0 +1,15 @@ +; This is an example of how to call an assembly routine from C with a retun value. +; Mark A. Yoder, 9-July-2018 + + .cdecls "delay-test2.pru0.c" + + .global my_delay_cycles +my_delay_cycles: +delay: + sub r14, r14, 1 ; The first argument is passed in r14 + qbne delay, r14, 0 + + ldi r14, TEST ; TEST is defined in delay-test2.c + ; r14 is the return register + + jmp r3.w2 ; r3 contains the return address \ No newline at end of file diff --git a/pru-cookbook/07more/code/logic.c b/pru-cookbook/07more/code/logic.c new file mode 100644 index 0000000000000000000000000000000000000000..f774708d22f3ef26ede77fe45a8057d7f1e905f2 --- /dev/null +++ b/pru-cookbook/07more/code/logic.c @@ -0,0 +1,34 @@ +// Access the CYCLE and STALL registers +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + // Copy lower 8 bits to r16 + struct { + uint8_t b0; + uint8_t b1; + uint8_t b2; + uint8_t b3; + } r17; + + // Clear SYSCFG[STANDBY_INIT] to enable OCP master port + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + +// r16.b0 = __R31.b0; + __asm(" mov r17.b0, r31.b0"); + __delay_cycles(1); + r17.b1 = (uint32_t) __R31; + __delay_cycles(1); + r17.b2 = (uint32_t) __R31; + __delay_cycles(1); + r17.b3 = (uint32_t) __R31; + + __xout(10, 16, 0, r17); + + __halt(); +} diff --git a/pru-cookbook/07more/code/logic_setup.sh b/pru-cookbook/07more/code/logic_setup.sh new file mode 100644 index 0000000000000000000000000000000000000000..2253459cf1f8efde2e61281525f26872a3940a42 --- /dev/null +++ b/pru-cookbook/07more/code/logic_setup.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# +export PRUN=0 +export TARGET=logic +echo PRUN=$PRUN +echo TARGET=$TARGET + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_31 P9_29 P9_30 P9_28 P9_92 P9_27 P9_91 P9_25 " +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P1_36 P1_33 P2_32 P2_30 P1_31 P2_34 P2_28 P1_29" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruin + config-pin -q $pin +done diff --git a/pru-cookbook/07more/code/resource_table_pru0.h b/pru-cookbook/07more/code/resource_table_pru0.h new file mode 100644 index 0000000000000000000000000000000000000000..06c148006b7a892d30f16d69891c6165e3525161 --- /dev/null +++ b/pru-cookbook/07more/code/resource_table_pru0.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ======== rsc_table_pru.h ======== + * + * Define the resource table entries for PRU0. This will be + * incorporated into corresponding base images, and used by the remoteproc + * on the host-side to allocated/reserve resources. Note the remoteproc + * driver requires that all PRU firmware be built with a resource table. + * + * + */ + +#ifndef _RSC_TABLE_PRU_H_ +#define _RSC_TABLE_PRU_H_ + +#include <stddef.h> +#include <rsc_types.h> +#include "pru_virtio_ids.h" + +/* + * Sizes of the virtqueues (expressed in number of buffers supported, + * and must be power of 2) + */ +#define PRU_RPMSG_VQ0_SIZE 2 +#define PRU_RPMSG_VQ1_SIZE 2 + +/* flip up bits whose indices represent features we support */ +#define RPMSG_PRU_C0_FEATURES 1 + +/* Definition for unused interrupts */ +#define HOST_UNUSED 255 + +/* Mapping sysevts to a channel. Each pair contains a sysevt, channel */ +struct ch_map pru_intc_map[] = { {17, 1}, {18, 0}, {19, 2}, {20, 3}, {21, 0}, + {22, 1}, {24, 4}, {25, 5}, {26, 6}, {27, 7}, +}; + +struct my_resource_table { + struct resource_table base; + + uint32_t offset[1]; /* Should match 'num' in actual definition */ + + /* intc definition */ + struct fw_rsc_custom pru_ints; +}; + +#pragma DATA_SECTION(am335x_pru_remoteproc_ResourceTable, ".resource_table") +#pragma RETAIN(am335x_pru_remoteproc_ResourceTable) +struct my_resource_table am335x_pru_remoteproc_ResourceTable = { + 1, /* we're the first version that implements this */ + 1, /* number of entries in the table */ + 0, 0, /* reserved, must be zero */ + /* offsets to entries */ + { + offsetof(struct my_resource_table, pru_ints), + }, + + { + TYPE_CUSTOM, TYPE_PRU_INTS, + sizeof(struct fw_rsc_custom_ints), + { /* PRU_INTS version */ + 0x0000, + /* Channel-to-host mapping, 255 for unused */ + 0, 1, 2, 3, 0, 6, 1, 7, HOST_UNUSED, HOST_UNUSED, + /* Number of evts being mapped to channels */ + (sizeof(pru_intc_map) / sizeof(struct ch_map)), + /* Pointer to the structure containing mapped events */ + pru_intc_map, + }, + }, +}; + +#endif /* _RSC_TABLE_PRU_H_ */ diff --git a/pru-cookbook/07more/code/setup.sh b/pru-cookbook/07more/code/setup.sh new file mode 100644 index 0000000000000000000000000000000000000000..f1d0d9db334b125b68171dd18ce04abec94ace08 --- /dev/null +++ b/pru-cookbook/07more/code/setup.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# +export TARGET=delay-test.pru0 +export TARGETasm=delay.pru0 +echo TARGET=$TARGET +echo TARGETasm=$TARGETasm + +# Configure the PRU pins based on which Beagle is running +machine=$(awk '{print $NF}' /proc/device-tree/model) +echo -n $machine +if [ $machine = "Black" ]; then + echo " Found" + pins="P9_31" +elif [ $machine = "Blue" ]; then + echo " Found" + pins="" +elif [ $machine = "PocketBeagle" ]; then + echo " Found" + pins="P1_33" +else + echo " Not Found" + pins="" +fi + +for pin in $pins +do + echo $pin + config-pin $pin pruout + config-pin -q $pin +done diff --git a/pru-cookbook/07more/code/xin.pru1.c b/pru-cookbook/07more/code/xin.pru1.c new file mode 100644 index 0000000000000000000000000000000000000000..56d4a68209d974c51e50559cc6d90ff9046f3a68 --- /dev/null +++ b/pru-cookbook/07more/code/xin.pru1.c @@ -0,0 +1,34 @@ +// From: http://git.ti.com/pru-software-support-package/pru-software-support-package/trees/master/examples/am335x/PRU_Direct_Connect1 +#include <stdint.h> +#include "resource_table_empty.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +typedef struct { + uint32_t reg5; + uint32_t reg6; + uint32_t reg7; + uint32_t reg8; + uint32_t reg9; + uint32_t reg10; +} bufferData; + +bufferData dmemBuf; + +/* PRU-to-ARM interrupt */ +#define PRU1_PRU0_INTERRUPT (18) +#define PRU1_ARM_INTERRUPT (20+16) + +void main(void) +{ + /* Let PRU0 know that I am awake */ + __R31 = PRU1_PRU0_INTERRUPT+16; + + /* XFR registers R5-R10 from PRU0 to PRU1 */ + /* 14 is the device_id that signifies a PRU to PRU transfer */ + __xin(14, 5, 0, dmemBuf); + + /* Halt the PRU core */ + __halt(); +} diff --git a/pru-cookbook/07more/code/xout-cycle.pru0.c b/pru-cookbook/07more/code/xout-cycle.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..339fedfc38eed9d9372a0b55ee74dfc031be70c2 --- /dev/null +++ b/pru-cookbook/07more/code/xout-cycle.pru0.c @@ -0,0 +1,62 @@ +// Version of xout.c with code to use CYCLE to count cycle times. +#include <stdint.h> +#include <pru_intc.h> +#include <pru_ctrl.h> +#include "resource_table_pru0.h" + +#define PRU0 + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +typedef struct { + uint32_t reg5; + uint32_t reg6; + uint32_t reg7; + uint32_t reg8; + uint32_t reg9; + uint32_t reg10; +} bufferData; + +bufferData dmemBuf; + +/* PRU-to-ARM interrupt */ +#define PRU1_PRU0_INTERRUPT (18) +#define PRU0_ARM_INTERRUPT (19+16) + +void main(void) +{ + uint32_t cycleXX; // Use a name that's easy to search + /* Clear the status of all interrupts */ + CT_INTC.SECR0 = 0xFFFFFFFF; + CT_INTC.SECR1 = 0xFFFFFFFF; + + /* Load the buffer with default values to transfer */ + dmemBuf.reg5 = 0xDEADBEEF; + dmemBuf.reg6 = 0xAAAAAAAA; + dmemBuf.reg7 = 0x12345678; + dmemBuf.reg8 = 0xBBBBBBBB; + dmemBuf.reg9 = 0x87654321; + dmemBuf.reg10 = 0xCCCCCCCC; + + /* Poll until R31.30 (PRU0 interrupt) is set + * This signals PRU1 is initialized */ + while ((__R31 & (1<<30)) == 0) { + } + + /* XFR registers R5-R10 from PRU0 to PRU1 */ + /* 14 is the device_id that signifies a PRU to PRU transfer */ + PRU0_CTRL.CTRL_bit.CTR_EN = 1; // Enable cycle counter + + __xout(14, 5, 0, dmemBuf); + + cycleXX = PRU0_CTRL.CYCLE; // Read cycle and store in a register + + /* Clear the status of the interrupt */ + CT_INTC.SICR = PRU1_PRU0_INTERRUPT; + + dmemBuf.reg5 = cycleXX; + + /* Halt the PRU core */ + __halt(); +} diff --git a/pru-cookbook/07more/code/xout.pru0.c b/pru-cookbook/07more/code/xout.pru0.c new file mode 100644 index 0000000000000000000000000000000000000000..bfcdbf5f927700c2d250abc0f28850bb4884392f --- /dev/null +++ b/pru-cookbook/07more/code/xout.pru0.c @@ -0,0 +1,52 @@ +// From: http://git.ti.com/pru-software-support-package/pru-software-support-package/trees/master/examples/am335x/PRU_Direct_Connect0 +#include <stdint.h> +#include <pru_intc.h> +#include "resource_table_pru0.h" + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +typedef struct { + uint32_t reg5; + uint32_t reg6; + uint32_t reg7; + uint32_t reg8; + uint32_t reg9; + uint32_t reg10; +} bufferData; + +bufferData dmemBuf; + +/* PRU-to-ARM interrupt */ +#define PRU1_PRU0_INTERRUPT (18) +#define PRU0_ARM_INTERRUPT (19+16) + +void main(void) +{ + /* Clear the status of all interrupts */ + CT_INTC.SECR0 = 0xFFFFFFFF; + CT_INTC.SECR1 = 0xFFFFFFFF; + + /* Load the buffer with default values to transfer */ + dmemBuf.reg5 = 0xDEADBEEF; + dmemBuf.reg6 = 0xAAAAAAAA; + dmemBuf.reg7 = 0x12345678; + dmemBuf.reg8 = 0xBBBBBBBB; + dmemBuf.reg9 = 0x87654321; + dmemBuf.reg10 = 0xCCCCCCCC; + + /* Poll until R31.30 (PRU0 interrupt) is set + * This signals PRU1 is initialized */ + while ((__R31 & (1<<30)) == 0) { + } + + /* XFR registers R5-R10 from PRU0 to PRU1 */ + /* 14 is the device_id that signifies a PRU to PRU transfer */ + __xout(14, 5, 0, dmemBuf); + + /* Clear the status of the interrupt */ + CT_INTC.SICR = PRU1_PRU0_INTERRUPT; + + /* Halt the PRU core */ + __halt(); +} diff --git a/pru-cookbook/07more/code/xout_run.sh b/pru-cookbook/07more/code/xout_run.sh new file mode 100755 index 0000000000000000000000000000000000000000..158cf472beddca5d3781df4026dbeea4de3338b7 --- /dev/null +++ b/pru-cookbook/07more/code/xout_run.sh @@ -0,0 +1,3 @@ +# Be sure to start PRU 0 before PRU 1. PRU 0 will wait for PRU 1 to signal it. +make TARGET=xout.pru0 +make TARGET=xin.pru1 diff --git a/pru-cookbook/07more/figures/my_delay_cycles.png b/pru-cookbook/07more/figures/my_delay_cycles.png new file mode 100644 index 0000000000000000000000000000000000000000..125a85c0ba66e1bbc3e2bb6bffefae68538f0216 Binary files /dev/null and b/pru-cookbook/07more/figures/my_delay_cycles.png differ diff --git a/pru-cookbook/07more/more.rst b/pru-cookbook/07more/more.rst new file mode 100644 index 0000000000000000000000000000000000000000..ae3abcf84c1598a23f54a2a0ea044952809d38ce --- /dev/null +++ b/pru-cookbook/07more/more.rst @@ -0,0 +1,443 @@ +.. _pru-cookbook-more: + +More Performance +################## + +So far in all our examples we've been able to meet our timing goals by writing +our code in the C programming language. The C compiler does a suprisingly +good job at generating code, most the time. However there are times +when very precise timing is needed and the compiler isn't doing it. + +At these times you need to write in assembly language. This chapter +introduces the PRU assembler and shows how to call assembly code from +C. Detailing on how to program in assembly are beyond the scope of this text. + +The following are resources used in this chapter. + +Resources +~~~~~~~~~~ + +* `PRU Optimizing C/C++ Compiler, v2.2, User's Guide <http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf>`_ +* `PRU Assembly Language Tools User's Guide <http://www.ti.com/lit/ug/spruhv6b/spruhv6b.pdf>`_ +* `PRU Assembly Instruction User Guide <http://www.ti.com/lit/ug/spruij2/spruij2.pdf>`_ + +Calling Assembly from C +------------------------- + +Problem +~~~~~~~~~ + +You have some C code and you want to call an assembly language routine from it. + +Solution +~~~~~~~~~ + +You need to do two things, write the assembler file and modify the ``Makefile`` +to include it. For example, let's write our own ``my_delay_cycles`` routine in +in assembly. The intrinsic ``pass:[__]delay_cycles`` must be passed a compile time +constant. Our new ``delay_cycles`` can take a runtime delay value. + +:ref:`more_delay-test` is much like our other c code, but on line 10 we declare +``my_delay_cycles`` and then on lines 24 and 26 we'll call it with an argument of 1. + +.. _more_delay-test: + +delay-test.pru0.c +~~~~~~~~~~~~~~~~~~~ + +:download:`code/delay-test.pru0.c <code/delay-test.pru0.c>` + +:ref:`more_delay` is the assembly code. + +.. _more_delay: + +delay.pru0.asm +~~~~~~~~~~~~~~~ + +:download:`delay.pru0.asm <code/delay.pru0.asm>` + +The ``Makefile`` has one addition that needs to be made to compile both :ref:`more_delay-test` +and :ref:`more_delay`. +If you look in the local ``Makefile`` you'll see: + +.. _more_makefile: + +Makefile +~~~~~~~~~ + +:download:`Makefile <code/Makefile>` + +This Makefle includes a common Makfile at ``/var/lib/cloud9/common/Makefile``, this the Makefile +you need to edit. Edit ``/var/lib/cloud9/common/Makefile`` and go to line 195. + +.. code-block:: bash + + $(GEN_DIR)/%.out: $(GEN_DIR)/%.o *$(GEN_DIR)/$(TARGETasm).o* + @mkdir -p $(GEN_DIR) + @echo 'LD $^' + $(eval $(call target-to-proc,$@)) + $(eval $(call proc-to-build-vars,$@)) + @$(LD) $@ $^ $(LDFLAGS) + +Add ``*(GEN_DIR)/$(TARGETasm).o*`` as shown in bold above. You will want to remove +this addition once you are done with this example since it will break the other examples. + +The following will compile and run everything. + +.. code-block:: bash + + bone$ *config-pin P9_31 pruout* + bone$ *make TARGET=delay-test.pru0 TARGETasm=delay.pru0* + /var/lib/cloud9/common/Makefile:29: MODEL=TI_AM335x_BeagleBone_Black,TARGET=delay-test.pru0 + - Stopping PRU 0 + - copying firmware file /tmp/cloud9-examples/delay-test.pru0.out to /lib/firmware/am335x-pru0-fw + write_init_pins.sh + - Starting PRU 0 + MODEL = TI_AM335x_BeagleBone_Black + PROC = pru + PRUN = 0 + PRU_DIR = /sys/class/remoteproc/remoteproc1 + +The resulting output is shown in :ref:`more_my_delay_cycles`. + +.. _more_my_delay_cycles: + +Output of my_delay_cycles() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: figures/my_delay_cycles.png + :align: center + :alt: Output of my_delay_cycles() + +Notice the on time is about 35ns and the off time is 30ns. + +Discission +~~~~~~~~~~~~ + +There is much to explain here. Let's start with :ref:`more_delay`. + +Line-by-line of delay.pru0.asm +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. table:: + + +-------+-------------------------------------------------------------------------------------------------------+ + |Line | Explanation | + +=======+=======================================================================================================+ + |3 | Declare `my_delay_cycles` to be global so the linker can find it. | + +-------+-------------------------------------------------------------------------------------------------------+ + |4 | Label the starting point for `my_delay_cycles`. | + +-------+-------------------------------------------------------------------------------------------------------+ + |5 | Label for our delay loop. | + +-------+-------------------------------------------------------------------------------------------------------+ + |6 | The first argument is passed in register ``r14``. Page 111 of | + | | `PRU Optimizing C/C++ Compiler, v2.2, User's Guide <http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf>`_ | + | | gives the argument passing convention. Registers ``r14`` to ``r29`` are used | + | | to pass arguments, if there are more arguments, the argument stack (``r4``) | + | | is used. The other register conventions are found on page 108. | + | | Here we subtract 1 from ``r14`` and save it back into ``r14``. | + +-------+-------------------------------------------------------------------------------------------------------+ + |7 | `qbne` is a quick branch if not equal. | + +-------+-------------------------------------------------------------------------------------------------------+ + |9 | Once we've delayed enough we drop through the quick branch and | + | | hit the jump. The upper bits of register `r3` has the return address, | + | | therefore we return to the c code. | + +-------+-------------------------------------------------------------------------------------------------------+ + +:ref:`more_my_delay_cycles` shows the **on** time is 35ns and the off time is 30ns. +With 5ns/cycle this gives 7 cycles on and 6 off. These times make sense +because each instruction takes a cycle and you have, set ``R30``, jump to +``my_delay_cycles``, ``sub``, ``qbne``, ``jmp``. Plus the instruction (not seen) that +initilizes `r14` to the passed value. That's a total of six instructions. +The extra instruction is the branch at the bottom of the ``while`` loop. + + +Returning a Value from Assembly +-------------------------------- + +Problem +~~~~~~~~~ + +Your assembly code needs to return a value. + +Solution +~~~~~~~~~ + +``R14`` is how the return value is passed back. :ref:`more_test2` shows the c code. + +.. _more_test2: + +delay-test2.pru0.c +~~~~~~~~~~~~~~~~~~~ + +:download:`delay-test2.pru0.c <code/delay-test2.pru0.c>` + +:ref:`more_delay2` is the assembly code. + +.. _more_delay2: + +delay2.pru0.asm +~~~~~~~~~~~~~~~~~ + +:download:`delay2.pru0.asm <code/delay2.pru0.asm>` + +An additional feature is shown in line 4 of :ref:`more_delay2`. The +``.cdecls "delay-test2.pru0.c"`` says to include any defines from ``delay-test2.pru0.c`` +In this example, line 6 of :ref:`more_test2` `#defines` TEST and line 12 of +:ref:`more_delay2` reference it. + + +Using the Built-In Counter for Timing +--------------------------------------- + +Problem +~~~~~~~~~ + +I want to count how many cycles my routine takes. + +Solution +~~~~~~~~~ + +Each PRU has a ``CYCLE`` register which counts the number of cycles since +the PRU was enabled. They also have a ``STALL`` register that counts how +many times the PRU stalled fetching an instruction. +:ref:`more_cycle` shows they are used. + +.. _more_cycle: + +cycle.pru0.c - Code to count cycles. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`delay2.pru0.asm <code/cycle.pru0.c>` + +Discission +~~~~~~~~~~~~ + +The code is mostly the same as other examples. ``cycle`` and ``stall`` end up in registers which +we can read using prudebug. :ref:`more_cycle_lines` is the Line-by-line. + +.. _more_cycle_lines: + +Line-by-line for cycle.pru0.c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +-------+---------------------------------------------------------------------------------------+ + |Line | Explanation | + +=======+=======================================================================================+ + |4 | Include needed to reference `CYCLE` and `STALL`. | + +-------+---------------------------------------------------------------------------------------+ + |16 | Declaring `cycle` and `stall`. The compiler will optimize these and just | + | | keep them in registers. We'll have to look at the `cycle.pru0.lst` file to see where | + | | they are stored. | + +-------+---------------------------------------------------------------------------------------+ + |21 | Enables `CYCLE`. | + +-------+---------------------------------------------------------------------------------------+ + |26 | Reset `CYCLE`. It ignores the value assigned to it and always sets it | + | | to 0. `cycle` is on the right hand side to make the compiler give it it's own | + | | register. | + +-------+---------------------------------------------------------------------------------------+ + |28, 29 | Reads the `CYCLE` and `STALL` values into registers. | + +-------+---------------------------------------------------------------------------------------+ + +You can see where ``cycle`` and ``stall`` are stored by looking into :ref:`more_cycle_list0`. + +.. _more_cycle_list0: + +/tmp/cloud9-examples/cycle.pru0.lst Lines 113..119 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`cycle.pru0.lst lines=113..119 <code/cycle.pru0.lst>` + +Here the ``LDI32`` instruction loads the address ``0x22000`` into ``r0``. This is the offset to +the ``CTRL`` registers. Later in the file we see :ref:`more_cycle_list1`. + +.. _more_cycle_list1: + +/tmp/cloud9-examples/cycle.pru0.lst Lines 146..152 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:download:`lines=146..152 <code/cycle.pru0.lst>` + + +The first ``LBBO`` takes the contents of ``r0`` and adds the offset 12 to it and copies 4 bytes +into ``r1``. This points to ``CYCLE``, so ``r1`` has the contents of ``CYCLE``. + +The second ``LBBO`` does the same, but with offset 16, which points to ``STALL``, +thus ``STALL`` is now in ``r0``. + +Now fire up **prudebug** and look at those registers. + +.. code-block:: bash + + bone$ *sudo prudebug* + PRU0> *r* + r + r + Register info for PRU0 + Control register: 0x00000009 + Reset PC:0x0000 STOPPED, FREE_RUN, COUNTER_ENABLED, NOT_SLEEPING, PROC_DISABLED + + Program counter: 0x0012 + Current instruction: HALT + + R00: *0x00000005* R08: 0x00000200 R16: 0x000003c6 R24: 0x00110210 + R01: *0x00000003* R09: 0x00000000 R17: 0x00000000 R25: 0x00000000 + R02: 0x000000fc R10: 0xfff4ea57 R18: 0x000003e6 R26: 0x6e616843 + R03: 0x0004272c R11: 0x5fac6373 R19: 0x30203020 R27: 0x206c656e + R04: 0xffffffff R12: 0x59bfeafc R20: 0x0000000a R28: 0x00003033 + R05: 0x00000007 R13: 0xa4c19eaf R21: 0x00757270 R29: 0x02100000 + R06: 0xefd30a00 R14: 0x00000005 R22: 0x0000001e R30: 0xa03f9990 + R07: 0x00020024 R15: 0x00000003 R23: 0x00000000 R31: 0x00000000 + + +So ``cycle`` is 3 and ``stall`` is 5. It must be one cycle to clear the GPIO and 2 cycles to read the +``CYCLE`` register and save it in the register. It's interesting there are 5 ``stall`` cycles. + +If you switch the order of lines 30 and 31 you'll see ``cycle`` is 7 and ``stall`` is 2. ``cycle`` now includes the +time needed to read ``stall`` and ``stall`` no longer includes the time to read ``cycle``. + +Xout and Xin - Transfering Between PRUs +--------------------------------------- + +Problem +~~~~~~~~~ + +I need to transfer data between PRUs quickly. + +Solution +~~~~~~~~~ + +The ``pass:[__]xout()`` and ``pass:[__]xin()`` intrinsics are able to transfer up to 30 registers between PRU 0 and PRU 1 quickly. +:ref:`more_xout` shows how ``xout()`` running on PRU 0 transfers six registers to PRU 1. + +.. _more_xout: + +xout.pru0.c +~~~~~~~~~~~~ + +:download:`xout.pru0.c <code/xout.pru0.c>` + +PRU 1 waits at line 41 until PRU 0 signals it. :ref:`more_xin` sends sends an +interupt to PRU 0 and waits for it to send the data. + +.. _more_xin: + +xin.pru1.c +~~~~~~~~~~~ + +:download:`xin.pru1.c <code/xin.pru1.c>` + +Use ``prudebug`` to see registers R5-R10 are transfered from PRU 0 to PRU 1. + +.. code-block:: bash + + PRU0> *r* + Register info for PRU0 + Control register: 0x00000001 + Reset PC:0x0000 STOPPED, FREE_RUN, COUNTER_DISABLED, NOT_SLEEPING, PROC_DISABLED + + Program counter: 0x0026 + Current instruction: HALT + + R00: 0x00000012 *R08: 0xbbbbbbbb* R16: 0x000003c6 R24: 0x00110210 + R01: 0x00020000 *R09: 0x87654321* R17: 0x00000000 R25: 0x00000000 + R02: 0x000000e4 *R10: 0xcccccccc* R18: 0x000003e6 R26: 0x6e616843 + R03: 0x0004272c R11: 0x5fac6373 R19: 0x30203020 R27: 0x206c656e + R04: 0xffffffff R12: 0x59bfeafc R20: 0x0000000a R28: 0x00003033 + *R05: 0xdeadbeef* R13: 0xa4c19eaf R21: 0x00757270 R29: 0x02100000 + *R06: 0xaaaaaaaa* R14: 0x00000005 R22: 0x0000001e R30: 0xa03f9990 + *R07: 0x12345678* R15: 0x00000003 R23: 0x00000000 R31: 0x00000000 + + PRU0> *pru 1* + pru 1 + Active PRU is PRU1. + + PRU1> *r* + r + Register info for PRU1 + Control register: 0x00000001 + Reset PC:0x0000 STOPPED, FREE_RUN, COUNTER_DISABLED, NOT_SLEEPING, PROC_DISABLED + + Program counter: 0x000b + Current instruction: HALT + + R00: 0x00000100 *R08: 0xbbbbbbbb* R16: 0xe9da228b R24: 0x28113189 + R01: 0xe48cdb1f *R09: 0x87654321* R17: 0x66621777 R25: 0xddd29ab1 + R02: 0x000000e4 *R10: 0xcccccccc* R18: 0x661f83ea R26: 0xcf1cd4a5 + R03: 0x0004db97 R11: 0xdec387d5 R19: 0xa85adb78 R27: 0x70af2d02 + R04: 0xa90e496f R12: 0xbeac3878 R20: 0x048fff22 R28: 0x7465f5f0 + *R05: 0xdeadbeef* R13: 0x5777b488 R21: 0xa32977c7 R29: 0xae96b530 + *R06: 0xaaaaaaaa* R14: 0xffa60550 R22: 0x99fb123e R30: 0x52c42a0d + *R07: 0x12345678* R15: 0xdeb2142d R23: 0xa353129d R31: 0x00000000 + + +Discussion +~~~~~~~~~ + +:ref:`more_zout_lines` shows the line-by-line for ``xout.pru0.c`` + +.. _more_zout_lines: + +xout.pru0.c Line-by-line +~~~~~~~~~~~~~~~~~~~~~~~~~ +.. table:: + + +-------+---------------------------------------------------------------------------------------------------------+ + |Line | Explanation | + +=======+=========================================================================================================+ + |4 | A different resource so PRU 0 can receive a signal from PRU 1. | + +-------+---------------------------------------------------------------------------------------------------------+ + |9-16 | ``dmemBuf`` holds the data to be sent to PRU 1. Each will be transfered | + | | to its corresponding register by ``xout()``. | + +-------+---------------------------------------------------------------------------------------------------------+ + |21-22 | Define the interupts we're using. | + +-------+---------------------------------------------------------------------------------------------------------+ + |27-28 | Clear the interrupts. | + +-------+---------------------------------------------------------------------------------------------------------+ + |31-36 | Initialize dmemBuf with easy to recognize values. | + +-------+---------------------------------------------------------------------------------------------------------+ + |40 | Wait for PRU 1 to signal. | + +-------+---------------------------------------------------------------------------------------------------------+ + |45 | ``pass:[__]xout()`` does a direct transfer to PRU 1. Page 92 of | + | | `PRU Optimizing C/C++ Compiler, v2.2, User's Guide <http://www.ti.com/lit/ug/spruhv7b/spruhv7b.pdf>`_ | + | | shows how to use `xout()`. The first argument, 14, says to do a direct transfer to PRU 1. If the | + | | first argument is 10, 11 or 12, the data is transfered to one of three scratchpad memories that | + | | PRU 1 can access later. The second argument, 5, says to start transfering with register ``r5`` | + | | and use as many regsiters as needed to transfer all of ``dmemBuf``. The third argument, 0, | + | | says to not use remapping. (See the User's Guide for details.) | + | | The final argument is the data to be transfered. | + +-------+---------------------------------------------------------------------------------------------------------+ + |48 | Clear the interupt so it can go again. | + +-------+---------------------------------------------------------------------------------------------------------+ + +:ref:`more_xin_lines` shows the line-by-line for ``xin.pru1.c``. + +.. _more_xin_lines: + +xin.pru1.c Line-by-line +~~~~~~~~~~~~~~~~~~~~~~~~ +.. table:: + + +-------+-----------------------------------------------------------+ + |Line | Explanation | + +=======+===========================================================+ + |8-15 | Place to put the received data. | + +-------+-----------------------------------------------------------+ + |26 | Signal PRU 0 | + +-------+-----------------------------------------------------------+ + |30 | Receive the data. The arguments are the same as `xout()`, | + | | 14 says to get the data directly from PRU 0. | + | | 5 says to start with register `r5`. | + | | `dmemBuf` is where to put the data. | + +-------+-----------------------------------------------------------+ + +If you really need speed, considering using ``pass:[__]xout()`` and ``pass:[__]xin()`` in assembly. + +Copyright +---------- + +copyright.c +~~~~~~~~~~~~~ + +:download:`copyright.c <code/copyright.c>` diff --git a/pru-cookbook/08ai/ai.rst b/pru-cookbook/08ai/ai.rst new file mode 100644 index 0000000000000000000000000000000000000000..db36f383f27b505f3f613a471bae81e0525db48e --- /dev/null +++ b/pru-cookbook/08ai/ai.rst @@ -0,0 +1,377 @@ +.. _pru-cookbook-ai: + +Moving to the BeagleBone AI +############################ + +So far all our examples have focussed mostly on the BeagleBone Black and Pocket Beagle. +These are both based on the am335x chip. The new kid on the block is the BeagleBone AI +which is based on the am5729. The new chip brings with it new capabilities one of +which is four PRUs. This chapter details what changes when moving from two to +four PRUs. + +The following are resources used in this chapter. + +Resources +~~~~~~~~~~~ + +* `AM572x Technical Reference Manual <http://www.ti.com/lit/pdf/spruhz6l>`_ (AI) +* `BeagleBone AI PRU pins <https://docs.google.com/spreadsheets/d/1dFSBVem86vAUD7MLXvqdS-N0Efi8_g_O1iTqzql8DAo/edit#gid=0>`_ + +Moving from two to four PRUs +============================= + +Problem +-------- + +You have code that works on the am335x PRUs and you want to move it to the +am5729 on the AI. + +Solution +-------- + +Things to consider when moving to the AI are: + +* Which pins are you going to use +* Which PRU are you going to run on + +Knowing which pins to use impacts the PRU you'll use. + +Discission +-------- + +The various System Reference Manuals (SRM's) list which pins go to the PRUs. +Here the tables are combined into one to make it easier to see what goes where. + +.. _aimapping_bits: + +Mapping bit positions to pin names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. table:: + + +---+---+---------+-----------+-----------+-------------+ + |PRU|Bit|Black pin|AI PRU1 pin|AI PRU2 pin|Pocket pin | + |0 |0 |P9_31 | |P8_44 |P1.36 | + +---+---+---------+-----------+-----------+-------------+ + |0 |1 |P9_29 | |P8_41 |P1.33 | + +---+---+---------+-----------+-----------+-------------+ + |0 |2 |P9_30 | |P8_42/P8_21|P2.32 | + +---+---+---------+-----------+-----------+-------------+ + |0 |3 |P9_28 |P8_12 |P8_39/P8_20|P2.30 | + +---+---+---------+-----------+-----------+-------------+ + |0 |4 |P9_92 |P8_11 |P8_40/P8_25|P1.31 | + +---+---+---------+-----------+-----------+-------------+ + |0 |5 |P9_27 |P9_15 |P8_37/P8_24|P2.34 | + +---+---+---------+-----------+-----------+-------------+ + |0 |6 |P9_91 | |P8_38/P8_5 |P2.28 | + +---+---+---------+-----------+-----------+-------------+ + |0 |7 |P9_25 | |P8_36/P8_6 |P1.29 | + +---+---+---------+-----------+-----------+-------------+ + |0 |8 | | |P8_34/P8_23| | + +---+---+---------+-----------+-----------+-------------+ + |0 |9 | | |P8_35/P8_22| | + +---+---+---------+-----------+-----------+-------------+ + |0 |19 | | |P8_33/P8_3 | | + +---+---+---------+-----------+-----------+-------------+ + |0 |11 | | |P8_31/P8_4 | | + +---+---+---------+-----------+-----------+-------------+ + |0 |12 | | |P8_32 | | + +---+---+---------+-----------+-----------+-------------+ + |0 |13 | | |P8_45 | | + +---+---+---------+-----------+-----------+-------------+ + |0 |14 |P8_12(out) P8_16(in)||P9_11 |P2.24 | + +---+---+---------+-----------+-----------+-------------+ + |0 |15 |P8_11(out) P8_15(in)||P8_17/P9_13|P2.33 | + +---+---+---------+-----------+-----------+-------------+ + |0 |16 |P9_41(in) P9_26(in)| |P8_27 | | + +---+---+---------+-----------+-----------+-------------+ + |0 |17 | |P9_26 |P8_28 | | + +---+---+---------+-----------+-----------+-------------+ + |0 |18 | | |P8_29 | | + +---+---+---------+-----------+-----------+-------------+ + |0 |19 | | |P8_30 | | + +---+---+---------+-----------+-----------+-------------+ + |0 |20 | | |P8_46/P8_8 | | + +---+---+---------+-----------+-----------+-------------+ + | | | | | | | + +---+---+---------+-----------+-----------+-------------+ + |1 |0 |P8_45 | |P8_32 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |1 |P8_46 |*P9_20* | | | + +---+---+---------+-----------+-----------+-------------+ + |1 |2 |P8_43 |*P9_19* | | | + +---+---+---------+-----------+-----------+-------------+ + |1 |3 |P8_44 |P9_41 | | | + +---+---+---------+-----------+-----------+-------------+ + |1 |4 |P8_41 | | | | + +---+---+---------+-----------+-----------+-------------+ + |1 |5 |P8_42 |*P8_18* |P9_25 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |6 |P8_39 |*P8_19* |P8_9 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |7 |P8_40 |*P8_13* |P9_31 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |8 |P8_27 | |P9_18 |P2.35 | + +---+---+---------+-----------+-----------+-------------+ + |1 |9 |P8_29 |P8_14 |P9_17 |P2.01 | + +---+---+---------+-----------+-----------+-------------+ + |1 |10 |P8_28 |P9_42 |P9_31 |P1.35 | + +---+---+---------+-----------+-----------+-------------+ + |1 |11 |P8_30 |P9_27 |P9_29 |P1.04 | + +---+---+---------+-----------+-----------+-------------+ + |1 |12 |P8_21 | |P9_30 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |13 |P8_20 | |P9_26 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |14 | |P9_14 |P9_42 |P1.32 | + +---+---+---------+-----------+-----------+-------------+ + |1 |15 | |*P9_16* |P8_10 |P1.30 | + +---+---+---------+-----------+-----------+-------------+ + |1 |16 |P9_26(in)|*P8_15* |P8_7 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |17 | |*P8_26* |P8_27 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |18 | |*P8_16* |P8_45 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |19 | | |P8_46 | | + +---+---+---------+-----------+-----------+-------------+ + |1 |19 | | |P8_43 | | + +---+---+---------+-----------+-----------+-------------+ + +The pins in *bold* are already configured as pru pins. See :ref:`ai_config` to +see what's currently configured as what. See :ref:`ai_device_tree` to +configure pins. + +.. _ai_config: + +Seeing how pins are configured +=============================== + +Problem +-------- + +You want to know how the pins are currently configured. + +Solution +--------- + +The ``show-pins.pl`` command does what you want, but you have to set it up first. + +.. code-block:: bash + + bone$ cd ~/bin + bone$ ln -s /opt/scripts/device/bone/show-pins.pl . + +This creates a symbolic link to the ``show-pins.pl`` command that is rather hidden +away. The link is put in the ``bin`` directory which is in the default command +``$PATH``. Now you can run ``show-pins.pl`` from anywhere. + +.. code-block:: bash + + bone$ *show-pins.pl* + P9.19a 16 R6 7 fast rx up i2c4_scl + P9.20a 17 T9 7 fast rx up i2c4_sda + P8.35b 57 AD9 e fast down gpio3_0 + P8.33b 58 AF9 e fast down gpio3_1 + ... + +Here you see ``P9.19a`` and ``P9.20a`` are configured for i2c with pull up resistors. +The ``P8`` pins are configured as gpio with pull down resistors. They are +both on gpio port 3. ``P8.35b`` is bit 0 while ``P8.33b`` is bit 1. You can find +which direction they are set by using ``gpioinfo`` and the chip number. +Unfortunately you subtract one from the port number to get the chip number. +So ``P8.35b`` is on chip number 2. + +.. code-block:: bash + + bone$ *gpioinfo 2* + line 0: unnamed unused *input* active-high + line 1: unnamed unused *input* active-high + line 2: unnamed unused input active-high + line 3: unnamed unused input active-high + line 4: unnamed unused input active-high + ... + +Here we see both (lines 0 and 1) are set to input. + +Adding ``-v`` gives more details. + +.. code-block:: bash + + bone$ *show-pins.pl -v* + ... + sysboot 14 14 H2 f fast down sysboot14 + sysboot 15 15 H3 f fast down sysboot15 + P9.19a 16 R6 7 fast rx up i2c4_scl + P9.20a 17 T9 7 fast rx up i2c4_sda + 18 T6 f fast down Driver off + 19 T7 f fast down Driver off + bluetooth in 20 P6 8 fast rx uart6_rxd mmc@480d1000 (wifibt_extra_pins_default) + bluetooth out 21 R9 8 fast rx uart6_txd mmc@480d1000 (wifibt_extra_pins_default) + ... + +The best way to use ``show-pins.pl`` is with ``grep``. To see all the pru pins try: + +.. code-block:: bash + + bone$ *show-pins.pl | grep -i pru | sort* + P8.13 100 D3 c fast rx pr1_pru1_gpi7 + P8.15b 109 A3 d fast down pr1_pru1_gpo16 + P8.16 111 B4 d fast down pr1_pru1_gpo18 + P8.18 98 F5 c fast rx pr1_pru1_gpi5 + P8.19 99 E6 c fast rx pr1_pru1_gpi6 + P8.26 110 B3 d fast down pr1_pru1_gpo17 + P9.16 108 C5 d fast down pr1_pru1_gpo15 + P9.19b 95 F4 c fast rx up pr1_pru1_gpi2 + P9.20b 94 D2 c fast rx up pr1_pru1_gpi1 + +Here we have nine pins configured for the PRU registers ``R30`` and ``R31``. +Five are input pins and four are out. + +.. _ai_device_tree: + +Configuring pins on the AI via device trees +============================================ + +Problem +-------- + +I want to configure another pin for the PRU, but I get an error. + +.. code-block:: bash + + bone$ *config-pin P9_31 pruout* + ERROR: open() for /sys/devices/platform/ocp/ocp:P9_31_pinmux/state failed, No such file or directory + +Solution +--------- + +The pins on the AI must be configure at boot time and therefor cannot be +configured with ``config-pin``. Instead you must edit the device tree. + +Discission +----------- + +Suppose you want to make ``P9_31`` a PRU output pin. First go to the +`am5729 System Reference Manual <https://github.com/beagleboard/beaglebone-ai/wiki/System-Reference-Manual#p8.10-p8.13>`_ +and look up ``P9_31``. + +.. tip:: + + The `BeagleBone AI PRU pins <https://docs.google.com/spreadsheets/d/1dFSBVem86vAUD7MLXvqdS-N0Efi8_g_O1iTqzql8DAo/edit#gid=0>`_ + table may be easier to use. + +``P9_31`` appears twice, as ``P9_31a`` and ``P9_31b``. Either should work, let's pick ``P9_31a``. + +.. warning:: + When you have two internal pins attached to the same header (either P8 or P9) + make sure only one is configured as an output. If both are outputs, you could + damage the AI. + +We see that when ``P9_31a`` is set to ``MODE13`` it will be a PRU **out** pin. +``MODE12`` makes it a PRU **in** pin. It appears at bit 10 on PRU2_1. + +Next, find which kernel you are running. + +.. code-block:: bash + bone$ uname -a + Linux ai 4.14.108-ti-r131 #1buster SMP PREEMPT Tue Mar 24 19:18:36 UTC 2020 armv7l GNU/Linux + +I'm running the 4.14 version. Now look in ``/opt/source`` for your kernel. + +.. code-block:: bash + + bone$ cd /opt/source/ + bone$ ls + adafruit-beaglebone-io-python dtb-5.4-ti rcpy + BBIOConfig librobotcontrol u-boot_v2019.04 + bb.org-overlays list.txt u-boot_v2019.07-rc4 + *dtb-4.14-ti* pyctrl + dtb-4.19-ti py-uio + +``am5729-beagleboneai.dts`` is the file we need to edit. Search for ``P9_31``. You'l see: + +.. code-block:: bash + :linenos: + + DRA7XX_CORE_IOPAD(0x36DC, MUX_MODE14) // B13: P9.30: mcasp1_axr10.off // + DRA7XX_CORE_IOPAD(0x36D4, *MUX_MODE13*) // B12: *P9.31a*: mcasp1_axr8.off // + DRA7XX_CORE_IOPAD(0x36A4, MUX_MODE14) // C14: P9.31b: mcasp1_aclkx.off // + +Change the ``MUX_MODE14`` to ``MUX_MODE13`` for output, or ``MUX_MODE12`` for input. + +Compile and install. The first time will take a while since it recompiles all the dts files. + +.. code-block:: bash + :linenos: + + bone$ make + ... + DTC src/arm/am335x-sl50.dtb + DTC src/arm/am5729-beagleboneai.dtb + DTC src/arm/am335x-nano.dtb + ... + bone$ sudo make install + ... + 'src/arm/am5729-beagleboneai.dtb' -> '/boot/dtbs/4.14.108-ti-r131/am5729-beagleboneai.dtb' + ... + bone$ reboot + ... + bone$ *show-pins.pl -v | sort | grep -i pru* + P8.13 100 D3 c fast rx pr1_pru1_gpi7 + P8.15b 109 A3 d fast down pr1_pru1_gpo16 + P8.16 111 B4 d fast down pr1_pru1_gpo18 + P8.18 98 F5 c fast rx pr1_pru1_gpi5 + P8.19 99 E6 c fast rx pr1_pru1_gpi6 + P8.26 110 B3 d fast down pr1_pru1_gpo17 + P9.16 108 C5 d fast down pr1_pru1_gpo15 + P9.19b 95 F4 c fast rx up pr1_pru1_gpi2 + P9.20b 94 D2 c fast rx up pr1_pru1_gpi1 + P9.31a 181 B12 d fast down pr2_pru1_gpo10 + + +There it is. `P9_31` is now a PRU output pin on PRU1_0, bit 3. + +.. _ai_using_pru_pins: + +Using the PRU pins +==================== + +Problem +-------- + +Once I have the PRU pins configured on the AI how do I use them? + +Solution +-------- + +In :ref:`ai_device_tree` we configured ``P9_31a`` to be a PRU pin. ``show-pins.pl`` showed +that it appears at ``pr2_pru1_gpo10``, which means pru2_1 accesses it using +bit 10 of register ``R30``. + +Discission +-------- + +It's easy to modify the pwm example from :ref:`blocks_pwm` to use this pin. +First copy the example you want to modify to ``pwm1.pru2_1.c``. The ``pru2_1`` in +the file name tells the Makefile to run the code on pru2_1. :ref:`ai_pwm1` shows +the adapted code. + +.. _ai_pwm1: + +pwm1.pru2_1.c +~~~~~~~~~~~~~~ + +:download:`pwm1.pru2_1.c <code/pwm1.pru2_1.c>` + + +One line 6 ``P9_31`` is defined as ``(0x1:ref:`10)``, which means shift ``1`` over by 10 bits. +That's the only change needed. Copy the local Makefile to the same directory and +compile and run. + +.. code-block:: bash + :linenos: + + bone$ make TARGET=pwm1.pru2_1 + +Attach an LED to ``P9_31`` and it should be blinking. diff --git a/pru-cookbook/08ai/code/Makefile b/pru-cookbook/08ai/code/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a7557fdaa22988d89cec879477ded78522d7116f --- /dev/null +++ b/pru-cookbook/08ai/code/Makefile @@ -0,0 +1 @@ +include /var/lib/cloud9/common/Makefile diff --git a/pru-cookbook/08ai/code/pwm1.pru2_1.c b/pru-cookbook/08ai/code/pwm1.pru2_1.c new file mode 100644 index 0000000000000000000000000000000000000000..d35f2185cffd779cb1f18e252fe5252b803cd26e --- /dev/null +++ b/pru-cookbook/08ai/code/pwm1.pru2_1.c @@ -0,0 +1,24 @@ +#include <stdint.h> +#include <pru_cfg.h> +#include "resource_table_empty.h" +#include "prugpio.h" + +#define P9_31 (0x1<<10) + +volatile register uint32_t __R30; +volatile register uint32_t __R31; + +void main(void) +{ + uint32_t gpio = P9_31; // Select which pin to toggle.; + + /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ + CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; + + while(1) { + __R30 |= gpio; // Set the GPIO pin to 1 + __delay_cycles(100000000); + __R30 &= ~gpio; // Clear the GPIO pin + __delay_cycles(100000000); + } +} diff --git a/pru-cookbook/common/Makefile b/pru-cookbook/common/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5b3999031af3d04540e6d4c8057624d1fe21664b --- /dev/null +++ b/pru-cookbook/common/Makefile @@ -0,0 +1,235 @@ +# +# Optional definitions +# +# TARGET - executable to create (currently supports single .c source) +# should have .<proc>(<n>) extension (lower case, check below for valid options) +# without TARGET, as of now, we don't have any build targets +# TODO: work with a list of targets, rather than a single file +# PRUN - TBD + +# +# Directories (external packages, etc.) +# +# COMMON points to where this primary Makefile and shell scripts live. +# PRU_CGT points to the TI PRU compiler directory. +# PRU_SUPPORT points to pru-software-support-package. +# C6X_CGT points to the TI C6X compiler directory. +# TIDL_API_DIR points to the TIDL API install directory. +# GEN_DIR points to where to build the binaries. +# MODEL is the board model (BeagleBoard.org_BeagleBone_AI, TI_AM335x_BeagleBone_Blue, etc.) +COMMON:=$(abspath $(lastword $(MAKEFILE_LIST)/..)) +PRU_CGT:=/usr/share/ti/cgt-pru +PRU_SUPPORT:=/usr/lib/ti/pru-software-support-package +PRU_STARTERWARE:=/usr/share/ti/starterware +C6X_CGT:=/usr/share/ti/cgt-c6x +TIDL_API_DIR:=/usr/share/ti/tidl/tidl_api +GEN_DIR:=/tmp/cloud9-examples +MODEL:=$(shell cat /proc/device-tree/model | sed 's/ /_/g' | tr -d '\000') +# $(warning MODEL=$(MODEL),TARGET=$(TARGET),COMMON=$(COMMON)) +$(warning MODEL=$(MODEL),TARGET=$(TARGET)) + +# +# Define PROC and build variables +# +# Arguments: +# $@ - target name +# +# Variables defined: +# CHIP - target system-on-chip (am57xx, am335x) +# CHIP_REV - target system-on-chip with rev (am572x_2_0, am335x) +# PROC - cpu type (arm, pru, c6x, etc.) +# PRUN - identifier for target PRU core +# PRU_DIR - control directory for the PRU +# CC - +# LD - +# LDFLAGS - +# CFLAGS - +# +# Depends on udev rules: https://github.com/beagleboard/customizations/blob/master/etc/udev/rules.d/86-remoteproc-noroot.rules +# Check which model +define target-to-proc = + ifeq ($(suffix $(basename $(1))),.pru1_0) + CHIP=am57xx + CHIP_REV=am572x_2_0 + PRU_DIR=/dev/remoteproc/pruss1-core0 + PRUN=1_0 + PROC=pru + EXE=.out + else ifeq ($(suffix $(basename $(1))),.pru1_1) + CHIP=am57xx + CHIP_REV=am572x_2_0 + PRU_DIR=/dev/remoteproc/pruss1-core1 + PRUN=1_1 + PROC=pru + EXE=.out + else ifeq ($(suffix $(basename $(1))),.pru2_0) + CHIP=am57xx + CHIP_REV=am572x_2_0 + PRU_DIR=/dev/remoteproc/pruss2-core0 + PRUN=2_0 + PROC=pru + EXE=.out + else ifeq ($(suffix $(basename $(1))),.pru2_1) + CHIP=am57xx + CHIP_REV=am572x_2_0 + PRU_DIR=/dev/remoteproc/pruss2-core1 + PRUN=2_1 + PROC=pru + EXE=.out + else ifeq ($(suffix $(basename $(1))),.pru0) + CHIP=am335x + CHIP_REV=am335x + PRU_DIR=/dev/remoteproc/pruss-core0 + PRUN=0 + PROC=pru + EXE=.out + else ifeq ($(suffix $(basename $(1))),.pru1) + CHIP=am335x + CHIP_REV=am335x + PRU_DIR=/dev/remoteproc/pruss-core1 + PRUN=1 + PROC=pru + EXE=.out + else ifeq ($(suffix $(basename $(1))),.tidl) + CHIP=am57xx + PROC=tidl + EXE=.so + else + PROC=arm + EXE=.out + endif +endef + +# +# Arguments: +# $@ - target name +# +# Variables required: +# CHIP - target system-on-chip (am57xx, am335x) +# CHIP_REV - target system-on-chip with rev (am572x_2_0, am335x) +# PROC - cpu type (arm, pru, c6x, etc.) +# PRUN - identifier for target PRU core +# PRU_DIR - control directory for the PRU +define proc-to-build-vars = + ifeq ($(PROC),pru) + LD=lnkpru -o + LDFLAGS=--reread_libs --warn_sections --stack_size=0x100 --heap_size=0x100 -m $(basename $(1)).map \ + -i$(PRU_CGT)/lib -i$(PRU_CGT)/include $(COMMON)/$(CHIP)_$(PROC).cmd --library=libc.a \ + --library=$(PRU_SUPPORT)/lib/rpmsg_lib.lib + CC=clpru -fe + CFLAGS=--include_path=$(COMMON) --include_path=$(PRU_SUPPORT)/include \ + --include_path=$(PRU_SUPPORT)/include/$(CHIP_REV) \ + --include_path=$(PRU_STARTERWARE)/include --include_path=$(PRU_STARTERWARE)/include/hw \ + --include_path=$(PRU_CGT)/include -DCHIP=$(CHIP) -DCHIP_IS_$(CHIP) -DMODEL=$(MODEL) -DPROC=$(PROC) -DPRUN=$(PRUN) \ + -v3 -O2 --printf_support=minimal --display_error_number --endian=little --hardware_mac=on \ + --obj_directory=$(GEN_DIR) --pp_directory=$(GEN_DIR) --asm_directory=$(GEN_DIR) -ppd -ppa --asm_listing \ + --c_src_interlist + else ifeq ($(PROC),tidl) + LD=g++ -o + LDFLAGS=-lopencv_highgui -lopencv_imgcodecs -lopencv_videoio -lopencv_imgproc -lopencv_core \ + $(TIDL_API_DIR)/tidl_api.a $(TIDL_API_DIR)/tidl_imgutil.a \ + -lTIOpenCL -locl_util -lpthread + CXX=g++ -c -o + CXXFLAGS=-DCHIP=$(CHIP) -DMODEL=$(MODEL) -DPROC=$(PROC) -fPIC -O3 -Wall -Werror -Wno-error=ignored-attributes \ + -I. -I$(TIDL_API_DIR)/inc -std=c++14 -I/usr/share/ti/opencl + else + LD=gcc -o + LDFLAGS=-lc -lm + CC=gcc -c -o + CFLAGS=-DCHIP=$(CHIP) -DMODEL=$(MODEL) -DPROC=$(PROC) + endif +endef + +# +# +# + +ifneq ($(TARGET),) +$(eval $(call target-to-proc,$(TARGET).out)) +# $(warning GEN_DIR=$(GEN_DIR),CHIP=$(CHIP),PROC=$(PROC),PRUN=$(PRUN),PRU_DIR=$(PRU_DIR),EXE=$(EXE)) + +all: stop install start + @echo "MODEL = $(MODEL)" + @echo "PROC = $(PROC)" + @echo "PRUN = $(PRUN)" + @echo "PRU_DIR = $(PRU_DIR)" + +# TODO: think about what we want to say if stop fails +stop: +ifneq ($(PRU_DIR),) + @echo "- Stopping PRU $(PRUN)" + @echo stop > $(PRU_DIR)/state || echo Cannot stop $(PRUN) +endif + +start: +ifneq ($(PRU_DIR),) + @echo write_init_pins.sh + @$(COMMON)/write_init_pins.sh /lib/firmware/$(CHIP)-pru$(PRUN)-fw + @echo "- Starting PRU $(PRUN)" + @echo start > $(PRU_DIR)/state +else ifeq ($(PROC),tidl) + ti-mct-heap-check -c + sudo mjpg_streamer -i "input_opencv.so -r 640x480 -d /dev/$(shell fgrep -v vpe /sys/class/video4linux/video*/name | perl -ne '/\/(video\d+)\/name/ && print $$1') \ + --filter ./$(TARGET)$(EXE)" -o "output_http.so -p 8090 -w /usr/share/mjpg-streamer/www" +else + ./$(TARGET)$(EXE) +endif + +install: $(GEN_DIR)/$(TARGET)$(EXE) +ifneq ($(PRU_DIR),) + @echo '- copying firmware file $(GEN_DIR)/$(TARGET).out to /lib/firmware/$(CHIP)-pru$(PRUN)-fw' + @cp $(GEN_DIR)/$(TARGET)$(EXE) /lib/firmware/$(CHIP)-pru$(PRUN)-fw +else + @cp $(GEN_DIR)/$(TARGET)$(EXE) ./$(TARGET)$(EXE) +endif +endif + +%.out: $(GEN_DIR)/%.out + @echo 'CP $^' + @cp $^ $@ + +%.so: $(GEN_DIR)/%.so + @echo 'CP $^' + @cp $^ $@ + +# TODO: look up how Makefiles typically break down the output file specification +# $(warning CHIP=$(CHIP),PROC=$(PROC)) +# $(warning CC=$(CC),LD=$(LD),CFLAGS=$(CFLAGS),LDFLAGS=$(LDFLAGS)) +$(GEN_DIR)/%.out: $(GEN_DIR)/%.o + @mkdir -p $(GEN_DIR) + @echo 'LD $^' + $(eval $(call target-to-proc,$@)) + $(eval $(call proc-to-build-vars,$@)) + @$(LD) $@ $^ $(LDFLAGS) + +$(GEN_DIR)/%.so: $(GEN_DIR)/%.o + @mkdir -p $(GEN_DIR) + @echo 'LD $^' + $(eval $(call target-to-proc,$@)) + $(eval $(call proc-to-build-vars,$@)) + @$(LD) $@ -shared $^ $(LDFLAGS) + +$(GEN_DIR)/%.o: %.asm + @mkdir -p $(GEN_DIR) + @echo 'CC $^' + $(eval $(call target-to-proc,$@)) + $(eval $(call proc-to-build-vars,$@)) + @$(CC) $@ $^ $(CFLAGS) + +$(GEN_DIR)/%.o: %.c + @mkdir -p $(GEN_DIR) + @echo 'CC $^' + $(eval $(call target-to-proc,$@)) + $(eval $(call proc-to-build-vars,$@)) + @$(CC) $@ $^ $(CFLAGS) + +$(GEN_DIR)/%.o: %.cpp + @mkdir -p $(GEN_DIR) + @echo 'CXX $^' + $(eval $(call target-to-proc,$@)) + $(eval $(call proc-to-build-vars,$@)) + @$(CXX) $@ $^ $(CXXFLAGS) + +clean: + @echo 'CLEAN' + @rm -rf $(GEN_DIR) diff --git a/pru-cookbook/common/README.md b/pru-cookbook/common/README.md new file mode 100644 index 0000000000000000000000000000000000000000..379ccc41af34ca13255e40b76c1b8461f5f78bea --- /dev/null +++ b/pru-cookbook/common/README.md @@ -0,0 +1,2 @@ +# common +These are the files used by all the platforms for running the PRUs. diff --git a/pru-cookbook/common/config-pin.sh b/pru-cookbook/common/config-pin.sh new file mode 100755 index 0000000000000000000000000000000000000000..682fecd697201463a0ab58d238aad25cfbffe760 --- /dev/null +++ b/pru-cookbook/common/config-pin.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Adds "in" and "out" to config-pin +# +# Usage: config-pin.sh P9_11 out + +pin=$1 # Name of pin to be changed +dir=$2 # Direction, either in or out + +if [ "$dir" != "in" ] && [ "$dir" != "out" ] ; then + # Use config-pin + /usr/bin/config-pin $* + exit +fi + +# Maps pin name (P9_11) to gpio number (gpio30) via libgpiod +# Find which gpio +chip=0 +found=0 + +# Check each gpio chip +while [ $chip -lt 4 ] ; do + # echo $chip + # Remove : from line number + line=$(gpioinfo $chip | grep $pin | awk '{ print substr($2, 1, length($2)-1) }') + + [ ! -z "$line" ] && found=1 && break + chip=$[$chip+1] +done + +# echo chip: $chip line: $line + +if [ $found -ne 0 ] ; then + gpio=gpio$[32*$chip+$line] + # echo $gpio + echo $dir > /sys/class/gpio/$gpio/direction + /usr/bin/config-pin $pin gpio +else + echo $pin not found +fi diff --git a/pru-cookbook/common/init_pins_empty.h b/pru-cookbook/common/init_pins_empty.h new file mode 100644 index 0000000000000000000000000000000000000000..9da8995e8c6ba25775f9748bc4366ce58d0e85c9 --- /dev/null +++ b/pru-cookbook/common/init_pins_empty.h @@ -0,0 +1,6 @@ +// Defins an empty table to write_init_pins wont' complain + +#pragma DATA_SECTION(init_pins, ".init_pins") +#pragma RETAIN(init_pins) +const char init_pins[] = + "\0\0"; diff --git a/pru-cookbook/common/prugpio.h b/pru-cookbook/common/prugpio.h new file mode 100644 index 0000000000000000000000000000000000000000..6d83e1d8a386442ea0f39895146b6fa040f3f0a6 --- /dev/null +++ b/pru-cookbook/common/prugpio.h @@ -0,0 +1,105 @@ +// This file defines the GPIO port addresses and PRU address + +#if defined(CHIP) && defined(CHIP_IS_am57xx) +#warning "Found AI" +// These are addresses for the am5729 +// First define the 9 GPIO port addresses +#define GPIO1 0x4AE10000 +#define GPIO2 0x48055000 +#define GPIO3 0x48057000 +#define GPIO4 0x48059000 +#define GPIO5 0x4805B000 +#define GPIO6 0x4805D000 +#define GPIO7 0x48051000 +#define GPIO8 0x48053000 + +// These define which bits in a given port go to the USR LEDs +// GPIO3 +#define USR0 (1<<17) +#define USR2 (1<<15) +#define USR3 (1<<14) +#define USR4 (1<< 7) +// GPIO5 +#define USR1 (1<< 5) +// The define a couple of GPIO pin addresses +// GPIO6 +#define P9_25 (1<<17) +// GPIO8 +#define P8_17 (1<18) + +// These define which bin in register R30 go to which header pins +// R30 bits - Output on pru1_1 +#define P9_14 (1<<14) +#define P9_16 (1<<15) +#define P8_15 (1<<16) +#define P8_26 (1<<17) +#define P8_16 (1<<18) +// R31 bits - Input on pru1_1 +#define P8_18 (1<<5) +#define P8_19 (1<<6) +#define P8_13 (1<<7) + +// Shared memory +#define AM33XX_DATARAM0_PHYS_BASE1 0x4b200000 +#define AM33XX_DATARAM1_PHYS_BASE1 0x4b202000 +#define AM33XX_PRUSS_SHAREDRAM_BASE1 0x4b210000 + +#define AM33XX_DATARAM0_PHYS_BASE2 0x4b280000 +#define AM33XX_DATARAM1_PHYS_BASE2 0x4b282000 +#define AM33XX_PRUSS_SHAREDRAM_BASE2 0x4b290000 + +#else + +#warning "Found am335x" +// These are addresses for the am35xx +#define GPIO0 0x44E07000 // From table 2.2 of am335x TRM +#define GPIO1 0x4804C000 +#define GPIO2 0x481AC000 +#define GPIO3 0x481AE000 + +// USR LED bit positions +// GPIO1 +#define USR0 (1<<21) +#define USR1 (1<<22) +#define USR2 (1<<23) +#define USR3 (1<<24) +// The define a couple of GPIO pin addresses on Black +// GPIO1 +#define P9_14 (1<<18) +#define P9_16 (1<<19) + +// The define a couple of GPIO pin addresses on Pocket +// GPIO1 +#define P2_1 (1<<18) +#define P1_32 (1<<10) + +// R30 output bits on pru0 +#define P9_31 (1<<0) +#define P9_29 (1<<1) +#define P9_30 (1<<2) +#define P9_28 (1<<3) +#define P9_92 (1<<4) +#define P9_27 (1<<5) +#define P9_91 (1<<6) +#define P9_25 (1<<7) + +// R30 output bits on pru0 on Pocket +#define P1_36 (1<<0) +#define P1_33 (1<<1) +#define P2_32 (1<<2) +#define P2_30 (1<<3) +#define P1_31 (1<<4) +#define P2_34 (1<<5) +#define P2_28 (1<<6) +#define P1_29 (1<<7) + +// Shared memory +#define AM33XX_DATARAM0_PHYS_BASE 0x4a300000 +#define AM33XX_DATARAM1_PHYS_BASE 0x4a302000 +#define AM33XX_PRUSS_SHAREDRAM_BASE 0x4a310000 + +#endif +// /4 to convert from byte address to word address +#define GPIO_CLEARDATAOUT 0x190/4 // Write 1 here to set a given bit +#define GPIO_SETDATAOUT 0x194/4 // A 1 here clears the corresponding bit +#define GPIO_DATAOUT 0x138/4 // For reading the GPIO registers diff --git a/pru-cookbook/common/resource_table_0.h b/pru-cookbook/common/resource_table_0.h new file mode 100644 index 0000000000000000000000000000000000000000..1c853b95775fd159d65ef12c71abfde1baff890e --- /dev/null +++ b/pru-cookbook/common/resource_table_0.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RSC_TABLE_PRU_H_ +#define _RSC_TABLE_PRU_H_ + +#include <stddef.h> +#include <rsc_types.h> +#include "pru_virtio_ids.h" + +/* + * Sizes of the virtqueues (expressed in number of buffers supported, + * and must be power of 2) + */ +#define PRU_RPMSG_VQ0_SIZE 16 +#define PRU_RPMSG_VQ1_SIZE 16 + +/* + * The feature bitmap for virtio rpmsg + */ +#define VIRTIO_RPMSG_F_NS 0 //name service notifications + +/* This firmware supports name service notifications as one of its features */ +#define RPMSG_PRU_C0_FEATURES (1 << VIRTIO_RPMSG_F_NS) + +/* Definition for unused interrupts */ +#define HOST_UNUSED 255 + +/* Mapping sysevts to a channel. Each pair contains a sysevt, channel. */ +struct ch_map pru_intc_map[] = { + {16, 2}, + {17, 0}, +}; + +struct my_resource_table { + struct resource_table base; + + uint32_t offset[2]; /* Should match 'num' in actual definition */ + + /* rpmsg vdev entry */ + struct fw_rsc_vdev rpmsg_vdev; + struct fw_rsc_vdev_vring rpmsg_vring0; + struct fw_rsc_vdev_vring rpmsg_vring1; + + /* intc definition */ + struct fw_rsc_custom pru_ints; +}; + +#pragma DATA_SECTION(resourceTable, ".resource_table") +#pragma RETAIN(resourceTable) +struct my_resource_table resourceTable = { + 1, /* Resource table version: only version 1 is supported by the current driver */ + 2, /* number of entries in the table */ + 0, 0, /* reserved, must be zero */ + /* offsets to entries */ + { + offsetof(struct my_resource_table, rpmsg_vdev), + offsetof(struct my_resource_table, pru_ints), + }, + + /* rpmsg vdev entry */ + { + (uint32_t)TYPE_VDEV, //type + (uint32_t)VIRTIO_ID_RPMSG, //id + (uint32_t)0, //notifyid + (uint32_t)RPMSG_PRU_C0_FEATURES, //dfeatures + (uint32_t)0, //gfeatures + (uint32_t)0, //config_len + (uint8_t)0, //status + (uint8_t)2, //num_of_vrings, only two is supported + { (uint8_t)0, (uint8_t)0 }, //reserved + /* no config data */ + }, + /* the two vrings */ + { + 0, //da, will be populated by host, can't pass it in + 16, //align (bytes), + PRU_RPMSG_VQ0_SIZE, //num of descriptors + 0, //notifyid, will be populated, can't pass right now + 0 //reserved + }, + { + 0, //da, will be populated by host, can't pass it in + 16, //align (bytes), + PRU_RPMSG_VQ1_SIZE, //num of descriptors + 0, //notifyid, will be populated, can't pass right now + 0 //reserved + }, + + { + TYPE_CUSTOM, TYPE_PRU_INTS, + sizeof(struct fw_rsc_custom_ints), + { /* PRU_INTS version */ + 0x0000, + /* Channel-to-host mapping, 255 for unused */ + 0, HOST_UNUSED, 2, HOST_UNUSED, HOST_UNUSED, + HOST_UNUSED, HOST_UNUSED, HOST_UNUSED, HOST_UNUSED, HOST_UNUSED, + /* Number of evts being mapped to channels */ + (sizeof(pru_intc_map) / sizeof(struct ch_map)), + /* Pointer to the structure containing mapped events */ + pru_intc_map, + }, + }, +}; + +#endif /* _RSC_TABLE_PRU_H_ */ diff --git a/pru-cookbook/common/resource_table_1.h b/pru-cookbook/common/resource_table_1.h new file mode 100644 index 0000000000000000000000000000000000000000..b062c71f3e66559102cc8f65f9b8d8274b144aef --- /dev/null +++ b/pru-cookbook/common/resource_table_1.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RSC_TABLE_PRU_H_ +#define _RSC_TABLE_PRU_H_ + +#include <stddef.h> +#include <rsc_types.h> +#include "pru_virtio_ids.h" + +/* + * Sizes of the virtqueues (expressed in number of buffers supported, + * and must be power of 2) + */ +#define PRU_RPMSG_VQ0_SIZE 16 +#define PRU_RPMSG_VQ1_SIZE 16 + +/* + * The feature bitmap for virtio rpmsg + */ +#define VIRTIO_RPMSG_F_NS 0 //name service notifications + +/* This firmware supports name service notifications as one of its features */ +#define RPMSG_PRU_C0_FEATURES (1 << VIRTIO_RPMSG_F_NS) + +/* Definition for unused interrupts */ +#define HOST_UNUSED 255 + +/* Mapping sysevts to a channel. Each pair contains a sysevt, channel. */ +struct ch_map pru_intc_map[] = { {18, 3}, + {19, 1}, +}; + +struct my_resource_table { + struct resource_table base; + + uint32_t offset[2]; /* Should match 'num' in actual definition */ + + /* rpmsg vdev entry */ + struct fw_rsc_vdev rpmsg_vdev; + struct fw_rsc_vdev_vring rpmsg_vring0; + struct fw_rsc_vdev_vring rpmsg_vring1; + + /* intc definition */ + struct fw_rsc_custom pru_ints; +}; + +#pragma DATA_SECTION(resourceTable, ".resource_table") +#pragma RETAIN(resourceTable) +struct my_resource_table resourceTable = { + 1, /* Resource table version: only version 1 is supported by the current driver */ + 2, /* number of entries in the table */ + 0, 0, /* reserved, must be zero */ + /* offsets to entries */ + { + offsetof(struct my_resource_table, rpmsg_vdev), + offsetof(struct my_resource_table, pru_ints), + }, + + /* rpmsg vdev entry */ + { + (uint32_t)TYPE_VDEV, //type + (uint32_t)VIRTIO_ID_RPMSG, //id + (uint32_t)0, //notifyid + (uint32_t)RPMSG_PRU_C0_FEATURES, //dfeatures + (uint32_t)0, //gfeatures + (uint32_t)0, //config_len + (uint8_t)0, //status + (uint8_t)2, //num_of_vrings, only two is supported + { (uint8_t)0, (uint8_t)0 }, //reserved + /* no config data */ + }, + /* the two vrings */ + { + 0, //da, will be populated by host, can't pass it in + 16, //align (bytes), + PRU_RPMSG_VQ0_SIZE, //num of descriptors + 0, //notifyid, will be populated, can't pass right now + 0 //reserved + }, + { + 0, //da, will be populated by host, can't pass it in + 16, //align (bytes), + PRU_RPMSG_VQ1_SIZE, //num of descriptors + 0, //notifyid, will be populated, can't pass right now + 0 //reserved + }, + + { + TYPE_CUSTOM, TYPE_PRU_INTS, + sizeof(struct fw_rsc_custom_ints), + { /* PRU_INTS version */ + 0x0000, + /* Channel-to-host mapping, 255 for unused */ + HOST_UNUSED, 1, HOST_UNUSED, 3, HOST_UNUSED, + HOST_UNUSED, HOST_UNUSED, HOST_UNUSED, HOST_UNUSED, HOST_UNUSED, + /* Number of evts being mapped to channels */ + (sizeof(pru_intc_map) / sizeof(struct ch_map)), + /* Pointer to the structure containing mapped events */ + pru_intc_map, + }, + }, +}; + +#endif /* _RSC_TABLE_PRU_H_ */ diff --git a/pru-cookbook/common/resource_table_empty.h b/pru-cookbook/common/resource_table_empty.h new file mode 100644 index 0000000000000000000000000000000000000000..07e97d9b383c9d937d4b55e705024d6c28dc748a --- /dev/null +++ b/pru-cookbook/common/resource_table_empty.h @@ -0,0 +1,39 @@ +/* + * ======== resource_table_empty.h ======== + * + * Define the resource table entries for all PRU cores. This will be + * incorporated into corresponding base images, and used by the remoteproc + * on the host-side to allocated/reserve resources. Note the remoteproc + * driver requires that all PRU firmware be built with a resource table. + * + * This file contains an empty resource table. It can be used either as: + * + * 1) A template, or + * 2) As-is if a PRU application does not need to configure PRU_INTC + * or interact with the rpmsg driver + * + */ + +#ifndef _RSC_TABLE_PRU_H_ +#define _RSC_TABLE_PRU_H_ + +#include <stddef.h> +#include <rsc_types.h> + +struct my_resource_table { + struct resource_table base; + + uint32_t offset[1]; /* Should match 'num' in actual definition */ +}; + +#pragma DATA_SECTION(pru_remoteproc_ResourceTable, ".resource_table") +#pragma RETAIN(pru_remoteproc_ResourceTable) +struct my_resource_table pru_remoteproc_ResourceTable = { + 1, /* we're the first version that implements this */ + 0, /* number of entries in the table */ + 0, 0, /* reserved, must be zero */ + 0, /* offset[0] */ +}; + +#endif /* _RSC_TABLE_PRU_H_ */ + diff --git a/pru-cookbook/common/write_init_pins.sh b/pru-cookbook/common/write_init_pins.sh new file mode 100755 index 0000000000000000000000000000000000000000..f52082365a8b2a72a6c30d39938077bd9addf741 --- /dev/null +++ b/pru-cookbook/common/write_init_pins.sh @@ -0,0 +1,9 @@ +#!/bin/bash +init_pins=$(readelf -x .init_pins $1 | grep 0x000 | cut -d' ' -f4-7 | xxd -r -p | tr '\0' '\n' | paste - -) +while read -a line; do + if [ ${#line[@]} == 2 ]; then + echo writing \"${line[1]}\" to \"${line[0]}\" + echo ${line[1]} > ${line[0]} + sleep 0.1 + fi +done <<< "$init_pins" diff --git a/pru-cookbook/index.rst b/pru-cookbook/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..981f2fb27405e0a3f32ceceab1cd7de890745413 --- /dev/null +++ b/pru-cookbook/index.rst @@ -0,0 +1,27 @@ +.. _pru-cookbook-home: + +PRU Cookbook +############# + +.. admonition:: Contributors + + - Author: `Mark A. Yoder <Mark.A.Yoder@Rose-Hulman.edu>`_ + - Book revision: v2.0 beta + +Outline + +A cookbook for programming the PRUs in C using remoteproc and +compiling on the Beagle + +.. toctree:: + :maxdepth: 1 + + 01case/case.rst + 02start/start.rst + 03details/details.rst + 04debug/debug.rst + 05blocks/blocks.rst + 06io/io.rst + 07more/more.rst + 08ai/ai.rst + projects.rst \ No newline at end of file diff --git a/pru-cookbook/projects.rst b/pru-cookbook/projects.rst new file mode 100644 index 0000000000000000000000000000000000000000..39263b91e03c611604c1e60d416f92e1db44e1b3 --- /dev/null +++ b/pru-cookbook/projects.rst @@ -0,0 +1,311 @@ +.. _pru-cookbook-projects: + +PRU Projects +############## + +Users of TI processors with PRU-ICSS have created application for many different uses. +A list of a few are shared below. For additional support resources, software and +documentation visit the PRU-ICSS wiki. + +PRU projects +~~~~~~~~~~~~~~ + +.. dropdown:: **LEDscape** + :open: + + **Description:** BeagleBone Black cape and firmware for driving a large number of WS281x LED strips. + + **Type:** Code Library Documentation and example projects. + + **References:** + * https://github.com/osresearch/LEDscape http://trmm.net/LEDscape + +.. dropdown:: **LDGraphy** + :open: + + **Description:** Laser direct lithography for printing PCBs. + + **Type:** Code Library and example project. + + **References:** + * https://github.com/hzeller/ldgraphy/blob/master/README.md + +.. dropdown:: **PRdUino** + :open: + + **Description:** This is a port of the Energia platform based on the Arduino framework allowing you to use Arduino software libraries on PRU. + + **Type:** Code Library + + **References:** + * https://github.com/lucas-ti/PRdUino + +.. dropdown:: **DMX Lighting** + :open: + + **Description:** Controlling professional lighting systems + + **Type:** Project Tutorial Code Library + + **References:** + * http://beagleboard.org/CapeContest/entries/BeagleBone+DMX+Cape/ + * http://blog.boxysean.com/2012/08/12/first-steps-with-the-beaglebone-pru/ + * https://github.com/boxysean/beaglebone-DMX + +.. dropdown:: **Interacto** + :open: + + **Description:** A cape making BeagleBone interactive with a triple-axis accelerometer, gyroscope + and magnetometer plus a 640 x 480/30 fps camera. All sensors are digital and communicate via I²C + to the BeagleBone. The camera frames are captured using the PRU-ICSS. The sensors on this cape + give hobbyists and students a starting point to easily build robots and flying drones. + + **Type:** Project 1 Project 2 Code Library + + **References:** + * http://beagleboard.org/CapeContest/entries/Interacto/ + * http://www.hitchhikeree.org/beaglebone_capes/interacto/ + * https://github.com/cclark2/interacto_bbone_cape + +.. dropdown:: **Replicape: 3D Printer** + :open: + + **Description:** Replicape is a high end 3D-printer electronics package in the form of a Cape + that can be placed on a BeagleBone Black. It has five high power stepper motors with cool running + MosFets and it has been designed to fit in small spaces without active cooling. For a Replicape + Daemon that processes G-code, see the Redeem Project + + **Type:** Project Code Library + + **References:** + * http://www.thing-printer.com/product/replicape/ + * https://bitbucket.org/intelligentagent/replicape/ + +.. dropdown:: **PyPRUSS: Python Library** + :open: + + **Description:** PyPRUSS is a Python library for programming the PRUs on BeagleBone (Black) + + **Type:** Code Library + + **References:** + http://hipstercircuits.com/pypruss-a-simple-pru-python-binding-for-beaglebone/ + +.. dropdown:: **Geiger** + :open: + + **Description:** The Geiger Cape, created by Matt Ranostay, is a design that measures radiation counts + from background and test sources by utilising multiple Geiger tubes. The cape can be used to detect + low-level radiation, which is needed in certain industries such as security and medical. + + **Type:** Project 1 Project 2 Code Library + + **References:** + * http://beagleboard.org/CapeContest/entries/Geiger+Cape/ + * http://elinux.org/BeagleBone/GeigerCapePrototype + * https://github.com/mranostay/beaglebone-telemetry-presentation + +.. dropdown:: **Servo Controller Foosball Table** + :open: + + **Description:** Used for ball tracking and motor control + + **Type:** Project Tutorial Code Library + + **References:** + * http://www.element14.com/community/community/knode/single-board_computers/next-gen_beaglebone/blog/2013/07/17/hackerspace-challenge--leeds-only-pru-can-make-the-leds-bright + * https://docs.google.com/spreadsheet/pub?key=0AmI_ryMKXUGJdDQ3LXB4X3VBWlpxQTFWbGh6RGJHUEE&output=html + * https://github.com/pbrook/pypruss + +.. dropdown:: **Imaging with connected camera** + :open: + + **Description:** Low resolution imaging ideal for machine vision use-cases, robotics and movement detection + + **Type:** Project Code Library + + **References:** + * http://www.element14.com/community/community/knode/single-board_computers/next-gen_beaglebone/blog/2013/08/18/bbb--imaging-with-a-pru-connected-camera + +.. dropdown:: **Computer Numerical Control (CNC) Translator** + :open: + + **Description:** Smooth stepper motor control; real embedded version of LinuxCNC + + **Type:** Tutorial Tutorial + + **References:** + * http://www.buildlog.net/blog/2013/09/cnc-translator-for-beaglebone/ http://bb-lcnc.blogspot.com/p/machinekit_16.html + +.. dropdown:: **Robotic Control** + :open: + + **Description:** Chubby SpiderBot + + **Type:** Project Code Library Project Reference + + **References:** + * http://www.youtube.com/watch?v=dEes9k7-DYY + * https://github.com/cagdasc/Chubby1_v1 + * http://www.youtube.com/watch?v=JXyewd98e9Q + * http://www.ti.com/lit/wp/spry235/spry235.pdf + +.. dropdown:: **Software UART** + :open: + + **Description:** Soft-UART implementation on the PRU of AM335x + + **Type:** Code Library Reference + + **References:** + * http://processors.wiki.ti.com/index.php/Soft-UART_Implementation_on_AM335X_PRU_-_Software_Users_Guide + +.. dropdown:: **Deviant LCD** + :open: + + **Description:** PRU bit-banged LCD interface @ 240x320 + + **Type:** Project Code Library + + **References:** + * http://www.beagleboard.org/CapeContest/entries/DeviantLCD/ + * https://github.com/cclark2/deviantlcd_bbone_cape + +.. dropdown:: **Nixie tube interface** + :open: + + **Description:** + + **Type:** Code Library + + **References:** + * https://github.com/mranostay/beagle-nixie + +.. dropdown:: **Thermal imaging camera** + :open: + + **Description:** Thermal camera using Beaglebone Black, a small LCD, and a thermal array sensor + + **Type:** Project Code Library + + **References:** + * https://element14.com/community/community/knode/single-board_computers/next-gen_beaglebone/blog/2013/06/07/bbb--building-a-thermal-imaging-camera + +.. dropdown:: **Sine wave generator using PWMs** + :open: + + **Description:** Simulation of a pulse width modulation + + **Type:** Project Reference Code Library + + **References:** + * http://elinux.org/ECE497_BeagleBone_PRU + * https://github.com/millerap/AM335x_PRU_BeagleBone + +.. dropdown:: **Emulated memory interface** + :open: + + **Description:** ABX loads amovie into the Beaglebone's memory and then launches the memory emulator + on the PRU sub-processor of the Beaglebone's ARM AM335x + + **Type:** Project + + **References:** + * https://github.com/lybrown/abx + +.. dropdown:: **6502 memory interface** + :open: + + **Description:** System permitting communication between Linux and 6502 processor + + **Type:** Project Code Library + + **References:** + * http://elinux.org/images/a/ac/What's_Old_Is_New-_A_6502-based_Remote_Processor.pdf + * https://github.com/lybrown/abx + +.. dropdown:: **JTAG/Debug** + :open: + + **Description:** Investigating the fastest way to program using JTAG and provide + for debugging facilities built into the Beaglebone. + + **Type:** Project + + **References:** + * http://beagleboard.org/project/PRUJTAG/ + +.. dropdown:: **High Speed Data Acquistion** + :open: + + **Description:** Reading data at high speeds + + **Type:** Reference + + **References:** + * http://www.element14.com/community/community/knode/single-board_computers/next-gen_beaglebone/blog/2013/08/04/bbb--high-speed-data-acquisition-and-web-based-ui + +.. dropdown:: **Prufh (PRU Forth)** + :open: + + **Description:** Forth Programming Language and Compiler. It consists of a compiler, + the forth system itself, and anoptional program for loading and communicating with the forth code proper. + + **Type:** Compiler + + **References:** + * https://github.com/biocode3D/prufh + +.. dropdown:: **VisualPRU** + :open: + + **Description:** VisualPRU is a minimal browser-based editor and debugger for the Beaglebone PRUs. + The app runs from a local server on the Beaglebone. + + **Type:** Editor and Debugger + + **References:** + * https://github.com/mmcdan/visualpru + +.. dropdown:: **libpruio** + :open: + + **Description:** Library for easy configuration and data handling at high speeds. + This library can configure and control the devices from single source (no need for + further overlays or the device tree compiler) + + **Type:** Documentation + + **References:** + * http://users.freebasic-portal.de/tjf/Projekte/libpruio/doc/html/index.html + * Library http://www.freebasic-portal.de/downloads/fb-on-arm/libpruio-325.html[(German)] + +.. dropdown:: **BeagleLogic** + :open: + + **Description:** 100MHz 14channel logic analyzer using both PRUs (one to capture and one to transfer the data) + + **Type:** Project + + **References:** + * http://beaglelogic.net + +.. dropdown:: **BeaglePilot** + :open: + + **Description:** Uses PRUs as part of code for a BeagleBone based autopilot + + **Type:** Code Library + + **References:** + * https://github.com/BeaglePilot/beaglepilot + +.. dropdown:: **PRU Speak** + :open: + + **Description:** Implements BotSpeak, a platform independent interpreter for tools like Labview, on the PRUs + + **Type:** Code Library + + **References:** + * https://github.com/deepakkarki/pruspeak \ No newline at end of file