Forum Discussion

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

How to read from a onchip memory

Hello i want to read data from some adress at the onchip memory, i can do it with IORD and IOWR using altera HAL functions. However those functions are not available for me inside the linux

9 Replies

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

    You won't be able to access memory directly from userspace in linux. You'll probably have to write a kernel driver or module. On the other hand, You can access heap memory if it is set in BSP config by using malloc().

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

    hello ...

    if you using uClinux no-mmu you can acess the memory using IORD and IOWR

    make a c program and cross compile for your design

    at uClinux no-mmu you can acess peripherials direct....

    cheers

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

    if you use uClinux no-mmu .......

    use a program like that to test you acess.....

    #include <stdio.h>
    # define BUFFER_MEMORY 0x10000000# define IORD(address, offset) (*(volatile unsigned *)(((address)| 0x80000000)+4*(offset)))
    # define IOWR(address, offset, value) (*(volatile unsigned *)(((address)|0x80000000)+4*(offset)))=(value)
    int main()
    {
    int op;
    int valor;
    int temp;
    while (1) {
        
     printf("\n\n\nDIGITE A OPCAO\n");
     printf("1 - ESCREVER\n");
     printf("2 - LER\n");
     scanf("%d",&op);
     
     if (op == 1) {
     printf("DIGITE O VALOR\n");
     scanf("%x", &valor);
     printf("ESCREVENDO %x\n", valor);
     IOWR(BUFFER_MEMORY, 2, valor);
     //IOWR(0x00041040, 0, valor);
     }
     else if (op == 2) {
        
     printf("LENDO\n");
     temp=IORD(BUFFER_MEMORY, 0X2);
     printf("temp = %x\n", temp);
     }
     else {
     printf("OPCAO INVALIDA\n\n");
     }
     
    }
      return 0;
    }

    good luck

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

    Thanks Franz, this works with NOMMU but i am using a MMU linux do you have any ideas on how to do it?

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

    hi man

    .... i trying use uclinux mmu now.........but i dont know how did that at mmu.........

    malloc() calloc() can help i guess........

    i will try do .....

    cheers....

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

    Device driver to acess on chip memory as a char device (must be made inside linux2.6/arch/nios2/driver)

    # include <linux/fs.h># include <linux/sched.h># include <linux/errno.h># include <linux/types.h># include <linux/cdev.h># include <linux/kernel.h># include <linux/module.h># include <asm/current.h># include <asm/segment.h># include <asm/uaccess.h># include <asm/io.h>
    # define DRIVER_NAME "shmem"
    # define SHARED_MEM_BASE 0x800# define SHARED_MEM_SPAN 2048
    typedef struct {
      int32_t mutex;
      int32_t reset;
    } mutex_t;
    typedef struct {
      mutex_t *mutex;
      unsigned char *buffer;
    } shmem_t;
    static shmem_t shmem;
    int shmem_open(struct inode *inode,struct file *filep)
    {
      return 0;
    }
    int shmem_release(struct inode *inode, struct file *filep)
    {
      return 0;
    }
    ssize_t shmem_read(struct file *filep ,char *buff, size_t count, loff_t *offp)
    {
      int retval;
      
      printk(KERN_INFO "read, count %i, off %i\n", count, *offp);
      
      if (*offp >= SHARED_MEM_SPAN) {
        return 0;
      }
      
      if (count > (SHARED_MEM_SPAN - *offp)) {
        count = (SHARED_MEM_SPAN - *offp);
      }
      
      
      retval = copy_to_user(buff, (shmem.buffer+*offp), count);
      if (retval != 0) {
        printk(KERN_ERR "Kernel to userspace copy failed!\n" );
        return retval;
      }
      *offp += count;
      
      return count;
    }
    ssize_t shmem_write(struct file *filep,const char *buff,size_t count,loff_t *offp )
    {
      int retval;
      if (*offp >= SHARED_MEM_SPAN) {
        return -ENOSPC;
      }
      
      if (count > (SHARED_MEM_SPAN - *offp)) {
        count = (SHARED_MEM_SPAN - *offp);
      }
      retval = copy_from_user((shmem.buffer+*offp), buff, count);
      if (retval != 0) {
        printk(KERN_ERR "Kernel to userspace copy failed!\n" );
        return retval;
      }
      *offp += count;
      
      return count;
    }
        
    struct file_operations shmem_fops={
    open: shmem_open,
    read: shmem_read,
    write: shmem_write,
    release:shmem_release,
    };
    static int shmem_init(void) {
      printk(KERN_INFO "shmem device driver init\n");
      if(register_chrdev(222,DRIVER_NAME, &shmem_fops)){
        printk(KERN_ERR "failed to register\n");
        goto chrdev_error;
      }
      shmem.mutex = (mutex_t *)ioremap(MUTEX_BASE, MUTEX_SPAN);
      if (shmem.mutex == NULL) {
        printk(KERN_ERR "failed to map mutex\n");
        goto mutex_error;
      }
      
      printk(KERN_INFO "mutex %p\n", shmem.mutex);
      shmem.buffer = (unsigned char *)ioremap(SHARED_MEM_BASE, SHARED_MEM_SPAN);
      if (shmem.buffer == NULL) {
        printk(KERN_ERR "failed to map shared memory\n");
        goto buffer_error;
      }
      printk(KERN_INFO "shmem %p\n", shmem.buffer);
      
      printk(KERN_INFO "shmem: mutex.reset %02x\n", shmem.mutex->reset);
      return 0;
    buffer_error:
      iounmap(shmem.mutex);
    mutex_error:
      unregister_chrdev(222, DRIVER_NAME);
    chrdev_error:
      return -ENODEV;
    }
    static void shmem_cleanup(void)
    {
      printk(KERN_INFO "shmem device driver unregister.\n");
      iounmap(shmem.buffer);
      iounmap(shmem.mutex);
      unregister_chrdev(222, DRIVER_NAME);
      return;
    }
    module_init(shmem_init);
    module_exit(shmem_cleanup);
    

    A program in user land (uclinuxdist/user/program) to read 32 bits per read

    # include <unistd.h># include <fcntl.h># include <sys/mman.h>
    int main()
    {
        int fd = 0;
        int value = 0;
        int bytes = 0;
        fd = open("/dev/mutex", O_RDWR);
        if (fd == NULL)
        {
            printf("Erro abrindo mutex\n");
            return 1;
        }
        bytes = read(fd, &value, sizeof(value));
        if (bytes < 0)
        {
            printf("Error lendo\n");
            return 1;
        }
        
        printf("Valor lido: %x\n", value);
        
        bytes = read(fd, &value, sizeof(value));
        if (bytes < 0)
        {
            printf("Error lendo\n");
            return 1;
        }
        
        printf("Valor lido: %x\n", value);
        
        lseek(fd, 0, SEEK_SET);
        
        bytes = read(fd, &value, sizeof(value));
        if (bytes < 0)
        {
            printf("Error lendo\n");
            return 1;
        }
        
        printf("Valor lido: %x\n", value);
        
        close(fd);
        return 0;
        
        
        
    }