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.

beaglebone gpmc?

Other Parts Discussed in Thread: AM3359

I have an existing board in need of a better processor and OS.. so.. I'd like to use my beaglebone's gpmc_ad0-15 as a multiplexed 16 bit address/data bus to talk to this board. I've built a circuit to latch the address and I can get things working with the pins configured as GPIO (mode 7) where I bit-bang the strobes and manually change the contents of the OE registers, etc.. What I'd like to do, however, is kick the pins into mode 0 and access my existing board as memory or IO. How to do this under arago / TI SDK? Where do I start?

Are there any good examples out there of how to do this? Do I just write some magic to /sys/kernel/some/gpmc/path and it starts working, or do I need to add custom code to my kernel? and a new u-boot to boot? Run PinMux? Is this even the right forum to post this in? Is it a linux question or a beaglebone question?

I know a little bit about linux device drivers.. I'm okay reading source code.. I just don't really have the high level view of what's required here... I don't know what I don't know.. what's there in the kernel already and what needs to be done?

Drew

  • If you are not very comfortable with writing kernel drivers or would like to get started poking your device right away, you can setup pin mux by echoing proper hex values to /sys/kernel/debug/omap_mux/gpmc_XXX and using /dev/mem to get access to any physical memory area that you might need. This worked fine in my case although I stumbled upon a mistery of using physical addresses 0x0 through 0x100000 while using csn0. You just need to be careful with what you write to /dev/mem since there is obviously no checking for any conflicts out there. If you need to get interrupts right away, this is not going to help much, you will have to write a driver.

     

  • So you were able to

    echo 0  > /sys/kernel/debug/omap_mux/gpmc_xxx

    and then mmap to /dev/mem and that worked? thanks, I'll try that.

    Can you post your "proper hex values"? (I found I needed 0x37 for the data pins in gpio mode, so is 0x30 required in mode 0?)

    Also: are you using gpmc_clk? I'd like to use that, but just setting it to mode 0 doesn't get it clocking. I don't know what else is exposed in sysfs to configure it.

  • Correct. I am using 0x20 (fast slew) but 0x30 (slow slew) also works. It is possible that the best setting for most gpmc_ pins except wait is to disable pullup/pulldown - 0x28/0x38.

    I am not using gpmc_clk. It is only active during the bus cycles so it is not very useful as a clock.

  • I was able to make this work too... thanks for pointing me in this direction.

    I used the sys/bios code posted at

    http://e2e.ti.com/support/dsp/sitara_arm174_microprocessors/f/791/p/176492/643640.aspx#643640

    as a starting point for initializing the GPMC, (re-defining the HWREG macro to use the mmap return pointer,) and used CSN1..

  • could you please share your code on how to configure GPMC using mmap ? I'am doing the same to access an FPGA with multiplexed bus. I have configure the mux, and opened mmap to the GPMC addresses bu i get :"Unhandeld fault: external abort on non line fetch". I believe it comes from the gpmc module being in idle.

  • Haven't forgotten about you.. just easily distracted.

    I'm sure my code is "wrong".... but it seems to work okay.

    I'll try to get it posted soon for you.

  • attached find gpmcpins.zip.

    buildit is probably wrong and should be done with a makefile. I just say

    ./buildit gpmc.c testgpmc

    on my host and it creates an executable that I copy to my beaglebone.

    I also copy over gpmcpins and run it on the beaglebone like

    sh gpmcpins

    and it configures the GPMC pins correctly.

    gpmc.c is pretty basic.. it just makes a large map into the am3359 starting at 44c00000.

    gpmc_init was ripped off from the dual port ram SYS-BIOS example for the IC, linked to previously in this thread.

    the .h files are copied in as well. I think there might be an arago equivalent for these files..

    I just modified a few of the strobe settings to get things working and then shorten the cycle time.

    This uses CSN1..

    config 7 sets the base address to 0x09000000.\\

    you can see this same address is used in the mmap call for extmem.

    I have a board that exposes memory from 0000 thru FF00, and then some memory mapped IO from FF00 thru FFFF.

    For starters I'm showing that the memory can be written to and read from successfully.

    anyway, hope this helps. Let me know if you have questions or suggestions

    Drew

    gpmcpins.zip
  • Hi,

    thanks a lot for the code, i got the DPRAM running in the meantime using mmap instead of HWREG.The only problem i had was the divide by 4 for offset ... I also forgot to set the correct direction on the pins. I'll try your code asap and let you know how it worked.

  • I did a quick capture of GPMC signal with example configuration (attached). in single access mode, the writing/reading speed i close to 12MB/s. This should be able to achieve much better speed with improved parameters. 

  • Looks pretty good! I couldn't get mine that fast, but my wiring isn't optimized for high speed.

    The gpmc.c that is in the zip file says csNum = 2, but that doesn't match the gpmcpins script.

    It should be csNum = 1 to match. I'm not sure how I accidentally changed it.. I was just doing "a little cleanup" (svn checkin comment) before posting it.

    Also, I use mmap inside of what looks like the HWREG. I redef'd the macro to use my _mmap pointer to make the sys/bios example work on linux:

    #define HWREG(x) __mmapl[(x-MMAP_OFFSET)/4]

  • I finally got a kernel space driver working and everything work well. The only disapointing thing is the read speed ... When writing i get up to 22MB/s but reading only gives 6MB/s. I gave a look using a logic analyzer and it seems that two subsequent reads are much more spaced when reading . I don't understand why but i'll try to sort this out.

  • why have you split the functionality between gmpc.c and gpmcpins ? Is it necessary to inform Linux of some of the changes ?

  • Simon Barnes said:

    why have you split the functionality between gmpc.c and gpmcpins ? Is it necessary to inform Linux of some of the changes ?

    gpmcpins is a shell script for setting the modes of the GPMC pins..

    I think the "proper" way to set the mode of the pins is a custom UBoot and the Pin mux utility. Then your linux just boots up with the pins in the proper modes. That looks a little complicated and what I have is working now (I'm prototyping, not building the production system) so I'm just trying to hit the other more critical path issues to get my "dog and pony" ready for the "show.." I'm a great procrastinator if it isn't on the critical path.. ;-)

    I'm not sure how to set the pin modes from C, but it's probably possible. Directly setting the mode bits doesn't seem to work though; I think the kernel protects them.

    The shell script did the job so I moved on.

    In my current configuration I also need to

    mount debugfs

    after I boot and before running the shell script

    I have

    debugfs              /sys/kernel/debug    debugfs    noauto                0  0

    in my /etc/fstab.

    There's probably a better way there too. I'm an electrical engineer.. but not a linux guru.

  • > Directly setting the mode bits doesn't seem to work though; I think the kernel protects them.

    as far as I know you cannot address them directly from user mode, as the CPU just ignores such writes, but I can't see why you can't write to them as you do in gpmc_init() via a mapping created by mmap()...

  • ah.. but my application *is* running in user mode. Someone else in this thread did the kernel driver code.. (which I'd be interested in seeing..)

    I used Alexander Hiam's PyBBIO as a reference implementation

    https://github.com/alexanderhiam/PyBBIO/blob/master/bbio/bbio.py

    The kernel protects them in the mmap mode, but debugfs jumps into kernel mode when you access it.

  • what I meant is, if you just create a user mode pointer to the chip registers, writes are ignored, but surely the whole point of using mmap() is to get round this ? Are you suggesting that you can map and access all the timing registers etc but not the pin muxes ?

  • That seems to be the case. You can mmap the registers and some, even most of them work, but the Pin Muxes do not.

    PyBBIO uses mmap to access the registers.. until you get to the pin mux.. then the _pinMux method takes a different route:

    def _pinMux(fn, mode):
      """ Uses kernel omap_mux files to set pin modes. """
      # There's no simple way to write the control module registers from a
      # user-level process because it lacks the proper privileges, but it's
      # easy enough to just use the built-in file-based system and let the
      # kernel do the work.
      try:
        with open(PINMUX_PATH+fn, 'wb') as f:
          f.write(hex(mode)[2:]) # Write hex string (stripping off '0x')
      except IOError:
        print "*omap_mux file not found: '%s'" % (PINMUX_PATH+fn)

  • well, thanks for letting me know that, I was scratching my head wondering about it. It does seem odd to me though - for a dedicated embedded system like this, it seems to me the memory protection just gets in the way - I'd like a "forget all the unnecessary crap, I know what I'm doing' configuration bit :)

  • Looks like this question opens back up again with the 3.8 kernel and device tree. No more omap_mux. I know this is an improvement, but it isn't making my life easier yet...

    Do I just come up with a dts file to do the pin muxing and compile to a dtbo that I can overlay, or is something else needed? (I'm still on beaglebone white, using a recent angstrom 3.8 SD card image.)

    I've come up with a simple dts that compiles and loads without complaint, but I don't see any activity on the pins with software that worked on the 3.2 kernel. Does this mean my dts has bugs in it? Or are there new methods of configuring the strobe timings, etc? I saw an example dts file that seemed to set strobe timings there.. Are there other things besides pin muxing that now must be done with device tree?

  • I made some progress on this. Device Tree is still a big mystery to me so I'm just modifying example code and guessing at what I'm changing. Which seems consistent with the adafruit documentation.. it's "overwhelming and obscure" so start with a file that is close, and hack away.. ;-)

    I started with the CAM3 and BACON files as examples, and originally just had the exclusive-use and fragment@0 sections, as they seemed to be the only ones that handled the data going into the conf_gpmc_adX registers. When I added a fragment@1 section, I started to get activity. I guess that section *is* necessary.. I'm guessing it's

    pinctrl-0 = <&gpmc_pins>

    that connects fragment@0 into the gpmc?

  • Hi,

    I referred your code... and  checked  CS signal with CRO. But I am always getting high signal at particular CS pin.

    I am using gpmc mode in am3359 microprocessor.
     How can i check the csn1 0r csn2 signal using CRO & without connecting an external memory.

    Thank you,