Download Sea Glider Development and Power Characterization Sean Lastuka

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Power over Ethernet wikipedia , lookup

Immunity-aware programming wikipedia , lookup

Rectiverter wikipedia , lookup

Transcript
Sea Glider Development and Power
Characterization
Sean Lastuka
EE542 Final Report
December 8, 2007
University of Washington
Table of Contents
1. Sea Glider Background
2
2. Sea Glider Design
3
3. Project Overview
4
a. Linux Installation
5
b. Serial Port Operation
8
c. SD Card Operation
9
d. Power Characterization
9
4. Conclusion and Final Thoughts
11
5. References
13
6. Code Appendix
14
1
Sea Glider Background
The Sea Glider is an autonomous underwater vehicle (AUV). It is used in scientific, military and
burgeoning commercial roles. It is used as a mobile platform equipped with sensors that monitor
salinity, water temperature, pressure, acoustics and other ocean related characteristics. Some primary
considerations in Sea Glider design include mission duration, electrical sensor load, maximum depth
rating, forward velocity and cargo capacity.
To travel forward, the Sea Glider must alternatively sink and rise through the water column, see Figure
1. The rising and falling motions create a hydrodynamic effect on the wings of the Sea Glider to
promote forward motion. Through this effect, a Sea Glider travels horizontally through the water at a
speed of approximately one foot per second. The primary component that enables the sea glider to rise
and fall through the water is a variable buoyancy device (VBD). This device is mounted on the Sea
Glider’s fuselage as shown in Figure 2. It effectively changes the density of the Sea Glider. When the
density of the VBD is reduced, the Sea Glider rises. Alternatively, when the density increases, the Sea
Glider sinks... like a rock.
Figure 1: Sea Glider motion.
A sinking glider has high density, and a rising glider has low density.
2
To better understand the VBD, compare it to a basketball. The ball has low density compared to water.
As you push it under the water, the very buoyant ball wants to return to the water surface, where it
more closely matches the density of the surrounding air. However, if the ball is deflated (its density is
increased), the less buoyant ball can more easily be pushed underwater and may even sink. In the same
way, if the density of a Sea Glider is low, it will tend to float at or near the surface. As the density
increases, the Sea Glider will begin to sink. It is the VBD which allows this change is density.
Figure 2: Sea Glider construction
Notice oval-shaped Variable Buoyancy Device near the tail section.
Sea Glider Design
As mentioned earlier, one of the primary considerations in Sea Glider design is mission duration. Most
Sea Glider missions involve data collection over wide expanses of ocean. Moving steadily at ¼ knot/hr,
the Sea Glider may need two months to collect data over a 1000 nautical mile mission path. Electrical
power must be conserved to ensure full glider operation is maintained over such an extended mission.
Effective use of sleep modes, power savings modes and low power peripherals are imperative to
minimize power consumption during different operating states encountered during a mission.
The current incarnation of the Sea Glider does an excellent job conserving power for its longer mission
times. However, it is based on a TT8 68332 32-bit microcontroller. The TT8 runs picoDos as a native
operating system. PicoDos is not a true multithreaded operating system. Hence, simultaneous tasks can
not be handled at once. As Sea Glider users begin requesting improved autonomous navigation and
decision making capabilities, a non-multithreaded architecture will hinder further performance
enhancements.
To improve Sea Glider performance, autonomous decision making will need to be improved. During
navigation, independent decisions about the surrounding ocean state will help make better use of
currents, up-welling and down-welling effects. Onboard processing of acoustic data will allow small
uploads of significant environmental data when surfacing. Since processor intensive operations take a
significant amount of time, a multi-threaded architecture is useful to perform multiple operations at
once. Also, if an operation must be performed in a limited span of time, processor performance should
3
have the ability to step up and quickly produce results. With these requirements in mind, the Sea Glider
began evaluating a replacement for its embedded TT8 microcontroller.
The embedded processor market is diverse, with manufacturers such as MicroChip, Atmel, Phillips, TI,
Freescale and Marvell. Ultimately, three microprocessors were evaluated the BlackFin, XScale, ARM9.
The ARM9 was selected because it was the only one of the three with an onboard Memory
Management Unit (MMU). The LPC3180 is also designed with a 1.2V core voltage and can support 0.9V
core voltages as long as the MCU is running at a speed of less than 13MHz.
The MMU creates an interface between the physical memory and the microprocessor core. The
microprocessor can then address virtual memory, which the MMU will interpret into physical memory
locations. The advantages of this architecture include better physical memory organization and
utilization, and a simple memory map from the processor standpoint. The disadvantages of an MMU
relate to reduced die space for other functions or peripherals and slower absolute memory access
speed, at least on the basis of a single word memory access operation. However, the main
advantage,for our purposes, of an MMU is that it is able to run a full distribution of Linux. Without an
MMU, only uCLinux (an abbreviation for microcontrollerLinux) is available. uCLinux does not require an
MMU to run, but therefore, needs special attention to run multiple applications simultaneously. Since
the Sea Glider program intends to take advantage of (and contribute to) the full range of the Open
Source community’s software the operating system needs to be fully compatible with the standard Linux
code base. The decision to run Linux narrowed our selection to the ARM9 based Phillips (now NXP
Semiconductor) LPC3180. Phytec, a local embedded system development kit supplier, provided the
PHYCore LPC3180 Development Kit.
The Phytec development kit consists of a Single Board Computer (SBC) and a carrier board. The SBC is
populated with the LPC3180, a 32MB NAND Flash Memory and a 32MB SDRAM Memory. There are also
two RS-232 transceivers, three of UARTs are connected through these transceivers. The carrier board
supports two RS-232 Serial connections, SD Card, USB, LEDs, a potentiometer for the A/D and user
definable switches. The SBC is connected carrier board through a pair of 100-pin connectors that carry
LPC3180 signals to the carrier board peripherals and on to an expansion board.
Project Overview
The full design of the next generation embedded system for the Sea Glider will encompass four phases.
1. Confirm LPC3180 system performance, develop a stable Linux OS and user applications
2. Interface existing sensors and communications hardware with the LPC3180 system
3. Characterize system performance
4.
Install the system in the current Sea Glider and test at sea
4
Before starting design, we have attempted to consider possible design roadblocks, but it is possible
there may be problems encountered during development. Should this be the case, we may be required
to fall back to a previous phase to rectify the issue. Once the previous phase has been corrected, it is
important to test all the previous deliverables, to ensure no other system function was mistakenly
compromised after the targeted design change.
In the limited time of this project, we will address the first development phase: confirm LPC3180 system
performance, develop a stable Linux OS and design the user applications
1. Linux installation and basic memory card interface
2. Serial setup
3. Power mode switching
4. Power characterization of above modes and peripherals
Linux installation
To begin running tests and applications on the LPC3180, an image of the Linux OS and the Linux
FileSystem is downloaded via a JTAG interface, into the NAND flash. A bootloader (UBoot) is also loaded
into Flash. A secondary bootloader (SIBL) is used to transfer the UBoot and Linux Image and Linux
Filesystem into SDRAM where UBoot then boots up Linux. Initially, this caused issues because Linux
would boot up successfully, but would constantly refresh making terminal input difficult. Luckily, we
had a second LPC3180 available with the same UBoot and Linux Images copied into the Flash, the
second system worked and reliably booted Linux.
Serial Port testing
Serial interfaces are the primary method of communications in ocean going embedded systems,
including those aboard the Sea Glider. The simplicity in board layout with a serial communications
device combined with easier debug is important in a field where power savings, simplicity and reliability
dominate the list of design criteria. Frequently, ocean going systems may need field repair and
diagnostic analysis. Serial communications can be quickly probed with an oscilloscope or logic analyzer
to get an idea of device operation. Where possible, we will layout boards with serial communication
break-out pads to be used as test points.
The LPC3180 has seven UARTS. Three UARTS are capable of 921kbps with the remainder at 460kbps.
The terminal communications use a standard UART. The auxiliary RS232 port is connected to a high
5
speed UART, which has the same range of frequencies as the regular UARTs, with one extra frequency at
921kbps. We interfaced this second RS232 jack with another terminal window.
With the serial port, we simply wished to perform a serial data transfer. To start, we investigated the
file system. The /dev directory displays all available devices. If the user wishes to access a device listed
under /dev they reference the file by name through the kernel’s open command. This command returns
a file descriptor. The file descriptor is a handle with properties and methods which may be used to
access the under lying device. The newser.c file at the end of this report shows examples of operations
using file descriptors and kernel commands to execute a serial data transfer.
On our system, before we get to the results from the file transfer, a little background on Linux devices
should be discussed. When checking out the dev file, the user can enter the ls –l command on a file
such as /dev/ttyPSHS0. The result will show a major and minor number in this form: 274 1. The
number 274 indicates the location of the driver in the kernel code and the minor number indicates the
driver instance. All drivers of the same device type will have the same major number, as they all use the
same driver code, but will have different minor number, to differentiate them by instance. A USB driver,
an Ethernet driver and a serial driver will each have a different major number. Their minor numbers will
typically start with zero and increment up for each instance of the driver.
The device drivers should be installed as modules. The module can be compiled in the Linux source tree,
and added to the system using the command insmod. However, our Linux image had no modules. The
Linux Image supplied with the phyCORE system was a monolithic image and couldn’t be tailored using
commands such as insmod /rmmod, which add/remove modules. In this case, we rely on the drivers
embedded in the development kit to work as is. If they don’t operate correctly, or have all the
functionality we need, a time consuming make on a large part of the kernel may be required to make
changes.
Assuming the installed Linux image has all the drivers available, the user must figure out which device
files will actually write to a physical serial port. There could be a dozen different devices files, so
knowing which one to use can quickly be determined through a process of trial and error, usually
starting with the file with the lowest number, like tty0, or ttyS0. In our case, we found our available
serial port was ttyPSHS0. However, we didn’t know this information immediately, and it took some
experimentation to figure this out. There will be more on serial port setup later in this paper.
As mentioned earlier, the newser.c serial transfer program is used to transmit a string of integers to the
host system. This serial code will open the selected driver and the driver will handle the setup of the
serial port.
A dedicated investigation checked a number of system processes to see if a serial interrupt was being
generated with each call of the serial program. Activity was present on the interrupt counters, IRQ
addresses and registers, which can be found in the following files:
/proc/tty/driver/serial
6
/proc/tty/driver/ttyPSHS
/proc/interrupts
One important thing to note is that if a serial program doesn’t appear to be working properly (there’s no
output on the serial line) with a given driver, every check should be made to ensure that the rest of the
system is set up properly. In the case of our development system, a serial port didn’t appear to be
working correctly via a probe of the TX pin with the oscilloscope. At this point we began checking to see
if the output could internally loopback to the input, so we could check the receive register. This
functionality was enabled via the loopback bit in register 0x40054008, the serial port loopback setup
register. The serial port schematic indicated that if the loopback bit were enabled, the output TX would
loopback to the RX register, while still continuing to propagate onto the TX pin to the RS232 level
shifters and physical serial connector.
Figure 3. Serial block diagram
There is a multiplexer where the node indicates a simple wire connection
After continuing to experiment for a handful of days with different serial ports, physical port
configurations, C code changes, and internal register modifications to no avail, I demonstrated the
problem to my advisor. Up to this point, I had found that the loopback mode disabled output on the
serial port. By turning off the loopback mode, the serial port began to function correctly and produce
output data. Also, I had found that setting the ‘No Connect’ serial port enable bit would actually enable
serial port output. When that bit was cleared, the serial port could not transmit. In my demonstration,
I highlighted these findings, but I did it in a newer incarnation of my code, where I ran the correct driver
/dev/ttyPSHS0. I set up the oscilloscope on the expansion board where the TX pin was represented and
executed the serial binary. To my surprise, the serial port actually worked. The new driver was used,
7
and apparently, had corrected the port enable register despite the improper documentation in the
datasheet. Early on, in my serial port debug, I believe I had not originally set up my oscilloscope
correctly and used a /dev/ttyS0, and therefore couldn’t see the serial port operating in the first place.
Those were the two main variables in not having correct operation. However, during the debug process,
I introduced a lot of additional parameters to the problem, which turned out to complicate the process.
Of course, this process was an excellent learning experience, no nothing was lost.
After finding the serial port working correctly, we wrote a simple Python program to receive the serial
data at the host end to verify correct operation. The Python received the LPC3180 data correctly.
SD Card
The SD Card is important to the development effort. We store executable binaries from the host system
onto an SD Card, remove the card from the Host system, and insert it into a slot on the LPC3180 carrier
board. The Linux kernel installed on the LPC3180 system has an SD Card driver. The mount command
allows access to the SD Card anywhere in the directory tree that we choose to the place the SD Card.
However, it is important to umount the SD Card directory before removing it from either the host
system or the LPC3180 carrier board. Failure to do so may result in a corrupted superblock on the SD
Card. This may be because the latest flash configuration was not properly written to the superblock
prior to shutdown. If this happens, an e2fsck command can reassign a secondary, backup superblock to
remount the drive. Aside, from when e2fsck is called on the command line, it will also run
automatically, after a certain number of flash card insertions. An inexperienced user may be confused
by some of the e2fsck messages. While an e2fsck should be periodically run to clean up bad flash
memory blocks, its frequency of execution could be reduced on a development system where the
number of insertions could be 50-100 a day. Using command line options with tune2fs, the user may
select the number of insertions before the e2fsck command issues. Also, there can be some confusion
between ext2 and ext3 file systems when the user invokes the fdisk command to format a new flash
memory device. Typically, it is ok to use an ext3 file system. The only difference between ext3 and ext2
is the inclusion of journaling in ext3.
Once the SD Card flash drive has mounted and can be accessed, it may be automatically mounted on
boot-up. A simple way to change the auto mount is to modify the last boot up file. The boot files are
usually numbered sequentially. Check the /etc/rcS.d or /etc/init.d directory. In our case, we have an
S90check_sd.sh script where the automatic mounting can take place. You can program in automatic
mounting by simply placing a mount command with the correct driver and mount directory in the shell
script. Other things we may optionally mount in this file are USB devices and other NAND flash devices.
8
Sleep Mode
The Sea Glider spends at least 75% of its time in sleep mode, as shown in the timing summary in Figure
6. However, it may need to wake up suddenly, perhaps in response to underwater current induced
heading changes or communication requests from an acoustic modem. The LPC3180 is ideally suited to
this task, as it comes out of sleep in less than one second, via a low power real time clock running at
32KHz. This real time clock is the only on-chip current draw while the LPC3180 is sleeping. Another
possible current draw is the 48MHz USB module, but it would, most likely, be disabled in our final
system configuration. Another system current draw is the SDRAM. During sleep mode, the SDRAM is
placed in an I/O disabled self-refresh mode. SDRAM self-refresh mode, allows the LPC3180 to wake up
with the same memory state it had right before shutdown, without having to perform a time consuming
state-saving operation on a large, on-board non-volatile memory.
The issue first encountered with the sleep mode was that terminal communications would cease after
placing the SDRAM in self-refresh mode. This was because terminal communications relied on reads
and writes to the SDRAM. Once the communications terminal was shut off, the final sleep mode
command could not be entered. The solution to this problem was to create a compiled C binary to issue
all the commands in series. With the binary loaded into the LPC3180 cache, the self-refresh would have
no effect on the continued execution of commands, until the final sleep mode command.
Wake-up begins with a Start Interrupt. On our test system, the start interrupt will be generated by the
RTC clock. However, it may also be generated by other external interrupts such as serial pins, timers
capture inputs, USB or SD card insertion among others. We could successfully wake up after an
interrupt from the real time clock. After waking up, the system state was preserved in the SDRAM, and
Linux was immediately available. We confirmed this operation by running binaries from the command
line on the next command after startup.
Power Characterization
We tested power by replacing the main Vcc jumper with two leads, to which we could connect the
current meter contacts. The preferred method to determine this current would have been to use a
small .05 or .025 Ohm shunt, whereby we could measure the voltage across the shunt. However, the
required shunt was in the 0805 package profile, and an example of such a small shunt was difficult to
find in the final days of the project.
Power characterization on this part was complicated by the interaction between our main Vcc test
point, the SBC and the other peripherals on the carrier board. However, compared to other available
test points, the Vcc input was our most trustworthy option.
Other current test points were available; specifically four jumpers that were located physically close to
the LPC3180. These jumpers represented Vdd and Vdd IO supplies on the chip. Since Vdd supplies are
9
the only power supply pins on the LPC3180, it seemed logical that only jumper supplied Vdd should be
applied to these pins. However, figure 5 includes a block diagram showing a Vcc input into the chip.
Without understanding every termination point for this Vcc input, we could not rely on the Vdd test
Figure 5, Block diagram of LPC3180 mounted on Phytec SBC, interfaced with phyCORE carrier board.
points for our current consumption numbers. However, a quick look at the sum total of the currents
passing through the Vdd jumpers was approximately 20mA at 1.2V @ 13MHz. As we will see shortly, it
is far lower than the power being consumed through the Vcc jumper at a similar performance setting.
This finding holds hope that a properly designed board will yield a very lower power device.
Our final power characterization, detailed in Figure 6 below, relies on placing the chip into a power
saving mode, and then disabling a number of carrier board elements. In regular operation after reset, at
208MHz, a 3V supply provides most of the system power and draws 130mA. This is high compared to
the estimates in the LPC3180 datasheet (80mA @ 1.2V), and it is obvious that the other board
electronics are sinking a significant quantity of current. By dropping the chip from 1.2V to 0.9V on the
core and using the minimum frequency of 13MHz (this configuration is called Direct Mode), we bring the
current consumption to 47.8mA at 3V. The Direct Mode spec into the device core is 7mA typical at 0.9V,
10
excluding currents to drive the I/O circuitry. Some obvious contributors to the 47.8mA are 4 x 6mA
LEDs. After removing the LEDs, the current drops by 23mA. Further reductions are realized by turning
off the USB PLL, disconnecting all serial cables and removing the SD Card from its slot. Current reduction
work will continue in the upcoming weeks, as we begin to determine the power consumption of each
peripheral device.
SLEEP
DISK ACCESS (WRT)
ACTIVE
SAMPLE
IDLE
COMPUTATION
(KALMAN)
TT8 (mA @
10V)
2.19
45.8
19.8
39.8
19.8
81.8
LPC3180 (mA @ 3V)
13.1
~19.5
19.4 (9.6k)
est 19.7(115k)
17.9
TIME
(SECONDS)
22771.996
755.016
1687.776
3066.738
967.334
33.378
Figure 6, Summary of currents during an average dive (simulated average dive for LPC3180 data,
using the code ion the appendix) Time could be considered to represent a percentage of time,
where it is obvious the glider is spending most of its time in sleep. At the time of this report,
sufficient data during sampling and processor intensive computations was not yet available.
Conclusion
The results are very promising, as active computation uses about 1/3 the power (same current and
about 1/3 of the voltage) of the active computation on the legacy TT8. The sleep power consumption
number is about twice as high on the LPC3180 compared to the TT8. We hope this can be reduced as
we account for the external draws on the LPC3180 power supply. Disk access is quite a bit lower, as
LPC3180 running at lowest speed, has plenty of bandwidth to handle the Linux access to an external
memory card, while the TT8 is running at full speed to accomplish the same objective. We also hope
that the reduce power of the idle and active modes, compared to the TT8 can be taken advantage of,
allowing the sea glider to actively compute during a greater portion of its mission. The intelligence
gained from active computation may lead to richer more data rich missions.
Finally, the results of the Sea Glider power measurements are relevant to the processor only. They
don’t consider the effect of sensing , control and communications electronics. Continued optimization
of the power requirements from these systems could have large gains in electrical performance.
11
Final Thoughts
Going forward, the main tasks for this part of the Sea Glider project will involve a better understanding
of the external circuitry which is drawing power on the SBC and also on the carrier board. The next
task will be development of a functional SPI bus, as many of the existing Sea Glider systems rely on this
bus. Then we will begin interfacing these functions with the existing Sea Glider hardware.
12
References
Phytec phyCORE-LPC3180 Hardware Manual, April 2007, L-681e-2.pdf
Phillips LPC3180 Preliminary Datasheet, February 21, 2006, Rev 0.1, lpc3180_DS-1.pdf
Phillips UM10198 LPC3180 User Manual , June 6, 2006, Rev 01, UM10198_1.pdf
ARM926EJ-S Development Chip Reference Manual, 2006,
DD10287B_arm926ejs_dev_chip_technical_reference_manual.pdf
Micron Mobile SDRAM datasheet, 2005, MT48H32M16LFm.pdf
Analog Devices Port Transceivers Datasheet, 2006, ADM3307E_3310E_3311E_3312E_3315E.pdf
13
Code Appendix
/* autoslp.c: Sleep code */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<unistd.h>
<string.h>
<errno.h>
<signal.h>
<fcntl.h>
<ctype.h>
<termios.h>
<sys/types.h>
<sys/mman.h>
<linux/gpio.h>
<sys/ioctl.h>
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
unsigned long write_mem(off_t target, unsigned long writeval);
unsigned long read_mem(off_t target);
int led_off(void);
int main(int argc, char **argv) {
unsigned long read_result;
int always_zero;
if(argc > 1) {
fprintf(stderr, "\nUsage:\t%s\n", argv[0]);
exit(1);
}
//
always_zero = led_off();
read_result=write_mem(0x40004044, 0x0); // Direct RUN mode in PWR CTRL
read_result=write_mem(0x40004050, 0x142); // Enable 13' Clk (from PLL397)
do{
read_result=read_mem(0x40004050); // wait for 13' to stabilize
}while (read_result!=0x143);
read_result=write_mem(0x40004020, 0x1000000); // enable rtc interrupt to main processor
read_result=write_mem(0x4000402C, 0x1000000); // rising edge of start signal
read_result=write_mem(0x40004024, 0x1000000); // clear the interrupt
//
read_result=write_mem(0x40004030, 0x1000000); // pin int start up is probably
unnecessary
read_result=write_mem(0x40024010, 0x10); // reset rtc
read_result=write_mem(0x40024010, 0x00); // reset rtc
read_result=write_mem(0x40024008, 0xA); // set rtc timer to 10 seconds
read_result=write_mem(0x40024010, 0x1); // enable rtc interrupt from rtc module
read_result=write_mem(0x40004044, 0x280); // auto exit SDRAM self refresh enable and
self refresh request
read_result=write_mem(0x40004044, 0x380); // self refresh request
read_result=write_mem(0x40004044, 0x80); // self refresh request
read_result=write_mem(0x40004044, 0x81); // enter STOP mode
// sleep
read_result=write_mem(0x40004044, 0x0); // exit STOP mode and make sure Direct RUN is
started
read_result=write_mem(0x40024008, 0x0); // return match register to 0 seconds
read_result=write_mem(0x40024014, 0x1); // clear match interrupt status
read_result=write_mem(0x40024010, 0x0); // clear match interrupt status
read_result=write_mem(0x40004020, 0x0000000); // disable rtc interrupt to main processor
read_result=write_mem(0x40004024, 0x0000000); // clear the interrupt
14
read_result=write_mem(0x40004044, 0x62);
// exit STOP mode and make sure Direct RUN is
started
return(0);
}
unsigned long write_mem(off_t target, unsigned long writeval) {
unsigned long read_result;
int fd;
void *map_base, *virt_addr;
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
fflush(stdout);
/* Map one page */
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
if(map_base == (void *) -1) FATAL;
fflush(stdout);
virt_addr = map_base + (target & MAP_MASK);
read_result = *((unsigned long *) virt_addr);
printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result);
fflush(stdout);
*((unsigned long *) virt_addr) = writeval;
read_result = *((unsigned long *) virt_addr);
printf("Written 0x%X; readback 0x%X\n", writeval, read_result);
fflush(stdout);
if(munmap(map_base, MAP_SIZE) == -1) FATAL;
close(fd);
return read_result;
}
unsigned long read_mem(off_t target) {
unsigned long read_result;
int fd;
void *map_base, *virt_addr;
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
fflush(stdout);
/* Map one page */
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
if(map_base == (void *) -1) FATAL;
fflush(stdout);
virt_addr = map_base + (target & MAP_MASK);
read_result = *((unsigned long *) virt_addr);
printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result);
fflush(stdout);
if(munmap(map_base, MAP_SIZE) == -1) FATAL;
close(fd);
return read_result;
}
int led_off(void)
{
/*
int f_gpio;
int j;
struct gpio_control leds[4];
*/
15
unsigned long dummy;
printf("Turning LEDs off\n");
dummy=write_mem(0x40028008, 0x8C);
/*
leds[0].Pin
leds[1].Pin
leds[2].Pin
leds[3].Pin
=
=
=
=
GPO_02;
GPO_03;
GPO_07;
GPO_06;
//
//
//
//
// clear GPO LED bits
LED1
LED2
LED3
LED4
f_gpio = open("/dev/gpio",1);
for (j = 0; j < 4; j++) {
leds[j].Arg = 0;
ioctl(f_gpio,GPIO_IOCSPIN,&leds[j]);
sleep(2);
}
close(f_gpio);
printf("LEDs off\n");
*/
return 0;
}
/* serial communications code */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<stdio.h>
<termio.h>
<string.h>
<stdarg.h>
<stdlib.h>
<unistd.h>
<fcntl.h>
<math.h>
<sys/time.h>
<ctype.h>
<errno.h>
int ConnectSerial(char *portname, int baud, char parity,
char databits, char stopbits, char flowcontrol)
{
int fd;
struct termios options;
int baudflag;
fd = open(portname, O_RDWR | O_NDELAY | O_NOCTTY);
if (fd == -1) {
return -1;
}
tcgetattr(fd, &options);
switch(baud)
case 110:
case 300:
case 600:
case 1200:
case 2400:
case 4800:
case 9600:
case 19200:
case 38400:
{
baudflag
baudflag
baudflag
baudflag
baudflag
baudflag
baudflag
baudflag
baudflag
=
=
=
=
=
=
=
=
=
B110; break;
B300; break;
B600; break;
B1200; break;
B2400; break;
B4800; break;
B9600; break;
B19200; break;
B38400; break;
16
case 57600: baudflag = B57600; break;
case 115200: baudflag = B115200; break;
case 230400: baudflag = B230400; break;
case 460800: baudflag = B460800; break;
case 921600: baudflag = B921600; break;
default:
baudflag = B9600;
printf("Baud rate entered is not available\n");
printf("Default will now be 9600bps\n");
break;
}
cfsetispeed(&options, baudflag);
cfsetospeed(&options, baudflag);
options.c_cflag
options.c_lflag
options.c_oflag
options.c_iflag
|=
&=
&=
&=
(CLOCAL | CREAD);
~(ICANON | ECHO | ECHOE | ISIG);
~OPOST;
~(INLCR | IGNCR | ICRNL);
switch(parity) {
case 'e':
case 'E':
options.c_cflag
options.c_cflag
options.c_iflag
break;
case 'o':
case 'O':
options.c_cflag
options.c_cflag
options.c_iflag
break;
default:
options.c_cflag
options.c_cflag
options.c_iflag
break;
}
|= PARENB;
&= ~PARODD;
|= (INPCK | ISTRIP);
|= PARENB;
|= PARODD;
|= (INPCK | ISTRIP);
&= ~PARENB;
&= ~PARODD;
&= ~(INPCK | ISTRIP);
switch(stopbits) {
case 2:
options.c_cflag |= CSTOPB;
break;
default:
options.c_cflag &= ~CSTOPB;
break;
}
switch(databits) {
case 7:
options.c_cflag
options.c_cflag
break;
default:
options.c_cflag
options.c_cflag
break;
}
switch(flowcontrol)
case 1:
options.c_iflag
options.c_cflag
break;
case 2:
options.c_iflag
options.c_cflag
break;
&= ~CSIZE;
|= CS7;
&= ~CSIZE;
|= CS8;
{
|= (IXON | IXOFF | IXANY);
&= ~CRTSCTS;
&= ~(IXON | IXOFF | IXANY);
|= CRTSCTS;
17
default:
options.c_iflag &= ~(IXON | IXOFF | IXANY);
options.c_cflag &= ~CRTSCTS;
}
tcsetattr(fd, TCSANOW, &options);
return fd;
}
int main(int argc, char *argv[])
{
int port_fd;
int bit, n;
int cmd;
char buff [80];
int len, ret;
int baud;
printf("Pick a baud rate between 110 and 115200\n");
scanf("%d", &baud);
if ((port_fd = ConnectSerial(argv[1], baud, 'N', 8, 1, 0)) == -1) {
perror("Could not open serial port");
fprintf(stderr, "(%d)\n", errno);
return 1;
}
for(n = 0; n < 63; n++) {
sprintf(buff, "This serial port is working just fine, for the %dth time.\n", n+1);
len = strlen(buff);
ret = write(port_fd, buff, len);
if(len != ret) {
fprintf(stderr, "Cycle %d Tried to write %d, wrote %d\n", n, len, ret);
}
}
/*
bit = TIOCM_DTR; */
/*
/*
ioctl(port_fd, TIOCMBIC, &bit); */
printf("DTR is off\n"); */
/*
/*
/*
/*
while (1) { */
cmd = getchar(); */
if (cmd == 13 || cmd == 10) */
continue; */
/*
/*
if (cmd != '1' && cmd != '0') */
break; */
/*
/*
/*
/*
if (cmd == '1') */
ioctl(port_fd, TIOCMBIS, &bit); */
else if (cmd == '0') */
ioctl(port_fd, TIOCMBIC, &bit); */
/*
/*
/*
n = sprintf(buff, "turning %s\r\n", cmd == '1' ? "on" : "off"); */
Write(port_fd, buff, n); */
} */
close(port_fd);
return 0;
}
# Python serial receive code
import serial, sys
18
# removed import serial and import sys
#out = serial.Serial(baudrate=115200, timeout=5, port='/dev/ttyUSB0')
#inp = serial.Serial(baudrate=115200, timeout=5, port='/dev/ttyUSB1')
#test_string = "01234567890123456789012345678901234567890123456789"
ser = serial.Serial(baudrate=115200, timeout=5, port='/dev/ttyS1')
sys.stdout.write("Starting\n")
while(1):
sys.stdout.write(ser.read(1))
ser.close()
#ser = serial.Serial(baudrate=9600, port='/dev/ttyS1')
#print ser.portstr
#ser.write("got it")
#ser.close()
19