ts-7000
[Top] [All Lists]

[ts-7000] Re: test TS7300 DIO1 Header

To:
Subject: [ts-7000] Re: test TS7300 DIO1 Header
From: "dave_w_hawkins" <>
Date: Sat, 12 May 2007 22:20:36 -0000
--- 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/
 

<Prev in Thread] Current Thread [Next in Thread>
Admin

Disclaimer: Neither Andrew Taylor nor the University of NSW School of Computer and Engineering take any responsibility for the contents of this archive. It is purely a compilation of material sent by many people to the birding-aus mailing list. It has not been checked for accuracy nor its content verified in any way. If you wish to get material removed from the archive or have other queries about the archive e-mail Andrew Taylor at this address: andrewt@cse.unsw.EDU.AU