This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to set my memory device as EMMC or GPMC am437x gp evm

Other Parts Discussed in Thread: ASH

I am currently trying to evaluate the /dev/mem device. I have written the following program

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.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 masks    */
/* for read and write  */
/********************************************************************/

//#define ADDR_RANGE_MASK 0xE2000FFF                                      // "00111111111111" Allows only the the
                                                                          // 12 first bit's to be set since we use the
                                                                          // first 12 bits for addressing in the FPGA
//#define READ_MASK 0xE2001FFF                                            // "01111111111111" read bit 1 & write bit 0
//#define WRITE_MASK 0xE2002FFF                                           // "10111111111111" read bit 0 & write bit 1
//#define BASE_ADDR 0xE2000000                                            //CS_2 range starts @ 0xE2000000
/********************************************************************/
/*  Define size to allocate */
/********************************************************************/
#define MAP_SIZE 4096UL                                                   // needs to be looked at....
#define MAP_MASK (MAP_SIZE - 4)

int main(int argc, char **argv) {
   int fd;
   void *map_base, *virt_addr;
   unsigned long read_result, writeval;
   off_t target;
         if(argc < 2){                                                    //error message in case of wrong input
           fprintf (stderr, "\nUsage:\t%s { address } [ data ]\n"
              "\taddress : memory address to act upon\n"
              "\tdata : data to be written (32bit)\n\n"
              "To [i]nitialize type only i leaving out the addresses \n\n",
              argv[0] );
          exit(1);
         }

/********************************************************************/
/*  Init */
/********************************************************************/

if(strcmp(argv[1],"i" ) == 0 )                                           //strcmp() returns 0 if strings are the same (case sensitive)
{
    printf ("init started.\n");
    target = 0x31080240;
  //              Open /dev/mem file & error handling
    if ((fd = open ("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
    printf ("/dev/mem opened.\n");
    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;
    printf ("Memory (0x31080240) mapped at address %p.\n", map_base);
    fflush (stdout);
  // start WRITE
    virt_addr = map_base + (target & MAP_MASK);
    writeval = 0x2;                                                        //32Bit data bus setting for static memory of CS_2
          *((unsigned long *) virt_addr) = writeval;
          printf ("Written 0x%X\n", writeval);
          fflush (stdout);
          printf ("init successful\nRestart program to write or read data\n\n");
  // stop WRITE
}
else
  /********************************************************************/
  /*  Read/Write */
  /********************************************************************/
{
target = strtoul (argv[1], 0, 0);                                         // Parsing the input & leaving out leading 0 & 0x's
// Open /dev/mem file & error handling
   if( (fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
   printf ("/dev/mem opened.\n");
   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;
   printf ("Memory mapped at address %p.\n", map_base);
   fflush (stdout);

   virt_addr = map_base + (target & MAP_MASK);
// start READ
   if (argc <= 2) {
         read_result = *((unsigned long *) virt_addr); //unsigned long fits the 32 bit bus data
         printf("read_result: %d \n",read_result);
// stop READ
         printf ("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result);
         fflush (stdout);
}
// start WRITE if there is data to write given in the arguments
         if (argc > 2) {
       writeval = strtoul(argv[2], 0, 0);
         *((unsigned long *) virt_addr) = writeval;
         printf ("Written 0x%X\n", writeval);
         fflush (stdout);
}
// stop WRITE
}

/********************************************************************/
/*  UnMap one page  */
/********************************************************************/
  if (munmap(map_base, MAP_SIZE) == -1) FATAL;
  close (fd);
  return 0;
}

I can see from the schematics that the EMMC and GPMC shares the same memory device. How will i be able to toggle between the emmc and gpmc in Kernel level.
 Is there any reference document for this operation.

Regards

-Ash

  • Hi Ash,

    ash parker said:
    I can see from the schematics that the EMMC and GPMC shares the same memory device. How will i be able to toggle between the emmc and gpmc in Kernel level.

    This is not possible. eMMC is connected to MMC1 interface, while NAND is connected to the GPMC. The two interfaces are pinmuxed on the same processor pins. It's not possible to switch them on the fly.

  • Thanks Biser,

    How do I know what protocol is the memory device in dev/mem  uses to communicate ?? is it gpmc or emif ??

    root@am437x-evm:/dev# dmesg | grep mem                                          
    [    0.000000] free_area_init_node: node 0, pgdat c086e354, node_mem_map ed7ee00
    [    0.000000]   Normal zone: 1520 pages used for memmap                        
    [    0.000000]   HighMem zone: 528 pages used for memmap                        
    [    0.000000] Memory: 1003864K/1046528K available (5871K kernel code, 311K rwd)
    [    0.000000] Virtual kernel memory layout:                                    
    [    0.000000]     lowmem  : 0xc0000000 - 0xef800000   ( 760 MB)                
    [    0.152275] syscon 44e10000.control_module: regmap [mem 0x44e10000-0x44e107fd
    [    1.746128] gpmc_mem_init: disabling cs 0 mapped at 0x0-0x1000000            
    [    7.713276] Freeing unused kernel memory: 264K (c07df000 - c0821000)         
    [   13.430362] xhci-hcd xhci-hcd.1.auto: irq 206, io mem 0x483d0000             
    root@am437x-evm:/dev# 
    

    here is my dmesg output for memory device..

    Regards

    -Ash

  • This grep outputs the available DDR memory.
  • is There a document help for NAND communication via gpmc on the evaluation board and emmc communication to the U65 micron chip ???
    Do i need to make changes to the dtsi file to enable the gomc/emmc.

    Regards
    -Ash
  • Hi,

    You can see to which interface your external memories are connected, simply by checking the dts file in your kernel sources (or board file, depending on the kernel version). As a rule the DDR is always connected to the EMIF.

    You can write to most physical addresses (except the ones reserved for the kernel accesses) from within the user space using mmap(). This applies to the addresses of each external memory: NOR, NAND, IP registers, etc. The forum has a lot of discussions on this topic, i.e.:
    e2e.ti.com/.../1641674
    e2e.ti.com/.../1576212
    and many more.

    You can always take as a reference the source of devmem2.

    There are no step-by-step wiki guides, as these programs depend on the use case.

    Best Regards,
    Yordan