Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
20 years ago

IOWR and direct adress access

I can use IOWR,IORD and direct address access to operate SDRAM, But

i can not use address to access Uart, for example:

1. use address

alt_u8 * UartTxAdr;

UartTxAdr = UART0_BASE+1;

//that can not send the data

* UartTxAdr = 0x30;

2.use IOWR

//that can send the data ok

IOWR(UART0_BASE,1,0x30);

I do not know what different between these two way.

in my DMA operate code, from memory to uart, the code is as follow:

static volatile int rx_done = 0;

alt_u8 buffer[16] __attribute__((section(".sdram")));

static void done (void* handle, void* data)

{

rx_done++;

}

// in main function

buffer[0]=0x30; //'0'

buffer[1]=0x31; //'1'

buffer[2]=0x32; //'2'

buffer[3]=0x33; //'3'

void* tx_data = (void*) &buffer[0]; /* pointer to data to send */

if ((txchan = alt_dma_txchan_open("/dev/dma_0")) == NULL)

{

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 2);

exit (1);

}

alt_dma_txchan_ioctl(txchan,ALT_DMA_SET_MODE_8,NULL);

alt_dma_txchan_ioctl(txchan,ALT_DMA_RX_STREAM_ON,(void*)UART0_BASE+1);

if ((rc = alt_dma_txchan_send (txchan,tx_data,4,done,NULL)) < 0)

{

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 3);

exit (1);

}

while (!rx_done);

alt_dma_txchan_close(txchan);

the code is execute OK, the rx_done is set, but the data never send out from the

uart, maybe it can not use direct address access?? (i think the dma operate is use

direct address operate),

i add the uart0 in SOPC and set the "include end-of packet register", and connect

DMA write-master to usrt0, read-master to sdram by set the small rect with "1",

anyone can help me ????

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi hugeant,

    > I do not know what different between these two way.

    When you use "direct access" you end up using stx/ldx instructions. When you use

    the IOWR/IORD macros, you get the stxio/ldxio instructions. The "io" instructions

    bypass the data cache.

    > but the data never send out from the uart

    Do you mean you didn&#39;t see any data on your terminal? ... or nothing was

    transmitted at all? Your terminal software simply may not be displaying NULL

    for example -- but the transmission may actually be occurring.

    If you&#39;re using a data cache, you should flush prior to calling alt_dma_txchan_send.

    The last time I looked at that code, it didn&#39;t flush the cache for you ... so it&#39;s your

    program&#39;s responsibility. You might be transmitting all NULL, since your buffer data

    is still in the cache (it was never written back).

    Regards,

    --Scott
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    >When you use "direct access" you end up using stx/ldx instructions. When you use

    the IOWR/IORD macros, you get the stxio/ldxio instructions. The "io" instructions

    bypass the data cache.

    thanks,Now i understand it , when a do the memory transfer, maybe it first move to data cache, not move to the address i what.

    >Do you mean you didn&#39;t see any data on your terminal? ... or nothing was

    transmitted at all? Your terminal software simply may not be displaying NULL

    Yes, nothing was transmitted, I made the terminal program in PC and it can display any data when received. I set the display mode in hex mode.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    /* Here is my test code. To Test DMA from Memory -> UART

    some of them cames from this forum.

    In The Terminal in My PC, I can see the followed data received

    =========================================

    0x68 0x65 0x6c 0x6c 0x6f 0x20 0x77 0x6f 0x72 0x6c 0x64 0x0a

    0x30

    0x31

    0x32

    0x33

    =========================================

    the first line is the "hello world"

    then i received 4 data send by IOWR macro

    after that, nothing received,even NULL.

    before DMA,i flush all cache,but nothing changed.

    the Timer is running,that means the dma transmit complete,

    but i do not know why nothing out from UART.

    */

    # include "system.h"# include <stdio.h># include "altera_avalon_pio_regs.h"# include "altera_avalon_timer_regs.h"# include "sys/alt_dma.h"# include "altera_avalon_dma_regs.h"# include "alt_types.h"

    volatile alt_u8 count;

    static volatile int rx_done = 0;

    alt_u8 buffer[16] __attribute__((section(".onchip_ram")));

    static void done (void* handle, void* data)

    {

    rx_done++;

    }

    void delay(void)

    {

    volatile int i;

    i=0;

    while (i<400000) i++;

    }

    static void handle_Timer0_interrupts(void* context, alt_u32 id)

    {

    alt_u8 a;

    volatile alt_u8 *countptr = (volatile alt_u8 *)context;

    IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0);//?TO??

    a = *countptr;

    a=a<<1;

    if (a == 0x10) a=1;

    *countptr=a;

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, a);

    }

    void startTimer(void)

    {

    count=1;

    alt_irq_register(TIMER_0_IRQ, (void *)&count, handle_Timer0_interrupts);

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0);

    IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, 7);

    }

    int main (void)

    {

    int rc;

    alt_dma_txchan txchan;

    FILE *uart;

    uart = fopen("/dev/uart0","w");

    if(uart==NULL){

    }else{

    char *str="hello world\n";

    fprintf(uart,str);

    }

    delay();

    buffer[0]=0x30; //&#39;0&#39;

    buffer[1]=0x31; //&#39;1&#39;

    buffer[2]=0x32; //&#39;2&#39;

    buffer[3]=0x33; //&#39;3&#39;

    IOWR(UART0_BASE,1,buffer[0]);

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 1);

    delay();

    IOWR(UART0_BASE,1,buffer[1]);

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 2);

    delay();

    IOWR(UART0_BASE,1,buffer[2]);

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 4);

    delay();

    IOWR(UART0_BASE,1,buffer[3]);

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 8);

    delay();

    void* tx_data = (void*) &buffer[0]; /* pointer to data to send */

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 1);

    if ((txchan = alt_dma_txchan_open("/dev/dma_0")) == NULL)

    {

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 2);

    exit (1);

    }

    alt_dma_txchan_ioctl(txchan,ALT_DMA_SET_MODE_8,NULL);

    alt_dma_txchan_ioctl(txchan,ALT_DMA_RX_STREAM_ON,(void*)UART0_BASE+1);

    alt_dcache_flush_all();

    alt_icache_flush_all();

    if ((rc = alt_dma_txchan_send (txchan,tx_data,4,done,NULL)) < 0)

    {

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 4);

    exit (1);

    }

    while (!rx_done);

    alt_dma_txchan_close(txchan);

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 15);

    delay();

    // end of DMA stream translate

    IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0);

    startTimer();

    while (1) {;}

    if(uart)

    {

    fclose(uart);

    }

    return 0;

    }
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Any "I/O variables" should be qualified as volatile

    so : volatile alt_u8 * UartTxAdr

    This prevents the optimiser from tuning the code out (because it will detect that nothing is "reading" the location).
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    originally posted by jasondiplomat@Oct 22 2005, 05:20 AM

    any "i/o variables" should be qualified as volatile[/b]

    so : volatile alt_u8 * UartTxAdr

    This prevents the optimiser from tuning the code out (because it will detect that nothing is "reading" the location).

    <div align='right'><{post_snapback}> (index.php?act=findpost&pid=10525)

    --- Quote End ---

    [/b]

    --- Quote End ---

    Thanks for you reply ,JasonDiplomat.

    you means that the DMA controller also effected by "volatile" ??