Showing preview only (4,360K chars total). Download the full file or copy to clipboard to get everything.
Repository: osresearch/LEDscape
Branch: master
Commit: f94708c188f5
Files: 109
Total size: 4.1 MB
Directory structure:
gitextract__f3o1sre/
├── .gitignore
├── Makefile
├── Makefile.common
├── README.md
├── Setup.md
├── am335x/
│ ├── app_loader/
│ │ ├── include/
│ │ │ ├── pruss_intc_mapping.h
│ │ │ └── prussdrv.h
│ │ └── interface/
│ │ ├── Makefile
│ │ ├── __prussdrv.h
│ │ └── prussdrv.c
│ └── pasm/
│ ├── LICENCE.txt
│ ├── Makefile
│ ├── pasm.c
│ ├── pasm.h
│ ├── pasmdbg.h
│ ├── pasmdot.c
│ ├── pasmexp.c
│ ├── pasmmacro.c
│ ├── pasmop.c
│ ├── pasmpp.c
│ ├── pasmstruct.c
│ └── pru_ins.h
├── brackets/
│ ├── Letters.dxf
│ ├── Write.scad
│ ├── flat-bracket.scad
│ ├── matrix-bracket.scad
│ ├── octoscroller.scad
│ └── spiral.scad
├── default.config
├── dts/
│ ├── CAPE-BONE-OCTO-00A0.dtbo
│ ├── LEDscape.dts
│ ├── README.md
│ ├── angstrom.dtb
│ ├── angstrom.dts
│ ├── cape-bone-octo.dts
│ └── ubuntu-3.8.13-bone32.dts
├── fonts/
│ ├── json2bmp
│ └── mta-sign.json
├── lib/
│ └── .empty
├── obj/
│ └── .empty
├── pcb/
│ ├── LEDscape pin assignments.csv
│ ├── LEDscape.brd
│ ├── LEDscape.lbr
│ ├── LEDscape.sch
│ ├── TODO
│ ├── flat-20mm.scad
│ ├── lightbuddy-transmitter.brd
│ ├── lightbuddy-transmitter.sch
│ ├── octoscroller.brd
│ ├── octoscroller.sch
│ ├── receiver-2x.brd
│ ├── receiver-2x.sch
│ ├── receiver-4x.brd
│ ├── receiver-4x.sch
│ ├── receiver.brd
│ └── receiver.sch
├── radials.config
├── src/
│ ├── demos/
│ │ ├── Makefile
│ │ ├── companion-cube.raw
│ │ ├── cube-image.c
│ │ ├── cube-life.c
│ │ ├── fire.c
│ │ ├── identify.c
│ │ ├── life.c
│ │ ├── lightcycles.c
│ │ └── matrix-test.c
│ ├── ledscape/
│ │ ├── Makefile
│ │ ├── bitpattern.h
│ │ ├── config.c
│ │ ├── fixed-font.c
│ │ ├── ledscape.c
│ │ ├── ledscape.h
│ │ ├── matrix.p
│ │ ├── pru.c
│ │ ├── pru.h
│ │ ├── util.c
│ │ ├── util.h
│ │ ├── ws281x.hp
│ │ └── ws281x.p
│ ├── mta/
│ │ ├── Makefile
│ │ ├── mta-font.c
│ │ └── mta-sign.c
│ ├── net/
│ │ ├── Makefile
│ │ ├── matrix-tcp-rx.c
│ │ ├── matrix-udp-rx.c
│ │ └── opc-rx.c
│ ├── perlin/
│ │ ├── Makefile
│ │ ├── gammalut.h
│ │ ├── globals.h
│ │ ├── knobs/
│ │ │ └── knobs.ino
│ │ ├── pattern.cpp
│ │ ├── pattern.h
│ │ ├── perlin-ledscape.cpp
│ │ ├── pf2.cpp
│ │ └── pf2.h
│ └── script/
│ ├── Makefile
│ ├── bbb-network-setup
│ ├── find-serial
│ ├── install
│ ├── ledscape.service
│ ├── python-test
│ ├── run-ledscape
│ ├── run-videoplayer
│ ├── twitter-scroller
│ ├── videoplayer
│ └── videoplayer.service
├── strips.config
├── tall-cylinder.config
└── ubuntu/
└── ledscape.conf
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.*.swp
.*.swo
*.i
*.o
*.a
*.bin
pcb/*.b[^r][^d]
pcb/*.p[^c][^b]
rgb-test
am335x/pasm/pasm
.*.d
*~
*~
bin/*
================================================
FILE: Makefile
================================================
#########
#
# Top level Makefile.
# Mostly just recurse into subdirectories.
SUBDIR-y += src/ledscape
SUBDIR-y += src/demos
SUBDIR-y += src/perlin
SUBDIR-y += src/mta
SUBDIR-y += src/net
SUBDIR-y += src/script
all:
for dir in $(SUBDIR-y); do \
$(MAKE) -C $$dir || exit 1; \
done
clean:
for dir in $(SUBDIR-y); do \
$(MAKE) -C $$dir clean; \
done
firmware:
echo CAPE-BONE-OCTO > /sys/devices/bone_capemgr.8/slots
================================================
FILE: Makefile.common
================================================
#########
#
# Common build targets
#
#
TOP ?= ../..
OBJDIR ?= $(TOP)/obj
LIBDIR ?= $(TOP)/lib
BINDIR ?= $(TOP)/bin
all: \
$(TARGETS-y) \
$(foreach O,$(BIN-y),$(BINDIR)/$O) \
$(foreach O,$(LIB-y),$(LIBDIR)/$O) \
ifeq ($(shell uname -m),armv7l)
# We are on the BeagleBone Black itself;
# do not cross compile.
export CROSS_COMPILE:=
else
# We are not on the BeagleBone and might be cross compiling.
# If the environment does not set CROSS_COMPILE, set our
# own. Install a cross compiler with something like:
#
# sudo apt-get install gcc-arm-linux-gnueabi
#
export CROSS_COMPILE?=arm-linux-gnueabi-
endif
GENERIC_CFLAGS += \
-g \
-W \
-Wall \
-D_BSD_SOURCE \
-Wp,-MMD,$(dir $@).$(notdir $@).d \
-Wp,-MT,$@ \
-I. \
-I$(TOP)/src/ledscape \
-O2 \
-mtune=cortex-a8 \
-march=armv7-a \
CFLAGS += \
-std=c99 \
$(GENERIC_CFLAGS) \
CPPFLAGS += \
$(GENERIC_CFLAGS) \
LDFLAGS += \
LDLIBS += \
-L$(LIBDIR) \
-lledscape \
-lpthread \
-lm \
COMPILE.c-o = $(CROSS_COMPILE)gcc $(CFLAGS) -c -o $@ $<
COMPILE.cpp-o = $(CROSS_COMPILE)g++ $(CPPFLAGS) -c -o $@ $<
COMPILE.a = $(CROSS_COMPILE)ar crv $@ $^
COMPILE.link = $(CROSS_COMPILE)g++ $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(OBJDIR)/%.o: %.c
$(COMPILE.c-o)
$(OBJDIR)/%.o: %.cpp
$(COMPILE.cpp-o)
$(LIBDIR)/%.a:
$(RM) $@
$(COMPILE.a)
$(BINDIR)/%:
$(COMPILE.link)
#####
#
# The TI "app_loader" is the userspace library for talking to
# the PRU and mapping memory between it and the ARM.
#
APP_LOADER_DIR ?= $(TOP)/am335x/app_loader
APP_LOADER_LIB := $(APP_LOADER_DIR)/lib/libprussdrv.a
CFLAGS += -I$(APP_LOADER_DIR)/include
LDLIBS += $(APP_LOADER_LIB)
#####
#
# The TI PRU assembler looks like it has macros and includes,
# but it really doesn't. So instead we use cpp to pre-process the
# file and then strip out all of the directives that it adds.
# PASM also doesn't handle multiple statements per line, so we
# insert hard newline characters for every ; in the file.
#
PASM_DIR ?= $(TOP)/am335x/pasm
PASM := $(PASM_DIR)/pasm
$(LIBDIR)/%.bin: %.p $(PASM)
$(CPP) - < $< | perl -p -e 's/^#.*//; s/;/\n/g; s/BYTE\((\d+)\)/t\1/g' > /tmp/$(basename $<).i
$(PASM) -V3 -b /tmp/$(basename $<).i $(basename $@)
$(RM) /tmp/$(basename $<).i
#
# Generate a target for each of the binaries, with dependencies on
# object files for that source.
#
$(foreach O,$(BIN-y),\
$(eval $(BINDIR)/$O: $(foreach s,$($O.srcs),$(OBJDIR)/$(basename $s).o) $(LIBDIR)/libledscape.a))
$(foreach O,$(LIB-y),\
$(eval $(LIBDIR)/$O: $(foreach s,$($(basename $O).srcs),$(OBJDIR)/$(basename $s).o) $(APP_LOADER_LIB)))
#$(TARGETS):
#$(COMPILE.link)
.PHONY: clean
# Include all of the generated dependency files
-include $(OBJDIR)/.*.o.d
clean:
rm -rf \
$(OBJDIR)/*.o \
$(LIBDIR)/*.a \
$(OBJDIR)/.*.o.d \
$(LIBDIR)/*.bin \
###########
#
# The correct way to reserve the GPIO pins on the BBB is with the
# capemgr and a Device Tree file. But it doesn't work.
#
SLOT_FILE=/sys/devices/bone_capemgr.9/slots
DTS=CAPE-BONE-OCTO
DTB=/lib/firmware/$(DTS)-00A0.dtbo
dts: LEDscape.dts
@SLOT="`grep LEDSCAPE $(SLOT_FILE) | cut -d: -f1`"; \
if [ ! -z "$$SLOT" ]; then \
echo "Removing slot $$SLOT"; \
echo -$$SLOT > $(SLOT_FILE); \
fi
dtc -O dtb -o /lib/firmware/BB-LEDSCAPE-00A0.dtbo -b 0 -@ LEDscape.dts
echo BB-LEDSCAPE > $(SLOT_FILE)
firmware: $(DTB)
echo $(DTS) > $(SLOT_FILE)
$(DTB): cape-bone-octo.dts FORCE
dtc -O dtb -o $@ -b 0 -@ $<
FORCE:
###########
#
# PRU Libraries and PRU assembler are build from their own trees.
#
$(APP_LOADER_LIB):
$(MAKE) -C $(APP_LOADER_DIR)/interface
$(PASM):
$(MAKE) -C $(PASM_DIR)
================================================
FILE: README.md
================================================

DANGER!
=======
This code works with the PRU units on the Beagle Bone and can easily
cause *hard crashes*. It is still being debugged and developed.
Be careful hot-plugging things into the headers -- it is possible to
damage the pin drivers and cause problems in the ARM, especially if
there are +5V signals involved.
Overview
========
The WS281x LED chips are built like shift registers and make for very
easy LED strip construction. The signals are duty-cycle modulated,
with a 0 measuring 250 ns long and a 1 being 600 ns long, and 1250 ns
between bits. Since this doesn't map to normal SPI hardware and requires
an 800 KHz bit clock, it is typically handled with a dedicated microcontroller
or DMA hardware on something like the Teensy 3.
However, the TI AM335x ARM Cortex-A8 in the BeagleBone Black has two
programmable "microcontrollers" built into the CPU that can handle realtime
tasks and also access the ARM's memory. This allows things that
might have been delegated to external devices to be handled without
any additional hardware, and without the overhead of clocking data out
the USB port.
The frames are stored in memory as a series of 4-byte pixels in the
order GRBA, packed in strip-major order. This means that it looks
like this in RAM:
S0P0 S1P0 S2P0 ... S31P0 S0P1 S1P1 ... S31P1 S0P2 S1P2 ... S31P2
This way length of the strip can be variable, although the memory used
will depend on the length of the longest strip. 4 * 32 * longest strip
bytes are required per frame buffer. The maximum frame rate also depends
on the length of th elongest strip.
API
===
<ledscape.h> defines the API. The sample rgb-test program pulses
the first three LEDs in red, green and blue. The key components are:
ledscape_t * ledscape_init(unsigned num_pixels)
ledscape_frame_t * ledscape_frame(ledscape_t*, unsigned frame_num);
ledscape_draw(ledscape_t*, unsigned frame_num);
unsigned ledscape_wait(ledscape_t*)
You can double buffer like this:
const int num_pixels = 256;
ledscape_t * const leds = ledscape_init(num_pixels);
unsigned i = 0;
while (1)
{
// Alternate frame buffers on each draw command
const unsigned frame_num = i++ % 2;
ledscape_frame_t * const frame
= ledscape_frame(leds, frame_num);
render(frame);
// wait for the previous frame to finish;
ledscape_wait(leds);
ledscape_draw(leds, frame_num);
}
ledscape_close(leds);
The 24-bit RGB data to be displayed is laid out with BRGA format,
since that is how it will be translated during the clock out from the PRU.
The frame buffer is stored as a "strip-major" array of pixels.
typedef struct {
uint8_t b;
uint8_t r;
uint8_t g;
uint8_t a;
} __attribute__((__packed__)) ledscape_pixel_t;
typedef struct {
ledscape_pixel_t strip[32];
} __attribute__((__packed__)) ledscape_frame_t;
Low level API
=============
If you want to poke at the PRU directly, there is a command structure
shared in PRU DRAM that holds a pointer to the current frame buffer,
the length in pixels, a command byte and a response byte.
Once the PRU has cleared the command byte you are free to re-write the
dma address or number of pixels.
typedef struct
{
// in the DDR shared with the PRU
const uintptr_t pixels_dma;
// Length in pixels of the longest LED strip.
unsigned num_pixels;
// write 1 to start, 0xFF to abort. will be cleared when started
volatile unsigned command;
// will have a non-zero response written when done
volatile unsigned response;
} __attribute__((__packed__)) ws281x_command_t;
LED Strips
==========

* http://www.adafruit.com/products/1138
* http://www.adafruit.com/datasheets/WS2811.pdf
================================================
FILE: Setup.md
================================================
# Getting Started
This is a quick introduction on how to set up LEDscape on a Debian-based image
# Setting up the BBB environment
To develop for LEDscape on a Debian environment, Start by copying the latest BBB image to an SD card. These instructions were made using:
BBB-eMMC-flasher-debian-7.8-console-armhf-2015-03-01-2gb.img.xz
The latest version can be found at:
http://elinux.org/Beagleboard:BeagleBoneBlack_Debian#Debian_Releases
First, we need to expand the image to use the whole SD card. By default, it is only 2GB.
Note: If using a RevC or lower BBB, the EMMC is only 2GB so this isn't necessicary.
cd /opt/scripts/tools/
sudo ./grow_partition.sh
sudo reboot
Next, update the the Debian environment:
sudo apt-get update
sudo apt-get install usbmount -y
sudo apt-get install git build-essential python vim -y
Disable the HDMI output:
If you are using a Debian image from 2014.8.13 or newer, do this:
sudo cp /boot/uEnv.txt /boot/uEnv.txt.backup
sudo sed -i 's/#cape_disable=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN$/cape_disable=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN/g' /boot/uEnv.txt
Otherwise, modify the uEnv boot file by hand to disable HDMI and HDMIN overlays.
Enable a larger shared memory space (8MB) with the PRU:
echo 'options uio_pruss extram_pool_sz=0x800000' | sudo tee -a /etc/modprobe.d/ledscape.conf
Finally, reboot to apply these changs:
sudo reboot
# Next, set up LEDscape:
Use git to download the repository:
cd /opt
sudo git clone http://github.com/osresearch/LEDscape.git
cd LEDscape
sudo make
Copy the device tree file into place, and add it to the slots:
sudo cp dts/CAPE-BONE-OCTO-00A0.dtbo /lib/firmware
echo 'CAPE-BONE-OCTO' | sudo tee -a /sys/devices/bone_capemgr.*/slots
Then run the identification program to test if all is well:
sudo bin/identify
# Make a configuration file for your screen
The configuration file is what tells LEDscape how to draw it's virtual screen onto your matrix tiles or LED strips. There are two basic formats:
## Matrix screen
Let's look at a sample matrix configuration. Here's one for a small display consisting of 4 LED matricies, arranged in a square:
matrix16
0,6 N 0,0
0,7 N 32,0
1,6 N 0,16
2,7 N 32,16
The first line of the configuration file describes the type of matrix. Here are the valid matrix types:
| Type | Description |
| ------------- |:-------------:|
| matrix16 | 32x16 LED matrix, 1/8th scanning (three address pins) |
Each following line consists of three sets of information: Controller position, Rotation, and LEDscape virtual screen offset.
The controller position consists of two values. The first is the output channel. This corresponds to the physical output that the matrix is plugged into on the board. There are 8 outputs available on the OCTOscroller shield. The second is the position in the output chain. This one is a little more tricky, as it is backwards from you might expect. The *first* matrix panel in the chain, which is the one connected to the OCTOscroller shield, is called 7. The second one is called 6, and so on, until the eighth and final one. For example, a single matrix panel connected to output #3 has the following controller position:
3,7
The rotation is any one of the following values: N, U, L, R. 'N' and 'U' are used when the long side of the panel is parallel to the ground, and 'L' and 'R' are used when it is perpendicular. Try one, then the other, to figure out the correct orientation for your panels.
The Virtual screen offset is the top-left position in the LEDscape virtual screen that will be drawn to this matrix panel. Normally you will want to map sections of the screen into contigouos regions, so the top-left panel in your display should have a virtual screen offset of 0,0, then the panel to the right of that one should be offset by the width of the first panel, either 16,0 or 32,0, and so on.
## WS2812 strips
Let's look at a sample WS2812 strip configuration. Here's one that can control a single strip output:
ws2812
64,48
The first line of the configuration file describes the type of matrix. Here are the valid matrix types:
| Type | Description |
| ------------- |:-------------:|
| ws2812 | Strip of WS2812/WS2812B LEDs, aka NeoPixels |
The following line consists of Width,Height. For LED strip mode, this means:
W: length of the longest strip
H: number of output strips
## Testing your configuration
For matricies, there is a handy identification program to draw some text that identifies each panel. Run it to test your new configuration:
sudo bin/identify myconfig.config
# Set up the UDP listener to display incoming packets
To run the matrix listener:
sudo bin/matrix-udp-rx -W 256 -H 32 -c sign.config &
Or for WS2812B strips:
sudo bin/matrix-udp-rx -W 256 -H 32 -c strips.config &
There are a bunch of command line arguments, and the whole thing seems to be in a bit of flux. Here's what exists now:
| Argument | Description | Default |
| ------------- |:-------------:| -----:|
| -v | Verbose mode | |
| -n | Skip LEDscape initialization | |
| -c | Configuration file to use. Note: Use full pathname, for example: /home/debian/LEDscape/default.config | |
| -t | Number of seconds the display server will show the previous image before timing out | 60 |
| -W | LEDscape virtual screen width | 256 |
| -H | LEDscape virtual screen height | 128 |
| -m | Message to display at startup | |
# Run the UDP listener automatically at system boot
There's a handy script for starting LEDscape at boot. It should listen on the ethernet interface on port 9999 automatically.
## Debian
Debian uses systemd. Do this:
sudo cp bin/ledscape.service /etc/systemd/system
sudo systemctl enable ledscape.service
Extra: for video playback
sudo cp bin/videoplayer.service /etc/systemd/system
sudo systemctl enable videoplayer.service
## Ubuntu
Note: The Ubuntu startup script is old and probably needs fixing.
Ubuntu appears to use upstart. Do this:
sudo cp ubuntu/ledscape.conf /etc/init
sudo start ledscape
# Extra credit
## Make the filesystem read-only
To help prevent the configuration from breaking, it's helpful to configure the system as read only. The insructions are from:
http://armsdr.blogspot.com/2014/11/beaglebone-debian-read-only-filesystem.html
First, back up the original fstab:
sudo cp /etc/fstab /etc/fstab_rw
Now, set the root filesystem to be readonly:
sudo sed -i 's/ext4 noatime/ext4 ro,noatime/g' /etc/fstab
Finally, add some temporary rw mounts so that the system can continue to function:
echo "tmpfs /tmp tmpfs nodev,nosuid,size=32M 0 0
tmpfs /srv tmpfs nodev,size=512K 0 0
tmpfs /var/log tmpfs defaults,noatime,size=1M 0 0
tmpfs /var/tmp tmpfs defaults,noatime,size=512K 0 0
tmpfs /var/run tmpfs defaults,noatime,size=512K 0 0" | sudo tee -a /etc/fstab
Later, write capability can be restored using the following command:
sudo mount -o remount,rw /
And disabled again using:
sudo mount -o remount,ro /
## Speed up boot when Ethernet is not connected
The ethernet PHY on some BBBs can be flaky and cause a long delay during boot. To work around this, set it to not load at boot:
sudo sudo sed -i 's/auto eth0/#auto eth0/g' /etc/network/interfaces
Later it can be enabled by typing:
sudo ifup eth0
## Set the time automatically (when network is available)
sudo apt-get install ntpdate -y
# Video playback
Playing a video is as simple as running the video player (after running the UDP listener):
bin/video_player -s 256x32 -l ../Daft\ Punk\ -\ Around\ The\ World.avi
To use the video player, some additional packages will need to be installed:
sudo apt-get install libavformat-dev x264 v4l-utils ffmpeg libcv2.3 libcvaux2.3 libhighgui2.3 python-opencv opencv-doc libcv-dev libcvaux-dev libhighgui-dev -y
#Helpful things for development
## Make VIM prettier
Enable color highlighting
echo 'syntax on' >>~/.vimrc
================================================
FILE: am335x/app_loader/include/pruss_intc_mapping.h
================================================
/*
* pruss_intc_mapping.h
*
* Example PRUSS INTC mapping for the application
*
* Copyright (C) 2010 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.
*
*/
/*
* ============================================================================
* Copyright (c) Texas Instruments Inc 2010-11
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
#define AM33XX
#ifdef AM33XX
#define PRU0_PRU1_INTERRUPT 17
#define PRU1_PRU0_INTERRUPT 18
#define PRU0_ARM_INTERRUPT 19
#define PRU1_ARM_INTERRUPT 20
#define ARM_PRU0_INTERRUPT 21
#define ARM_PRU1_INTERRUPT 22
#else
#define PRU0_PRU1_INTERRUPT 32
#define PRU1_PRU0_INTERRUPT 33
#define PRU0_ARM_INTERRUPT 34
#define PRU1_ARM_INTERRUPT 35
#define ARM_PRU0_INTERRUPT 36
#define ARM_PRU1_INTERRUPT 37
#endif
#define CHANNEL0 0
#define CHANNEL1 1
#define CHANNEL2 2
#define CHANNEL3 3
#define CHANNEL4 4
#define CHANNEL5 5
#define CHANNEL6 6
#define CHANNEL7 7
#define CHANNEL8 8
#define CHANNEL9 9
#define PRU0 0
#define PRU1 1
#define PRU_EVTOUT0 2
#define PRU_EVTOUT1 3
#define PRU_EVTOUT2 4
#define PRU_EVTOUT3 5
#define PRU_EVTOUT4 6
#define PRU_EVTOUT5 7
#define PRU_EVTOUT6 8
#define PRU_EVTOUT7 9
#define PRU0_HOSTEN_MASK 0x0001
#define PRU1_HOSTEN_MASK 0x0002
#define PRU_EVTOUT0_HOSTEN_MASK 0x0004
#define PRU_EVTOUT1_HOSTEN_MASK 0x0008
#define PRU_EVTOUT2_HOSTEN_MASK 0x0010
#define PRU_EVTOUT3_HOSTEN_MASK 0x0020
#define PRU_EVTOUT4_HOSTEN_MASK 0x0040
#define PRU_EVTOUT5_HOSTEN_MASK 0x0080
#define PRU_EVTOUT6_HOSTEN_MASK 0x0100
#define PRU_EVTOUT7_HOSTEN_MASK 0x0200
#define PRUSS_INTC_INITDATA { \
{ PRU0_PRU1_INTERRUPT, PRU1_PRU0_INTERRUPT, PRU0_ARM_INTERRUPT, PRU1_ARM_INTERRUPT, ARM_PRU0_INTERRUPT, ARM_PRU1_INTERRUPT, -1 }, \
{ {PRU0_PRU1_INTERRUPT,CHANNEL1}, {PRU1_PRU0_INTERRUPT, CHANNEL0}, {PRU0_ARM_INTERRUPT,CHANNEL2}, {PRU1_ARM_INTERRUPT, CHANNEL3}, {ARM_PRU0_INTERRUPT, CHANNEL0}, {ARM_PRU1_INTERRUPT, CHANNEL1}, {-1,-1}}, \
{ {CHANNEL0,PRU0}, {CHANNEL1, PRU1}, {CHANNEL2, PRU_EVTOUT0}, {CHANNEL3, PRU_EVTOUT1}, {-1,-1} }, \
(PRU0_HOSTEN_MASK | PRU1_HOSTEN_MASK | PRU_EVTOUT0_HOSTEN_MASK | PRU_EVTOUT1_HOSTEN_MASK) /*Enable PRU0, PRU1, PRU_EVTOUT0 */ \
} \
================================================
FILE: am335x/app_loader/include/prussdrv.h
================================================
/*
* prussdrv.h
*
* Describes PRUSS userspace driver for Industrial Communications
*
* Copyright (C) 2010 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.
*
*/
/*
* ============================================================================
* Copyright (c) Texas Instruments Inc 2010-11
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
#ifndef _PRUSSDRV_H
#define _PRUSSDRV_H
#include <sys/types.h>
#include <pthread.h>
#if defined (__cplusplus)
extern "C" {
#endif
#define NUM_PRU_HOSTIRQS 8
#define NUM_PRU_HOSTS 10
#define NUM_PRU_CHANNELS 10
#define NUM_PRU_SYS_EVTS 64
#define PRUSS0_PRU0_DATARAM 0
#define PRUSS0_PRU1_DATARAM 1
#define PRUSS0_PRU0_IRAM 2
#define PRUSS0_PRU1_IRAM 3
//Available in AM33xx series - begin
#define PRUSS0_SHARED_DATARAM 4
#define PRUSS0_CFG 5
#define PRUSS0_UART 6
#define PRUSS0_IEP 7
#define PRUSS0_ECAP 8
#define PRUSS0_MII_RT 9
#define PRUSS0_MDIO 10
//Available in AM33xx series - end
#define PRU_EVTOUT_0 0
#define PRU_EVTOUT_1 1
#define PRU_EVTOUT_2 2
#define PRU_EVTOUT_3 3
#define PRU_EVTOUT_4 4
#define PRU_EVTOUT_5 5
#define PRU_EVTOUT_6 6
#define PRU_EVTOUT_7 7
typedef void *(*prussdrv_function_handler) (void *);
typedef struct __sysevt_to_channel_map {
short sysevt;
short channel;
} tsysevt_to_channel_map;
typedef struct __channel_to_host_map {
short channel;
short host;
} tchannel_to_host_map;
typedef struct __pruss_intc_initdata {
//Enabled SYSEVTs - Range:0..63
//{-1} indicates end of list
char sysevts_enabled[NUM_PRU_SYS_EVTS];
//SysEvt to Channel map. SYSEVTs - Range:0..63 Channels -Range: 0..9
//{-1, -1} indicates end of list
tsysevt_to_channel_map sysevt_to_channel_map[NUM_PRU_SYS_EVTS];
//Channel to Host map.Channels -Range: 0..9 HOSTs - Range:0..9
//{-1, -1} indicates end of list
tchannel_to_host_map channel_to_host_map[NUM_PRU_CHANNELS];
//10-bit mask - Enable Host0-Host9 {Host0/1:PRU0/1, Host2..9 : PRUEVT_OUT0..7)
unsigned int host_enable_bitmask;
} tpruss_intc_initdata;
int prussdrv_init(void);
int prussdrv_open(unsigned int pru_evtout_num);
int prussdrv_pru_reset(unsigned int prunum);
int prussdrv_pru_disable(unsigned int prunum);
int prussdrv_pru_enable(unsigned int prunum);
int prussdrv_pru_write_memory(unsigned int pru_ram_id,
unsigned int wordoffset,
unsigned int *memarea,
unsigned int bytelength);
int prussdrv_pruintc_init(tpruss_intc_initdata * prussintc_init_data);
int prussdrv_map_l3mem(void **address);
int prussdrv_map_extmem(void **address);
int prussdrv_map_prumem(unsigned int pru_ram_id, void **address);
int prussdrv_map_peripheral_io(unsigned int per_id, void **address);
unsigned int prussdrv_get_phys_addr(void *address);
void *prussdrv_get_virt_addr(unsigned int phyaddr);
int prussdrv_pru_wait_event(unsigned int pru_evtout_num);
int prussdrv_pru_send_event(unsigned int eventnum);
int prussdrv_pru_clear_event(unsigned int eventnum);
int prussdrv_pru_send_wait_clear_event(unsigned int send_eventnum,
unsigned int pru_evtout_num,
unsigned int ack_eventnum);
int prussdrv_exit(void);
int prussdrv_exec_program(int prunum, char *filename);
int prussdrv_start_irqthread(unsigned int pru_evtout_num, int priority,
prussdrv_function_handler irqhandler);
#if defined (__cplusplus)
}
#endif
#endif
================================================
FILE: am335x/app_loader/interface/Makefile
================================================
ROOTDIR = ..
TARGET = libprussdrv
CROSS_COMPILE?=arm-linux-gnueabi-
CC = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar
INCLUDEDIR = ../include
LIBDIR = ../lib
C_FLAGS += -I. -Wall -I$(INCLUDEDIR)
COMPILE.c = $(CC) $(C_FLAGS) $(CPP_FLAGS) -c
AR.c = $(AR) rc
DBGTARGET = $(LIBDIR)/$(TARGET)d.a
RELTARGET = $(LIBDIR)/$(TARGET).a
DBGCFLAGS = -g -O0 -D__DEBUG
RELCFLAGS = -O3 -mtune=cortex-a8 -march=armv7-a
SOURCES = $(wildcard *.c)
HEADERS = $(wildcard *.h)
TARGETHEADERS = $(addprefix $(INCLUDEDIR)/, $(HEADERS))
DBGOBJFILES = $(SOURCES:%.c=debug/%.o)
RELOBJFILES = $(SOURCES:%.c=release/%.o)
.PHONY: clean debug release install
all: debug release
install:
release: $(RELTARGET)
#release: $(RELTARGET) $(TARGETHEADERS)
debug: $(DBGTARGET)
#debug: $(DBGTARGET) $(TARGETHEADERS)
$(RELTARGET): $(RELOBJFILES)
@mkdir -p $(ROOTDIR)/lib
$(AR.c) $@ $(RELOBJFILES)
$(DBGTARGET): $(DBGOBJFILES)
@mkdir -p $(ROOTDIR)/lib
$(AR.c) $@ $(DBGOBJFILES)
$(RELOBJFILES): release/%.o: %.c $(HEADERS)
@mkdir -p release
$(COMPILE.c) $(RELCFLAGS) -o $@ $<
$(DBGOBJFILES): debug/%.o: %.c $(HEADERS)
@mkdir -p debug
$(COMPILE.c) $(DBGCFLAGS) -o $@ $<
$(TARGETHEADERS): $(HEADERS)
@echo Installing headers...
@install -d $(INCLUDEDIR)
@install -c $< $@
clean:
-rm -rf release debug *~ ../lib/*
================================================
FILE: am335x/app_loader/interface/__prussdrv.h
================================================
/*
* __prussdrv.h
*
*
* Copyright (C) 2012 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.
*
*/
/*
* ============================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/unistd.h>
#define DISABLE_L3RAM_SUPPORT
#define PAGE_SIZE 4096
#define PRUSS_V1 1
#define PRUSS_V2 2
#define AM33XX_PRUSS_INTC_REV 0x4E82A900
#define AM18XX_PRUSS_INTC_REV 0x4E825900
#define PRUSS_MAX_IRAM_SIZE 8192
#define AM33XX_PRUSS_IRAM_SIZE 8192
#define AM33XX_PRUSS_MMAP_SIZE 0x40000
#define AM33XX_DATARAM0_PHYS_BASE 0x4a300000
#define AM33XX_DATARAM1_PHYS_BASE 0x4a302000
#define AM33XX_INTC_PHYS_BASE 0x4a320000
#define AM33XX_PRU0CONTROL_PHYS_BASE 0x4a322000
#define AM33XX_PRU0DEBUG_PHYS_BASE 0x4a322400
#define AM33XX_PRU1CONTROL_PHYS_BASE 0x4a324000
#define AM33XX_PRU1DEBUG_PHYS_BASE 0x4a324400
#define AM33XX_PRU0IRAM_PHYS_BASE 0x4a334000
#define AM33XX_PRU1IRAM_PHYS_BASE 0x4a338000
#define AM33XX_PRUSS_SHAREDRAM_BASE 0x4a310000
#define AM33XX_PRUSS_CFG_BASE 0x4a326000
#define AM33XX_PRUSS_UART_BASE 0x4a328000
#define AM33XX_PRUSS_IEP_BASE 0x4a32e000
#define AM33XX_PRUSS_ECAP_BASE 0x4a330000
#define AM33XX_PRUSS_MIIRT_BASE 0x4a332000
#define AM33XX_PRUSS_MDIO_BASE 0x4a332400
#define AM18XX_PRUSS_IRAM_SIZE 4096
#define AM18XX_PRUSS_MMAP_SIZE 0x7C00
#define AM18XX_DATARAM0_PHYS_BASE 0x01C30000
#define AM18XX_DATARAM1_PHYS_BASE 0x01C32000
#define AM18XX_INTC_PHYS_BASE 0x01C34000
#define AM18XX_PRU0CONTROL_PHYS_BASE 0x01C37000
#define AM18XX_PRU0DEBUG_PHYS_BASE 0x01C37400
#define AM18XX_PRU1CONTROL_PHYS_BASE 0x01C37800
#define AM18XX_PRU1DEBUG_PHYS_BASE 0x01C37C00
#define AM18XX_PRU0IRAM_PHYS_BASE 0x01C38000
#define AM18XX_PRU1IRAM_PHYS_BASE 0x01C3C000
//PRUSS INTC register offsets
#define PRU_INTC_REVID_REG 0x000
#define PRU_INTC_CR_REG 0x004
#define PRU_INTC_HCR_REG 0x00C
#define PRU_INTC_GER_REG 0x010
#define PRU_INTC_GNLR_REG 0x01C
#define PRU_INTC_SISR_REG 0x020
#define PRU_INTC_SICR_REG 0x024
#define PRU_INTC_EISR_REG 0x028
#define PRU_INTC_EICR_REG 0x02C
#define PRU_INTC_HIEISR_REG 0x034
#define PRU_INTC_HIDISR_REG 0x038
#define PRU_INTC_GPIR_REG 0x080
#define PRU_INTC_SRSR1_REG 0x200
#define PRU_INTC_SRSR2_REG 0x204
#define PRU_INTC_SECR1_REG 0x280
#define PRU_INTC_SECR2_REG 0x284
#define PRU_INTC_ESR1_REG 0x300
#define PRU_INTC_ESR2_REG 0x304
#define PRU_INTC_ECR1_REG 0x380
#define PRU_INTC_ECR2_REG 0x384
#define PRU_INTC_CMR1_REG 0x400
#define PRU_INTC_CMR2_REG 0x404
#define PRU_INTC_CMR3_REG 0x408
#define PRU_INTC_CMR4_REG 0x40C
#define PRU_INTC_CMR5_REG 0x410
#define PRU_INTC_CMR6_REG 0x414
#define PRU_INTC_CMR7_REG 0x418
#define PRU_INTC_CMR8_REG 0x41C
#define PRU_INTC_CMR9_REG 0x420
#define PRU_INTC_CMR10_REG 0x424
#define PRU_INTC_CMR11_REG 0x428
#define PRU_INTC_CMR12_REG 0x42C
#define PRU_INTC_CMR13_REG 0x430
#define PRU_INTC_CMR14_REG 0x434
#define PRU_INTC_CMR15_REG 0x438
#define PRU_INTC_CMR16_REG 0x43C
#define PRU_INTC_HMR1_REG 0x800
#define PRU_INTC_HMR2_REG 0x804
#define PRU_INTC_HMR3_REG 0x808
#define PRU_INTC_SIPR1_REG 0xD00
#define PRU_INTC_SIPR2_REG 0xD04
#define PRU_INTC_SITR1_REG 0xD80
#define PRU_INTC_SITR2_REG 0xD84
#define PRU_INTC_HIER_REG 0x1500
#define MAX_HOSTS_SUPPORTED 10
//UIO driver expects user space to map PRUSS_UIO_MAP_OFFSET_XXX to
//access corresponding memory regions - region offset is N*PAGE_SIZE
#define PRUSS_UIO_MAP_OFFSET_PRUSS 0*PAGE_SIZE
#define PRUSS_UIO_DRV_PRUSS_BASE "/sys/class/uio/uio0/maps/map0/addr"
#define PRUSS_UIO_DRV_PRUSS_SIZE "/sys/class/uio/uio0/maps/map0/size"
#ifndef DISABLE_L3RAM_SUPPORT
#define PRUSS_UIO_MAP_OFFSET_L3RAM 1*PAGE_SIZE
#define PRUSS_UIO_DRV_L3RAM_BASE "/sys/class/uio/uio0/maps/map1/addr"
#define PRUSS_UIO_DRV_L3RAM_SIZE "/sys/class/uio/uio0/maps/map1/size"
#define PRUSS_UIO_MAP_OFFSET_EXTRAM 2*PAGE_SIZE
#define PRUSS_UIO_DRV_EXTRAM_BASE "/sys/class/uio/uio0/maps/map2/addr"
#define PRUSS_UIO_DRV_EXTRAM_SIZE "/sys/class/uio/uio0/maps/map2/size"
#else
#define PRUSS_UIO_MAP_OFFSET_EXTRAM 1*PAGE_SIZE
#define PRUSS_UIO_DRV_EXTRAM_BASE "/sys/class/uio/uio0/maps/map1/addr"
#define PRUSS_UIO_DRV_EXTRAM_SIZE "/sys/class/uio/uio0/maps/map1/size"
#endif
typedef struct __prussdrv {
int version;
int fd[NUM_PRU_HOSTIRQS];
void *pru0_dataram_base;
void *pru1_dataram_base;
void *intc_base;
void *pru0_control_base;
void *pru0_debug_base;
void *pru1_control_base;
void *pru1_debug_base;
void *pru0_iram_base;
void *pru1_iram_base;
void *l3ram_base;
void *extram_base;
pthread_t irq_thread[NUM_PRU_HOSTIRQS];
int mmap_fd;
void *pruss_sharedram_base;
void *pruss_cfg_base;
void *pruss_uart_base;
void *pruss_iep_base;
void *pruss_ecap_base;
void *pruss_miirt_base;
void *pruss_mdio_base;
unsigned int pru0_dataram_phy_base;
unsigned int pru1_dataram_phy_base;
unsigned int intc_phy_base;
unsigned int pru0_control_phy_base;
unsigned int pru0_debug_phy_base;
unsigned int pru1_control_phy_base;
unsigned int pru1_debug_phy_base;
unsigned int pru0_iram_phy_base;
unsigned int pru1_iram_phy_base;
unsigned int l3ram_phy_base;
unsigned int extram_phy_base;
unsigned int pruss_sharedram_phy_base;
unsigned int pruss_cfg_phy_base;
unsigned int pruss_uart_phy_base;
unsigned int pruss_iep_phy_base;
unsigned int pruss_ecap_phy_base;
unsigned int pruss_miirt_phy_base;
unsigned int pruss_mdio_phy_base;
unsigned int pruss_phys_base;
unsigned int pruss_map_size;
unsigned int l3ram_phys_base;
unsigned int l3ram_map_size;
unsigned int extram_phys_base;
unsigned int extram_map_size;
} tprussdrv;
int __pruss_detect_hw_version(unsigned int *pruss_io)
{
if (pruss_io[(AM18XX_INTC_PHYS_BASE - AM18XX_DATARAM0_PHYS_BASE) >> 2]
== AM18XX_PRUSS_INTC_REV)
return PRUSS_V1;
else {
if (pruss_io
[(AM33XX_INTC_PHYS_BASE - AM33XX_DATARAM0_PHYS_BASE) >> 2] ==
AM33XX_PRUSS_INTC_REV)
return PRUSS_V2;
else
return -1;
}
}
void __prussintc_set_cmr(unsigned int *pruintc_io, unsigned short sysevt,
unsigned short channel)
{
pruintc_io[(PRU_INTC_CMR1_REG + (sysevt & ~(0x3))) >> 2] |=
((channel & 0xF) << ((sysevt & 0x3) << 3));
}
void __prussintc_set_hmr(unsigned int *pruintc_io, unsigned short channel,
unsigned short host)
{
pruintc_io[(PRU_INTC_HMR1_REG + (channel & ~(0x3))) >> 2] =
pruintc_io[(PRU_INTC_HMR1_REG +
(channel & ~(0x3))) >> 2] | (((host) & 0xF) <<
(((channel) & 0x3) << 3));
}
================================================
FILE: am335x/app_loader/interface/prussdrv.c
================================================
/*
* prussdrv.c
*
* User space driver for PRUSS
*
* Copyright (C) 2012 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.
*
*/
/*
* ============================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
#include <prussdrv.h>
#include "__prussdrv.h"
#include <pthread.h>
#define PRUSS_UIO_PRAM_PATH_LEN 128
#define PRUSS_UIO_PARAM_VAL_LEN 20
#define HEXA_DECIMAL_BASE 16
static tprussdrv prussdrv;
int __prussdrv_memmap_init(void)
{
int i, fd;
char hexstring[PRUSS_UIO_PARAM_VAL_LEN];
if (prussdrv.mmap_fd == 0) {
for (i = 0; i < NUM_PRU_HOSTIRQS; i++) {
if (prussdrv.fd[i])
break;
}
if (i == NUM_PRU_HOSTIRQS)
return -1;
else
prussdrv.mmap_fd = prussdrv.fd[i];
}
fd = open(PRUSS_UIO_DRV_PRUSS_BASE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.pruss_phys_base =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
fd = open(PRUSS_UIO_DRV_PRUSS_SIZE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.pruss_map_size =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
prussdrv.pru0_dataram_base =
mmap(0, prussdrv.pruss_map_size, PROT_READ | PROT_WRITE,
MAP_SHARED, prussdrv.mmap_fd, PRUSS_UIO_MAP_OFFSET_PRUSS);
prussdrv.version =
__pruss_detect_hw_version(prussdrv.pru0_dataram_base);
switch (prussdrv.version) {
case PRUSS_V1:
{
printf("AM18XX\n");
prussdrv.pru0_dataram_phy_base = AM18XX_DATARAM0_PHYS_BASE;
prussdrv.pru1_dataram_phy_base = AM18XX_DATARAM1_PHYS_BASE;
prussdrv.intc_phy_base = AM18XX_INTC_PHYS_BASE;
prussdrv.pru0_control_phy_base = AM18XX_PRU0CONTROL_PHYS_BASE;
prussdrv.pru0_debug_phy_base = AM18XX_PRU0DEBUG_PHYS_BASE;
prussdrv.pru1_control_phy_base = AM18XX_PRU1CONTROL_PHYS_BASE;
prussdrv.pru1_debug_phy_base = AM18XX_PRU1DEBUG_PHYS_BASE;
prussdrv.pru0_iram_phy_base = AM18XX_PRU0IRAM_PHYS_BASE;
prussdrv.pru1_iram_phy_base = AM18XX_PRU1IRAM_PHYS_BASE;
}
break;
case PRUSS_V2:
{
printf("AM33XX\n");
prussdrv.pru0_dataram_phy_base = AM33XX_DATARAM0_PHYS_BASE;
prussdrv.pru1_dataram_phy_base = AM33XX_DATARAM1_PHYS_BASE;
prussdrv.intc_phy_base = AM33XX_INTC_PHYS_BASE;
prussdrv.pru0_control_phy_base = AM33XX_PRU0CONTROL_PHYS_BASE;
prussdrv.pru0_debug_phy_base = AM33XX_PRU0DEBUG_PHYS_BASE;
prussdrv.pru1_control_phy_base = AM33XX_PRU1CONTROL_PHYS_BASE;
prussdrv.pru1_debug_phy_base = AM33XX_PRU1DEBUG_PHYS_BASE;
prussdrv.pru0_iram_phy_base = AM33XX_PRU0IRAM_PHYS_BASE;
prussdrv.pru1_iram_phy_base = AM33XX_PRU1IRAM_PHYS_BASE;
prussdrv.pruss_sharedram_phy_base =
AM33XX_PRUSS_SHAREDRAM_BASE;
prussdrv.pruss_cfg_phy_base = AM33XX_PRUSS_CFG_BASE;
prussdrv.pruss_uart_phy_base = AM33XX_PRUSS_UART_BASE;
prussdrv.pruss_iep_phy_base = AM33XX_PRUSS_IEP_BASE;
prussdrv.pruss_ecap_phy_base = AM33XX_PRUSS_ECAP_BASE;
prussdrv.pruss_miirt_phy_base = AM33XX_PRUSS_MIIRT_BASE;
prussdrv.pruss_mdio_phy_base = AM33XX_PRUSS_MDIO_BASE;
}
break;
default:
printf("UNKNOWN\n");
}
prussdrv.pru1_dataram_base =
prussdrv.pru0_dataram_base + prussdrv.pru1_dataram_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.intc_base =
prussdrv.pru0_dataram_base + prussdrv.intc_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru0_control_base =
prussdrv.pru0_dataram_base + prussdrv.pru0_control_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru0_debug_base =
prussdrv.pru0_dataram_base + prussdrv.pru0_debug_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru1_control_base =
prussdrv.pru0_dataram_base + prussdrv.pru1_control_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru1_debug_base =
prussdrv.pru0_dataram_base + prussdrv.pru1_debug_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru0_iram_base =
prussdrv.pru0_dataram_base + prussdrv.pru0_iram_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pru1_iram_base =
prussdrv.pru0_dataram_base + prussdrv.pru1_iram_phy_base -
prussdrv.pru0_dataram_phy_base;
if (prussdrv.version == PRUSS_V2) {
prussdrv.pruss_sharedram_base =
prussdrv.pru0_dataram_base +
prussdrv.pruss_sharedram_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_cfg_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_cfg_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_uart_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_uart_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_iep_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_iep_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_ecap_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_ecap_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_miirt_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_miirt_phy_base -
prussdrv.pru0_dataram_phy_base;
prussdrv.pruss_mdio_base =
prussdrv.pru0_dataram_base + prussdrv.pruss_mdio_phy_base -
prussdrv.pru0_dataram_phy_base;
}
#ifndef DISABLE_L3RAM_SUPPORT
fd = open(PRUSS_UIO_DRV_L3RAM_BASE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.l3ram_phys_base =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
fd = open(PRUSS_UIO_DRV_L3RAM_SIZE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.l3ram_map_size =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
prussdrv.l3ram_base =
mmap(0, prussdrv.l3ram_map_size, PROT_READ | PROT_WRITE,
MAP_SHARED, prussdrv.mmap_fd, PRUSS_UIO_MAP_OFFSET_L3RAM);
#endif
fd = open(PRUSS_UIO_DRV_EXTRAM_BASE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.extram_phys_base =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
fd = open(PRUSS_UIO_DRV_EXTRAM_SIZE, O_RDONLY);
if (fd >= 0) {
read(fd, hexstring, PRUSS_UIO_PARAM_VAL_LEN);
prussdrv.extram_map_size =
strtoul(hexstring, NULL, HEXA_DECIMAL_BASE);
close(fd);
} else
return -1;
prussdrv.extram_base =
mmap(0, prussdrv.extram_map_size, PROT_READ | PROT_WRITE,
MAP_SHARED, prussdrv.mmap_fd, PRUSS_UIO_MAP_OFFSET_EXTRAM);
return 0;
}
int prussdrv_init(void)
{
memset(&prussdrv, 0, sizeof(prussdrv));
return 0;
}
int prussdrv_open(unsigned int pru_evtout_num)
{
char name[PRUSS_UIO_PRAM_PATH_LEN];
if (!prussdrv.fd[pru_evtout_num]) {
sprintf(name, "/dev/uio%d", pru_evtout_num);
prussdrv.fd[pru_evtout_num] = open(name, O_RDWR | O_SYNC);
return __prussdrv_memmap_init();
} else {
return -1;
}
}
int prussdrv_pru_reset(unsigned int prunum)
{
unsigned int *prucontrolregs;
if (prunum == 0)
prucontrolregs = (unsigned int *) prussdrv.pru0_control_base;
else if (prunum == 1)
prucontrolregs = (unsigned int *) prussdrv.pru1_control_base;
else
return -1;
*prucontrolregs = 0;
return 0;
}
int prussdrv_pru_enable(unsigned int prunum)
{
unsigned int *prucontrolregs;
if (prunum == 0)
prucontrolregs = (unsigned int *) prussdrv.pru0_control_base;
else if (prunum == 1)
prucontrolregs = (unsigned int *) prussdrv.pru1_control_base;
else
return -1;
*prucontrolregs = 2;
return 0;
}
int prussdrv_pru_disable(unsigned int prunum)
{
unsigned int *prucontrolregs;
if (prunum == 0)
prucontrolregs = (unsigned int *) prussdrv.pru0_control_base;
else if (prunum == 1)
prucontrolregs = (unsigned int *) prussdrv.pru1_control_base;
else
return -1;
*prucontrolregs = 1;
return 0;
}
int prussdrv_pru_write_memory(unsigned int pru_ram_id,
unsigned int wordoffset,
unsigned int *memarea,
unsigned int bytelength)
{
unsigned int *pruramarea, i, wordlength;
switch (pru_ram_id) {
case PRUSS0_PRU0_IRAM:
pruramarea = (unsigned int *) prussdrv.pru0_iram_base;
break;
case PRUSS0_PRU1_IRAM:
pruramarea = (unsigned int *) prussdrv.pru1_iram_base;
break;
case PRUSS0_PRU0_DATARAM:
pruramarea = (unsigned int *) prussdrv.pru0_dataram_base;
break;
case PRUSS0_PRU1_DATARAM:
pruramarea = (unsigned int *) prussdrv.pru1_dataram_base;
break;
case PRUSS0_SHARED_DATARAM:
if (prussdrv.version != PRUSS_V2)
return -1;
pruramarea = (unsigned int *) prussdrv.pruss_sharedram_base;
break;
default:
return -1;
}
wordlength = (bytelength + 3) >> 2; //Adjust length as multiple of 4 bytes
for (i = 0; i < wordlength; i++) {
*(pruramarea + i + wordoffset) = *(memarea + i);
}
return wordlength;
}
int prussdrv_pruintc_init(tpruss_intc_initdata * prussintc_init_data)
{
unsigned int *pruintc_io = (unsigned int *) prussdrv.intc_base;
unsigned int i, mask1, mask2;
pruintc_io[PRU_INTC_SIPR1_REG >> 2] = 0xFFFFFFFF;
pruintc_io[PRU_INTC_SIPR2_REG >> 2] = 0xFFFFFFFF;
for (i = 0; i < (NUM_PRU_SYS_EVTS + 3) >> 2; i++)
pruintc_io[(PRU_INTC_CMR1_REG >> 2) + i] = 0;
for (i = 0;
((prussintc_init_data->sysevt_to_channel_map[i].sysevt != -1)
&& (prussintc_init_data->sysevt_to_channel_map[i].channel !=
-1)); i++) {
__prussintc_set_cmr(pruintc_io,
prussintc_init_data->sysevt_to_channel_map[i].
sysevt,
prussintc_init_data->sysevt_to_channel_map[i].
channel);
}
for (i = 0; i < (NUM_PRU_HOSTS + 3) >> 2; i++)
pruintc_io[(PRU_INTC_HMR1_REG >> 2) + i] = 0;
for (i = 0;
((prussintc_init_data->channel_to_host_map[i].channel != -1)
&& (prussintc_init_data->channel_to_host_map[i].host != -1));
i++) {
__prussintc_set_hmr(pruintc_io,
prussintc_init_data->channel_to_host_map[i].
channel,
prussintc_init_data->channel_to_host_map[i].
host);
}
pruintc_io[PRU_INTC_SITR1_REG >> 2] = 0x0;
pruintc_io[PRU_INTC_SITR2_REG >> 2] = 0x0;
mask1 = mask2 = 0;
for (i = 0; prussintc_init_data->sysevts_enabled[i] != 255; i++) {
if (prussintc_init_data->sysevts_enabled[i] < 32) {
mask1 =
mask1 + (1 << (prussintc_init_data->sysevts_enabled[i]));
} else if (prussintc_init_data->sysevts_enabled[i] < 64) {
mask2 =
mask2 +
(1 << (prussintc_init_data->sysevts_enabled[i] - 32));
} else {
printf("Error: SYS_EVT%d out of range\n",
prussintc_init_data->sysevts_enabled[i]);
return -1;
}
}
pruintc_io[PRU_INTC_ESR1_REG >> 2] = mask1;
pruintc_io[PRU_INTC_SECR1_REG >> 2] = mask1;
pruintc_io[PRU_INTC_ESR2_REG >> 2] = mask2;
pruintc_io[PRU_INTC_SECR2_REG >> 2] = mask2;
for (i = 0; i < MAX_HOSTS_SUPPORTED; i++)
if (prussintc_init_data->host_enable_bitmask & (1 << i)) {
pruintc_io[PRU_INTC_HIEISR_REG >> 2] = i;
}
pruintc_io[PRU_INTC_GER_REG >> 2] = 0x1;
return 0;
}
int prussdrv_pru_send_event(unsigned int eventnum)
{
unsigned int *pruintc_io = (unsigned int *) prussdrv.intc_base;
if (eventnum < 32)
pruintc_io[PRU_INTC_SRSR1_REG >> 2] = 1 << eventnum;
else
pruintc_io[PRU_INTC_SRSR2_REG >> 2] = 1 << (eventnum - 32);
return 0;
}
int prussdrv_pru_wait_event(unsigned int pru_evtout_num)
{
int event_count;
unsigned int *pruintc_io = (unsigned int *) prussdrv.intc_base;
read(prussdrv.fd[pru_evtout_num], &event_count, sizeof(int));
pruintc_io[PRU_INTC_HIEISR_REG >> 2] = pru_evtout_num+2;
return 0;
}
int prussdrv_pru_clear_event(unsigned int eventnum)
{
unsigned int *pruintc_io = (unsigned int *) prussdrv.intc_base;
if (eventnum < 32)
pruintc_io[PRU_INTC_SECR1_REG >> 2] = 1 << eventnum;
else
pruintc_io[PRU_INTC_SECR2_REG >> 2] = 1 << (eventnum - 32);
return 0;
}
int prussdrv_pru_send_wait_clear_event(unsigned int send_eventnum,
unsigned int pru_evtout_num,
unsigned int ack_eventnum)
{
prussdrv_pru_send_event(send_eventnum);
prussdrv_pru_wait_event(pru_evtout_num);
prussdrv_pru_clear_event(ack_eventnum);
return 0;
}
int prussdrv_map_l3mem(void **address)
{
*address = prussdrv.l3ram_base;
return 0;
}
int prussdrv_map_extmem(void **address)
{
*address = prussdrv.extram_base;
return 0;
}
int prussdrv_map_prumem(unsigned int pru_ram_id, void **address)
{
switch (pru_ram_id) {
case PRUSS0_PRU0_DATARAM:
*address = prussdrv.pru0_dataram_base;
break;
case PRUSS0_PRU1_DATARAM:
*address = prussdrv.pru1_dataram_base;
break;
case PRUSS0_SHARED_DATARAM:
if (prussdrv.version != PRUSS_V2)
return -1;
*address = prussdrv.pruss_sharedram_base;
break;
default:
*address = 0;
return -1;
}
return 0;
}
int prussdrv_map_peripheral_io(unsigned int per_id, void **address)
{
if (prussdrv.version != PRUSS_V2)
return -1;
switch (per_id) {
case PRUSS0_CFG:
*address = prussdrv.pruss_cfg_base;
break;
case PRUSS0_UART:
*address = prussdrv.pruss_uart_base;
break;
case PRUSS0_IEP:
*address = prussdrv.pruss_iep_base;
break;
case PRUSS0_ECAP:
*address = prussdrv.pruss_ecap_base;
break;
case PRUSS0_MII_RT:
*address = prussdrv.pruss_miirt_base;
break;
case PRUSS0_MDIO:
*address = prussdrv.pruss_mdio_base;
break;
default:
*address = 0;
return -1;
}
return 0;
}
unsigned int prussdrv_get_phys_addr(void *address)
{
unsigned int retaddr = 0;
if ((address >= prussdrv.pru0_dataram_base)
&& (address <
prussdrv.pru0_dataram_base + prussdrv.pruss_map_size)) {
retaddr =
((unsigned int) (address - prussdrv.pru0_dataram_base) +
prussdrv.pru0_dataram_phy_base);
} else if ((address >= prussdrv.l3ram_base)
&& (address <
prussdrv.l3ram_base + prussdrv.l3ram_map_size)) {
retaddr =
((unsigned int) (address - prussdrv.l3ram_base) +
prussdrv.l3ram_phys_base);
} else if ((address >= prussdrv.extram_base)
&& (address <
prussdrv.extram_base + prussdrv.extram_map_size)) {
retaddr =
((unsigned int) (address - prussdrv.extram_base) +
prussdrv.extram_phys_base);
}
return retaddr;
}
void *prussdrv_get_virt_addr(unsigned int phyaddr)
{
void *address = 0;
if ((phyaddr >= prussdrv.pru0_dataram_phy_base)
&& (phyaddr <
prussdrv.pru0_dataram_phy_base + prussdrv.pruss_map_size)) {
address =
(void *) ((unsigned int) prussdrv.pru0_dataram_base +
(phyaddr - prussdrv.pru0_dataram_phy_base));
} else if ((phyaddr >= prussdrv.l3ram_phys_base)
&& (phyaddr <
prussdrv.l3ram_phys_base + prussdrv.l3ram_map_size)) {
address =
(void *) ((unsigned int) prussdrv.l3ram_base +
(phyaddr - prussdrv.l3ram_phys_base));
} else if ((phyaddr >= prussdrv.extram_phys_base)
&& (phyaddr <
prussdrv.extram_phys_base + prussdrv.extram_map_size)) {
address =
(void *) ((unsigned int) prussdrv.extram_base +
(phyaddr - prussdrv.extram_phys_base));
}
return address;
}
int prussdrv_exit()
{
int i;
munmap(prussdrv.pru0_dataram_base, prussdrv.pruss_map_size);
munmap(prussdrv.l3ram_base, prussdrv.l3ram_map_size);
munmap(prussdrv.extram_base, prussdrv.extram_map_size);
for (i = 0; i < NUM_PRU_HOSTIRQS; i++) {
if (prussdrv.fd[i])
close(prussdrv.fd[i]);
if (prussdrv.irq_thread[i])
pthread_join(prussdrv.irq_thread[i], NULL);
}
return 0;
}
int prussdrv_exec_program(int prunum, char *filename)
{
FILE *fPtr;
unsigned char fileDataArray[PRUSS_MAX_IRAM_SIZE];
int fileSize = 0;
unsigned int pru_ram_id;
if (prunum == 0)
pru_ram_id = PRUSS0_PRU0_IRAM;
else if (prunum == 1)
pru_ram_id = PRUSS0_PRU1_IRAM;
else
return -1;
// Open an File from the hard drive
fPtr = fopen(filename, "rb");
if (fPtr == NULL) {
printf("File %s open failed\n", filename);
} else {
printf("File %s open passed\n", filename);
}
// Read file size
fseek(fPtr, 0, SEEK_END);
fileSize = ftell(fPtr);
if (fileSize == 0) {
printf("File read failed.. Closing program\n");
fclose(fPtr);
return -1;
}
fseek(fPtr, 0, SEEK_SET);
if (fileSize !=
fread((unsigned char *) fileDataArray, 1, fileSize, fPtr)) {
printf("WARNING: File Size mismatch\n");
}
fclose(fPtr);
// Make sure PRU sub system is first disabled/reset
prussdrv_pru_disable(prunum);
prussdrv_pru_write_memory(pru_ram_id, 0,
(unsigned int *) fileDataArray, fileSize);
prussdrv_pru_enable(prunum);
return 0;
}
int prussdrv_start_irqthread(unsigned int pru_evtout_num, int priority,
prussdrv_function_handler irqhandler)
{
pthread_attr_t pthread_attr;
struct sched_param sched_param;
pthread_attr_init(&pthread_attr);
if (priority != 0) {
pthread_attr_setinheritsched(&pthread_attr,
PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&pthread_attr, SCHED_FIFO);
sched_param.sched_priority = priority;
pthread_attr_setschedparam(&pthread_attr, &sched_param);
}
pthread_create(&prussdrv.irq_thread[pru_evtout_num], &pthread_attr,
irqhandler, NULL);
pthread_attr_destroy(&pthread_attr);
return 0;
}
================================================
FILE: am335x/pasm/LICENCE.txt
================================================
/*
* {module name}
*
* {module description}
*
* Copyright (C) {YEAR} 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.
*
*/
================================================
FILE: am335x/pasm/Makefile
================================================
# Builds with whatever the host format is
CC := gcc
CFLAGS += \
-O3 \
-W \
-Wall \
-D_UNIX_ \
OBJS := \
pasm.o \
pasmpp.o \
pasmexp.o \
pasmop.o \
pasmdot.o \
pasmstruct.o \
pasmmacro.o \
all: pasm
pasm: $(OBJS)
$(CC) -o $@ $^
clean:
$(RM) -f *.o
================================================
FILE: am335x/pasm/pasm.c
================================================
/*
* pasm.c
*
* Copyright (C) 2012 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.
*
*/
/*===========================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
/*===========================================================================
// PASM - PRU Assembler
//---------------------------------------------------------------------------
//
// File : pasm.c
//
// Description:
// Main assembler control program.
// - Processes command line and flags
// - Runs the main assembler engine (dual pass)
// - Handles error reporting
// - Handles label creation and matching
// - Handle output file generation
//
//---------------------------------------------------------------------------
// Revision:
// 21-Jun-13: 0.84 - Open source version
============================================================================*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#if !defined(__APPLE__)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <ctype.h>
#include "pasm.h"
#include "pasmdbg.h"
/*
// Multiple Core Revision Support
// ------------------------------
//
// -V0 PRU Legacy (same as -x)
// -V1 PRU Generation 1 (default)
// Adds [LMBD,SCAN,HALT,ZERO(1),MVI(1),SLP(1)] Removes [LFC,STC]
// -V2 PRU Generation 2 (same as -X)
// Adds [ZERO(2),FILL,XIN,XOUT,XCHG,MVI(2)] Removes [SCAN]
// -V3 PRU Generation 3
// Adds [SLP(2),LOOP,ILOOP,SXIN,SXOUT,SXCHG,NOPx]
//
// ZERO(1) : Zero is multi-cycle pseudo op encoded via moves
// ZERO(2) : Zero is single-cycle pseudo op encoded via XFR
//
// MVI(1) : Pseudo op forms of MVI only
// MVI(2) : Pseudo op forms of MVI only
//
// SLP(1) : SLP with trailing NOP
// SLP(2) : SLP without trailing NOP
*/
/* ---------- Local Macro Definitions ----------- */
#define PROCESSOR_NAME_STRING ("PRU")
#define VERSION_STRING ("0.84")
#define MAXFILE (256) /* Max file length for output files */
#define MAX_PROGRAM (16384) /* Max instruction count */
#define MAX_CMD_EQUATE (8) /* Max equates that can be put on command line */
#define RET_ERROR (1)
#define RET_SUCCESS (0)
/* Big/Little Endian Conversions */
#define HNC16(a) ((((a)>>8)&0xff)+(((a)<<8)&0xff00))
#define HNC32(a) ((((a)>>24)&0xff)+(((a)>>8)&0xff00)+(((a)<<8)&0xff0000)+(((a)<<24)&0xff000000))
/* User Options */
unsigned int Options = 0;
unsigned int Core = CORE_NONE;
FILE *ListingFile = 0;
/* Assembler Engine */
int Pass; /* Pass 1 or 2 of parser */
int HaveEntry; /* Entrypont flag (init to 0) */
int EntryPoint; /* Entrypont (init to -1) */
int CodeOffset; /* Current instruction "word" offset (zero based) */
int Errors; /* Total number or errors */
int FatalError; /* Set on fatal error */
int Warnings; /* Total number of warnings */
uint RetRegValue; /* Return register index */
uint RetRegField; /* Return register field */
LABEL *pLabelList=0; /* List of installed labels */
int LabelCount=0;
CODEGEN ProgramImage[MAX_PROGRAM];
SOURCEFILE cmdLine = { 0, 0, 0, 0, 0, 0, 0, 0, "[CommandLine]", "" };
char cmdLineName[MAX_CMD_EQUATE][EQUATE_NAME_LEN];
char cmdLineData[MAX_CMD_EQUATE][EQUATE_DATA_LEN];
int cmdLineEquates = 0;
char nameCArray[EQUATE_DATA_LEN];
int nameCArraySet = 0;
/* Local Support Funtions */
static int ValidateOffset( SOURCEFILE *ps );
static int PrintLine( FILE *pfOut, SOURCEFILE *ps );
static int GetInfoFromAddr( uint address, uint *pIndex, uint *pLineNo, uint *pCodeWord );
static int ListFile( FILE *pfOut, SOURCEFILE *ps );
/*
// Main Assembler Entry Point
//
*/
int main(int argc, char *argv[])
{
int i,j;
int CodeOffsetPass1 = 0;
char *infile, *outfile, *flags;
SOURCEFILE *mainsource;
char outbase[MAXFILE],outfilename[MAXFILE];
printf("\n\n%s Assembler Version %s\n",PROCESSOR_NAME_STRING, VERSION_STRING);
printf("Copyright (C) 2005-2013 by Texas Instruments Inc.\n\n");
/* Scan argv[0] to the final '/' in program name */
i=0;
j=-1;
while( argv[0][i] )
{
if( argv[0][i] == '/' || argv[0][i] == '\\')
j=i;
i++;
}
argv[0]+=(j+1);
/*
// Process command line
*/
infile=0;
flags=0;
outfile=0;
if( argc<2 )
{
USAGE:
printf("Usage: %s [-V#EBbcmLldz] [-Dname=value] [-Cname] InFile [OutFileBase]\n\n",argv[0]);
printf(" V# - Specify core version (V0,V1,V2,V3). (Default is V1)\n");
printf(" E - Assemble for big endian core\n");
printf(" B - Create big endian binary output (*.bib)\n");
printf(" b - Create little endian binary output (*.bin)\n");
printf(" c - Create 'C array' binary output (*_bin.h)\n");
printf(" m - Create 'image' binary output (*.img)\n");
printf(" L - Create annotated source file style listing (*.txt)\n");
printf(" l - Create raw listing file (*.lst)\n");
printf(" d - Create pView debug file (*.dbg)\n");
printf(" z - Enable debug messages\n");
printf("\n D - Set equate 'name' to 1 using '-Dname', or to any\n");
printf(" value using '-Dname=value'\n");
printf(" C - Name the C array in 'C array' binary output\n");
printf(" to 'name' using '-Cname'\n");
printf("\n");
return(RET_ERROR);
}
/* Get all non-flag arguments */
for( i=1; i<argc; i++ )
{
if( argv[i][0] != '-' )
{
if( !infile )
infile = argv[i];
else if( !outfile )
outfile = argv[i];
else
goto USAGE;
}
}
/* Get all flag arguments */
for( i=1; i<argc; i++ )
{
if( argv[i][0] == '-' )
{
flags = argv[i];
flags++;
while( *flags )
{
if( *flags == 'D' )
{
flags++;
if( cmdLineEquates==MAX_CMD_EQUATE )
{
printf("\nToo many command line equates\n\n");
goto USAGE;
}
j=0;
while( j<EQUATE_NAME_LEN && *flags && *flags!='=' )
cmdLineName[cmdLineEquates][j++]=*flags++;
if( j==EQUATE_NAME_LEN )
{
printf("\nCommand line equate name too long\n\n");
goto USAGE;
}
strcpy( cmdLineData[cmdLineEquates], "1" );
if( *flags=='=' )
{
flags++;
j=0;
while( j<EQUATE_DATA_LEN && *flags )
cmdLineData[cmdLineEquates][j++]=*flags++;
if( j==EQUATE_DATA_LEN )
{
printf("\nCommand line equate data too long\n\n");
goto USAGE;
}
}
cmdLineEquates++;
break;
}
else if( *flags == 'C' )
{
flags++;
j = 0;
while( j<EQUATE_DATA_LEN && *flags )
{
nameCArray[j++]=*flags++;
}
if( j==EQUATE_DATA_LEN )
{
printf("\nCArray name too long\n\n");
goto USAGE;
}
nameCArraySet = 1;
break;
}
else if( *flags == 'V' )
{
flags++;
if( *flags<'0' || *flags>'3' )
{
printf("\nExpected a number (0-3) after option 'V'\n\n");
goto USAGE;
}
if( Core != CORE_NONE )
{
printf("\nDo not specify more than one core version or use -V with -X or -x\n\n");
goto USAGE;
}
Core = CORE_V0 + *flags - '0';
}
else if( *flags == 'x' )
{
if( Core != CORE_NONE )
{
printf("\nDo not use -x with -X or -V\n\n");
goto USAGE;
}
Core = CORE_V0;
}
else if( *flags == 'X' )
{
if( Core != CORE_NONE )
{
printf("\nDo not use -X with -x or -V\n\n");
goto USAGE;
}
Core = CORE_V2;
}
else if( *flags == 'E' )
Options |= OPTION_BIGENDIAN;
else if( *flags == 'b' )
Options |= OPTION_BINARY;
else if( *flags == 'B' )
Options |= OPTION_BINARYBIG;
else if( *flags == 'c' )
Options |= OPTION_CARRAY;
else if( *flags == 'm' )
Options |= OPTION_IMGFILE;
else if( *flags == 'l' )
Options |= OPTION_LISTING;
else if( *flags == 'L' )
Options |= OPTION_SOURCELISTING;
else if( *flags == 'd' )
Options |= OPTION_DBGFILE;
else if( *flags == 'z' )
Options |= OPTION_DEBUG;
else
{
printf("\nUnknown flag '%c'\n\n",*flags);
goto USAGE;
}
flags++;
}
}
}
if( Core==CORE_NONE )
Core = CORE_V1;
/* Check input file */
if( !infile )
goto USAGE;
/* Check output file base - make sure no '.' */
if( outfile )
{
if( strlen(outfile) > (MAXFILE-5) )
{ Report(0,REP_ERROR,"Outfile name too long"); return(RET_ERROR); }
i=0;
while( outfile[i] )
{
if( outfile[i]=='.' )
{
if( outfile[i+1]=='.' )
i++;
else
{ Report(0,REP_ERROR,"Outfile should be basename only - no '.'"); return(RET_ERROR); }
}
i++;
}
strcpy( outbase, outfile );
}
/* Test opening the main source file */
if( !(mainsource=InitSourceFile(0,infile)) )
return(RET_ERROR);
/* Setup outfile base */
if( !outfile )
{
for(i=0; mainsource->SourceName[i] && mainsource->SourceName[i]!='.'; i++ )
outbase[i]=mainsource->SourceName[i];
outbase[i] = 0;
}
if( Options & OPTION_DEBUG )
printf("Output base filename: '%s'\n",outbase);
/* Close the source file for now */
CloseSourceFile( mainsource );
/* If no output specified, default to 'C' array */
if( !(Options & (OPTION_BINARY|OPTION_CARRAY|OPTION_BINARYBIG|OPTION_IMGFILE|OPTION_DBGFILE)) )
{
printf("Note: Using default output '-c' (C array *_bin.h)\n\n");
Options |= OPTION_CARRAY;
}
/* Open listing file */
if( Options & OPTION_LISTING )
{
strcpy( outfilename, outbase );
strcat( outfilename, ".lst" );
if (!(ListingFile = fopen(outfilename,"wb")))
{ Report(0,REP_ERROR,"Unable to open output file: %s",outfilename); return(RET_ERROR); }
}
/* Clear the binary image */
memset( ProgramImage, 0, sizeof(ProgramImage) );
/* Make 2 assembler passes */
Pass = 0;
Errors = 0;
Warnings = 0;
FatalError = 0;
RetRegValue = DEFAULT_RETREGVAL;
RetRegField = DEFAULT_RETREGFLD;
while( !Errors && Pass<2 )
{
Pass++;
CodeOffset = -1;
HaveEntry = 0;
EntryPoint = -1;
/* Initialize the PP and DOT modules */
for(i=0; i<cmdLineEquates; i++ )
EquateCreate( &cmdLine, cmdLineName[i], cmdLineData[i] );
DotInitialize(Pass);
/* Process the main source file */
if( !(mainsource=InitSourceFile(0,infile)) )
break;
ProcessSourceFile( mainsource );
CloseSourceFile( mainsource );
/* Cleanup the PP and DOT modules */
ppCleanup(Pass);
DotCleanup(Pass);
if( Pass==1 )
{
CodeOffsetPass1 = CodeOffset;
}
}
/* Close the listing file */
if( ListingFile )
fclose( ListingFile );
/* Make sure user didn't do something silly */
if( CodeOffsetPass1!=CodeOffset )
{
printf("Error: Offset changed between pass 1 and pass 2\n");
Errors++;
}
/* Process the results */
printf("\nPass %d : %d Error(s), %d Warning(s)\n\n",Pass,Errors,Warnings);
if( Errors || CodeOffset<=0 )
Options = 0;
else
printf("Writing Code Image of %d word(s)\n\n",CodeOffset);
/* Create the output files */
if( Options & OPTION_CARRAY )
{
FILE *Outfile;
strcpy( outfilename, outbase );
strcat( outfilename, "_bin.h" );
if (!(Outfile = fopen(outfilename,"wb")))
Report(0,REP_ERROR,"Unable to open output file: %s",outfilename);
else
{
fprintf( Outfile, "\n\n"
"/* This file contains the %s instructions in a C array which are to */\n"
"/* be downloaded from the host CPU to the %s instruction memory. */\n"
"/* This file is generated by the %s assembler. */\n",
PROCESSOR_NAME_STRING, PROCESSOR_NAME_STRING, PROCESSOR_NAME_STRING);
if( !nameCArraySet )
fprintf(Outfile,"\nconst unsigned int %scode[] = {\n",PROCESSOR_NAME_STRING);
else
fprintf(Outfile,"\nconst unsigned int %s[] = {\n",nameCArray);
for(i=0;i<(CodeOffset-1);i++)
fprintf(Outfile," 0x%08x,\n",ProgramImage[i].CodeWord);
fprintf(Outfile," 0x%08x };\n\n",ProgramImage[CodeOffset-1].CodeWord);
fclose( Outfile );
}
}
if( Options & OPTION_IMGFILE )
{
FILE *Outfile;
strcpy( outfilename, outbase );
strcat( outfilename, ".img" );
if (!(Outfile = fopen(outfilename,"wb")))
Report(0,REP_ERROR,"Unable to open output file: %s",outfilename);
else
{
for(i=0;i<CodeOffset;i++)
fprintf(Outfile,"%08x\n",ProgramImage[i].CodeWord);
fclose( Outfile );
}
}
if( Options & OPTION_DBGFILE )
{
FILE *Outfile;
uint BigEndian;
BigEndian = 0;
*(unsigned char *)&BigEndian = 1;
if( BigEndian != 1 )
BigEndian = 1;
else
BigEndian = 0;
strcpy( outfilename, outbase );
strcat( outfilename, ".dbg" );
if (!(Outfile = fopen(outfilename,"wb")))
Report(0,REP_ERROR,"Unable to open output file: %s",outfilename);
else
{
DBGFILE_HEADER hdr;
DBGFILE_HEADER hdr_write;
DBGFILE_LABEL lbl;
DBGFILE_FILE file;
DBGFILE_CODE code;
LABEL *pLabel;
unsigned int file_offset;
int i;
memset( &hdr, 0, sizeof(DBGFILE_HEADER) );
hdr.FileID = DBGFILE_FILEID_VER3;
file_offset = sizeof(DBGFILE_HEADER);
hdr.LabelCount = LabelCount;
hdr.LabelOffset = file_offset;
file_offset += hdr.LabelCount * sizeof(DBGFILE_LABEL);
hdr.FileCount = sfIndex;
hdr.FileOffset = file_offset;
file_offset += hdr.FileCount * sizeof(DBGFILE_FILE);
hdr.CodeCount = CodeOffset;
hdr.CodeOffset = file_offset;
hdr.EntryPoint = EntryPoint;
if( Options & OPTION_BIGENDIAN )
hdr.Flags |= DBGHDR_FLAGS_BIGENDIAN;
if(!BigEndian)
hdr_write = hdr;
else
{
hdr_write.FileID = HNC32(hdr.FileID);
hdr_write.LabelCount = HNC32(hdr.LabelCount);
hdr_write.LabelOffset = HNC32(hdr.LabelOffset);
hdr_write.FileCount = HNC32(hdr.FileCount);
hdr_write.FileOffset = HNC32(hdr.FileOffset);
hdr_write.CodeCount = HNC32(hdr.CodeCount);
hdr_write.CodeOffset = HNC32(hdr.CodeOffset);
hdr_write.EntryPoint = HNC32(hdr.EntryPoint);
hdr_write.Flags = HNC32(hdr.Flags);
}
if( fwrite(&hdr_write,1,sizeof(DBGFILE_HEADER),Outfile) != sizeof(DBGFILE_HEADER) )
Report(0,REP_ERROR,"File write error");
pLabel = pLabelList;
for( i=0; i<(int)hdr.LabelCount; i++ )
{
memset( &lbl, 0, sizeof(DBGFILE_LABEL) );
if( !pLabel )
Report(0,REP_ERROR,"Fatal label tracking error");
else
{
lbl.AddrOffset = pLabel->Offset;
strcpy(lbl.Name,pLabel->Name);
if(BigEndian)
lbl.AddrOffset = HNC32(lbl.AddrOffset);
if( fwrite(&lbl,1,sizeof(DBGFILE_LABEL),Outfile) != sizeof(DBGFILE_LABEL) )
Report(0,REP_ERROR,"File write error");
pLabel = pLabel->pNext;
}
}
for(i=0; i<(int)hdr.FileCount; i++)
{
memset( &file, 0, sizeof(DBGFILE_FILE) );
if( !strcmp( sfArray[i].SourceBaseDir,"./") ||
((strlen(sfArray[i].SourceName)+strlen(sfArray[i].SourceBaseDir)) >= DBGFILE_NAMELEN_SHORT) )
strcpy(file.SourceName,sfArray[i].SourceName);
else
{
strcpy(file.SourceName,sfArray[i].SourceBaseDir);
strcat(file.SourceName,sfArray[i].SourceName);
}
if( fwrite(&file,1,sizeof(DBGFILE_FILE),Outfile) != sizeof(DBGFILE_FILE) )
Report(0,REP_ERROR,"File write error");
}
for(i=0; i<(int)hdr.CodeCount; i++)
{
memset( &code, 0, sizeof(DBGFILE_CODE) );
code.Flags = ProgramImage[i].Flags;
code.Resv8 = ProgramImage[i].Resv8;
code.FileIndex = ProgramImage[i].FileIndex;
code.Line = ProgramImage[i].Line;
code.AddrOffset = ProgramImage[i].AddrOffset;
code.CodeWord = ProgramImage[i].CodeWord;
if(BigEndian)
{
code.FileIndex = HNC16(code.FileIndex);
code.Line = HNC32(code.Line);
code.AddrOffset = HNC32(code.AddrOffset);
code.CodeWord = HNC32(code.CodeWord);
}
if( fwrite(&code,1,sizeof(DBGFILE_CODE),Outfile) != sizeof(DBGFILE_CODE) )
Report(0,REP_ERROR,"File write error");
}
fclose( Outfile );
}
}
if( Options & OPTION_SOURCELISTING )
{
FILE *Outfile;
strcpy( outfilename, outbase );
strcat( outfilename, ".txt" );
if (!(Outfile = fopen(outfilename,"wb")))
Report(0,REP_ERROR,"Unable to open output file: %s",outfilename);
else
{
char FullPath[SOURCE_BASE_DIR+SOURCE_NAME];
for( i=0; i<(int)sfIndex; i++ )
{
fprintf(Outfile, "Source File %d : '%s' ", i+1, sfArray[i].SourceName);
strcpy(FullPath,sfArray[i].SourceBaseDir);
strcat(FullPath,sfArray[i].SourceName);
sfArray[i].FilePtr=fopen(FullPath,"rb");
if( sfArray[i].FilePtr!=0 )
{
sfArray[i].CurrentLine = 1;
sfArray[i].CurrentColumn = 1;
sfArray[i].LastChar = 0;
ListFile(Outfile,&sfArray[i]);
fclose(sfArray[i].FilePtr);
fprintf(Outfile, "\n\n");
}
else
fprintf(Outfile, "(File Not Found '%s')\n\n",FullPath);
}
fclose(Outfile);
}
}
if( Options & OPTION_BINARY )
{
FILE *Outfile;
strcpy( outfilename, outbase );
strcat( outfilename, ".bin" );
if (!(Outfile = fopen(outfilename,"wb")))
Report(0,REP_ERROR,"Unable to open output file: %s",outfilename);
else
{
unsigned char tmp;
/* Write out as Little Endian */
for(i=0;i<CodeOffset;i++)
{
tmp = (unsigned char)ProgramImage[i].CodeWord;
fwrite(&tmp,1,1,Outfile);
tmp = (unsigned char)(ProgramImage[i].CodeWord>>8);
fwrite(&tmp,1,1,Outfile);
tmp = (unsigned char)(ProgramImage[i].CodeWord>>16);
fwrite(&tmp,1,1,Outfile);
tmp = (unsigned char)(ProgramImage[i].CodeWord>>24);
fwrite(&tmp,1,1,Outfile);
}
fclose( Outfile );
}
}
if( Options & OPTION_BINARYBIG )
{
FILE *Outfile;
strcpy( outfilename, outbase );
strcat( outfilename, ".bib" );
if (!(Outfile = fopen(outfilename,"wb")))
Report(0,REP_ERROR,"Unable to open output file: %s",outfilename);
else
{
unsigned char tmp;
/* Write out as Big Endian */
for(i=0;i<CodeOffset;i++)
{
tmp = (unsigned char)(ProgramImage[i].CodeWord>>24);
fwrite(&tmp,1,1,Outfile);
tmp = (unsigned char)(ProgramImage[i].CodeWord>>16);
fwrite(&tmp,1,1,Outfile);
tmp = (unsigned char)(ProgramImage[i].CodeWord>>8);
fwrite(&tmp,1,1,Outfile);
tmp = (unsigned char)ProgramImage[i].CodeWord;
fwrite(&tmp,1,1,Outfile);
}
fclose( Outfile );
}
}
/* Assember label cleanup */
while( pLabelList )
LabelDestroy( pLabelList );
if( Errors || CodeOffset<=0 )
return(RET_ERROR);
return(RET_SUCCESS);
}
/*
// ProcessSourceFile
//
// New source file to assemble.
//
// Returns 1 on success, 0 on error
*/
#define MAX_SOURCE_LINE 256
int ProcessSourceFile( SOURCEFILE *ps )
{
char src[MAX_SOURCE_LINE];
int i;
for(;;)
{
/* Abort on a total disaster */
if( FatalError || Errors >= 25 )
{ printf("Aborting...\n"); return(0); }
/* Get a line of source code */
i = GetSourceLine( ps, src, MAX_SOURCE_LINE );
if( !i )
return(1);
if( i<0 )
continue;
if( !ProcessSourceLine(ps, i, src) && Pass==2 )
return(0);
}
}
/*
// ProcessSourceLine
//
// New source line to assemble.
//
// Returns 1 on success, 0 on error
*/
int ProcessSourceLine( SOURCEFILE *ps, int length, char *src )
{
char *pParams[MAX_TOKENS];
SRCLINE sl;
int i,rc;
REPEAT:
if( !ParseSourceLine(ps,length,src,&sl) )
return(0);
/* Process Label */
if( sl.Flags & SRC_FLG_LABEL )
{
/* Make sure offset is ready */
if( !ValidateOffset(ps) )
return(0);
/* Create Label */
if( Pass==1 )
{
LabelCreate(ps, sl.Label, CodeOffset);
}
/* Note it in listing file */
if( Pass==2 && (Options & OPTION_LISTING) )
{
fprintf(ListingFile,"%s(%5d) : 0x%04x = Label : %s:\n",
ps->SourceName,ps->CurrentLine,CodeOffset,sl.Label);
}
}
/* Process Command/Opcode */
if( sl.Terms )
{
/* Get the parameters into a collection of string pointers */
for(i=0; i<(int)sl.Terms; i++)
pParams[i]=sl.Term[i];
for( ; i<MAX_TOKENS; i++ )
pParams[i]=0;
/* Perform structure processing */
if (!CheckMacro(pParams[0]))
for(i=0; i<(int)sl.Terms; i++)
if( StructParamProcess(ps, i, pParams[i])<0 )
{ Report(ps,REP_ERROR,"Error in struct parsing parameter %d",i); return(0); }
/* Process a dot command */
if( sl.Flags & SRC_FLG_DOTCMD1 )
{
src[0] = 0;
rc = DotCommand(ps,sl.Terms,pParams,src,MAX_SOURCE_LINE);
if( rc<0 )
return(0);
if( !rc )
return(1);
/*
// The dot command generated new code, process it now
*/
goto REPEAT;
}
else
{
/* Process the macro or opcode */
if (CheckMacro(pParams[0]))
{
// Process Macros
if ( !ProcessMacro(ps, sl.Terms, pParams) )
return (0);
}
else
{
// Process Opcodes
if( !ProcessOp(ps, sl.Terms, pParams) )
{
GenOp( ps, sl.Terms, pParams, 0xFFFFFFFF );
return (0);
}
}
}
}
return(1);
}
/*
// ParseSourceLine
//
// New source line to parse.
//
// Returns 1 on success, 0 on error
*/
int ParseSourceLine( SOURCEFILE *ps, int length, char *src, SRCLINE *pa )
{
char c;
int srcIdx,wordIdx;
int parmCnt;
srcIdx = 0;
pa->Flags = 0;
pa->Terms = 0;
PROCESS_LINE:
/* Make sure character 1 is legal */
c = src[srcIdx++];
if( !LabelChar(c,1) && c!='.' )
{
Report(ps,REP_ERROR,"Syntax error in Cmd/Opcode");
return(0);
}
/* Get the Opcode or Command */
wordIdx = 0;
while( LabelChar(c,0) || c=='.' )
{
if( wordIdx>=(TOKEN_MAX_LEN-1) )
{ Report(ps,REP_ERROR,"Cmd/Opcode too long"); return(0); }
pa->Term[0][wordIdx++] = c;
c = src[srcIdx++];
}
pa->Term[0][wordIdx]=0;
/* See if it is a label */
if( c==':' )
{
if( pa->Flags & SRC_FLG_LABEL )
{ Report(ps,REP_ERROR,"Two labels found on the same line"); return(0); }
pa->Flags |= SRC_FLG_LABEL;
strcpy(pa->Label,pa->Term[0]);
/* Process any assembly after the label */
c = src[srcIdx];
if( c!=0 )
{
while( c==' ' || c==0x9 )
c = src[++srcIdx];
goto PROCESS_LINE;
}
return(1);
}
if( c!=' ' && c!=0 && c!=0x9 )
{
Report(ps,REP_ERROR,"Syntax error in Cmd/Opcode");
return(0);
}
/* Get up to "MAX_TOKENS-1" parameters (comma delimited) */
parmCnt=0;
while(c)
{
wordIdx=0;
parmCnt++;
if( parmCnt==MAX_TOKENS )
{ Report(ps,REP_ERROR,"Too many parameters on line"); return(0); }
/* Trim off leading white space */
while( c==' ' || c==0x9 )
c = src[srcIdx++];
if( !LabelChar(c,0) &&
c!='.' && c!='#' && c!='-' && c!='(' && c!='"' && c!='&' && c!='*' )
{ Report(ps,REP_ERROR,"Syntax error in parameter %d",parmCnt); return(0); }
if( parmCnt==1 && c=='.' )
{
while( c!=0 && c!=',' && c!=' ' && c!=0x9 )
{
if( wordIdx>=(TOKEN_MAX_LEN-1) )
{ Report(ps,REP_ERROR,"Parameter %d too long",parmCnt); return(0); }
pa->Term[parmCnt][wordIdx++] = c;
c = src[srcIdx++];
}
if(c==' ' || c==0x9)
c=',';
pa->Flags |= SRC_FLG_DOTCMD2;
}
else
{
while( c!=0 && c!=',' )
{
if( wordIdx>=(TOKEN_MAX_LEN-1) )
{ Report(ps,REP_ERROR,"Parameter %d too long",parmCnt); return(0); }
pa->Term[parmCnt][wordIdx++] = c;
c = src[srcIdx++];
}
}
pa->Term[parmCnt][wordIdx] = 0;
/* Trim off trailing white space */
while( wordIdx && (pa->Term[parmCnt][wordIdx-1]==0x9 || pa->Term[parmCnt][wordIdx-1]==' ') )
pa->Term[parmCnt][--wordIdx]=0;
/* This character must be a comma or NULL */
if( c==',' )
c = src[srcIdx++];
else if( c )
{ Report(ps,REP_ERROR,"Syntax error in parameter %d",parmCnt); return(0); }
}
parmCnt++;
pa->Terms = parmCnt;
/* If its a dot command, mark it */
if( pa->Term[0][0]=='.' )
pa->Flags |= SRC_FLG_DOTCMD1;
return(1);
}
/*
// GenOp
//
// Generate an opcode to the ouput file
//
// ps - Pointer to source file record
// TermCnt - Number of terms (including the command)
// pTerms - Pointer to the terms
// opcode - Generated Opcode
*/
void GenOp( SOURCEFILE *ps, int TermCnt, char **pTerms, uint opcode )
{
int i;
if( !ValidateOffset(ps) )
return;
if( (Options & OPTION_LISTING) && Pass==2 )
{
fprintf(ListingFile,"%s(%5d) : 0x%04x = 0x%08x : ",
ps->SourceName,ps->CurrentLine,CodeOffset,opcode);
fprintf(ListingFile,"%-8s ",pTerms[0]);
for(i=1; i<TermCnt; i++)
{
if( i>1 )
fprintf(ListingFile,", %s",pTerms[i]);
else
fprintf(ListingFile,"%s",pTerms[i]);
}
if( opcode==0xFFFFFFFF )
fprintf(ListingFile," // *** ERROR ***");
fprintf(ListingFile,"\n");
}
ProgramImage[CodeOffset].Flags = CODEGEN_FLG_FILEINFO|CODEGEN_FLG_CANMAP;
ProgramImage[CodeOffset].FileIndex = ps->FileIndex;
ProgramImage[CodeOffset].Line = ps->CurrentLine;
ProgramImage[CodeOffset].AddrOffset = CodeOffset;
ProgramImage[CodeOffset++].CodeWord = opcode;
}
/*
// Report
//
// Report an abnormal condition
*/
void Report( SOURCEFILE *ps, int Level, char *fmt, ... )
{
va_list arg_ptr;
if( Pass==1 && Level==REP_WARN2 )
return;
if( Pass==2 && (Level==REP_INFO || Level==REP_WARN1) )
return;
/* Log to stdout */
if( ps )
printf("%s(%d) ",ps->SourceName,ps->CurrentLine);
if( Level == REP_FATAL )
{
printf("Fatal Error: ");
FatalError=1;
Errors++;
}
else if( Level == REP_ERROR )
{
printf("Error: ");
Errors++;
}
else if( Level==REP_WARN1 || Level==REP_WARN2 )
{
printf("Warning: ");
Warnings++;
}
else
printf("Note: ");
va_start( arg_ptr, fmt );
vprintf( fmt, arg_ptr );
va_end( arg_ptr );
if( !ps )
printf("\n");
printf("\n");
}
/*
// LabelChar
//
// Return whether the character is legal for a label.
// Numbers are not allowed when FlagFirstChar is set.
//
// Returns 1 on success, 0 on error
*/
int LabelChar( char c, int FlagFirstChar )
{
if( FlagFirstChar )
{
if( (c>='A'&&c<='Z')||(c>='a'&&c<='z')||(c=='_') )
return(1);
else
return(0);
}
if( (c>='A'&&c<='Z')||(c>='a'&&c<='z')||(c>='0'&&c<='9')||(c=='_'))
return(1);
else
return(0);
}
/*
// LabelCreate
//
// Create a label with the supplied offset value
//
// Returns 1 on success, 0 on error
*/
int LabelCreate( SOURCEFILE *ps, char *label, int value )
{
LABEL *pl;
if( strlen(label) >= LABEL_NAME_LEN )
{ Report(ps,REP_ERROR,"Label too long"); return(0); }
/* Make sure this name is OK to use */
if( !CheckName(ps,label) )
return(0);
/* Allocate a new record */
pl = malloc(sizeof(LABEL));
if( !pl )
{ Report(ps,REP_FATAL,"Memory allocation failed"); return(0); }
strcpy( pl->Name, label );
pl->Offset = value;
/* Put this label in the master list */
pl->pPrev = 0;
pl->pNext = pLabelList;
if( pLabelList )
pLabelList->pPrev = pl;
pLabelList = pl;
LabelCount++;
if( (Options & OPTION_DEBUG) )
printf("%s(%5d) : LABEL : '%s' = %05d\n", ps->SourceName,ps->CurrentLine,label,value);
return(1);
}
/*
// LabelFind
//
// Searches for an equate by name. If found, returns the record pointer.
//
// Returns LABEL * on success, 0 on error
*/
LABEL *LabelFind( char *name )
{
LABEL *pl;
pl = pLabelList;
while( pl )
{
if( !strcmp( name, pl->Name ) )
break;
pl = pl->pNext;
}
return(pl);
}
/*
// LabelDestroy
//
// Frees and label record.
//
// void
*/
void LabelDestroy( LABEL *pl )
{
if( !pl->pPrev )
pLabelList = pl->pNext;
else
pl->pPrev->pNext = pl->pNext;
if( pl->pNext )
pl->pNext->pPrev = pl->pPrev;
LabelCount--;
free(pl);
}
/*
// Check Name
//
// Returns 1 if the name is free, or 0 if it is in use
*/
int CheckName( SOURCEFILE *ps, char *name )
{
/* Make sure its not a reserved word */
if( CheckTokenType(name)!=TOKENTYPE_UNRESERVED )
{ Report(ps,REP_ERROR,"Illegal use of reserved word '%s'",name); return(0); }
if( LabelFind(name) )
{ Report(ps,REP_ERROR,"'%s' is already a label",name); return(0); }
if( CheckEquate(name) )
{ Report(ps,REP_ERROR,"'%s' is already an equate",name); return(0); }
if( CheckStruct(name) )
{ Report(ps,REP_ERROR,"'%s' is already a structure or scope",name); return(0); }
if( CheckMacro(name) )
{ Report(ps,REP_ERROR,"'%s' is already a macro",name); return(0); }
return(1);
}
/*===================================================================
//
// Private Functions
//
====================================================================*/
/*
// ValidateOffset
//
// Validates that the current offset is ready to be used
//
// Returns 1 on success, 0 on error
*/
static int ValidateOffset( SOURCEFILE *ps )
{
uint opcode;
if( CodeOffset==-1 )
{
CodeOffset = 8;
if( EntryPoint<0 )
EntryPoint = 8;
if( Core != CORE_V0 )
Report(ps,REP_WARN1,"Using default code origin of 8");
else
{
opcode = 0x21000900;
/* Note it in listing file */
if( Pass==2 && (Options & OPTION_LISTING) )
{
fprintf(ListingFile,
"%s(%5d) : 0x%04x = 0x%08x : JMP #0x9 // Legacy Mode\n",
ps->SourceName,ps->CurrentLine,CodeOffset,opcode);
}
ProgramImage[CodeOffset].Flags = CODEGEN_FLG_FILEINFO;
ProgramImage[CodeOffset].FileIndex = ps->FileIndex;
ProgramImage[CodeOffset].Line = ps->CurrentLine;
ProgramImage[CodeOffset].AddrOffset = CodeOffset;
ProgramImage[CodeOffset++].CodeWord = opcode;
}
}
if( CodeOffset >= MAX_PROGRAM )
{ Report(ps,REP_FATAL,"Max program size exceeded"); return(0); }
return(1);
}
/*
// PrintLine
//
// Prints out a line of the source file for source listings
//
// Returns 1 on success, 0 on EOF
*/
static int PrintLine( FILE *pfOut, SOURCEFILE *ps )
{
int i;
char c;
AGAIN:
i = fread( &c, 1, 1, ps->FilePtr );
if( i != 1 )
return(0);
if( c == 0xd )
goto AGAIN;
if( c == 0xa )
{
ps->CurrentLine++;
fprintf(pfOut,"\n");
return(1);
}
fprintf(pfOut,"%c",c);
goto AGAIN;
}
/*
// GetInfoFromAddr
//
// Returns the SourceFileIndex, Line Number, and CodeWord for a given address offset
//
// Returns 0 on success, -1 on error
*/
static int GetInfoFromAddr( uint address, uint *pIndex, uint *pLineNo, uint *pCodeWord )
{
int i;
for(i=0; i<(int)CodeOffset; i++)
{
if( ProgramImage[i].AddrOffset == address )
{
*pIndex = ProgramImage[i].FileIndex;
*pLineNo = ProgramImage[i].Line;
*pCodeWord = ProgramImage[i].CodeWord;
return 0;
}
}
return -1;
}
/*
// ListFile
//
// Prints out an object code annotated listing of an original source file
//
// Returns 1 on success
*/
static int ListFile( FILE *pfOut, SOURCEFILE *ps )
{
uint addr, index, line, code, count, output, cline;
count = 0;
for( addr=0; addr<(uint)CodeOffset; addr++ )
{
if( GetInfoFromAddr( addr, &index, &line, &code ) >= 0 )
{
if( index == ps->FileIndex )
count++;
}
}
if( !count )
{
// No code section
fprintf(pfOut,"(No Ouput Generated)\n\n");
for(;;)
{
fprintf(pfOut,"%5d : : ",ps->CurrentLine );
if( !PrintLine(pfOut,ps) )
return(1);
}
}
else
{
fprintf(pfOut,"(%d Instructions Generated)\n\n",count);
for(;;)
{
output = 0;
cline = ps->CurrentLine;
for( addr=0; addr<(uint)CodeOffset; addr++ )
{
if( (GetInfoFromAddr( addr, &index, &line, &code ) < 0) || index!=ps->FileIndex || line<cline )
continue;
if( line == cline )
{
if( !output )
{
fprintf(pfOut,"%5d : 0x%04x 0x%08x : ",line,addr,code );
if( !PrintLine(pfOut,ps) )
return(1);
output = 1;
}
else
{
fprintf(pfOut," : 0x%04x 0x%08x : \n",addr,code );
}
}
}
if( !output )
{
fprintf(pfOut,"%5d : : ",ps->CurrentLine );
if( !PrintLine(pfOut,ps) )
return(1);
}
}
}
return(1);
}
================================================
FILE: am335x/pasm/pasm.h
================================================
/*
* pasm.h
*
* Copyright (C) 2012 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.
*
*/
/*===========================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
/*===========================================================================
// PASM - PRU Assembler
//---------------------------------------------------------------------------
//
// File : pasm.h
//
// Description:
// Main include file
// - Global data structures and assembler state
// - Declarations of all public functions
//
//---------------------------------------------------------------------------
// Revision:
// 21-Jun-13: 0.84 - Open source version
============================================================================*/
typedef unsigned int uint;
#include "pru_ins.h"
#define TOKEN_MAX_LEN 128
/* Label Record */
#define LABEL_NAME_LEN TOKEN_MAX_LEN
typedef struct _LABEL {
struct _LABEL *pPrev; /* Previous in LABEL list */
struct _LABEL *pNext; /* Next in LABEL list */
int Offset; /* Offset Value */
char Name[LABEL_NAME_LEN];
} LABEL;
/* Source File Record */
#define SOURCE_NAME 64
#define SOURCE_BASE_DIR 256
typedef struct _SOURCEFILE {
struct _SOURCE *pParent; /* The file that included this file */
FILE *FilePtr; /* Open file handle */
unsigned int InUse; /* Set to '1' if file is active */
unsigned int FileIndex; /* Index of this source file in CODEGEN */
unsigned int CurrentLine; /* The current line being read */
unsigned int CurrentColumn; /* The current column being read */
unsigned int ccDepthIn; /* Original condition code depth */
char LastChar; /* Last character read from file */
char SourceName[SOURCE_NAME];
char SourceBaseDir[SOURCE_BASE_DIR];
} SOURCEFILE;
/* Source Line Record */
#define MAX_TOKENS 12
#define SRC_FLG_LABEL (1<<0)
#define SRC_FLG_DOTCMD1 (1<<1)
#define SRC_FLG_DOTCMD2 (1<<2)
typedef struct _SRCLINE {
uint Flags;
uint Terms;
char Label[TOKEN_MAX_LEN];
char Term[MAX_TOKENS][TOKEN_MAX_LEN];
} SRCLINE;
/* CodeGen Record */
typedef struct _CODEGEN {
unsigned char Flags; /* Record flags */
#define CODEGEN_FLG_FILEINFO 0x01
#define CODEGEN_FLG_CANMAP 0x02
unsigned char Resv8; /* Reserved */
unsigned short FileIndex; /* Source file index */
unsigned int Line; /* The line number */
unsigned int AddrOffset; /* Code address offset */
unsigned int CodeWord; /* Code */
} CODEGEN;
/* User Options */
extern unsigned int Options;
#define OPTION_BINARY (1<<0)
#define OPTION_BINARYBIG (1<<1)
#define OPTION_CARRAY (1<<2)
#define OPTION_IMGFILE (1<<3)
#define OPTION_DBGFILE (1<<4)
#define OPTION_LISTING (1<<5)
#define OPTION_DEBUG (1<<6)
#define OPTION_BIGENDIAN (1<<7)
#define OPTION_RETREGSET (1<<8)
#define OPTION_SOURCELISTING (1<<9)
extern unsigned int Core;
#define CORE_NONE 0
#define CORE_V0 1
#define CORE_V1 2
#define CORE_V2 3
#define CORE_V3 4
extern FILE *CArrayFile;
extern FILE *ListingFile;
/* Assembler Engine */
extern int Pass; /* Pass 1 or 2 of parser */
extern int HaveEntry; /* Entrypont flag (init to 0) */
extern int EntryPoint; /* Entrypont (init to -1) */
extern int CodeOffset; /* Current instruction "word" offset (zero based) */
extern int Errors; /* Total number or errors */
extern int FatalError; /* Set on fatal error */
extern int Warnings; /* Total number of warnings */
extern uint RetRegValue; /* Return register index */
extern uint RetRegField; /* Return register field */
#define DEFAULT_RETREGVAL 30
#define DEFAULT_RETREGFLD FIELDTYPE_15_0
#define SOURCEFILE_MAX 64
extern SOURCEFILE sfArray[SOURCEFILE_MAX];
extern unsigned int sfIndex;
/* Use platform appropriate function for case-insensitive string compare */
#ifdef _MSC_VER
#define stricmp _stricmp
#elif defined(__GNUC__)
#define stricmp strcasecmp
#endif
/*=====================================================================
//
// Functions Implemented by the Opcode Module
//
//====================================================================*/
/*
// CheckOpcode
//
// Called to see if the supplied token is a reserved word.
//
// Returns index of opcode, 0 if not an opcode
*/
int CheckOpcode( char *word );
/*
// CheckTokenType
//
// Called to see if the supplied token is reserved word.
//
// Returns token type flags
*/
uint CheckTokenType( char *word );
#define TOKENTYPE_UNRESERVED 0
#define TOKENTYPE_FLG_OPCODE 0x0001
#define TOKENTYPE_FLG_DIRECTIVE 0x0002
#define TOKENTYPE_FLG_REG_BASE 0x0004
#define TOKENTYPE_FLG_REG_ADDR 0x0008
#define TOKENTYPE_FLG_REG_PTR 0x0010
#define TOKENTYPE_FLG_REG_POSTINC 0x0020
#define TOKENTYPE_FLG_REG_PREDEC 0x0040
/*
// ProcessOp
//
// Opcode processor
//
// This is the function that assembles opcode statements
//
// ps - Pointer to source file record
// TermCnt - Number of terms (including the command)
// pTerms - Pointer to the terms
//
// Returns:
// 1 : Success
// 0 : Error
*/
int ProcessOp( SOURCEFILE *ps, int TermCnt, char **pTerms );
/*
// GetRegister
//
// Get Register Argument
//
// Parses the source string for a register and field
//
// ps - Pointer to source file record
// num - operand number (1 based)
// src - source string
// pa - Pointer to register structure
// fBitOk - Can accept Rxx.Txx
// termC - Set to non-zero if special terminating character ('+')
//
// Returns:
// 1 : Success
// 0 : Error
*/
int GetRegister( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa, int fBitOk, char termC );
/*=====================================================================
//
// Functions Implemented by the DotCommand Module
//
//====================================================================*/
/*
// CheckDotCommand
//
// Check to see if supplied word is a dot command
//
// Returns 1 if the word is a command, else zero
*/
int CheckDotCommand( char *word );
/*
// DotCommand
//
// Dot command processor
//
// This is the function where users add their assembler commands
//
// ps - Pointer to source file record
// TermCnt - Number of terms (including the command)
// pTerms - Pointer to the terms
// Src - Buffer to write any resulting assembly line
// MaxSrc - Size of assembly line buffer
//
// Returns:
// >=0 : Success - Length of assemby line (0 to MaxSrc)
// <0 : Illegal command
*/
int DotCommand( SOURCEFILE *ps, int TermCnt, char **pTerms, char *Src, int MaxSrc );
/*
// DotInitialize
//
// Open the dot-command environment
//
// void
*/
void DotInitialize(int pass);
/*
// DotCleanup
//
// Clean up the dot environment
//
// void
*/
void DotCleanup(int pass);
/*=====================================================================
//
// Functions Implemented by the Structure/Scope Module
//
//====================================================================*/
/*
// ScopeEnter
//
// Returns:
// 0 - Success
// -1 - Error
*/
int ScopeEnter( SOURCEFILE *ps, char *Name );
/*
// ScopeLeave
//
// Returns:
// 0 - Success
// -1 - Error
*/
int ScopeLeave( SOURCEFILE *ps, char *Name );
/*
// ScopeUsing
//
// Returns:
// 0 - Success
// -1 - Error
*/
int ScopeUsing( SOURCEFILE *ps, char *Name );
/*
// StructInit
//
// Returns: void
*/
void StructInit();
/*
// StructCleanup
//
// Returns: void
*/
void StructCleanup();
/*
// StructNew
//
// Returns:
// 0 - Success
// -1 - Error
*/
int StructNew( SOURCEFILE *ps, char *Name );
/*
// StructEnd
//
// Returns:
// 0 - Success
// -1 - Error
*/
int StructEnd( SOURCEFILE *ps );
/*
// StructAddElement
//
// Create a new structure record
//
// Returns 0 on success, -1 on error
*/
int StructAddElement( SOURCEFILE *ps, char *Name, uint size );
/*
// StructAssign
//
// Assign a structure to an instance
//
// Returns 0 on success, -1 on error
*/
int StructAssign( SOURCEFILE *ps, char *structName, char *rsName,
char *reName, char *defName );
/*
// Struct Param Process
//
// Processes the supplied argument for stucture references or SIZE/OFFSET
// operations. When found, the structure definition is used to substitute
// in the proper register or numeric value.
//
// The string 'source' is assumed to be be able to hold a length of
// at least 'TOKEN_MAX_LEN' bytes.
//
// Returns 0 for OK, or -1 for Fatal Error
//
*/
int StructParamProcess( SOURCEFILE *ps, int ParamIdx, char *source );
/*
// CheckStruct
//
// Searches for struct template or struct by name.
//
// Returns 1 on success, 0 on error
*/
int CheckStruct( char *name );
/*=====================================================================
//
// Main Assembler Functions
//
//====================================================================*/
/*
// ProcessSourceFile
//
// New source file to assemble.
//
// Returns 1 on success, 0 on error
*/
int ProcessSourceFile( SOURCEFILE *ps );
/*
// ProcessSourceLine
//
// New source line to assemble.
//
// Returns 1 on success, 0 on error
*/
int ProcessSourceLine( SOURCEFILE *ps, int length, char *src );
/*
// ParseSourceLine
//
// New source line to parse.
//
// Returns 1 on success, 0 on error
*/
int ParseSourceLine( SOURCEFILE *ps, int length, char *src, SRCLINE *pa );
/*
// Report
//
// Report an abnormal condition
*/
#define REP_INFO 0 /* Information only */
#define REP_WARN1 1 /* Warn on pass1 */
#define REP_WARN2 2 /* Warn on pass2 */
#define REP_ERROR 3
#define REP_FATAL 4
void Report( SOURCEFILE *ps, int Level, char *fmt, ... );
/*
// LabelChar
//
// Return whether the character is legal for a label.
// Numbers are not allowed when FlagFirstChar is set.
//
// Returns 1 on success, 0 on error
*/
int LabelChar( char c, int FlagFirstChar );
/*
// LabelCreate
//
// Create a label with the supplied offset value
//
// Returns 1 on success, 0 on error
*/
int LabelCreate( SOURCEFILE *ps, char *label, int value );
/*
// LabelFind
//
// Searches for an equate by name. If found, returns the record pointer.
//
// Returns LABEL * on success, 0 on error
*/
LABEL *LabelFind( char *name );
/*
// LabelDestroy
//
// Frees and label record.
//
// void
*/
void LabelDestroy( LABEL *pl );
/*
// GenOp
//
// Generate an opcode to the ouput file
//
// ps - Pointer to source file record
// TermCnt - Number of terms (including the command)
// pTerms - Pointer to the terms
// opcode - Generated Opcode
*/
void GenOp( SOURCEFILE *ps, int TermCnt, char **pTerms, uint opcode );
/*
// Check Name
//
// Returns 1 if the name is free, or 0 if it is in use
*/
int CheckName( SOURCEFILE *ps, char *name );
/*=======================================================================
//
// Expression Analyzer
//
=======================================================================*/
/*
// Expression - Math Expression Parser
//
// Returns 0 on success, <0 on error
*/
int Expression( SOURCEFILE *ps, char *s, uint *pResult, int *pIndex );
/*=======================================================================
//
// Pre-processor Functions
//
=======================================================================*/
/*
// InitSourceFile
//
// Initializes all the fields in SOURCEFILE, and attempts to to open the
// file.
//
// Returns 1 on success, 0 on error
*/
SOURCEFILE *InitSourceFile( SOURCEFILE *pParent, char *filename );
/*
// CloseSourceFile
//
// Close the source file and free the block.
//
// void
*/
void CloseSourceFile( SOURCEFILE *ps );
/*
// GetSourceLine
//
// Get a new line of source code.
//
// This module also processes:
// '#' directives
// #define expansion
// Comments
//
// Returns length of line, 0 on EOF, -1 on Error
*/
int GetSourceLine( SOURCEFILE *ps, char *Dst, int MaxLen );
/*
// ppCleanup
//
// Clean up the pre-processor environment
//
// void
*/
void ppCleanup();
/*
// EquateCreate
//
// Creates an equate record
//
// Returns 0 on success, -1 on error
*/
#define EQUATE_NAME_LEN TOKEN_MAX_LEN
#define EQUATE_DATA_LEN 256
int EquateCreate( SOURCEFILE *ps, char *Name, char *Value );
/*
// CheckEquate
//
// Searches for an equate by name.
//
// Returns 1 on success, 0 on error
*/
int CheckEquate( char *name );
/*=======================================================================
//
// Macro Functions
//
=======================================================================*/
/*
// MacroEnter
// Returns:
// 0 - Success
// -1 - Error
*/
int MacroEnter( SOURCEFILE *ps, char *Name );
/*
// ProcessMacro
//
// ps - Pointer to source file record
// TermCnt - Number of terms (including the command)
// pTerms - Pointer to the terms
//
// Returns:
// 1 : Success
// 0 : Error
*/
int ProcessMacro( SOURCEFILE *ps, int TermCnt, char **pTerms );
/*
// MacroCleanup
//
// Returns: void
*/
void MacroCleanup();
/*
// CheckMacro
//
// Searches for an macro by name.
//
// Returns 1 on success, 0 on error
*/
int CheckMacro( char *name );
================================================
FILE: am335x/pasm/pasmdbg.h
================================================
/*
* pasmdbg.h
*
* Copyright (C) 2012 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.
*
*/
/*===========================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
/*===========================================================================
// PASM - PRU Assembler
//---------------------------------------------------------------------------
//
// File : pasmdbg.h
//
// Description:
// File format for pView debugger debug file
//
//---------------------------------------------------------------------------
// Revision:
// 21-Jun-13: 0.84 - Open source version
============================================================================*/
#define DBGFILE_NAMELEN_SHORT 64
typedef struct _DBGFILE_HEADER {
unsigned int FileID;
#define DBGFILE_FILEID_VER3 (0x10150000 | 0x03)
unsigned int LabelCount; /* Number of label records */
unsigned int LabelOffset; /* File offset to label records */
unsigned int FileCount; /* Number of file records */
unsigned int FileOffset; /* File offset to file records */
unsigned int CodeCount; /* Number of code records */
unsigned int CodeOffset; /* File offset to code records */
unsigned int EntryPoint; /* Program entrypoint */
unsigned int Flags; /* File format flags */
#define DBGHDR_FLAGS_BIGENDIAN 0x00000001
} DBGFILE_HEADER;
typedef struct _DBGFILE_LABEL {
unsigned int AddrOffset;
char Name[DBGFILE_NAMELEN_SHORT];
} DBGFILE_LABEL;
typedef struct _DBGFILE_FILE {
char SourceName[DBGFILE_NAMELEN_SHORT];
} DBGFILE_FILE;
typedef struct _DBGFILE_CODE {
unsigned char Flags; /* Record flags */
#define DBGFILE_CODE_FLG_FILEINFO 0x01
#define DBGFILE_CODE_FLG_CANMAP 0x02
unsigned char Resv8; /* Reserved */
unsigned short FileIndex; /* Source file index */
unsigned int Line; /* The line number */
unsigned int AddrOffset; /* Code address offset */
unsigned int CodeWord; /* Code */
} DBGFILE_CODE;
================================================
FILE: am335x/pasm/pasmdot.c
================================================
/*
* pasmdot.c
*
* Copyright (C) 2012 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.
*
*/
/*===========================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
/*===========================================================================
// PASM - PRU Assembler
//---------------------------------------------------------------------------
//
// File : pasmdot.c
//
// Description:
// Processes the "dot" commands (.ret, .origin, .main, etc.)
//
//---------------------------------------------------------------------------
// Revision:
// 21-Jun-13: 0.84 - Open source version
============================================================================*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#if !defined(__APPLE__)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <ctype.h>
#include "pasm.h"
#define DOTCMD_MAIN 0
#define DOTCMD_END 1
#define DOTCMD_PROC 2
#define DOTCMD_RET 3
#define DOTCMD_ORIGIN 4
#define DOTCMD_ENTRYPOINT 5
#define DOTCMD_STRUCT 6
#define DOTCMD_ENDS 7
#define DOTCMD_U32 8
#define DOTCMD_U16 9
#define DOTCMD_U8 10
#define DOTCMD_ASSIGN 11
#define DOTCMD_SETCALLREG 12
#define DOTCMD_ENTER 13
#define DOTCMD_LEAVE 14
#define DOTCMD_USING 15
#define DOTCMD_MACRO 16
#define DOTCMD_MPARAM 17
#define DOTCMD_ENDM 18
#define DOTCMD_CODEWORD 19
#define DOTCMD_MAX 19
char *DotCmds[] = { ".main",".end",".proc",".ret",".origin",".entrypoint",
".struct",".ends",".u32",".u16",".u8",".assign",
".setcallreg", ".enter", ".leave", ".using",
".macro", ".mparam", ".endm", ".codeword" };
/*===================================================================
//
// Public Functions
//
====================================================================*/
/*
// CheckDotCommand
//
// Check to see if supplied word is a dot command
//
// Returns 1 if the word is a command, else zero
*/
int CheckDotCommand( char *word )
{
int i;
/* Commands are reserved */
for(i=0; i<=DOTCMD_MAX; i++)
{
if( !stricmp( word, DotCmds[i] ) )
return(1);
}
return(0);
}
/*
// DotCommand
//
// Dot command processor
//
// This is the function where users add their assembler commands
//
// ps - Pointer to source file record
// TermCnt - Number of terms (including the command)
// pTerms - Pointer to the terms
// Src - Buffer to write any resulting assembly line
// MaxSrc - Size of assembly line buffer
//
// Returns:
// >=0 : Success - Length of assemby line (0 to MaxSrc)
// <0 : Illegal command
*/
int DotCommand( SOURCEFILE *ps, int TermCnt, char **pTerms, char *Src, int MaxSrc )
{
int i;
for(i=0; i<=DOTCMD_MAX; i++)
{
if( !stricmp( pTerms[0], DotCmds[i] ) )
break;
}
if( i>DOTCMD_MAX )
{
Report(ps,REP_ERROR,"Unrecognized dot command");
return(-1);
}
if( i==DOTCMD_MAIN )
{
char c,cs;
int quote=0;
int idx=0,nameidx=0;
/*
// .main command
//
// Just print a warning - its only here for compatibility
*/
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
/* If the string is in quotes, skip the first charater */
if( pTerms[1][0]=='"' )
{
quote++;
idx++;
}
c = pTerms[1][idx++];
cs = ps->SourceName[nameidx++];
while( c && c!='"' )
{
if( toupper(c) != toupper(cs) )
{
NO_MATCH:
Report(ps,REP_WARN1,".main name '%s' doesn't match '%s'",
pTerms[1],ps->SourceName);
return(0);
}
c = pTerms[1][idx++];
cs = ps->SourceName[nameidx++];
}
if( cs && cs!='.' )
goto NO_MATCH;
if( c=='"' )
{
quote--;
c = pTerms[1][idx++];
}
if( c )
{ Report(ps,REP_ERROR,"Trailing characters on name"); return(-1); }
if( quote )
{ Report(ps,REP_ERROR,"Unbalanced quotes on name"); return(-1); }
return(0);
}
else if( i==DOTCMD_END )
{
/*
// .end command
//
// Do nothing - its only here for compatibility
*/
if( TermCnt != 1 )
{ Report(ps,REP_ERROR,"Expected no operands"); return(-1); }
return(0);
}
else if( i==DOTCMD_PROC )
{
/*
// .proc command
//
// Create a label from the proc name, with a leading '.'
// (this is for compatibility)
*/
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
sprintf( Src, ".%s:", pTerms[1] );
return(strlen(Src));
}
else if( i==DOTCMD_RET )
{
/*
// .ret command
//
// Generate the line "jmp r30.w0"
// This makes us compatible with "CALL", although inexplicably,
// the CALL command is not a "dot" command.
//
*/
if( TermCnt != 1 )
{ Report(ps,REP_ERROR,"Expected no operands"); return(-1); }
if( Options & OPTION_RETREGSET )
{ Report(ps,REP_ERROR,".ret incompatible with .setcallreg, use ret"); return(-1); }
if( Core > CORE_V1 )
{ Report(ps,REP_ERROR,".ret illegal with specified core version, use ret"); return(-1); }
strcpy( Src, "jmp r30.w0" );
return(strlen(Src));
}
else if( i==DOTCMD_ORIGIN )
{
int val,tmp;
char tstr[TOKEN_MAX_LEN];
/*
// .origin command
//
// Alter the origin for writing code
*/
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
strcpy( tstr, pTerms[1] );
if( Expression(ps, tstr, (uint *)&val, &tmp)<0 )
{ Report(ps,REP_ERROR,"Error in processing .origin value"); return(-1); }
if( Core == CORE_V0 )
{ Report(ps,REP_ERROR,".origin illegal with specified core version"); return(-1); }
if( val<CodeOffset )
{ Report(ps,REP_ERROR,".origin value is less than current offset"); return(-1); }
if( CodeOffset>=0 )
Report(ps,REP_WARN1,"Resetting .origin value after use");
if( EntryPoint<0 )
EntryPoint = val;
CodeOffset = val;
return(0);
}
else if( i==DOTCMD_ENTRYPOINT )
{
int val,tmp;
char tstr[TOKEN_MAX_LEN];
/*
// .entrypoint command
//
// Alter the origin for writing code
*/
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
strcpy( tstr, pTerms[1] );
if( Expression(ps, tstr, (uint *)&val, &tmp)<0 )
{ Report(ps,REP_ERROR,"Error in processing .entrypoint value"); return(-1); }
if( Core == CORE_V0 )
{ Report(ps,REP_ERROR,".entrypoint illegal with specified core version"); return(-1); }
if( HaveEntry )
{ Report(ps,REP_ERROR,"Multiple .entrypoint declarations"); return(-1); }
EntryPoint = val;
HaveEntry = 1;
return(0);
}
else if( i==DOTCMD_STRUCT )
{
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
return( StructNew(ps,pTerms[1]) );
}
else if( i==DOTCMD_ENDS )
{
if( TermCnt != 1 )
{ Report(ps,REP_ERROR,"Expected no operands"); return(-1); }
return( StructEnd(ps) );
}
else if( i==DOTCMD_U32 )
{
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
return( StructAddElement( ps, pTerms[1], 4 ) );
}
else if( i==DOTCMD_U16 )
{
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
return( StructAddElement( ps, pTerms[1], 2 ) );
}
else if( i==DOTCMD_U8 )
{
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
return( StructAddElement( ps, pTerms[1], 1 ) );
}
else if( i==DOTCMD_ASSIGN )
{
if( TermCnt != 5 )
{ Report(ps,REP_ERROR,"Expected 4 operands"); return(-1); }
return( StructAssign(ps, pTerms[1], pTerms[2], pTerms[3], pTerms[4]) );
}
else if( i==DOTCMD_SETCALLREG )
{
PRU_ARG r;
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
if( Core == CORE_V0 )
{ Report(ps,REP_ERROR,".setcallreg illegal with specified core version"); return(-1); }
if( Pass==1 && (Options & OPTION_RETREGSET) )
{ Report(ps,REP_ERROR,".setcallreg redefinition"); return(-1); }
if( CodeOffset>=0 )
{ Report(ps,REP_ERROR,"Can not use .setcallreg after code generation"); return(-1); }
if( !GetRegister( ps, 1, pTerms[1], &r, 0, 0 ) )
return -1;
switch( r.Field )
{
case FIELDTYPE_15_0:
case FIELDTYPE_23_8:
case FIELDTYPE_31_16:
if( r.Value<31 )
{
RetRegValue = r.Value;
RetRegField = r.Field;
Options |= OPTION_RETREGSET;
return 0;
}
}
Report(ps,REP_ERROR,"Register field must be r0 to r30 and 16 bits wide");
return(-1);
}
else if( i==DOTCMD_ENTER )
{
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
return( ScopeEnter(ps, pTerms[1]) );
}
else if( i==DOTCMD_LEAVE )
{
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
return( ScopeLeave(ps, pTerms[1]) );
}
else if( i==DOTCMD_USING )
{
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
return( ScopeUsing(ps, pTerms[1]) );
}
else if( i==DOTCMD_MACRO )
{
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
return( MacroEnter(ps, pTerms[1]) );
}
else if( i==DOTCMD_MPARAM || i==DOTCMD_ENDM )
{ Report(ps,REP_ERROR,"%s can not be used outside of macro",pTerms[0]); return(-1); }
else if( i==DOTCMD_CODEWORD )
{
uint opcode;
int tmp;
char tstr[TOKEN_MAX_LEN];
/*
// .codeword command
*/
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(-1); }
strcpy( tstr, pTerms[1] );
if( Expression(ps, tstr, &opcode, &tmp)<0 )
{ Report(ps,REP_ERROR,"Error in processing .codeword value"); return(-1); }
GenOp( ps, TermCnt, pTerms, opcode );
return(0);
}
Report(ps,REP_ERROR,"Dot command - Internal Error");
return(-1);
}
/*
// DotInitialize
//
// Open the dot-command environment
//
// void
*/
void DotInitialize(int pass)
{
StructInit();
}
/*
// DotCleanup
//
// Clean up the dot-command environment
//
// void
*/
void DotCleanup(int pass)
{
StructCleanup();
MacroCleanup();
}
================================================
FILE: am335x/pasm/pasmexp.c
================================================
/*
* pasmexp.c
*
* Copyright (C) 2012 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.
*
*/
/*===========================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
/*===========================================================================
// PASM - PRU Assembler
//---------------------------------------------------------------------------
//
// File : pasmexp.c
//
// Description:
// Expression analyzer. This module is a "drop in", and thus does't
// have much knowledge of the rest of the assembler.
// - Handles expression processing
//
// Note that the expression analyzer will only report errors on pass 2
//
//---------------------------------------------------------------------------
// Revision:
// 21-Jun-13: 0.84 - Open source version
============================================================================*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#if !defined(__APPLE__)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <ctype.h>
#include "pasm.h"
#define MAXTERM 32
#define EOP_MULTIPLY 1
#define EOP_DIVIDE 2
#define EOP_MOD 3
#define EOP_ADD 4
#define EOP_SUBTRACT 5
#define EOP_LEFTSHIFT 6
#define EOP_RIGHTSHIFT 7
#define EOP_AND 8
#define EOP_XOR 9
#define EOP_OR 10
uint prec[] = { 999,
1, /* EOP_MULTIPLY */
1, /* EOP_DIVIDE */
1, /* EOP_MOD */
2, /* EOP_ADD */
2, /* EOP_SUBTRACT */
3, /* EOP_LEFTSHIFT */
3, /* EOP_RIGHTSHIFT */
4, /* EOP_AND */
5, /* EOP_XOR */
6 };/* EOP_OR */
int EXP_getValue( SOURCEFILE *ps, char *s, int *pIdx, uint *pValue );
int EXP_getOperation( SOURCEFILE *ps, char *s, int *pIdx, uint *pValue );
static int GetRegisterOffset( char *src, uint *pValue );
/*
// Expression - Math Expression Parser
//
// Returns 0 on success, <0 on error
*/
int Expression( SOURCEFILE *ps, char *s, uint *pResult, int *pIndex )
{
uint values[MAXTERM];
uint ops[MAXTERM];
int maxprec;
int i;
int validx,opidx,stridx;
validx=0;
opidx=0;
stridx=0;
while( validx<MAXTERM )
{
i= EXP_getValue(ps, s, &stridx, &values[validx]);
if( !i )
break;
if( i<0 )
{
if( pIndex )
*pIndex = stridx;
return(-1);
}
validx++;
i= EXP_getOperation(ps, s, &stridx, &ops[opidx]);
if( !i )
break;
if( i<0 )
{
if( pIndex )
*pIndex = stridx;
return(-1);
}
opidx++;
}
if( i )
{
Report(ps,REP_ERROR,"Max term count exceeded");
return(-1);
}
if( pIndex )
*pIndex = stridx;
/* If values and ops unbalanced, quit now */
if( opidx >= validx || !validx )
return(-1);
while( opidx )
{
/* Find the highest prec op */
maxprec = 0;
for( i=1; i<opidx; i++)
if( prec[ops[i]] < prec[ops[maxprec]] )
maxprec = i;
switch( ops[maxprec] )
{
case EOP_MULTIPLY:
values[maxprec] = values[maxprec] * values[maxprec+1];
break;
case EOP_DIVIDE:
if( !values[maxprec+1] )
{
if( Pass==2 )
{
Report(ps,REP_ERROR,"Divide by zero");
return(-1);
}
else
values[maxprec] = 0;
}
else
values[maxprec] = values[maxprec] / values[maxprec+1];
break;
case EOP_MOD:
if( !values[maxprec+1] )
{
if( Pass==2 )
{
Report(ps,REP_ERROR,"Mod by zero");
return(-1);
}
else
values[maxprec] = 0;
}
else
values[maxprec] = values[maxprec] % values[maxprec+1];
break;
case EOP_ADD:
values[maxprec] = values[maxprec] + values[maxprec+1];
break;
case EOP_SUBTRACT:
values[maxprec] = values[maxprec] - values[maxprec+1];
break;
case EOP_LEFTSHIFT:
values[maxprec] = values[maxprec] << values[maxprec+1];
break;
case EOP_RIGHTSHIFT:
values[maxprec] = values[maxprec] >> values[maxprec+1];
break;
case EOP_AND:
values[maxprec] = values[maxprec] & values[maxprec+1];
break;
case EOP_XOR:
values[maxprec] = values[maxprec] ^ values[maxprec+1];
break;
case EOP_OR:
values[maxprec] = values[maxprec] | values[maxprec+1];
break;
}
// Remove this op and 2nd value term from the list
i = MAXTERM-2-maxprec;
if( i>0 )
{
memcpy( &values[maxprec+1], &values[maxprec+2], i*sizeof(uint));
memcpy( &ops[maxprec], &ops[maxprec+1], i*sizeof(uint));
}
opidx--;
validx--;
}
if( validx != 1 )
{ Report(ps,REP_ERROR,"Exp internal error"); return(-1); }
*pResult = values[0];
return(0);
}
/*
// EXP_getValue - Get a value from the supplied string
//
// Returns 0 no value, 1 on success, <0 on error
*/
int EXP_getValue( SOURCEFILE *ps, char *s, int *pIdx, uint *pValue )
{
int base = 10,index,i,j,k;
int rc = 1;
uint tval = 0;
char c;
index = *pIdx;
c = s[index];
while( c==' ' || c==9 )
{
index++;
c = s[index];
}
if( !c )
return(0);
/* Look for a label */
if( LabelChar(c,1) || c=='.' || c=='&' )
{
LABEL *pl;
char lblstr[LABEL_NAME_LEN];
int lblidx = 0;
for(;;)
{
lblstr[lblidx++]=c;
index++;
c = s[index];
if( !LabelChar(c,0) && c!='.' )
break;
}
lblstr[lblidx]=0;
*pIdx = index;
if( CheckTokenType(lblstr) & TOKENTYPE_FLG_REG_ADDR )
{
if( GetRegisterOffset(lblstr+1,&tval) )
{
*pValue = tval;
return(1);
}
}
pl = LabelFind(lblstr);
if(!pl && Pass==1)
*pValue = 0;
else if( !pl )
{ Report(ps,REP_ERROR,"Not found: '%s'",lblstr); return(0); }
else
*pValue = pl->Offset;
return(1);
}
if( c=='-' )
{
index++;
i = EXP_getValue( ps, s, &index, &tval );
if( i<0 )
rc = i;
else
tval = (uint)(-(int)tval);
goto EGV_EXIT;
}
if( c=='~' )
{
index++;
i = EXP_getValue( ps, s, &index, &tval );
if( i<0 )
rc = i;
else
tval = ~tval;
goto EGV_EXIT;
}
if( c=='(' )
{
/* Scan to the far ')' */
index++;
j = index;
i=1;
for(;;)
{
c = *(s+j);
if( !c )
{
rc = -1;
goto EGV_EXIT;
}
if( c=='(' )
i++;
if( c==')' )
{
i--;
if(!i)
{
/* Terminate the string and eval the () */
*(s+j) = 0;
i = Expression( 0, s+index, &tval, &k );
if( i<0 )
{
index+=k;
rc=i;
}
else
index=j+1;
goto EGV_EXIT;
}
}
j++;
}
}
/* This character must be a number */
if( c<'0' || c>'9' )
{
rc = -1;
goto EGV_EXIT;
}
index++;
tval = c-'0';
if( tval==0 )
{
c = s[index];
if( c=='x' )
{
base=16;
index++;
}
else if( c=='b' )
{
base=2;
index++;
}
else
base=8;
}
for(;;)
{
c = s[index];
if( c>='0' && c<='9' )
i = c-'0';
else if( c>='a' && c<='f' )
i = c-'a'+10;
else if( c>='A' && c<='F' )
i = c-'A'+10;
else
break;
if( i>=base )
{
rc = -1;
goto EGV_EXIT;
}
tval *= base;
tval += i;
index++;
}
EGV_EXIT:
*pValue = tval;
*pIdx = index;
return(rc);
}
/*
// EXP_getOperation - Get an operation from the supplied string
//
// Returns 0 no value, 1 on success, <0 on error
*/
int EXP_getOperation( SOURCEFILE *ps, char *s, int *pIdx, uint *pValue )
{
int index;
char c;
int rc = 1;
index = *pIdx;
c = s[index];
while( c==' ' || c==9 )
{
index++;
c = s[index];
}
if( !c )
return(0);
else if( c=='*' )
*pValue = EOP_MULTIPLY;
else if( c=='/' )
*pValue = EOP_DIVIDE;
else if( c=='%' )
*pValue = EOP_MOD;
else if( c=='+' )
*pValue = EOP_ADD;
else if( c=='-' )
*pValue = EOP_SUBTRACT;
else if( c=='<' )
{
index++;
c = s[index];
if( c != '<' )
rc=-1;
else
*pValue = EOP_LEFTSHIFT;
}
else if( c=='>' )
{
index++;
c = s[index];
if( c != '>' )
rc=-1;
else
*pValue = EOP_RIGHTSHIFT;
}
else if( c=='&' )
*pValue = EOP_AND;
else if( c=='^' )
*pValue = EOP_XOR;
else if( c=='|' )
*pValue = EOP_OR;
else
rc = -1;
if( rc == 1)
index++;
*pIdx = index;
return(rc);
}
/*
// GetRegisterOffset
//
// Get Register Offset
//
// Returns:
// 1 : Success
// 0 : Error
*/
static int GetRegisterOffset( char *src, uint *pValue )
{
uint idx;
char c,field;
int val,reg,width,offset;
if( Core == CORE_V0 )
return(0);
/*
// The following register syntaxes are valid:
// Raa aa=(0-31)
// Raa.Wb aa=(0-31) b=(0-2)
// Raa.Bc aa=(0-31) c=(0-3)
// Raa.Tdd aa=(0-31) dd=(0-31)
// Raa.Wb.Be aa=(0-31) b=(0-2) e=(0-1)
*/
idx=0;
c = src[idx++];
/* Get initial 'R##' */
if( toupper(c) != 'R' )
return(0);
c = src[idx++];
if( !isdigit(c) )
return(0);
val = 0;
while( isdigit(c) )
{
val *= 10;
val += c-'0';
c = src[idx++];
}
if( val>31 )
return(0);
reg = val;
width = 32;
offset = 0;
for(;;)
{
/* This char must be '.', or terminator */
/* If terminated, we're done */
if( !c )
break;
if( c != '.' )
return(0);
c = src[idx++];
/* This char must be 'W', or 'B' */
c = toupper(c);
if( c!='W' && c!='B' )
return(0);
field=c;
c = src[idx++];
if( !isdigit(c) )
return(0);
val = 0;
while( isdigit(c) )
{
val *= 10;
val += c-'0';
c = src[idx++];
}
if( field=='W' )
{
if( ((val*8)+16)>width )
return(0);
width = 16;
offset += val;
}
if( field=='B' )
{
if( ((val*8)+8)>width )
return(0);
width = 8;
offset += val;
}
}
if( !(Options & OPTION_BIGENDIAN) )
*pValue = reg * 4 + offset;
else
{
width /= 8;
offset = 4 - offset - width;
*pValue = reg * 4 + offset;
}
return(1);
}
================================================
FILE: am335x/pasm/pasmmacro.c
================================================
/*
* pasmmacro.c
*
* Copyright (C) 2012 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.
*
*/
/*===========================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
/*===========================================================================
// PASM - PRU Assembler
//---------------------------------------------------------------------------
//
// File : pasmmacro.c
//
// Description:
// Processes the macro commands
//
//---------------------------------------------------------------------------
// Revision:
// 21-Jun-13: 0.84 - Open source version
============================================================================*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#if !defined(__APPLE__)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <ctype.h>
#include "pasm.h"
/* Local Macro Definitions */
#define MACRO_NAME_LEN TOKEN_MAX_LEN
#define MACRO_MAX_ARGS 8
#define MACRO_MAX_LINES 128
#define MACRO_LINE_LENGTH 256
#define MACRO_MAX_LABELS 32
#define MAX_SOURCE_LINE 256
/* Macro Struct Record */
typedef struct _MACRO {
struct _MACRO *pPrev; /* Previous in MACRO list */
struct _MACRO *pNext; /* Next in MACRO list */
char Name[MACRO_NAME_LEN];
int InUse; /* Macro is in use */
int Id; /* Macro ID */
int Arguments; /* Number of arguments */
int Required; /* Number of required arguments */
int Labels; /* Number of labels */
int Expands; /* Number of label expansions */
int CodeLines; /* Number of code lines */
char ArgName[MACRO_MAX_ARGS][TOKEN_MAX_LEN];
char ArgDefault[MACRO_MAX_ARGS][TOKEN_MAX_LEN];
char LableName[MACRO_MAX_LABELS][TOKEN_MAX_LEN];
char Code[MACRO_MAX_LINES][MACRO_LINE_LENGTH];
} MACRO;
/* Local Support Funtions */
static int _strncat( char *dst, int len, char *src );
static MACRO *MacroFind( char *Name );
static MACRO *MacroCreate( SOURCEFILE *ps, char *Name );
int MacroAddArg( SOURCEFILE *ps, MACRO *pm, char *ArgText );
static void MacroDestroy( MACRO *pm );
/* Local macro list */
int MacroId=0;
MACRO *pMacroList=0; /* List of declared structs */
MACRO *pMacroCurrent=0;
/*===================================================================
//
// Public Functions
//
====================================================================*/
/*
// MacroEnter
// Returns:
// 0 - Success
// -1 - Error
*/
int MacroEnter( SOURCEFILE *ps, char *Name )
{
SRCLINE sl;
MACRO *pm;
char src[MAX_SOURCE_LINE];
int i;
if( Core == CORE_V0 )
{ Report(ps,REP_ERROR,".macro illegal with specified core version"); return(-1); }
/* Create the macro */
pm = MacroCreate( ps, Name );
if( !pm )
return(-1);
/* Scan source lines until we see .endm */
for(;;)
{
/* Abort on a total disaster */
if( FatalError || Errors >= 25 )
return(-1);
/* Get a line of source code */
i = GetSourceLine( ps, src, MAX_SOURCE_LINE );
if( !i )
{ Report(ps,REP_ERROR,"Missing .endm on macro"); return(-1); }
if( i<0 )
continue;
if( !ParseSourceLine(ps,i,src,&sl) )
continue;
/* Check for a label */
if( sl.Flags & SRC_FLG_LABEL )
{
if( pm->Labels==MACRO_MAX_LABELS )
Report(ps,REP_ERROR,"Macro contains too many labels");
else
{
strcpy( pm->LableName[pm->Labels], sl.Label );
pm->Labels++;
}
}
/* Check for a macro related dot command */
if( sl.Terms && (sl.Flags & SRC_FLG_DOTCMD1) )
{
if( !stricmp( sl.Term[0], ".mparam" ) )
{
if( sl.Terms==1 )
{ Report(ps,REP_ERROR,"Expected at least 1 parameter on .mparam"); continue; }
for( i=1; i<(int)sl.Terms; i++)
MacroAddArg(ps,pm,sl.Term[i]);
continue;
}
else if( !stricmp( sl.Term[0], ".macro" ) )
{ Report(ps,REP_ERROR,"Macro definitions may not be nested"); continue; }
else if( !stricmp( sl.Term[0], ".endm" ) )
{
pm->InUse = 0;
return(0);
}
}
/* Else store the line as part of the macro */
else
{
if( pm->CodeLines == MACRO_MAX_LINES )
{ Report(ps,REP_ERROR,"Macro line count exceeded"); continue; }
strcpy(pm->Code[pm->CodeLines],src);
pm->CodeLines++;
}
}
}
/*
// ProcessMacro
//
// ps - Pointer to source file record
// TermCnt - Number of terms (including the command)
// pTerms - Pointer to the terms
//
// Returns:
// 1 : Success
// 0 : Error
*/
int ProcessMacro( SOURCEFILE *ps, int TermCnt, char **pTerms )
{
MACRO *pm;
int cidx,sidx,nidx,i;
char src[MAX_SOURCE_LINE];
char namebuf[MACRO_NAME_LEN];
char c;
pm = MacroFind(pTerms[0]);
if( !pm )
return(0);
if( pm->InUse )
{ Report(ps,REP_ERROR,"Illegal recursive use of macro '%s'",pTerms[0]); return(0); }
if( pm->Required >= TermCnt )
{ Report(ps,REP_ERROR,"Expected at least %d arguments on '%s'",pm->Required,pTerms[0]); return(0); }
if( pm->Arguments < (TermCnt-1) )
{ Report(ps,REP_ERROR,"Expected no more than %d arguments on '%s'",pm->Arguments,pTerms[0]); return(0); }
/* Bump expansion count */
pm->Expands++;
pm->InUse = 1;
for( cidx=0; cidx<pm->CodeLines; cidx++ )
{
/* Build the assembly statement */
sidx=0;
nidx=0;
src[0] = 0;
for(;;)
{
c=pm->Code[cidx][sidx++];
/* Check for start of name */
if( !nidx )
{
if(LabelChar(c,1))
{
namebuf[nidx++]=c;
continue;
}
}
/* Else continue a previously started name */
else
{
if(LabelChar(c,0))
{
/* Check for name too long */
if( nidx==(MACRO_NAME_LEN-1) )
{ Report(ps,REP_ERROR,"Term too long in macro assembly text"); pm->InUse=0; return(0); }
namebuf[nidx++]=c;
continue;
}
/* This name is done */
namebuf[nidx]=0;
/* Look for an argument match */
for(i=0;i<pm->Arguments;i++)
{
if(!strcmp(namebuf,pm->ArgName[i]))
{
/* Match! */
if( (i+1)>=TermCnt )
_strncat( src, MAX_SOURCE_LINE, pm->ArgDefault[i] );
else
_strncat( src, MAX_SOURCE_LINE, pTerms[i+1] );
goto SUBTEXTDONE;
}
}
/* Look for a label match */
for(i=0;i<pm->Labels;i++)
{
if(!strcmp(namebuf,pm->LableName[i]))
{
char labeltext[TOKEN_MAX_LEN+32];
/* Match! */
sprintf(labeltext,"_%s_%d_%d_", pm->LableName[i],pm->Id,pm->Expands);
_strncat( src, MAX_SOURCE_LINE, labeltext );
goto SUBTEXTDONE;
}
}
/* Sub in the original text */
_strncat( src, MAX_SOURCE_LINE, namebuf );
SUBTEXTDONE:
nidx = 0;
}
/* Check for text too long */
i=strlen(src);
if( i==(MAX_SOURCE_LINE-1) )
{ Report(ps,REP_ERROR,"Macro expansion too long"); pm->InUse=0; return(0); }
src[i++]=c;
src[i]=0;
if( !c )
break;
}
i=strlen(src);
if(i)
{
if( !ProcessSourceLine(ps, i, src) )
{
Report(ps,REP_ERROR,"(While expanding code line %d of macro '%s')",(cidx+1),pm->Name);
pm->InUse=0;
return(0);
}
}
}
pm->InUse = 0;
return(1);
}
/*
// MacroCleanup
//
// Returns: void
*/
void MacroCleanup()
{
while( pMacroList )
MacroDestroy( pMacroList );
MacroId = 0;
}
/*
// CheckMacro
//
// Searches for an macro by name.
//
// Returns 1 on success, 0 on error
*/
int CheckMacro( char *name )
{
if( MacroFind(name) )
return(1);
return(0);
}
/*===================================================================
//
// Private Functions
//
====================================================================*/
static int _strncat( char *dst, int len, char *src )
{
int sidx,didx;
didx = 0;
while( didx<len && dst[didx] )
didx++;
if( didx>(len-1) )
return(-1);
sidx = 0;
while( src[sidx] )
{
if( didx>(len-1) )
{
dst[didx] = 0;
return(-1);
}
dst[didx++] = src[sidx++];
}
dst[didx] = 0;
return(didx);
}
/*
// MacroFind
//
// Searches for a macro record by name. If found, returns the record pointer.
//
// Returns MACRO * on success, 0 on error
*/
static MACRO *MacroFind( char *Name )
{
MACRO *pm;
pm = pMacroList;
while( pm )
{
if( !strcmp( Name, pm->Name ) )
break;
pm = pm->pNext;
}
return(pm);
}
/*
// MacroCreate
//
// Create a new macro record
//
// Returns MACRO * on success, 0 on error
*/
static MACRO *MacroCreate( SOURCEFILE *ps, char *Name )
{
MACRO *pm;
/* Make sure this name is OK to use */
if( !CheckName(ps,Name) )
return(0);
/* Make sure its not too long */
if( strlen(Name)>=MACRO_NAME_LEN )
{ Report(ps,REP_ERROR,"Macro name too long"); return(0); }
/* Allocate a new record */
pm = malloc(sizeof(MACRO));
if( !pm )
{ Report(ps,REP_ERROR,"Memory allocation failed"); return(0); }
strcpy( pm->Name, Name );
pm->InUse = 1;
pm->Id = MacroId++;
pm->Arguments = 0;
pm->Required = 0;
pm->CodeLines = 0;
pm->Labels = 0;
pm->Expands = 0;
/* Put this equate in the master list */
pm->pPrev = 0;
pm->pNext = pMacroList;
pMacroList = pm;
if( Pass==1 && (Options & OPTION_DEBUG) )
printf("%s(%5d) : DOTCMD : Macro '%s' declared\n",
ps->SourceName,ps->CurrentLine,pm->Name);
return(pm);
}
/*
// MacroAddArg
//
// Add an argument to a macro record
//
// Returns 0 on success, -1 on error
*/
int MacroAddArg( SOURCEFILE *ps, MACRO *pm, char *ArgText )
{
int i,sidx;
if( Pass==1 && (Options & OPTION_DEBUG) )
printf("%s(%5d) : DOTCMD : Macro Parameter '%s' declared\n",
ps->SourceName,ps->CurrentLine,ArgText);
if( pm->Arguments == MACRO_MAX_ARGS )
{ Report(ps,REP_ERROR,"Too many macro arguments"); return(-1); }
/* Scan in the argument */
sidx=0;
while( ArgText[sidx]==' ' || ArgText[sidx]==9 )
sidx++;
i=0;
while( ArgText[sidx]!=' ' && ArgText[sidx]!=9 && ArgText[sidx]!='=' && ArgText[sidx]!=0 )
{
if(i==TOKEN_MAX_LEN)
{ Report(ps,REP_ERROR,"Macro argument name too long"); return(-1); }
if( (i==0 && !LabelChar(ArgText[sidx],1)) ||
(i!=0 && !LabelChar(ArgText[sidx],0)) )
{ Report(ps,REP_ERROR,"Illegal character in macro argument name"); return(-1); }
pm->ArgName[pm->Arguments][i++] = ArgText[sidx++];
}
pm->ArgName[pm->Arguments][i] = 0;
if( !i )
goto MARG_SYNTAX;
/* Verify no duplicate naming */
for(i=0; i<pm->Arguments; i++)
{
if( !strcmp(pm->ArgName[i],pm->ArgName[pm->Arguments]) )
{
Report(ps,REP_ERROR,"Duplicate macro argument name '%s'",pm->ArgName[i]);
return(-1);
}
}
/* Scan in the default value (if any) */
while( ArgText[sidx]==' ' || ArgText[sidx]==9 )
sidx++;
if( ArgText[sidx]=='=' )
{
sidx++;
while( ArgText[sidx]==' ' || ArgText[sidx]==9 )
sidx++;
i=0;
while( ArgText[sidx]!=' ' && ArgText[sidx]!=9 && ArgText[sidx]!='=' && ArgText[sidx]!=0 )
{
if(i==TOKEN_MAX_LEN)
{ Report(ps,REP_ERROR,"Macro argument value too long"); return(-1); }
if( !LabelChar(ArgText[sidx],0) && ArgText[sidx]!='.' )
goto MARG_SYNTAX;
pm->ArgDefault[pm->Arguments][i++] = ArgText[sidx++];
}
pm->ArgDefault[pm->Arguments][i] = 0;
if( !i )
goto MARG_SYNTAX;
pm->Arguments++;
}
else
{
pm->ArgDefault[pm->Arguments][0] = 0;
if(pm->Arguments > pm->Required)
{ Report(ps,REP_ERROR,"Optional macro arguments must be listed last"); return(-1); }
pm->Arguments++;
pm->Required++;
}
if( ArgText[sidx]!=0 )
{
MARG_SYNTAX:
Report(ps,REP_ERROR,"Syntax error in macro argument '%s' around character %d",ArgText,sidx+1);
return(-1);
}
return(0);
}
/*
// MacroDestroy
//
// Frees a macro record.
//
// void
*/
static void MacroDestroy( MACRO *pm )
{
if( !pm->pPrev )
pMacroList = pm->pNext;
else
pm->pPrev->pNext = pm->pNext;
if( pm->pNext )
pm->pNext->pPrev = pm->pPrev;
free(pm);
}
================================================
FILE: am335x/pasm/pasmop.c
================================================
/*
* pasmop.c
*
* Copyright (C) 2012 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.
*
*/
/*===========================================================================
* Copyright (c) Texas Instruments Inc 2010-12
*
* Use of this software is controlled by the terms and conditions found in the
* license agreement under which this software has been supplied or provided.
* ============================================================================
*/
/*===========================================================================
// PASM - PRU Assembler
//---------------------------------------------------------------------------
//
// File : pasmop.c
//
// Description:
// Handles the processing of PRU opcodes.
// - Provides a function to test for reserved words
// - Processes assembly lines and generates opcodes
// - Contains private functions to process operand fields
//
//---------------------------------------------------------------------------
// Revision:
// 21-Jun-13: 0.84 - Open source version
============================================================================*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#if !defined(__APPLE__)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#include <ctype.h>
#include "pasm.h"
char *OpText[] = {
"$ERROR$","ADD","ADC","SUB","SUC","LSL","LSR","RSB","RSC","AND","OR",
"XOR","NOT","MIN","MAX","CLR","SET","LDI","LBBO","LBCO","SBBO",
"SBCO","LFC","STC","JAL","JMP","QBGT","QBLT","QBEQ","QBGE","QBLE",
"QBNE","QBA","QBBS","QBBC","LMBD","CALL","WBC","WBS","MOV","MVIB",
"MVIW","MVID","SCAN","HALT","SLP", "RET", "ZERO", "FILL", "XIN", "XOUT",
"XCHG","SXIN","SXOUT","SXCHG","LOOP","ILOOP","NOP0","NOP1","NOP2","NOP3",
"NOP4","NOP5","NOP6","NOP7","NOP8","NOP9","NOPA","NOPB","NOPC","NOPD",
"NOPE","NOPF"};
/* Local Support Funtions */
static int GetImValue( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa, uint low, uint high );
static int GetConstant( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa );
static int GetR0offset( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa );
static int GetJmpOffset( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa );
static int GetLoopOffset( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa );
static int Offset2Reg( SOURCEFILE *ps, int num, PRU_ARG *pa, uint addr, uint size );
/*
// CheckOpcode
//
// Called to see if the supplied token is an opcode.
//
// Returns index of opcode, 0 if not an opcode
*/
int CheckOpcode( char *word )
{
int i;
for(i=1; i<=OP_MAXIDX; i++)
{
if( !stricmp( word, OpText[i] ) )
return(i);
}
return(0);
}
/*
// GetTokenType
//
// Called to see if the supplied token is reserved word.
//
// Returns 1 if reserved, 0 if not
*/
uint CheckTokenType( char *word )
{
int i,parse_state;
uint flags;
char c;
/* Opcodes are reserved */
if( CheckOpcode(word) )
return(TOKENTYPE_FLG_OPCODE);
/* Check for command */
if( CheckDotCommand( word ) )
return(TOKENTYPE_FLG_DIRECTIVE);
if( !strcmp(word,"SIZE") || !strcmp(word,"OFFSET") )
return(TOKENTYPE_FLG_DIRECTIVE);
/*
// [&,*][--](B,C,R,T,W)#[#][.(B,C,R,T,W)#[#]][++ ] is reserved
//
// For example:
// R - not reserved
// R23 - reserved
// R100 - not reserved
// C34.XYZ - not reserved
// C34.T34 - reserved
*/
i=0;
parse_state=0;
if( word[i]=='*' )
{
/* Mark as a pointer */
flags = TOKENTYPE_FLG_REG_PTR;
i++;
/* Check if its an immediate address */
if( word[i]=='&' )
{
flags |= TOKENTYPE_FLG_REG_ADDR;
i++;
}
/* Else its a register base */
else
{
flags |= TOKENTYPE_FLG_REG_BASE;
/* Registers can also be pre-dec */
if( word[i]=='-' )
{
if( word[i+1]!='-' )
return(TOKENTYPE_UNRESERVED);
i+=2;
flags |= TOKENTYPE_FLG_REG_PREDEC;
}
}
}
else if( word[i]=='&' )
{
flags = TOKENTYPE_FLG_REG_ADDR;
i++;
}
else
flags = TOKENTYPE_FLG_REG_BASE;
for(;;)
{
c = word[i++];
c = toupper(c);
switch( parse_state )
{
case 0:
if( c=='B' || c=='C' || c=='R' || c=='T' || c=='W' )
parse_state=1;
else
return(TOKENTYPE_UNRESERVED);
break;
case 1:
if( isdigit(c) )
parse_state=2;
else
return(TOKENTYPE_UNRESERVED);
break;
case 2:
case 3:
if( isdigit(c) )
{
parse_state++;
if( parse_state>3 )
return(TOKENTYPE_UNRESERVED);
}
else if( c=='.' )
parse_state=0;
else if( !c || c==' ' || c==0x9 )
return(flags);
else if( c=='+' )
{
/* Can not be an address or predec */
if( flags & (TOKENTYPE_FLG_REG_ADDR|TOKENTYPE_FLG_REG_PREDEC) )
return(TOKENTYPE_UNRESERVED);
/* Rest of type must match */
if( word[i]!=c || word[i+1]!=0 )
return(TOKENTYPE_UNRESERVED);
flags |= TOKENTYPE_FLG_REG_POSTINC;
return(flags);
}
else
return(TOKENTYPE_UNRESERVED);
break;
}
}
}
/*
// ProcessOp
//
// Opcode processor
//
// This is the function that assembles opcode statements
//
// ps - Pointer to source file record
// TermCnt - Number of terms (including the command)
// pTerms - Pointer to the terms
//
// Returns:
// 1 : Success
// 0 : Error
*/
int ProcessOp( SOURCEFILE *ps, int TermCnt, char **pTerms )
{
PRU_INST inst;
unsigned int opcode;
unsigned int utmp;
/* Get opcode */
inst.Op = CheckOpcode(pTerms[0]);
if( !inst.Op )
{ Report(ps,REP_ERROR,"Invalid opcode"); return(0); }
switch( inst.Op )
{
case OP_NOT:
/*
// Instruction in the form of:
// NOT Rdst, Rsrc, OP(255)
// NOT Rdst, Rsrc
*/
if( TermCnt!=3 && TermCnt!=4 )
{ Report(ps,REP_ERROR,"Expected 2 or 3 operands on NOT"); return(0); }
goto PARSE_ARITHMETIC;
case OP_ADD:
case OP_ADC:
case OP_SUB:
case OP_SUC:
case OP_LSL:
case OP_LSR:
case OP_RSB:
case OP_RSC:
case OP_AND:
case OP_OR:
case OP_XOR:
case OP_MIN:
case OP_MAX:
case OP_LMBD:
case OP_NOP0:
case OP_NOP1:
case OP_NOP2:
case OP_NOP3:
case OP_NOP4:
case OP_NOP5:
case OP_NOP6:
case OP_NOP7:
case OP_NOP8:
case OP_NOP9:
case OP_NOPA:
case OP_NOPB:
case OP_NOPC:
case OP_NOPD:
case OP_NOPE:
case OP_NOPF:
/*
// Instruction in the form of:
// OPCODE Rdst, Rsrc, OP(255)
*/
if( inst.Op==OP_LMBD && Core<CORE_V1 )
{ Report(ps,REP_ERROR,"Instruction illegal with specified core version"); return(0); }
if( inst.Op>=OP_NOP0 && inst.Op<=OP_NOPF && Core<CORE_V3 )
{ Report(ps,REP_ERROR,"Instruction illegal with specified core version"); return(0); }
if( TermCnt!=4 )
{ Report(ps,REP_ERROR,"Expected 3 operands"); return(0); }
PARSE_ARITHMETIC:
if( !GetRegister( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 0 ) )
return(0);
if( !GetRegister( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 0 ) )
return(0);
if( TermCnt==4 )
{
if( CheckTokenType(pTerms[3]) & TOKENTYPE_FLG_REG_BASE )
{
if( !GetRegister( ps, 3, pTerms[3], &(inst.Arg[2]), 0, 0 ) )
return(0);
}
else
{
if( !GetImValue( ps, 3, pTerms[3], &(inst.Arg[2]), 0, 255 ) )
return(0);
}
}
else
{
inst.Arg[2].Type = ARGTYPE_IMMEDIATE;
inst.Arg[2].Value = 0;
}
CODE_ARITHMETIC:
if( inst.Op>=OP_NOP0 && inst.Op<=OP_NOPF )
opcode = (0x50+inst.Op-OP_NOP0) << 25;
else if( inst.Op == OP_LMBD )
opcode = 0x13 << 25;
else if( inst.Op == OP_SCAN )
opcode = 0x14 << 25;
else
opcode = (inst.Op-OP_ADD) << 25;
opcode |= inst.Arg[0].Value;
opcode |= inst.Arg[0].Field << 5;
opcode |= inst.Arg[1].Value << 8;
opcode |= inst.Arg[1].Field << 13;
if( inst.Arg[2].Type == ARGTYPE_REGISTER )
{
opcode |= inst.Arg[2].Value << 16;
opcode |= inst.Arg[2].Field << 21;
}
else
{
opcode |= inst.Arg[2].Value << 16;
opcode |= 1<<24;
}
GenOp( ps, TermCnt, pTerms, opcode );
return(1);
case OP_CLR:
case OP_SET:
/*
// Instruction in the form of:
// OPCODE Rdst, Rsrc, OP(255) -or-
// OPCODE Rdst, Rsrc.Tnn -or-
// OPCODE Rdst, OP(255) -or-
// OPCODE Rdst.Tnn
*/
if( TermCnt<2 || TermCnt>4 )
{ Report(ps,REP_ERROR,"Expected 1 to 3 operands"); return(0); }
/* The 3 argument (4 term) variant can be parsed as arithmetic */
if( TermCnt==4 )
goto PARSE_ARITHMETIC;
else if( TermCnt==2 )
{
/*
// Hande "OPCODE Rdst.Tnn"
*/
if( !GetRegister( ps, 1, pTerms[1], &(inst.Arg[0]), 1, 0 ) )
return(0);
if( inst.Arg[0].Type != ARGTYPE_REGISTERBIT )
{ Report(ps,REP_ERROR,"Single operand mode must specify .T field"); return(0); }
/* 2nd arg = 1st arg, move bit# to 3rd arg */
inst.Arg[0].Type = ARGTYPE_REGISTER;
inst.Arg[1] = inst.Arg[0];
inst.Arg[2].Type = ARGTYPE_IMMEDIATE;
inst.Arg[2].Value = inst.Arg[0].Bit;
}
else
{
/*
// Handle "OPCODE Rdst, Rsrc.Tnn", and
// "OPCODE Rdst, OP(255)"
*/
if( !GetRegister( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 0 ) )
return(0);
if( CheckTokenType(pTerms[2]) & TOKENTYPE_FLG_REG_BASE )
{
if( !GetRegister( ps, 2, pTerms[2], &(inst.Arg[1]), 1, 0 ) )
return(0);
}
else
{
if( !GetImValue( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 31 ) )
return(0);
}
/* Patch up the args to the standard "arithmetic" form */
if( inst.Arg[1].Type == ARGTYPE_REGISTERBIT )
{
/* Here the 2nd arg is Rsrc.Tnn, move bit# to 3rd arg */
inst.Arg[1].Type = ARGTYPE_REGISTER;
inst.Arg[2].Type = ARGTYPE_IMMEDIATE;
inst.Arg[2].Value = inst.Arg[1].Bit;
}
else
{
/* Here the 2nd arg is OP(255), 3rd arg = 2nd arg, 2nd=1st */
inst.Arg[2] = inst.Arg[1];
inst.Arg[1] = inst.Arg[0];
}
}
goto CODE_ARITHMETIC;
case OP_LDI:
/*
// Instruction in the form of:
// LDI Rdst, &Rsrc
// LDI Rdst, #Im65535
*/
if( TermCnt != 3 )
{ Report(ps,REP_ERROR,"Expected 2 operands"); return(0); }
if( !GetRegister( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 0 ) )
{
return(0);
}
if( !GetImValue( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 65535 ) )
{
return(0);
}
opcode = 0x24 << 24;
opcode |= inst.Arg[0].Value;
opcode |= inst.Arg[0].Field << 5;
opcode |= inst.Arg[1].Value << 8;
GenOp( ps, TermCnt, pTerms, opcode );
return(1);
case OP_MOV:
/*
// Instruction in the form of:
// MOV Rdst, Rsrc -or-
// MOV Rdst, &Rsrc -or-
// MOV Rdst, #Imm
*/
if( TermCnt != 3 )
{ Report(ps,REP_ERROR,"Expected 2 operands"); return(0); }
/* If the second term is not reg, treat similar to LDI */
if( !(CheckTokenType(pTerms[2]) & TOKENTYPE_FLG_REG_BASE) )
{
// Unlike LDI, we will auto-select the best opcodes to implement the move
if( !GetRegister( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 0 ) )
{
return(0);
}
switch( inst.Arg[0].Field )
{
case FIELDTYPE_7_0:
case FIELDTYPE_15_8:
case FIELDTYPE_23_16:
case FIELDTYPE_31_24:
if( !GetImValue( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 255 ) )
return(0);
break;
case FIELDTYPE_15_0:
case FIELDTYPE_23_8:
case FIELDTYPE_31_16:
if( !GetImValue( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 65535 ) )
return(0);
break;
case FIELDTYPE_31_0:
if( !GetImValue( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 0xFFFFFFFF ) )
return(0);
// If the value is greater than 0xFFFF, code the upper half here
if( inst.Arg[1].Value > 0xFFFF )
{
opcode = 0x24 << 24;
opcode |= inst.Arg[0].Value;
opcode |= FIELDTYPE_31_16 << 5;
opcode |= (inst.Arg[1].Value>>16) << 8;
GenOp( ps, TermCnt, pTerms, opcode );
inst.Arg[0].Field = FIELDTYPE_15_0;
inst.Arg[1].Value &= 0xFFFF;
}
break;
default:
return(0);
}
opcode = 0x24 << 24;
opcode |= inst.Arg[0].Value;
opcode |= inst.Arg[0].Field << 5;
opcode |= inst.Arg[1].Value << 8;
GenOp( ps, TermCnt, pTerms, opcode );
return(1);
}
if( !GetRegister( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 0 ) )
return(0);
if( !GetRegister( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 0 ) )
return(0);
/* Code as an AND */
inst.Op = OP_AND;
inst.Arg[2] = inst.Arg[1];
goto CODE_ARITHMETIC;
case OP_SCAN:
/*
// Instruction in the form of:
// SCAN Rdst, OP(255)
*/
if( Core!=CORE_V1 )
{ Report(ps,REP_ERROR,"Instruction illegal with specified core version"); return(0); }
if( TermCnt!=3 )
{ Report(ps,REP_ERROR,"Expected 2 operands"); return(0); }
if( !GetRegister( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 0 ) )
return(0);
if( inst.Arg[0].Field != FIELDTYPE_31_0 )
{ Report(ps,REP_ERROR,"Register fields not allowed on operand 1"); return(0); }
inst.Arg[1] = inst.Arg[0];
if( CheckTokenType(pTerms[2]) & TOKENTYPE_FLG_REG_BASE )
{
if( !GetRegister( ps, 2, pTerms[2], &(inst.Arg[2]), 0, 0 ) )
return(0);
}
else
{
if( !GetImValue( ps, 2, pTerms[2], &(inst.Arg[2]), 0, 255 ) )
return(0);
}
goto CODE_ARITHMETIC;
case OP_MVIB:
/*
// Instruction in the form of:
// MVIB [*][&][--]Rdst[++], [*][&][--]Rsrc[++] [, bn]
*/
utmp = 1;
goto CODE_MVI;
case OP_MVIW:
/*
// Instruction in the form of:
// MVIW [*][&][--]Rdst[++], [*][&][--]Rsrc[++] [, bn]
*/
utmp = 2;
goto CODE_MVI;
case OP_MVID:
/*
// Instruction in the form of:
// MVID [*][&][--]Rdst[++], [*][&][--]Rsrc[++] [, bn]
*/
utmp = 4;
CODE_MVI:
if( Core<CORE_V1 )
{ Report(ps,REP_ERROR,"Instruction illegal with specified core version"); return(0); }
if( TermCnt==4 )
{ Report(ps,REP_ERROR,"3 operand mode not supported on this core"); return(0); }
else if( TermCnt!=3 )
{ Report(ps,REP_ERROR,"Expected 2 operands"); return(0); }
else
{
uint argtype;
int i;
for(i=1;i<=2;i++)
{
/* Params must be a register in this version */
argtype = CheckTokenType(pTerms[i]);
if( argtype == (TOKENTYPE_FLG_REG_PTR|TOKENTYPE_FLG_REG_ADDR) )
{
if( !GetImValue( ps, i, pTerms[i]+1, &(inst.Arg[i-1]), 0, 127 ) )
return(0);
if( !Offset2Reg( ps, i, &(inst.Arg[i-1]), inst.Arg[i-1].Value, utmp ) )
return(0);
}
else if( argtype == TOKENTYPE_FLG_REG_BASE )
{
if( !GetRegister( ps, i, pTerms[i], &(inst.Arg[i-1]), 0, 0 ) )
return(0);
}
else
goto CODE_MVI_PLUS;
}
/* Arg[1] must not be larger than the move size */
if( utmp == 1 && inst.Arg[1].Type == ARGTYPE_REGISTER )
{
switch(inst.Arg[1].Field)
{
case FIELDTYPE_15_0:
case FIELDTYPE_31_0:
inst.Arg[1].Field = FIELDTYPE_7_0;
break;
case FIELDTYPE_31_16:
inst.Arg[1].Field = FIELDTYPE_23_16;
break;
}
}
else if( utmp == 2 && inst.Arg[1].Type == ARGTYPE_REGISTER )
{
switch(inst.Arg[1].Field)
{
case FIELDTYPE_31_0:
inst.Arg[1].Field = FIELDTYPE_15_0;
break;
}
}
/* Code as an AND */
inst.Op = OP_AND;
inst.Arg[2] = inst.Arg[1];
goto CODE_ARITHMETIC;
}
CODE_MVI_PLUS:
if( Core<CORE_V2 )
{ Report(ps,REP_ERROR,"This form of MVIx illegal with specified core version"); return(0); }
else
{
int idx;
uint argtype;
char termC;
unsigned int itype;
argtype = CheckTokenType(pTerms[1]);
itype = 0;
termC = 0;
idx = 0;
if( (argtype & TOKENTYPE_FLG_REG_PTR) && !(argtype & TOKENTYPE_FLG_REG_ADDR) )
{
itype = 4;
idx = 1;
if( argtype & TOKENTYPE_FLG_REG_POSTINC )
{
itype = 8;
termC = '+';
}
else if( argtype & TOKENTYPE_FLG_REG_PREDEC )
{
itype = 12;
idx = 3;
}
}
if( argtype == (TOKENTYPE_FLG_REG_PTR|TOKENTYPE_FLG_REG_ADDR) )
{
if( !GetImValue( ps, 1, pTerms[1]+1, &(inst.Arg[0]), 0, 127 ) )
return(0);
if( !Offset2Reg( ps, 1, &(inst.Arg[0]), inst.Arg[0].Value, utmp ) )
return(0);
}
else
{
if( !GetRegister( ps, 1, pTerms[1]+idx, &(inst.Arg[0]), 0, termC ) )
return(0);
}
argtype = CheckTokenType(pTerms[2]);
termC = 0;
idx = 0;
if( (argtype & TOKENTYPE_FLG_REG_PTR) && !(argtype & TOKENTYPE_FLG_REG_ADDR) )
{
itype += 1;
idx = 1;
if( argtype & TOKENTYPE_FLG_REG_POSTINC )
{
itype += 1;
termC = '+';
}
else if( argtype & TOKENTYPE_FLG_REG_PREDEC )
{
itype += 2;
idx = 3;
}
}
if( argtype == (TOKENTYPE_FLG_REG_PTR|TOKENTYPE_FLG_REG_ADDR) )
{
if( !GetImValue( ps, 2, pTerms[2]+1, &(inst.Arg[1]), 0, 127 ) )
return(0);
if( !Offset2Reg( ps, 2, &(inst.Arg[1]), inst.Arg[1].Value, utmp ) )
return(0);
}
else
{
if( !GetRegister( ps, 2, pTerms[2]+idx, &(inst.Arg[1]), 0, termC ) )
return(0);
}
if( TermCnt==4 )
{
if( !GetR0offset( ps, 3, pTerms[3], &(inst.Arg[2]) ) )
return(0);
}
/* Validate pointers are R1.b0 to R1.b3 */
if( (itype>=4 && (inst.Arg[0].Value!=1 || inst.Arg[0].Field>FIELDTYPE_31_24)) ||
(itype%4 && (inst.Arg[1].Value!=1 || inst.Arg[1].Field>FIELDTYPE_31_24)) )
{ Report(ps,REP_ERROR,"RegFile pointers must be R1.b0 through R1.b3"); return(0); }
if( itype==0 )
{ Report(ps,REP_ERROR,"No indirection specified (use MOV)"); return(0); }
opcode = 0x16 << 25;
opcode |= itype << 21;
if( TermCnt==4 )
{
opcode |= 1 << 20;
opcode |= inst.Arg[2].Value << 18;
}
opcode |= (utmp/2) << 16;
opcode |= inst.Arg[0].Value;
opcode |= inst.Arg[0].Field << 5;
opcode |= inst.Arg[1].Value << 8;
opcode |= inst.Arg[1].Field << 13;
}
GenOp( ps, TermCnt, pTerms, opcode );
return(1);
case OP_HALT:
if( Core<CORE_V1 )
{ Report(ps,REP_ERROR,"Instruction illegal with specified core version"); return(0); }
if( TermCnt != 1 )
{ Report(ps,REP_ERROR,"Expected no operands"); return(0); }
opcode = 0x15 << 25;
GenOp( ps, TermCnt, pTerms, opcode );
return(1);
case OP_SLP:
if( Core<CORE_V1 )
{ Report(ps,REP_ERROR,"Instruction illegal with specified core version"); return(0); }
if( TermCnt != 2 )
{ Report(ps,REP_ERROR,"Expected 1 operand"); return(0); }
opcode = 0x1F << 25;
if( !GetImValue( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 1 ) )
return(0);
opcode |= inst.Arg[0].Value << 23;
GenOp( ps, TermCnt, pTerms, opcode );
if( Core<CORE_V3 )
{
opcode = 0x8 << 25;
GenOp( ps, TermCnt, pTerms, opcode );
}
return(1);
case OP_SBBO:
opcode = 0xE << 28;
goto BURST_OPCODE;
case OP_LBBO:
opcode = 0xF << 28;
goto BURST_OPCODE;
case OP_SBCO:
opcode = 0x8 << 28;
goto BURST_OPCODE;
case OP_LBCO:
opcode = 0x9 << 28;
BURST_OPCODE:
/*
// Instruction in the form of:
// OPCODE Rdst, Rnn/Cnn, OP(255), n -or-
// OPCODE Rdst, Rnn/Cnn, OP(255), bn
*/
if( TermCnt != 5 )
{ Report(ps,REP_ERROR,"Expected 4 operands"); return(0); }
if( CheckTokenType(pTerms[1]) & TOKENTYPE_FLG_REG_BASE )
{
if( !GetRegister( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 0 ) )
return(0);
}
else
{
if( !GetImValue( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 127 ) )
return(0);
}
if( inst.Op==OP_SBBO || inst.Op==OP_LBBO )
{
if( !GetRegister( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 0 ) )
return(0);
if( inst.Arg[1].Field != FIELDTYPE_31_0 )
{ Report(ps,REP_ERROR,"Register fields not allowed on operand 2"); return(0); }
}
else
{
if( !GetConstant( ps, 2, pTerms[2], &(inst.Arg[1]) ) )
return(0);
}
if( CheckTokenType(pTerms[3]) & TOKENTYPE_FLG_REG_BASE )
{
if( !GetRegister( ps, 3, pTerms[3], &(inst.Arg[2]), 0, 0 ) )
return(0);
}
else
{
if( !GetImValue(ps, 3, pTerms[3], &(inst.Arg[2]), 0, 255) )
return(0);
}
if( CheckTokenType(pTerms[4]) & TOKENTYPE_FLG_REG_BASE )
{
if( !GetR0offset( ps, 4, pTerms[4], &(inst.Arg[3]) ) )
return(0);
}
else
{
if( !GetImValue( ps, 4, pTerms[4], &(inst.Arg[3]), 1, 124 ) )
return(0);
}
if( inst.Arg[0].Type == ARGTYPE_IMMEDIATE )
{
opcode |= (inst.Arg[0].Value>>2) & 0x1F;
opcode |= (inst.Arg[0].Value&0x3) << 5;
}
else
{
opcode |= inst.Arg[0].Value;
if( !(Options & OPTION_BIGENDIAN) )
{
/*
// ** Little Endian Version **
*/
switch( inst.Arg[0].Field )
{
case FIELDTYPE_15_8:
case FIELDTYPE_23_8:
opcode |= 1<<5;
break;
case FIELDTYPE_23_16:
case FIELDTYPE_31_16:
opcode |= 2<<5;
break;
case FIELDTYPE_31_24:
opcode |= 3<<5;
break;
}
}
else
{
/*
// ** Big Endian Version **
*/
switch( inst.Arg[0].Field )
{
case FIELDTYPE_23_16:
case FIELDTYPE_23_8:
opcode |= 1<<5;
break;
case FIELDTYPE_15_0:
case FIELDTYPE_15_8:
opcode |= 2<<5;
break;
case FIELDTYPE_7_0:
opcode |= 3<<5;
break;
}
}
}
opcode |= inst.Arg[1].Value << 8;
if( inst.Arg[2].Type == ARGTYPE_REGISTER )
{
opcode |= inst.Arg[2].Value << 16;
opcode |= inst.Arg[2].Field << 21;
}
else
{
opcode |= inst.Arg[2].Value << 16;
opcode |= 1<<24;
}
if( inst.Arg[3].Type == ARGTYPE_R0BYTE )
utmp = inst.Arg[3].Value + 124;
else
utmp = inst.Arg[3].Value - 1;
opcode |= (utmp&0x70)<<(25-4);
opcode |= (utmp&0x0E)<<(13-1);
opcode |= (utmp&0x01)<<7;
GenOp( ps, TermCnt, pTerms, opcode );
return(1);
case OP_SXIN:
opcode = (0x5D << 23) | (1 << 14);
goto CODE_XFR_V3;
case OP_SXOUT:
opcode = (0x5E << 23) | (1 << 14);
goto CODE_XFR_V3;
case OP_SXCHG:
opcode = (0x5F << 23) | (1 << 14);
goto CODE_XFR_V3;
case OP_XIN:
opcode = 0x5D << 23;
goto CODE_XFR;
case OP_XOUT:
opcode = 0x5E << 23;
goto CODE_XFR;
case OP_XCHG:
opcode = 0x5F << 23;
goto CODE_XFR;
CODE_XFR_V3:
if( Core<CORE_V3 )
{ Report(ps,REP_ERROR,"Instruction illegal with specified core version"); return(0); }
CODE_XFR:
/*
// Instruction in the form of:
// OPCODE IM(511), Rdst, OP(124), n -or-
// OPCODE IM(511), Rdst, bn
*/
if( Core<CORE_V2 )
{ Report(ps,REP_ERROR,"Instruction illegal with specified core version"); return(0); }
if( TermCnt != 4 )
{ Report(ps,REP_ERROR,"Expected 3 operands"); return(0); }
if( !GetImValue( ps, 1, pTerms[1], &(inst.Arg[0]), 0, 253 ) )
return(0);
if( CheckTokenType(pTerms[2]) & TOKENTYPE_FLG_REG_BASE )
{
if( !GetRegister( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 0 ) )
return(0);
if( inst.Arg[1].Value==31 )
{ Report(ps,REP_ERROR,"Operand 2 R31 is illegal"); return(0); }
}
else
{
if( !GetImValue( ps, 2, pTerms[2], &(inst.Arg[1]), 0, 123 ) )
return(0);
gitextract__f3o1sre/
├── .gitignore
├── Makefile
├── Makefile.common
├── README.md
├── Setup.md
├── am335x/
│ ├── app_loader/
│ │ ├── include/
│ │ │ ├── pruss_intc_mapping.h
│ │ │ └── prussdrv.h
│ │ └── interface/
│ │ ├── Makefile
│ │ ├── __prussdrv.h
│ │ └── prussdrv.c
│ └── pasm/
│ ├── LICENCE.txt
│ ├── Makefile
│ ├── pasm.c
│ ├── pasm.h
│ ├── pasmdbg.h
│ ├── pasmdot.c
│ ├── pasmexp.c
│ ├── pasmmacro.c
│ ├── pasmop.c
│ ├── pasmpp.c
│ ├── pasmstruct.c
│ └── pru_ins.h
├── brackets/
│ ├── Letters.dxf
│ ├── Write.scad
│ ├── flat-bracket.scad
│ ├── matrix-bracket.scad
│ ├── octoscroller.scad
│ └── spiral.scad
├── default.config
├── dts/
│ ├── CAPE-BONE-OCTO-00A0.dtbo
│ ├── LEDscape.dts
│ ├── README.md
│ ├── angstrom.dtb
│ ├── angstrom.dts
│ ├── cape-bone-octo.dts
│ └── ubuntu-3.8.13-bone32.dts
├── fonts/
│ ├── json2bmp
│ └── mta-sign.json
├── lib/
│ └── .empty
├── obj/
│ └── .empty
├── pcb/
│ ├── LEDscape pin assignments.csv
│ ├── LEDscape.brd
│ ├── LEDscape.lbr
│ ├── LEDscape.sch
│ ├── TODO
│ ├── flat-20mm.scad
│ ├── lightbuddy-transmitter.brd
│ ├── lightbuddy-transmitter.sch
│ ├── octoscroller.brd
│ ├── octoscroller.sch
│ ├── receiver-2x.brd
│ ├── receiver-2x.sch
│ ├── receiver-4x.brd
│ ├── receiver-4x.sch
│ ├── receiver.brd
│ └── receiver.sch
├── radials.config
├── src/
│ ├── demos/
│ │ ├── Makefile
│ │ ├── companion-cube.raw
│ │ ├── cube-image.c
│ │ ├── cube-life.c
│ │ ├── fire.c
│ │ ├── identify.c
│ │ ├── life.c
│ │ ├── lightcycles.c
│ │ └── matrix-test.c
│ ├── ledscape/
│ │ ├── Makefile
│ │ ├── bitpattern.h
│ │ ├── config.c
│ │ ├── fixed-font.c
│ │ ├── ledscape.c
│ │ ├── ledscape.h
│ │ ├── matrix.p
│ │ ├── pru.c
│ │ ├── pru.h
│ │ ├── util.c
│ │ ├── util.h
│ │ ├── ws281x.hp
│ │ └── ws281x.p
│ ├── mta/
│ │ ├── Makefile
│ │ ├── mta-font.c
│ │ └── mta-sign.c
│ ├── net/
│ │ ├── Makefile
│ │ ├── matrix-tcp-rx.c
│ │ ├── matrix-udp-rx.c
│ │ └── opc-rx.c
│ ├── perlin/
│ │ ├── Makefile
│ │ ├── gammalut.h
│ │ ├── globals.h
│ │ ├── knobs/
│ │ │ └── knobs.ino
│ │ ├── pattern.cpp
│ │ ├── pattern.h
│ │ ├── perlin-ledscape.cpp
│ │ ├── pf2.cpp
│ │ └── pf2.h
│ └── script/
│ ├── Makefile
│ ├── bbb-network-setup
│ ├── find-serial
│ ├── install
│ ├── ledscape.service
│ ├── python-test
│ ├── run-ledscape
│ ├── run-videoplayer
│ ├── twitter-scroller
│ ├── videoplayer
│ └── videoplayer.service
├── strips.config
├── tall-cylinder.config
└── ubuntu/
└── ledscape.conf
SYMBOL INDEX (235 symbols across 34 files)
FILE: am335x/app_loader/include/prussdrv.h
type tsysevt_to_channel_map (line 88) | typedef struct __sysevt_to_channel_map {
type tchannel_to_host_map (line 92) | typedef struct __channel_to_host_map {
type tpruss_intc_initdata (line 96) | typedef struct __pruss_intc_initdata {
FILE: am335x/app_loader/interface/__prussdrv.h
type tprussdrv (line 192) | typedef struct __prussdrv {
function __pruss_detect_hw_version (line 242) | int __pruss_detect_hw_version(unsigned int *pruss_io)
function __prussintc_set_cmr (line 258) | void __prussintc_set_cmr(unsigned int *pruintc_io, unsigned short sysevt,
function __prussintc_set_hmr (line 267) | void __prussintc_set_hmr(unsigned int *pruintc_io, unsigned short channel,
FILE: am335x/app_loader/interface/prussdrv.c
function __prussdrv_memmap_init (line 60) | int __prussdrv_memmap_init(void)
function prussdrv_init (line 239) | int prussdrv_init(void)
function prussdrv_open (line 246) | int prussdrv_open(unsigned int pru_evtout_num)
function prussdrv_pru_reset (line 262) | int prussdrv_pru_reset(unsigned int prunum)
function prussdrv_pru_enable (line 275) | int prussdrv_pru_enable(unsigned int prunum)
function prussdrv_pru_disable (line 290) | int prussdrv_pru_disable(unsigned int prunum)
function prussdrv_pru_write_memory (line 304) | int prussdrv_pru_write_memory(unsigned int pru_ram_id,
function prussdrv_pruintc_init (line 342) | int prussdrv_pruintc_init(tpruss_intc_initdata * prussintc_init_data)
function prussdrv_pru_send_event (line 411) | int prussdrv_pru_send_event(unsigned int eventnum)
function prussdrv_pru_wait_event (line 421) | int prussdrv_pru_wait_event(unsigned int pru_evtout_num)
function prussdrv_pru_clear_event (line 431) | int prussdrv_pru_clear_event(unsigned int eventnum)
function prussdrv_pru_send_wait_clear_event (line 441) | int prussdrv_pru_send_wait_clear_event(unsigned int send_eventnum,
function prussdrv_map_l3mem (line 453) | int prussdrv_map_l3mem(void **address)
function prussdrv_map_extmem (line 461) | int prussdrv_map_extmem(void **address)
function prussdrv_map_prumem (line 470) | int prussdrv_map_prumem(unsigned int pru_ram_id, void **address)
function prussdrv_map_peripheral_io (line 491) | int prussdrv_map_peripheral_io(unsigned int per_id, void **address)
function prussdrv_get_phys_addr (line 522) | unsigned int prussdrv_get_phys_addr(void *address)
function prussdrv_exit (line 575) | int prussdrv_exit()
function prussdrv_exec_program (line 590) | int prussdrv_exec_program(int prunum, char *filename)
function prussdrv_start_irqthread (line 639) | int prussdrv_start_irqthread(unsigned int pru_evtout_num, int priority,
FILE: am335x/pasm/pasm.c
function main (line 154) | int main(int argc, char *argv[])
function ProcessSourceFile (line 716) | int ProcessSourceFile( SOURCEFILE *ps )
function ProcessSourceLine (line 747) | int ProcessSourceLine( SOURCEFILE *ps, int length, char *src )
function ParseSourceLine (line 839) | int ParseSourceLine( SOURCEFILE *ps, int length, char *src, SRCLINE *pa )
function GenOp (line 970) | void GenOp( SOURCEFILE *ps, int TermCnt, char **pTerms, uint opcode )
function Report (line 1008) | void Report( SOURCEFILE *ps, int Level, char *fmt, ... )
function LabelChar (line 1058) | int LabelChar( char c, int FlagFirstChar )
function LabelCreate (line 1081) | int LabelCreate( SOURCEFILE *ps, char *label, int value )
function LABEL (line 1122) | LABEL *LabelFind( char *name )
function LabelDestroy (line 1144) | void LabelDestroy( LABEL *pl )
function CheckName (line 1165) | int CheckName( SOURCEFILE *ps, char *name )
function ValidateOffset (line 1195) | static int ValidateOffset( SOURCEFILE *ps )
function PrintLine (line 1239) | static int PrintLine( FILE *pfOut, SOURCEFILE *ps )
function GetInfoFromAddr (line 1267) | static int GetInfoFromAddr( uint address, uint *pIndex, uint *pLineNo, u...
function ListFile (line 1291) | static int ListFile( FILE *pfOut, SOURCEFILE *ps )
FILE: am335x/pasm/pasm.h
type uint (line 60) | typedef unsigned int uint;
type LABEL (line 68) | typedef struct _LABEL {
type SOURCEFILE (line 78) | typedef struct _SOURCEFILE {
type SRCLINE (line 96) | typedef struct _SRCLINE {
type CODEGEN (line 104) | typedef struct _CODEGEN {
FILE: am335x/pasm/pasmdbg.h
type DBGFILE_HEADER (line 63) | typedef struct _DBGFILE_HEADER {
type DBGFILE_LABEL (line 77) | typedef struct _DBGFILE_LABEL {
type DBGFILE_FILE (line 82) | typedef struct _DBGFILE_FILE {
type DBGFILE_CODE (line 86) | typedef struct _DBGFILE_CODE {
FILE: am335x/pasm/pasmdot.c
function CheckDotCommand (line 109) | int CheckDotCommand( char *word )
function DotCommand (line 139) | int DotCommand( SOURCEFILE *ps, int TermCnt, char **pTerms, char *Src, i...
function DotInitialize (line 426) | void DotInitialize(int pass)
function DotCleanup (line 440) | void DotCleanup(int pass)
FILE: am335x/pasm/pasmexp.c
function Expression (line 109) | int Expression( SOURCEFILE *ps, char *s, uint *pResult, int *pIndex )
function EXP_getValue (line 248) | int EXP_getValue( SOURCEFILE *ps, char *s, int *pIdx, uint *pValue )
function EXP_getOperation (line 420) | int EXP_getOperation( SOURCEFILE *ps, char *s, int *pIdx, uint *pValue )
function GetRegisterOffset (line 491) | static int GetRegisterOffset( char *src, uint *pValue )
FILE: am335x/pasm/pasmmacro.c
type MACRO (line 80) | typedef struct _MACRO {
function MacroEnter (line 123) | int MacroEnter( SOURCEFILE *ps, char *Name )
function ProcessMacro (line 209) | int ProcessMacro( SOURCEFILE *ps, int TermCnt, char **pTerms )
function MacroCleanup (line 331) | void MacroCleanup()
function CheckMacro (line 345) | int CheckMacro( char *name )
function _strncat (line 360) | static int _strncat( char *dst, int len, char *src )
function MACRO (line 391) | static MACRO *MacroFind( char *Name )
function MACRO (line 413) | static MACRO *MacroCreate( SOURCEFILE *ps, char *Name )
function MacroAddArg (line 459) | int MacroAddArg( SOURCEFILE *ps, MACRO *pm, char *ArgText )
function MacroDestroy (line 548) | static void MacroDestroy( MACRO *pm )
FILE: am335x/pasm/pasmop.c
function CheckOpcode (line 98) | int CheckOpcode( char *word )
function uint (line 118) | uint CheckTokenType( char *word )
function ProcessOp (line 250) | int ProcessOp( SOURCEFILE *ps, int TermCnt, char **pTerms )
function GetRegister (line 1644) | int GetRegister( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa, int fB...
function GetImValue (line 1799) | static int GetImValue( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa, ...
function GetConstant (line 1856) | static int GetConstant( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa )
function GetR0offset (line 1910) | static int GetR0offset( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa )
function GetJmpOffset (line 1964) | static int GetJmpOffset( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa )
function GetLoopOffset (line 2010) | static int GetLoopOffset( SOURCEFILE *ps, int num, char *src, PRU_ARG *pa )
function Offset2Reg (line 2055) | static int Offset2Reg( SOURCEFILE *ps, int num, PRU_ARG *pa, uint addr, ...
FILE: am335x/pasm/pasmpp.c
type EQUATE (line 79) | typedef struct _EQUATE {
function SOURCEFILE (line 128) | SOURCEFILE *InitSourceFile( SOURCEFILE *pParent, char *filename )
function CloseSourceFile (line 277) | void CloseSourceFile( SOURCEFILE *ps )
function GetSourceLine (line 298) | int GetSourceLine( SOURCEFILE *ps, char *Dst, int MaxLen )
function ppCleanup (line 427) | void ppCleanup()
function EquateCreate (line 442) | int EquateCreate( SOURCEFILE *ps, char *Name, char *Value )
function CheckEquate (line 488) | int CheckEquate( char *name )
function ReadCharacter (line 509) | static int ReadCharacter( SOURCEFILE *ps )
function GetTextLine (line 541) | static int GetTextLine( SOURCEFILE *ps, char *Dst, int MaxLen, int *pLen...
function ParseSource (line 631) | static int ParseSource( SOURCEFILE *ps, char *Src, char *Dst, int *pIdx,...
function LoadInclude (line 747) | static int LoadInclude( SOURCEFILE *ps, char *Src )
function EquateProcess (line 835) | static int EquateProcess( SOURCEFILE *ps, char *Src )
function UndefProcess (line 930) | static int UndefProcess( SOURCEFILE *ps, char *Src )
function EQUATE (line 986) | static EQUATE *EquateFind( char *name )
function EquateDestroy (line 1008) | static void EquateDestroy( EQUATE *peq )
function IfDefProcess (line 1029) | static int IfDefProcess( SOURCEFILE *ps, char *Src, int fTrue )
function ElseProcess (line 1111) | static int ElseProcess( SOURCEFILE *ps, char *Src )
function EndifProcess (line 1148) | static int EndifProcess( SOURCEFILE *ps, char *Src )
FILE: am335x/pasm/pasmstruct.c
type STRUCT (line 75) | typedef struct _STRUCT {
type ASSIGN (line 87) | typedef struct _ASSIGN {
type SCOPE (line 102) | typedef struct _SCOPE {
function ScopeEnter (line 153) | int ScopeEnter( SOURCEFILE *ps, char *Name )
function ScopeLeave (line 170) | int ScopeLeave( SOURCEFILE *ps, char *Name )
function ScopeUsing (line 191) | int ScopeUsing( SOURCEFILE *ps, char *Name )
function StructInit (line 211) | void StructInit()
function StructCleanup (line 222) | void StructCleanup()
function StructNew (line 238) | int StructNew( SOURCEFILE *ps, char *Name )
function StructEnd (line 258) | int StructEnd(SOURCEFILE *ps)
function StructAddElement (line 276) | int StructAddElement( SOURCEFILE *ps, char *Name, uint size )
function StructAssign (line 327) | int StructAssign( SOURCEFILE *ps, char *structName, char *rsName,
function StructParamProcess (line 526) | int StructParamProcess( SOURCEFILE *ps, int ParamIdx, char *source )
function CheckStruct (line 667) | int CheckStruct( char *name )
function STRUCT (line 688) | static STRUCT *StructFind( char *Name )
function STRUCT (line 710) | static STRUCT *StructCreate( SOURCEFILE *ps, char *Name )
function StructDestroy (line 751) | static void StructDestroy( STRUCT *pst )
function GetRegname (line 773) | static int GetRegname( SOURCEFILE *ps, uint element, char *str, uint off...
function ASSIGN (line 813) | static ASSIGN *AssignFind( char *Name )
function ASSIGN (line 844) | static ASSIGN *AssignCreate( SOURCEFILE *ps, ASSIGN **pList, char *Name )
function AssignDestroy (line 883) | static void AssignDestroy( ASSIGN **pList, ASSIGN *pas )
function StructValueOperand (line 958) | static int StructValueOperand( char *source, int CmdType, uint *pValue )
function GetFinalSize (line 1081) | static int GetFinalSize( char *ext, uint Size, uint *pValue )
function GetFinalOffset (line 1111) | static int GetFinalOffset( char *ext, uint Size, uint Offset, uint *pVal...
function SCOPE (line 1148) | static SCOPE *ScopeCreate( SOURCEFILE *ps, char *Name )
function ScopeDestroy (line 1194) | static void ScopeDestroy( SCOPE *psc )
function ScopeClose (line 1221) | static void ScopeClose( SCOPE *psc )
function SCOPE (line 1237) | static SCOPE *ScopeFind( char *Name )
FILE: am335x/pasm/pru_ins.h
type PRU_ARG (line 60) | typedef struct _PRU_ARG {
type PRU_INST (line 95) | typedef struct _PRU_INST {
FILE: src/demos/cube-image.c
function main (line 15) | int
FILE: src/demos/cube-life.c
type game_t (line 39) | typedef struct game game_t;
type edge_t (line 40) | typedef struct {
type game (line 45) | struct game
function randomize (line 60) | static void
function make_glider (line 82) | static void
function get_edge (line 139) | static uint8_t
function get_space (line 152) | static unsigned
function play_game (line 184) | static void
function identify (line 236) | static void
function copy_to_fb (line 279) | static void
function check_edge (line 337) | static void
function main (line 375) | int
FILE: src/demos/fire.c
function h2rgb (line 20) | static unsigned int
function hsv2rgb (line 47) | static uint32_t
function fire_draw (line 90) | static void
function sparkles (line 148) | static void
function constrain (line 158) | static int constrain(
function init_pallete (line 171) | static void
function main (line 196) | int
FILE: src/demos/identify.c
function main (line 14) | int
FILE: src/demos/life.c
type game_t (line 27) | typedef struct
function randomize (line 35) | static void
function make_glider (line 57) | static void
function get_space (line 82) | static unsigned
function play_game (line 105) | static void
function copy_to_fb (line 158) | static void
function main (line 214) | int
FILE: src/demos/lightcycles.c
type player_t (line 23) | typedef struct {
function player_update (line 34) | int
function fill (line 89) | static void
function new_game (line 100) | void
function tcp_socket (line 118) | static int
function rgb32_to_rgb24_and_decay (line 143) | static
function send_game (line 173) | static void
type termios (line 195) | struct termios
function tty_raw (line 197) | static void
function tty_reset (line 211) | static void
function set_dir (line 220) | static void
function bomb (line 239) | static void
function main (line 295) | int main(void)
FILE: src/demos/matrix-test.c
function h2rgb (line 16) | static unsigned int
function makeColor (line 43) | static uint32_t
function rainbow (line 91) | static void
function gradient (line 133) | static void
function main (line 197) | int
FILE: src/ledscape/config.c
function readline (line 12) | static ssize_t
function ledscape_config_t (line 42) | ledscape_config_t *
function ledscape_config_t (line 107) | ledscape_config_t *
function ledscape_config_t (line 144) | ledscape_config_t *
FILE: src/ledscape/ledscape.c
function ledscape_gpio_init (line 59) | static void
type ws281x_command_t (line 80) | typedef struct
type led_matrix_t (line 96) | typedef struct
type led_matrix_config_t (line 104) | typedef struct
type ledscape (line 114) | struct ledscape
function ledscape_frame_t (line 127) | ledscape_frame_t *
function bright_map (line 141) | static uint8_t
function ledscape_matrix_panel_copy (line 193) | static void
function ledscape_matrix_draw (line 255) | static void
function ledscape_strip_draw (line 317) | void
function ledscape_wait (line 363) | uint32_t
function ledscape_t (line 379) | static ledscape_t *
function ledscape_t (line 424) | static ledscape_t *
function ledscape_t (line 481) | ledscape_t *
function ledscape_draw (line 500) | void
function ledscape_close (line 521) | void
function ledscape_set_color (line 532) | void
function ledscape_draw_char (line 552) | void
function ledscape_printf (line 574) | void
FILE: src/ledscape/ledscape.h
type ledscape_matrix_panel_t (line 24) | typedef struct {
type ledscape_matrix_config_t (line 33) | typedef struct {
type ledscape_strip_config_t (line 45) | typedef struct {
type ledscape_config_t (line 52) | typedef union {
type ledscape_pixel_t (line 64) | typedef struct {
type ledscape_frame_t (line 78) | typedef struct {
type ledscape_t (line 83) | typedef struct ledscape ledscape_t;
FILE: src/ledscape/pru.c
function proc_read (line 20) | static unsigned int
function pru_t (line 35) | pru_t *
function pru_exec (line 111) | void
function pru_close (line 123) | void
function pru_gpio (line 136) | int
FILE: src/ledscape/pru.h
type pru_t (line 18) | typedef struct
FILE: src/ledscape/util.c
function write_all (line 24) | ssize_t
function serial_open (line 54) | int
function hexdump (line 74) | void
FILE: src/mta/mta-sign.c
function font_write (line 19) | static int
function main (line 102) | int
FILE: src/net/matrix-tcp-rx.c
function tcp_socket (line 30) | static int
function wait_socket (line 57) | static int
function recv_all (line 71) | static ssize_t
type option (line 95) | struct option
function usage (line 110) | static void usage(void)
function main (line 119) | int
FILE: src/net/matrix-udp-rx.c
function udp_socket (line 30) | static int
function wait_socket (line 51) | static int
type option (line 65) | struct option
function usage (line 80) | static void usage(void)
function main (line 87) | int
FILE: src/net/opc-rx.c
type opc_cmd_t (line 22) | typedef struct
function tcp_socket (line 30) | static int
function main (line 53) | int
FILE: src/perlin/pattern.h
function class (line 27) | class Pattern
FILE: src/perlin/perlin-ledscape.cpp
function main (line 97) | int main (int argc, char *argv[])
function Quit (line 164) | void Quit (int sig)
function BlankDisplay (line 170) | void BlankDisplay (void)
function WriteLevels (line 184) | void WriteLevels (void)
FILE: src/perlin/pf2.cpp
function grad3 (line 261) | static inline int16_t grad3(const uint8_t h, const int16_t x, const int1...
FILE: src/perlin/pf2.h
function class (line 46) | class Perlin : public Pattern
Condensed preview — 109 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,964K chars).
[
{
"path": ".gitignore",
"chars": 107,
"preview": ".*.swp\n.*.swo\n*.i\n*.o\n*.a\n*.bin\npcb/*.b[^r][^d]\npcb/*.p[^c][^b]\nrgb-test\nam335x/pasm/pasm\n.*.d\n*~\n*~\nbin/*\n"
},
{
"path": "Makefile",
"chars": 428,
"preview": "#########\n#\n# Top level Makefile.\n# Mostly just recurse into subdirectories.\n\nSUBDIR-y += src/ledscape\nSUBDIR-y += src/d"
},
{
"path": "Makefile.common",
"chars": 3594,
"preview": "#########\n#\n# Common build targets\n#\n#\n\nTOP ?= ../..\nOBJDIR ?= $(TOP)/obj\nLIBDIR ?= $(TOP)/lib\nBINDIR ?= $(TOP)/bin\n\nall"
},
{
"path": "README.md",
"chars": 3833,
"preview": "\n\nDANGER!\n=======\n\nThis co"
},
{
"path": "Setup.md",
"chars": 8267,
"preview": "# Getting Started\n\nThis is a quick introduction on how to set up LEDscape on a Debian-based image\n\n# Setting up the BBB "
},
{
"path": "am335x/app_loader/include/pruss_intc_mapping.h",
"chars": 4298,
"preview": "/*\n * pruss_intc_mapping.h\n * \n * Example PRUSS INTC mapping for the application\n *\n * Copyright (C) 2010 Texas Instrume"
},
{
"path": "am335x/app_loader/include/prussdrv.h",
"chars": 5666,
"preview": "/*\n * prussdrv.h\n * \n * Describes PRUSS userspace driver for Industrial Communications\n *\n * Copyright (C) 2010 Texas In"
},
{
"path": "am335x/app_loader/interface/Makefile",
"chars": 1311,
"preview": "ROOTDIR = ..\nTARGET = libprussdrv\nCROSS_COMPILE?=arm-linux-gnueabi-\n\nCC = $(CROSS_COMPILE)gcc\nAR = $(CROSS_COMPILE)ar\n\nI"
},
{
"path": "am335x/app_loader/interface/__prussdrv.h",
"chars": 9350,
"preview": "/*\n * __prussdrv.h\n * \n *\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ \n * \n * \n * Redistr"
},
{
"path": "am335x/app_loader/interface/prussdrv.c",
"chars": 21243,
"preview": "/*\n * prussdrv.c\n *\n * User space driver for PRUSS\n *\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www."
},
{
"path": "am335x/pasm/LICENCE.txt",
"chars": 1610,
"preview": "/*\n* {module name}\n*\n* {module description}\n*\n* Copyright (C) {YEAR} Texas Instruments Incorporated - http://www.ti.com/"
},
{
"path": "am335x/pasm/Makefile",
"chars": 267,
"preview": "# Builds with whatever the host format is\nCC := gcc\n\nCFLAGS += \\\n\t-O3 \\\n\t-W \\\n\t-Wall \\\n\t-D_UNIX_ \\\n\nOBJS := \\\n\tpasm.o \\\n"
},
{
"path": "am335x/pasm/pasm.c",
"chars": 41810,
"preview": "/*\r\n * pasm.c\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistribution"
},
{
"path": "am335x/pasm/pasm.h",
"chars": 16014,
"preview": "/*\r\n * pasm.h\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistribution"
},
{
"path": "am335x/pasm/pasmdbg.h",
"chars": 4052,
"preview": "/*\r\n * pasmdbg.h\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistribut"
},
{
"path": "am335x/pasm/pasmdot.c",
"chars": 13725,
"preview": "/*\r\n * pasmdot.c\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistribut"
},
{
"path": "am335x/pasm/pasmexp.c",
"chars": 14620,
"preview": "/*\r\n * pasmexp.c\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistribut"
},
{
"path": "am335x/pasm/pasmmacro.c",
"chars": 16299,
"preview": "/*\r\n * pasmmacro.c\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistrib"
},
{
"path": "am335x/pasm/pasmop.c",
"chars": 64422,
"preview": "/*\r\n * pasmop.c\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistributi"
},
{
"path": "am335x/pasm/pasmpp.c",
"chars": 30508,
"preview": "/*\r\n * pasmpp.c\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistributi"
},
{
"path": "am335x/pasm/pasmstruct.c",
"chars": 32390,
"preview": "/*\r\n * pasmstruct.c\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistri"
},
{
"path": "am335x/pasm/pru_ins.h",
"chars": 7450,
"preview": "/*\r\n * pru_ins.h\r\n *\r\n * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/\r\n *\r\n *\r\n * Redistribut"
},
{
"path": "brackets/Letters.dxf",
"chars": 97975,
"preview": "999\r\nDXF created by Inkscape\r\n 0\r\nSECTION\r\n 2\r\nHEADER\r\n 9\r\n$ACADVER\r\n 1\r\nAC1014\r\n 9\r\n$HANDSEED\r\n 5\r\nFFFF\r\n 9\r\n$ME"
},
{
"path": "brackets/Write.scad",
"chars": 13635,
"preview": "/* \tVersion 4\r\n\tAdded bold property bold=0 (not bold) bold=1(bolder by 1.1) bold=2(bolder by 1.2) \r\n\tAdded support for "
},
{
"path": "brackets/flat-bracket.scad",
"chars": 838,
"preview": "/** \\file\n * mounting bracket for 15mm extrusion.\n */\n\n\nmodule bracket()\n{\n\ttranslate([0,0,-3]) linear_extrude(height=3)"
},
{
"path": "brackets/matrix-bracket.scad",
"chars": 515,
"preview": "/** \\file\n * Bracket to hold a 16x2 LED panel in an Octoscroller configuration.\n */\n\nmodule bracket_half()\n{\n\trender() d"
},
{
"path": "brackets/octoscroller.scad",
"chars": 3548,
"preview": "/** \\file\n * 3D printed brackets for N sided LED matrix displays.\n *\n * Horizontal or vertical connections are possible."
},
{
"path": "brackets/spiral.scad",
"chars": 1047,
"preview": "/** \\file\n * 3D printed brackets for spiral matrix display\n *\n * Horizontal or vertical connections are possible.\n * The"
},
{
"path": "default.config",
"chars": 801,
"preview": "matrix16\n0,0 N 0,0\n0,1 N 32,0\n0,2 N 64,0\n0,3 N 96,0\n0,4 N 128,0\n0,5 N 160,0\n0,6 N 192,0\n0,7 N 224,0\n1,0 N 0,16\n1,1 N 32,"
},
{
"path": "dts/LEDscape.dts",
"chars": 3620,
"preview": "/** \\file\n * Try to play nice with the Beagle Bone device tree.\n *\n * But it really sucks. This is a waste of time; we "
},
{
"path": "dts/README.md",
"chars": 309,
"preview": "Generate DTS from DTB:\n\n\tdtc \\\n\t\t-I dtb \\\n\t\t-O dts \\\n\t\t-o ubuntu-`uname -r`.dts \\\n\t\t/boot/uboot/dtbs/am335x-boneblack.dt"
},
{
"path": "dts/angstrom.dts",
"chars": 28598,
"preview": "/dts-v1/;\n\n/ {\n\t#address-cells = <0x1>;\n\t#size-cells = <0x1>;\n\tcompatible = \"ti,am335x-bone\", \"ti,am33xx\";\n\tinterrupt-pa"
},
{
"path": "dts/cape-bone-octo.dts",
"chars": 3381,
"preview": "/*\n* pru dts file BB-BONE-PRU-00A0.dts\n*\n* Available outputs on pru 0 and their r30 pins:\n* p9.31: 0\n* p9.29: 1\n* p9.30:"
},
{
"path": "dts/ubuntu-3.8.13-bone32.dts",
"chars": 29496,
"preview": "/dts-v1/;\n\n/ {\n\t#address-cells = <0x1>;\n\t#size-cells = <0x1>;\n\tcompatible = \"ti,am335x-bone\", \"ti,am33xx\";\n\tinterrupt-pa"
},
{
"path": "fonts/json2bmp",
"chars": 481,
"preview": "#!/usr/bin/perl\nuse warnings;\nuse strict;\n\nlocal $/;\nlocal $_ = <>;\n\nprint <<\"\";\n/** \\file\n * Generated font from json f"
},
{
"path": "fonts/mta-sign.json",
"chars": 4538,
"preview": "{\"33\":[1920,8160,16368,31992,31864,64764,64764,64764,31992,31992,16368,8160,1920,0,0,0],\n\"35\":[1920,8160,16368,30840,294"
},
{
"path": "lib/.empty",
"chars": 0,
"preview": ""
},
{
"path": "obj/.empty",
"chars": 0,
"preview": ""
},
{
"path": "pcb/LEDscape pin assignments.csv",
"chars": 631,
"preview": "Signal,Header/Pin,Port\nS00,P8-18,GPIO2_01\nS01,P8-17,GPIO0_27\nS02,P8-15,GPIO1_15\nS03,P8-16,GPIO1_14\nS04,P8-14,GPIO0_26\nS0"
},
{
"path": "pcb/LEDscape.brd",
"chars": 672345,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"6.5.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/LEDscape.lbr",
"chars": 104188,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"7.2.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/LEDscape.sch",
"chars": 386588,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"6.5.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/TODO",
"chars": 428,
"preview": "x-Add bypass caps for MAX3041 chips\nx-Add shield holes to back of 8x2 RJ45 header\nx-Flip board so the BBB is upside down"
},
{
"path": "pcb/flat-20mm.scad",
"chars": 1261,
"preview": "/** \\file\n * Brackets for 20mm extrusion.\n *\n * These hold the panels a few mm away from the bracket in alternating\n * o"
},
{
"path": "pcb/lightbuddy-transmitter.brd",
"chars": 44509,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"7.2.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/lightbuddy-transmitter.sch",
"chars": 305264,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"7.2.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/octoscroller.brd",
"chars": 144383,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"6.5.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/octoscroller.sch",
"chars": 188512,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"6.5.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/receiver-2x.brd",
"chars": 98851,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"7.2.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/receiver-2x.sch",
"chars": 284834,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"7.2.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/receiver-4x.brd",
"chars": 110874,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"6.5.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/receiver-4x.sch",
"chars": 349765,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"6.5.0\">\n<drawing>\n<settings>\n"
},
{
"path": "pcb/receiver.brd",
"chars": 544651,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"6.4\">\n<drawing>\n<settings>\n<s"
},
{
"path": "pcb/receiver.sch",
"chars": 435794,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE eagle SYSTEM \"eagle.dtd\">\n<eagle version=\"6.4\">\n<drawing>\n<settings>\n<s"
},
{
"path": "radials.config",
"chars": 14,
"preview": "ws2812\n135,32\n"
},
{
"path": "src/demos/Makefile",
"chars": 293,
"preview": "#########\n#\n# Build the various demos\n#\n#\nBIN-y += fire\nBIN-y += life\nBIN-y += cube-life\nBIN-y += matrix-test\nBIN-y += i"
},
{
"path": "src/demos/cube-image.c",
"chars": 1355,
"preview": "/** \\file\n * Draw six images on the cube faces\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <"
},
{
"path": "src/demos/cube-life.c",
"chars": 9383,
"preview": "/** \\file\n * Play the game of life on the matrix cube.\n *\n * \\todo this is broken until the matrix.p can handle differen"
},
{
"path": "src/demos/fire.c",
"chars": 5702,
"preview": "/** \\file\n * Draw fire patterns, derived from the pyramid Fire code.\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include"
},
{
"path": "src/demos/identify.c",
"chars": 2298,
"preview": "/** \\file\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <time.h>\n#include "
},
{
"path": "src/demos/life.c",
"chars": 4491,
"preview": "/** \\file\n * Play the game of life on the normal pyramid\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n"
},
{
"path": "src/demos/lightcycles.c",
"chars": 6311,
"preview": "/** \\file\n * Lightcycles style game on the cylindrical megascroller.\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include"
},
{
"path": "src/demos/matrix-test.c",
"chars": 5504,
"preview": "/** \\file\n * Test the matrix LCD PRU firmware with a multi-hue rainbow.\n */\n#include <stdio.h>\n#include <stdlib.h>\n#incl"
},
{
"path": "src/ledscape/Makefile",
"chars": 292,
"preview": "#########\n#\n# Build the PRU and LEDscape libraries as well as the PRU firmware.\n#\n#\nTARGETS-y += $(LIBDIR)/matrix.bin\nTA"
},
{
"path": "src/ledscape/bitpattern.h",
"chars": 3653,
"preview": "/** \\file\n * ASCII art for bits.\n */\n#pragma once\n\n#define ________ 0x00 // 0\n#define _______X 0x01 // 1\n#define ______X"
},
{
"path": "src/ledscape/config.c",
"chars": 3290,
"preview": "/** \\file\n * Parse a matrix config file.\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <ctype.h>\n#include <string."
},
{
"path": "src/ledscape/fixed-font.c",
"chars": 8095,
"preview": "/** \\file\n * Font is encoded as 5 vertical stripes, 7 bits per stripe.\n * Array is in ASCII order, with an offset of 0x2"
},
{
"path": "src/ledscape/ledscape.c",
"chars": 13935,
"preview": "/** \\file\n * Userspace interface to the WS281x LED strip driver.\n *\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include "
},
{
"path": "src/ledscape/ledscape.h",
"chars": 2868,
"preview": "/** \\file\n * LEDscape for the BeagleBone Black.\n *\n * Drives up to 32 ws281x LED strips using the PRU to have no CPU ove"
},
{
"path": "src/ledscape/matrix.p",
"chars": 13469,
"preview": "// \\file\n /* PRU based 16x32 LED Matrix driver.\n *\n * Drives up to sixteen 16x32 matrices using the PRU hardware.\n *\n * "
},
{
"path": "src/ledscape/pru.c",
"chars": 3621,
"preview": "/** \\file\n * Userspace interface to the BeagleBone PRU.\n *\n * Wraps the prussdrv library in a sane interface.\n */\n#inclu"
},
{
"path": "src/ledscape/pru.h",
"chars": 1167,
"preview": "/** \\file\n * Simplified interface to the ARM PRU.\n *\n */\n#ifndef _pru_h_\n#define _pru_h_\n\n#include <stdio.h>\n#include <i"
},
{
"path": "src/ledscape/util.c",
"chars": 1499,
"preview": "/** \\file\n * Various utility functions\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <time.h>\n"
},
{
"path": "src/ledscape/util.h",
"chars": 967,
"preview": "/** \\file\n * Utility functions.\n */\n#ifndef _util_h_\n#define _util_h_\n\n#include <stdio.h>\n#include <stdint.h>\n#include <"
},
{
"path": "src/ledscape/ws281x.hp",
"chars": 2833,
"preview": "#ifndef _ws281x_HP_\r\n#define _ws281x_HP_\r\n\r\n\r\n#define AM33XX\r\n\r\n// ***************************************\r\n// * Gl"
},
{
"path": "src/ledscape/ws281x.p",
"chars": 13702,
"preview": "// \\file\n /* WS281x LED strip driver for the BeagleBone Black.\n *\n * Drives up to 32 strips using the PRU hardware. The"
},
{
"path": "src/mta/Makefile",
"chars": 149,
"preview": "#########\n#\n# Build the MTA sign demo\n#\n#\nBIN-y += mta-sign\n\nmta-sign.srcs += mta-sign.c\nmta-sign.srcs += mta-font.c\n\nin"
},
{
"path": "src/mta/mta-font.c",
"chars": 11465,
"preview": "/** \file\n * Generated font from json file output by\n * http://www.pentacom.jp/pentacom/bitfontmaker2/\n */\n#include <stdi"
},
{
"path": "src/mta/mta-sign.c",
"chars": 2709,
"preview": "/** \\file\n * Test the matrix LCD PRU firmware with a multi-hue rainbow.\n */\n#include <stdio.h>\n#include <stdlib.h>\n#incl"
},
{
"path": "src/net/Makefile",
"chars": 255,
"preview": "#########\n#\n# Build the various network receiving tools\n#\n#\nBIN-y += matrix-udp-rx\nBIN-y += matrix-tcp-rx\nBIN-y += opc-r"
},
{
"path": "src/net/matrix-tcp-rx.c",
"chars": 6878,
"preview": "/** \\file\n * TCP image packet receiver.\n *\n * Based on the HackRockCity LED Display code:\n * https://github.com/agwn/py"
},
{
"path": "src/net/matrix-udp-rx.c",
"chars": 5651,
"preview": "/** \\file\n * UDP image packet receiver.\n *\n * Based on the HackRockCity LED Display code:\n * https://github.com/agwn/py"
},
{
"path": "src/net/opc-rx.c",
"chars": 3181,
"preview": "/** \\file\n * OPC image packet receiver.\n */\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <time.h"
},
{
"path": "src/perlin/Makefile",
"chars": 1084,
"preview": "#==============================================================================================\n# LED Matrix Animated Pa"
},
{
"path": "src/perlin/gammalut.h",
"chars": 1851,
"preview": "//=============================================================================================\n// LED Matrix Animated P"
},
{
"path": "src/perlin/globals.h",
"chars": 1150,
"preview": "//=============================================================================================\n// LED Matrix Animated P"
},
{
"path": "src/perlin/knobs/knobs.ino",
"chars": 550,
"preview": "/** \\file\n * Teensy 2.0 firmware to read four analog knobs and print\n * their values periodically.\n */\n\n#define LED_PIN "
},
{
"path": "src/perlin/pattern.cpp",
"chars": 3295,
"preview": "//=============================================================================================\n// LED Matrix Animated P"
},
{
"path": "src/perlin/pattern.h",
"chars": 1827,
"preview": "//=============================================================================================\n// LED Matrix Animated P"
},
{
"path": "src/perlin/perlin-ledscape.cpp",
"chars": 4326,
"preview": "//=============================================================================================\n// LED Matrix Animated P"
},
{
"path": "src/perlin/pf2.cpp",
"chars": 12259,
"preview": "//=============================================================================================\n// LED Matrix Animated P"
},
{
"path": "src/perlin/pf2.h",
"chars": 4174,
"preview": "//=============================================================================================\n// LED Matrix Animated P"
},
{
"path": "src/script/Makefile",
"chars": 354,
"preview": "SCRIPTDIR = ../src/script/\nBINDIR = ../../bin/\n\nscripts = bbb-network-setup \\\n\tfind-serial \\\n\tinstall \\\n\tledscape.servic"
},
{
"path": "src/script/bbb-network-setup",
"chars": 218,
"preview": "#!/bin/sh\nDIR=\"`dirname $0`\"\ncd \"$DIR\"\n\nroute add default gw 192.168.7.1\necho 'nameserver 8.8.8.8' > /etc/resolv.conf\nec"
},
{
"path": "src/script/find-serial",
"chars": 307,
"preview": "#!/bin/sh\n# Locate the serial ports and their serial numbers.\n# This can then be used to map devices to positions in the"
},
{
"path": "src/script/install",
"chars": 744,
"preview": "#!/bin/sh -x\n#\n# Install the device tree fragment, the angstrom service file,\n# and make it runable.\n#\n\nDIRNAME=\"`dirnam"
},
{
"path": "src/script/ledscape.service",
"chars": 324,
"preview": "#\n# Copy this file to /etc/systemd/system/ and run:\n# systemctl enable ledscape.service\n# to enable LEDscape to start "
},
{
"path": "src/script/python-test",
"chars": 2343,
"preview": "#!/usr/bin/python\n# Draw images with PIL and send them to the display.\n# Dual scrolling example with fixed time on each "
},
{
"path": "src/script/run-ledscape",
"chars": 696,
"preview": "#!/bin/bash\nDIRNAME=\"`dirname \"$0\"`\"\ncd \"$DIRNAME/..\"\n\n# Enable the octoscroller overlay\n# Note that we can't do this at"
},
{
"path": "src/script/run-videoplayer",
"chars": 477,
"preview": "#!/bin/bash\nDIRNAME=\"`dirname \"$0\"`\"\ncd \"$DIRNAME\"\n\nUSBMOUNT=\"/media/usb0\"\n\n# Wait for a USB drive to be inserted\nwhile "
},
{
"path": "src/script/twitter-scroller",
"chars": 2428,
"preview": "#!/usr/bin/python\nimport Image, ImageFont, ImageDraw\nimport socket\nimport time, datetime\nimport pickle\nimport tweepy\nimp"
},
{
"path": "src/script/videoplayer",
"chars": 4175,
"preview": "#!/usr/bin/python\n# Play a video onto the screen\n\nimport cv2, cv\nimport socket\nimport numpy\nimport datetime\nimport time\n"
},
{
"path": "src/script/videoplayer.service",
"chars": 362,
"preview": "#\n# Copy this file to /etc/systemd/system/ and run:\n# systemctl enable videoplayer.service\n# to enable videoplayer to "
},
{
"path": "strips.config",
"chars": 14,
"preview": "ws2812\n240,32\n"
},
{
"path": "tall-cylinder.config",
"chars": 793,
"preview": "matrix16\n0,0 L 0,0\n0,1 R 16,0\n0,2 L 32,0\n0,3 R 48,0\n0,4 L 64,0\n0,5 R 80,0\n0,6 L 96,0\n0,7 R 112,0\n3,0 L 128,0\n3,1 R 144,0"
},
{
"path": "ubuntu/ledscape.conf",
"chars": 374,
"preview": "#\n# This task runs at boot to start the LEDscape service \n\ndescription \"sta"
}
]
// ... and 3 more files (download for full content)
About this extraction
This page contains the full source code of the osresearch/LEDscape GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 109 files (4.1 MB), approximately 1.1M tokens, and a symbol index with 235 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.