--- In "suptouch" <> wrote:
>
> I've made a small program to test the i/o of the DIO1 header on my
> TS7300 on output mode. I generate a 0.5Hz signal on each port, and the
> result is :
>
> Pin 1 : DIO_0 (PortB.0) : no signal
> Pin 3 : DIO_1 (PortB.1) : no signal
> Pin 5 : DIO_8 (PortF.1) : signal ok
> Pin 7 : DIO_3 (PortB.3) : no signal
> Pin 9 : DIO_4 (PortB.4) : no signal
> Pin 11 : DIO_5 (PortB.5) : signal ok
> Pin 13 : DIO_6 (PortB.6) : signal ok
> Pin 15 : DIO_7 (PortB.7) : signal ok
I've just run into the same problem;
Port B[4, 3, 1, 0] bits do not appear to work as output.
I have confirmed that those same pins work as input
by pulling the signals on the DIO header low.
Port B[7,6,5] work ok.
Port F[1] works ok.
The LCD signals also work fine.
Port A[6:0], C[0], H[5:3].
I've looked in the EP9301 user manual and in the
TS-7300 hardware manual, and there is no reason
why these pins should not work as bidirectional
I/O. The EP9302 chip revision is E0 (read from the
IC, and from the syscfg register). There are no
errata related to DIO on port B.
I've ohm-ed out the connections between the
processor and the DIO pins, and there is nothing
special about B[4:3, 1:0], they're all direct
connects.
The only other bit on port B is DMA_REQ1. I don't
think there is a driver installed that is over
writing the port configuration bits. The fact that
I can toggle B[7:5] seems to rule out interference
from another driver too.
I've checked into the suggestions posted for the original
thread, and using char types, or read-modify-writes does
not help.
I've put the code inline after this message. If
anyone with a TS-7300 would care to try it out,
and let the group know how your board fared.
Thanks!
Dave
/* toggle_io.c
Toggle an I/O pin as fast as possible to determine
the toggle speed.
Compile using optimization to get the fastest code, i.e.,
gcc -O2 -Wall -o toggle_io toggle_io.c
Then use objdump to disassemble the code, i.e.,
objdump -d toggle_io
For example, if the toggle function is as simple as;
void toggle_io(unsigned int *port, unsigned int mask)
{
volatile unsigned int *p = port;
while (1) {
*port = 0x00;
*port = mask;
}
}
the toggle I/O function reduces to;
00008644 <toggle_io>:
8644: e3a03000 mov r3, #0 ; 0x0
8648: e5803000 str r3, [r0]
864c: e5801000 str r1, [r0]
8650: eafffffc b 8648 <toggle_io+0x4>
i.e., two store operations and a branch back to the start of
the first store operation.
The store operations can be changed to store-byte by using
a volatile unsigned char *, rather than volatile unsigned int *,
i.e.,
00008644 <toggle_io>:
8644: e3a03000 mov r3, #0 ; 0x0
8648: e5c03000 strb r3, [r0]
864c: e5c01000 strb r1, [r0]
8650: eafffffc b 8648 <toggle_io+0x4>
For the while(1)-style loop, the output frequency on EGPIO[15]
on DIO.15 was 7.14MHz (140ns period). For a 200MHz processor,
this is 28 clock cycles.
For the while(!done)-style loop, with read-modify-writes,
the output frequency was 2.86MHz (350ns period, 70 clocks
at 200MHz).
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h> /* toupper */
#include <signal.h>
/* Put the toggle loop in a separate function so that the
* disassembly of the code is easier to interpret.
*/
void toggle_io(unsigned int *port, unsigned int mask);
static void show_usage()
{
printf("\nUsage: toggle_io -p <port>\n"\
" -h Help (this message)\n"\
" -p <port> Port; A, B, C, F, H\n\n");
}
volatile sig_atomic_t done = 0;
void sigint_handler(int signo)
{
done = 1;
}
int main(int argc, char *argv[])
{
int opt; /* getopt processing */
int fd; /* /dev/mem file descriptor */
int page_size = getpagesize();
char *mem_addr = NULL;
unsigned int mem_phys = 0x80840000;
unsigned int *port;
unsigned int *port_dir;
unsigned int port_mask;
char port_name = '?';
struct sigaction act;
/* Command line parsing */
while ((opt = getopt(argc, argv, "hp:")) != -1) {
switch (opt) {
case 'h':
show_usage();
return -1;
case 'p':
port_name = toupper(optarg[0]);
break;
default:
show_usage();
return -1;
}
}
/* Check the port name */
switch (port_name) {
case 'A':
case 'B':
case 'C':
case 'F':
case 'H':
break;
default:
printf("\nPlease provide a valid port name.\n");
show_usage();
return -1;
}
/* Setup SIGINT */
act.sa_handler = sigint_handler;
if (sigaction(SIGINT, &act, 0) < 0) {
printf("Error: SIGINT setup failed - %s\n",
strerror(errno));
return -1;
}
/* Open a page at the GPIO base address */
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0) {
printf("Open /dev/mem failed - %s\n",
strerror(errno));
return -1;
}
mem_addr = (char *)mmap(
0,
page_size,
PROT_READ|PROT_WRITE,
MAP_SHARED,
fd,
mem_phys);
if (mem_addr == (char *)MAP_FAILED) {
printf("Error: mmap failed\n");
close(fd);
return -1;
}
/* Port tests
*
* Port bits Location
* --------- --------
* A[6:0] LCD header
* B[7:3, 1:0] DIO1 header
* C[0] LCD header
* F[1] DIO1 header
* H[5:3] LCD header
*/
switch (port_name) {
case 'A':
port = (unsigned int *)(mem_addr + 0x00);
port_dir = (unsigned int *)(mem_addr + 0x10);
port_mask = 0x7F;
break;
case 'B':
port = (unsigned int *)(mem_addr + 0x04);
port_dir = (unsigned int *)(mem_addr + 0x14);
port_mask = 0xFB;
break;
case 'C':
port = (unsigned int *)(mem_addr + 0x08);
port_dir = (unsigned int *)(mem_addr + 0x18);
port_mask = 0x01;
break;
case 'F':
port = (unsigned int *)(mem_addr + 0x30);
port_dir = (unsigned int *)(mem_addr + 0x34);
port_mask = 0x02;
break;
case 'H':
port = (unsigned int *)(mem_addr + 0x40);
port_dir = (unsigned int *)(mem_addr + 0x44);
port_mask = 0x38;
break;
default:
return -1;
}
/* Set the direction bits */
*port_dir = port_mask;
/* Toggle the pins */
printf("Toggling pins on port %c. Use ctrl-C to stop.\n",
port_name);
toggle_io(port, port_mask);
/* Cleanup */
printf("Disabling outputs on port %c\n", port_name);
*port_dir &= ~port_mask; /* inputs again */
munmap((void *)mem_addr, page_size);
close(fd);
return 0;
}
void toggle_io(unsigned int *port, unsigned int mask)
{
/* Make sure optimization does not eliminate the loop */
/* volatile unsigned char *p = (volatile unsigned char *)port; */
volatile unsigned int *p = port;
while (!done) {
/*
*p = 0x00;
*p = mask;
*/
/* Use read-modify-write */
*p &= ~mask;
*p |= mask;
}
/* Clear the data register */
*p &= ~mask;
}
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/ts-7000/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http://groups.yahoo.com/group/ts-7000/join
(Yahoo! ID required)
<*> To change settings via email:
<*> To unsubscribe from this group, send an email to:
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
|