I am unable to set the default value of a GPIO for the PRU. I would like to have a “pull-down” default, but when I boot the signal is “high” > 3.3v.
My system:
Linux beaglebone 4.19.94-ti-r62 #1buster SMP PREEMPT Sat Apr 24 00:27:24 UTC 2021 armv7l GNU/Linux
Beaglebone Black Rev C
Booting with the UIO pruss
In /boot/uEnv.txt - uboot_overlay_pru=AM335X-PRU-UIO-00A0.dtbo
Steps I took:
Went to https://kilobaser.com/beaglebone-black-device-tree-overlay-generator/ to get a dts
Selected P9_27, fast Slew, Output, Pulldown, Mode5: pr1_pru0_pru_r30_5
It generated:
/dts-v1/;
/plugin/;
/{
compatible = "ti,beaglebone", "ti,beaglebone-black";
part_number = "BS_PINMODE_P9_27_0x5";
exclusive-use =
"P9.27",
"pr1_pru0_pru_r30_5";
fragment#0 {
target = <&am33xx_pinmux>;
__overlay__ {
bs_pinmode_P9_27_0x5: pinmux_bs_pinmode_P9_27_0x5 {
pinctrl-single,pins = <0x1a4 0x5>;
};
};
};
fragment#1 {
target = <&ocp>;
__overlay__ {
bs_pinmode_P9_27_0x5_pinmux {
compatible = "bone-pinmux-helper";
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&bs_pinmode_P9_27_0x5>;
};
};
};
};
Compiled and applied the device tree
Reboot, on boot the o-scope on P9_27 goes high
I’ve tried on P9_25 as well, same result. (Update: I have tried ALL of the PRU gpios on P9 with the same result). I’ve configured it for Mode 7 (standard GPIO) and it works fine. Just Mode 5 does not seem to be responding as expected.
Can anyone verify my issue and offer a solution?
Additional clarification, the reason I believe I have configured P9_27 in the above example to be low on boot is this:
pinctrl-single,pins = <0x1a4 0x5>;
The 0x1a4 is the address offset for P9_27
0x5 = 0000 0101 - the top 5 bits are the mode in the table below. The 101 selects mode 5 (Bits 2-0) in table below. For a general GPIO, this functionality works perfectly, and there does not seem to be different rules for GPIOs associated with the PRUs
Bit Field Reset Description
6 conf_<module>_<pin>_slewctrl X Slew Control. Slew Rate: Fast is 0, Slow is 1
5 conf_<module>_<pin>_rxactive 1h Receiver Active. Input Enable: Receiver Disable 0, Receiver Enable 1
4 conf_<module>_<pin>_putypesel X Pad Pullup/Pulldown Type. Pulldown is 0, Pullup is 1
3 conf_<module>_<pin>_puden X Pad Pullup/Pulldown enable. Enabled is 0, Disabled is 1
2-0 conf_<module>_<pin>_mmode X Mode. Pad functional mux select. A number between 0 and 7 i.e. 000 and 111. This depends on which mode we require.
Related
I have this LCD panel:
LED panel's backlight is driven by the MIC2297 chip which takes two signals:
BRT - PWM signal for setting brightness of the LCD's background LEDs.
BL_EN that - gpio signal that enables or disables the LCD's background LEDs.
MIC2297 is powered from the +12V.
Now I connected this display to the Beaglebone Black's (BBB's) expansion connector and I am already running Linux on the BBB's microcontroller AM335x.
In order to enable the backlight I have to properly define it in the device tree i.e. .dts file. Currently I managed to set this up:
backlightt: backlight {
compatible = "pwm-backlight";
pwms = <&ehrpwm1 0 500000000>;
power-supply <>; // ???
enable-gpios = <&gpio2 3 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <7>;
};
What I don't understand is the property power-supply. How can I know which regulator to use? My devicce uses external 12V! This is really confusing! Why do we even have to specify the regulator?
I found solution...
PWM backlight requires a property "power-supply" that points to some regulator inside the AM335x. This regulator is used to set the output voltage of the PWM - so we don't need to put any kind of voltage regulator between an AM335x and the backlight IC (which might only support 1.5V PWM input on some mobile devices). This is actually really useful.
How should I go about modifying and/or compiling the Robot Control Library for use with a different beaglebone cape that uses slightly different pin assignments?
My primary reason for wanting to re-use the Robot Control Library is the ability to read a fourth encoder via the PRU. Beyond that, I only need access to the encoder and pwm modules.
TL;DR
Modifying the PRU firmware to read the encoder signal from a different pin was easy. Figuring out how to assemble a working device tree for the combination of features I needed was way harder.
I would welcome any feedback on how I should have done this, or how I could improve upon what I currently have.
Robot Control Library + Motor Cape
The Robotics Cape and the BeagleBone Blue provide a turnkey solution for servo controlling four motors,
IFF you are satisfied with driving them at 8V (e.g. a 2S LIPO battery). The Motor Cape can handle a
higher drive voltage (and more current), but does not include encoders. Plugging encoders into the P8 & P9
headers on the Motor Cape is simple enough, but the BeagleBone itself only has 3 encoder counters (eQEP).
The Robot Control Library solves this problem by reading the fourth encoder with PRU0. However, some of the
pins conflict between the Motor Cape and what the Robot Control Library expects on the Robotics Cape.
So, how hard could it be to use the Robot Control Library to read encoders and drive motors with a slightly
different pinout on the Motor Cape? Probably not difficult at all if you are already competent with BeagleBone
device tree overlays, which I am not...
It all starts with a plan -- Pin Selection
Pin
PRU Bit
Robotics Cape
Motor Cape
P8_15
15
Enc 4B
--
P8_16
14
Enc 4A
M2 Dir
P9_25
7
IMU
--
The Robot Control Library expects the fourth encoder to show up on P8_15 and P8_16, but the
Motor Cape has P8_16 wired as a direction signal. There are only 12 pins than be configured
as inputs to PRU0 and I eventually selected P9_25 because I did not need the IMU functionality.
The best reference I found for what pins can be used for what purposes were these pdfs:
https://ofitselfso.com/BeagleNotes/BeagleboneBlackP8HeaderPinMuxModes.pdf
https://ofitselfso.com/BeagleNotes/BeagleboneBlackP9HeaderPinMuxModes.pdf
The Easy Part -- Modifying the PRU Code
The Robot Control Library defines the encoder signal input bits in pru_firmware/src/pur0-encoder.asm as
; Encoder counting definitions
; these pin definitions are specific to SD-101D Robotics Cape
.asg r0, OLD ; keep last known values of chA and B in memory
.asg r1, EXOR ; place to store the XOR of old with new AB vals
.asg 14, A
.asg 15, B
This can be modified to look for the A channel on bit 7 (of register 31, which is used for all inputs) as
; Encoder counting definitions
; these pin definitions are specific to SD-101D Robotics Cape
.asg r0, OLD ; keep last known values of chA and B in memory
.asg r1, EXOR ; place to store the XOR of old with new AB vals
.asg 07, A
.asg 15, B
N.B. The PRU firmware has to be separately compiled by by running make and sudo make install
inside the pru_firmware directory. It is not compiled automatically as part as part of building the rest
of the library from the top-level Makefile.
Helpful Tip: What version am I actually running?
There are instructions on modifying the repored version of librobotcontrol in
library/version_updating_howto.txt. I followed these instructions to create my own
"private" version number so that I could confirm that I was actually running my modified
version of the libray. This version is reported by rc_test_drivers.
However... as noted above, the PRU firmware was not getting compiled by the top-level Makefile,
so for a while I was running my "new" version of librobotcontrol with "old" firmware in the PRU.
The Part that Almost Worked -- The Device Tree
I found references in both the documentation and code for librobotcontrol that device tree overlays
were no longer needed because the Robotics Cape used its own device tree.
The overlay is deprecated now, instead the cape gets its own complete device tree.
I also observed that running the recommended configure_robotics_dt.sh replaced /boot/uEnv.txt with
the following simplified version that loads a single device tree binary (.dtb)
uname_r=4.19.94-ti-r42
dtb=am335x-boneblack-roboticscape.dtb
cmdline=coherent_pool=1M
My favorite reference that I found for general information about the device tree, pinmux, etc was
http://www.ofitselfso.com/BeagleNotes/AboutTheDeviceTree.pdf However, I now realize that some of the
details are a bit out of date, so be careful.
Because I had very little idea of where else to start, I set out to modify the robotics cape device tree
just enough to eliminate the conflicts with the Motor Cape. I forked and cloned
https://github.com/beagleboard/BeagleBoard-DeviceTrees and created two new files
am335x-boneblack-custom.dts
copy of am335x-boneblack-roboticscape.dts
changed model to make the new device tree recognizable
changed #include to point to am335x-custom.dtsi instead of am335x-roboticscape.dtsi
am335x-custom.dtsi
copy of am335x-roboticscape.dtsi
deleted a whole bunch of stuff I thought I didn't need anymore
routed P9_25 (instead of P8_16) to PRU0
Before
/* PRU encoder input */
0x03c 0x36 /* P8_15,PRU0_r31_15,MODE6 */
0x038 0x36 /* P8_16,PRU0_r31_14,MODE6 */
After
/* PRU encoder input */
0x03c 0x36 /* P8_15,PRU0_r31_15,MODE6 */
0x1ac 0x36 /* P9_25,PRU0_r31_7,MODE6 */
After compiling and installing the modified device trees (make, sudo make install in the
BeagleBoard-DeviceTrees repo), I modified /boot/uEnv.txt to call my new custom device tree
uname_r=4.19.94-ti-r42
dtb=am335x-boneblack-custom.dtb
cmdline=coherent_pool=1M
I was able to boot the BeagleBone with no cape installed, plug encoders directly into the desired pins
on P8_and P9 (including enc4a on P9_25) and read all four encoders using sudo rc_test_encoders.
I thought I had won and went to bed...
Motor Cape Won't Boot
After a good night's sleep, I plugged the Motor Cape onto the BeagleBone expecting nothing to change since
I was only passing encoder signals directly through the P8 and P9 headers. I thought the next step would be
to make similar tweaks to a few of the pwm direction pins.
However, the BeagleBone refused to boot my custom device tree with the MotorCape installed. I went back to
the "standard" am335x-boneblack-roboticscape.dtb device tree and observed that it would not boot either with
the Motor Cape intalled. I also became suspicious that the "factory" installation of the Robotics Cape might have
been using overlays after all
I had been torn from the beginning about whether I should be starting from the Robotics Cape device tree and removing
things I did not need in order to eliminate resource conflicts, versus starting with the "naked" BeagleBone device tree
and adding the things that I did need. Whether accurate or not, in my mind that kind-of mapped into trying to specify
a full device tree versus providing an overlay to apply on top of the base device tree. The latter seemed like
the conceptually more correct path, so once the Motor Cape failed to boot with the robotics-cape-derived device tree,
I decided to bite the bullet and try to figure out device tree overlays.
Unanswered Questions
[ ] Why won't the BB boot from am335x-boneblack-roboticscape.dtb with the motor cape installed? What is the actual error?
[ ] Does a "normal" installation of librobotcontrol install the simplified uEnv.txt above or does it use an overlay? Does it work?
I did not yet have USB-to-TTL serial cable that could fit under an installed cape, so I know very little about
why or how this was failing to boot.
The Part that Finally Worked -- Device Tree Overlays
I eventually figured out that the collection of device tree overlays is avialable both at
https://github.com/beagleboard/bb.org-overlays and in the v4.19.x-ti-overlays branch at
https://github.com/beagleboard/BeagleBoard-DeviceTrees. I suspect that this might be an
in-progress migration, but there was more documentation associated with the bb.org-overlays
repository so that is what I chose to use.
A few documentation links that I wish I had found earlier:
https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays
https://github.com/cdsteinkuehler/beaglebone-universal-io
https://vadl.github.io/beagleboneblack/2016/07/29/setting-up-bbb-gpio
I created forked, cloned, and branched the bb.org-overlays repo and created a new overlay at
src/arm/CustomCape-00A0.dts by hacking together pieces from BBORG_MOTOR-00A2.dts and RoboticsCape-00A0.dts
/*
* Device Tree Overlay for custom cape trying to reuse Robot Control Library's
* reading of 4x optical encoders.
*/
/*
pinmux control byte map courtesy of http://beaglebone.cameon.net/
Bit 5: 1 - Input, 0 - Output
Bit 4: 1 - Pull up, 0 - Pull down
Bit 3: 1 - Pull disabled, 0 - Pull enabled
Bit 2 \
Bit 1 |- Mode
Bit 0 /
*/
/dts-v1/;
/plugin/;
/ {
compatible = "ti,beaglebone-black";
/* identification */
part-number = "CustomCape";
/* version */
version = "00A0";
exclusive-use =
"P8.11", /*QEP_2B*/
"P8.12", /*QEP_2A*/
"P8.16", /*PRU_ENCODER_A*/
"P8.33", /*QEP_1B*/
"P8.35", /*QEP_1A*/
"P9.27", /*QEP_0B*/
"P9.41", /*MOT_STBY*/
"P9.42"; /*QEP_0A*/
/*
* Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
*/
fragment#0 {
target-path="/";
__overlay__ {
chosen {
overlays {
CustomCape-00A0 = __TIMESTAMP__;
};
};
};
};
fragment#1 {
target = <&am33xx_pinmux>;
__overlay__ {
/****************************************
* pinmux helper
****************************************/
mux_helper_pins: pins {
pinctrl-single,pins = <
/* EQEP */
0x1A0 0x31 /* P9_42,EQEP0A, MODE1 */
0x1A4 0x31 /* P9_27,EQEP0B, MODE1 */
0x0D4 0x32 /* P8_33,EQEP1B, MODE2 */
0x0D0 0x32 /* P8_35,EQEP1A, MODE2 */
0x030 0x34 /* P8_12,EQEP2A_in, MODE4 */
0x034 0x34 /* P8_11,EQEP2B_in, MODE4 */
/* PRU encoder input */
0x03c 0x36 /* P8_15,PRU0_r31_15,MODE6 */
0x1ac 0x36 /* P9_25,PRU0_r31_7,MODE6 */
>;
};
};
};
/****************************************
Pinmux Helper
activates the pinmux helper list of pin modes
****************************************/
fragment#2 {
target = <&ocp>;
__overlay__ {
test_helper: helper {
compatible = "bone-pinmux-helper";
pinctrl-names = "default";
pinctrl-0 = <&mux_helper_pins>;
status = "okay";
};
};
};
/*
* Free up the pins used by the cape from the pinmux helpers.
*/
fragment#3 {
target = <&ocp>;
__overlay__ {
P8_11_pinmux { status = "disabled"; }; /* enc3b */
P8_12_pinmux { status = "disabled"; }; /* enc3a */
P8_15_pinmux { status = "disabled"; }; /* enc4b */
P8_33_pinmux { status = "disabled"; }; /* enc0 */
P8_35_pinmux { status = "disabled"; }; /* enc0 */
P9_25_pinmux { status = "disabled"; }; /* enc4a */
P9_27_pinmux { status = "disabled"; }; /* enc1b */
P9_92_pinmux { status = "disabled"; }; /* enc1a */
};
};
/****************************************
Encoders
****************************************/
fragment#9 {
target = <&eqep0>;
__overlay__ {
count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
invert_qa = <1>; /* Should we invert the channel A input? */
invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
invert_qi = <0>; /* Should we invert the index input? */
invert_qs = <0>; /* Should we invert the strobe input? */
status = "okay";
};
};
fragment#10 {
target = <&eqep1>;
__overlay__ {
count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
invert_qa = <1>; /* Should we invert the channel A input? */
invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
invert_qi = <0>; /* Should we invert the index input? */
invert_qs = <0>; /* Should we invert the strobe input? */
status = "okay";
};
};
fragment#11 {
target = <&eqep2>;
__overlay__ {
count_mode = <0>; /* 0 - Quadrature mode, normal 90 phase offset cha & chb. 1 - Direction mode. cha input = clock, chb input = direction */
swap_inputs = <0>; /* Are channel A and channel B swapped? (0 - no, 1 - yes) */
invert_qa = <1>; /* Should we invert the channel A input? */
invert_qb = <1>; /* Should we invert the channel B input? I invert these because my encoder outputs drive transistors that pull down the pins */
invert_qi = <0>; /* Should we invert the index input? */
invert_qs = <0>; /* Should we invert the strobe input? */
status = "okay";
};
};
/****************************************
PRU
****************************************/
fragment#31 {
target = <&pruss>;
__overlay__ {
status = "okay";
};
};
};
I added my custom overlay to /boot/uEnv.txt and disabled the video and audio overlays
uname_r=4.19.94-ti-r42
#uuid=
#dtb=
###U-Boot Overlays###
###Documentation: http://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays
###Master Enable
enable_uboot_overlays=1
###
###Additional custom capes
uboot_overlay_addr4=/lib/firmware/CustomCape-00A0.dtbo
###
###Custom Cape
#dtb_overlay=/lib/firmware/<file8>.dtbo
###
###Disable auto loading of virtual capes (emmc/video/wireless/adc)
#disable_uboot_overlay_emmc=1
disable_uboot_overlay_video=1
disable_uboot_overlay_audio=1
#disable_uboot_overlay_wireless=1
#disable_uboot_overlay_adc=1
###
###PRUSS OPTIONS
###pru_rproc (4.19.x-ti kernel)
uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-19-TI-00A0.dtbo
###
###Cape Universal Enable
enable_uboot_cape_universal=1
###
###U-Boot Overlays###
cmdline=coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet
I make no claims of optimality or even correctness, but this configuration boots with or without the Motor Cape
installed and I can read all four encoders with rc_test_encoders. When the Motor Cape is installed, uBoot
is correctly picking up and applying the BBORG_MOTOR-00A2 overlay. I honestly thought that I would need a lot more
configuration of the PRU to get the PRU-based encoder counter from the Robot Control Library working, but this seeems
to do the trick.
I would welcome any feedback on how I should have done this, or how I could improve upon what I currently have.
Helpful Tip: Watch the serial terminal!
I am embarrassed that I even attempted to debug device tree booting issues without first having a serial terminal
open to the beaglebone so that I could observe the boot sequence. With the help of some 5-minute epoxy, I was
eventually able to make a 90-degree header to bring the JTAG port out from under an installed cape.
https://elinux.org/Beagleboard:BeagleBone_Black_Serial
I am currently working with pktgen in order to achieve high-rate packet generation for a project. I am using version 2.9.5 of pktgen, along with DPDK version 2.1.0. It does work perfectly fine ( I am able to generate and send packet at 10 Gb/s rate ) until I try to use lua scripts for formatting packets.
As a matter of fact, scripts examples that you can find with the sources seem to not always have the expected behaviour. Simplest scripts work perfectly fine ( HelloWorld.lua for example, I am also able to set packet size, rate or burst with script commands )
package.path = package.path ..";?.lua;test/?.lua;app/?.lua;"
2
3 pktgen.set("all", "count", 0);
4 pktgen.set("all", "rate", 50);
5 pktgen.set("all", "size", 256);
6 pktgen.set("all", "burst", 128);
7 pktgen.start(0)
( the code above does work )
However, I have encountered issues as I tried to define directly a packet format with a table, like in this example :
-- Lua uses '--' as comment to end of line read the
2 -- manual for more comment options.
3 local seq_table = { -- entries can be in any order
4 ["eth_dst_addr"] = "0011:4455:6677",
5 ["eth_src_addr"] = "0011:1234:5678",
6 ["ip_dst_addr"] = "10.12.0.1",
7 ["ip_src_addr"] = "10.12.0.1/16", -- the 16 is the size of the mask va lue
8 ["sport"] = 9, -- Standard port numbers
9 ["dport"] = 10, -- Standard port numbers
10 ["ethType"] = "ipv4", -- ipv4|ipv6|vlan
11 ["ipProto"] = "udp", -- udp|tcp|icmp
12 ["vlanid"] = 1, -- 1 - 4095
13 ["pktSize"] = 128 -- 64 - 1518
14 };
15 -- seqTable( seq#, portlist, table );
16 pktgen.seqTable(0, "all", seq_table );
17 pktgen.set("all", "seqCnt", 1);
When I try this script, Pktgen will usually give me a
Unknown Ethertype 0x0000
Error as soon as I try start 0 in commandline ( 0 is the port I use to transmit packet ).
Same problem occurs when I try the main.lua script.
Long story short, I have troubles understanding how the pktgen.seqtable function works, and why it does not work properly in my case. I did not find any really helpful documentation on the net on this subject.
the command I use to launch scripts is :
sudo -E $PKTGEN_CMD/pktgen -c 0x7 -n 4 -- -m "1.0,2.1" -f test/set_seq.lua
( test/set_seq.lua being a script example ).
I have got the same script running with small modification to enable vlan in packet generation. Please refer the changes below
local seq_table = { -- entries can be in any order
["eth_dst_addr"] = "0011:4455:6677",
["eth_src_addr"] = "0011:1234:5678",
["ip_dst_addr"] = "10.12.0.1",
["ip_src_addr"] = "10.12.0.1/16", -- the 16 is the size of the mask va lue
["sport"] = 9, -- Standard port numbers
["dport"] = 10, -- Standard port numbers
["ethType"] = "ipv4", -- ipv4|ipv6|vlan
["ipProto"] = "udp", -- udp|tcp|icmp
["vlanid"] = 1100, -- 1 - 4095
["pktSize"] = 128 -- 64 - 1518
};
-- seqTable( seq#, portlist, table );
pktgen.seqTable(0, "all", seq_table );
pktgen.vlan("all", "enable");
pktgen.set("all", "seqCnt", 1);
Executing the modified script does not produce Pktgen will usually give me a Unknown Ethertype 0x0000 Error as soon as I try start 0 in commandline ( 0 is the port I use to transmit packet ).
note: there is mention of a fix to range and vlan id in pktgen doc page 75 3.0.01- Fixed the Range sequence and VLAN problem. hence I recommend to use latest pktgen (I have tested this on PKTGEN 21.11.0)
the following post is quite long, but since I have had trouble making the SP605 board properly interact with the DDR3 for over a month now, hopefully this will be useful to others in the same situation as I find myself in. I am pretty certain it's a simple configuration or conceptual error, but I would be more than happy to have this resolved soon.
=== SCENARIO ===
I have created a USB-UART interface to communicate with the FPGA and control the DDR3. Using the IP generator in ISE, I generated a MIG wrapper and then I designed the memory interface controller. However, I have referenced manuals ug388 and ug416, but I have not been able to have the DDR3 behave as expected.
=== PROBLEM STATEMENT ===
Playing around with the burst lengths for write and read commands, I am able to get data back from the DDR3, yet the addressing scheme does not seem to be correct as data is duplicated in addresses 0 and 1, 2 and 3, 4 and 5, and so forth. Also, whenever I write into address 0, for example, nothing changes. Then, when I write into address 1, both addresses 0 and 1 are updated with the data value I just sent. It seems I am "losing" half of the memory space due to this coupled effect.
=== DDR3 IP CONFIGURATION ===
The setup for the DDR3 using the IP generator – considering the SP605 board scenario – is listed below. In sum, I activated the DDR3 Bank 3 and configured Port0 to be 32-bit bidirectional.
Memory selection:
Enable AXI interface: unchecked
Use extended MCB performance range: unchecked
Memory type for bank 3: DDR3 SDRAM
Memory type for bank 1: none
Options for C3 – DDR3 SDRAM
Frequency: 400 MHz
Memory part: MTJ41J64M16XX-187E
Memory options for C3 – DDR3 SDRAM
Output driver impedance control: RZQ/6
RTT (nominal) – ODT: RZQ/4
Auto self refresh: enabled
Port configuration for C3 – DDR3 SDRAM
Two 32-bit bi-directional and four 32-bit unidirectional ports
Port0: checked
Port1: unchecked
Port2: unchecked
Port3: unchecked
Port4: unchecked
Port5: unchecked
Memory address mapping selection: row-bank-column
FPGA options for C3 – DDR3 SDRAM
Memory interface pin termination: Calibrated input termination
Select RZQ pin location: R7
Select ZIO pin location: W4
Debug signals for memory controller: disable
System clock: differential
=== DATA STRUCTURE ===
From Matlab, I send in a 64-bit command which should write or read the DDR3 based on the address and data provided in this command.
wire [00:00] cmd_instruction = usb_data[63:63]; // ‘0’ = write; ‘1’ = read
wire [27:00] cmd_address = usb_data[62:37]; // 26-bit address
wire [31:00] cmd_data = usb_data[31:00]; // 32-bit data
In ug388, the following can be extracted:
Page 20: The address is 26 bits wide.
C_MEM_ADDR_WIDTH = 13
C_MEM_BANKADDR_WIDTH = 3
C_MEM_NUM_COL_BITS = 10
C_P0_DATA_PORT_SIZE = 32 // 32-bit data ports
C_P0_MASK_SIZE = 4 // 4 bytes = 32 bits (1 mask bit = 1 entire data byte)
Pages 26-27: Command data structure.
pX_cmd_addr[29:0]: 30-bit address, however the last two bits should = “00” since every word (32 bits) is formed by 4 bytes.
pX_cmd_bl[5:0]: Burst length of 1 is obtained by setting this signal to 0.
pX_cmd_instr[2:0]: The only command instructions used are write=”000” and read=”001”.
Page 28: Write data structure.
pX_wr_mask[PX_MASKSIZE-1:0]: 4-bit mask is set to “0000” so that all 4 bytes are always written into the memory.
=== SIGNAL ASSIGNMENTS ===
Using all this information, I assigned my signals in the following manner:
assign p0_mcb_cmd_instr = {2'b00, cmd_instruction};
assign p0_mcb_cmd_addr = {2’d0, cmd_address, 2'd0};
assign p0_mcb_cmd_bl = 6'd0;
assign p0_mcb_wr_data = cmd_data;
assign p0_mcb_wr_mask = 4'd0;
localparam C3_MEM_BURST_LEN = 8;
=== CONCLUSIONS ===
Based on the configuration, does anyone know what the expected behavior of my controller should be?
If any additional information is necessary for clarification, please let me know.
Thanks a lot,
Bruno.
I am working with a Beaglebone Black and I would like to use the mmc2 slot.
according to AM335xx TRM, a beaglebone black should have 3 mmc available:
mmc0 (sd card);
mmc1 (2G flash),
mmc2.
I am trying to enable mmc2 by device tree (and I am quite sure to have the right pin settings) but, by doing
dmesg
I obtain:
/ocp/mmc#47810000: can't find DMA channel
omap_hsmmc mmc.11: unable to obtain RX DMA engine channel 65
By putting the oscilloscope probe on the header (e.g. the mmc2 clk signal), I do not see any transition.
I already removed R 160 to have mmc2 cmd accessible but I do not see any transition also there.
I tried both to enable it by
echo > /sys/devices/..../slots
and by
capemgr.enable_partno
with no success:
I can see it in
/sys/devices/..../slots
(with the L meaning loaded)..but no way to see any signal on the header.
I already googled it but answers are not clear at all.
Any ideas?
My
uname -a
is:
Linux beaglebone 3.8.13 #1 SMP Tue Jun 18 02:11:09 EDT 2013 armv7l GNU/Linux
Thanks for your help.
You need to configure the mmc2 DMA events to some DMA channel since these events are not direct mapped.
I was not able to do this successfully using device tree overlays. So I made a change in the
am335-x-bone-common.dtsi directly (not sure this is the best way though):
&edma {
ti,edma-xbar-event-map = <32 12>, /* gpevt2 -> 12 */
<30 20>, /* xdma_event_intr2 -> 20 */
+ <1 32>,
+ <2 33>;
};
In the example above the event 1 (SDTXEVT2) was mapped to channel 32 and event 2 (SDRXEVT2) to channel 33.
In case you want to pick another open DMA channel check tables 11-23. Direct Mapped and Table 11-24. Crossbar Mapped from the technical reference manual Rev J.
In your device tree overlay file add these channels in the mmc3 node:
dmas = <&edma 32
&edma 33>;
dma-names = "tx", "rx";