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.

[参考译文] Linux/PROCESSOR-SDK-AM437X:A/D 多路复用8位 GPMC

Guru**** 2609955 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/582832/linux-processor-sdk-am437x-a-d-multiplexed-8-bit-gpmc

器件型号:PROCESSOR-SDK-AM437X

工具/软件:Linux

您好论坛、

我一直在尝试将8位地址数据多路复用 GPMC 总线实现到我的 FPGA。 运行时会遇到一些问题。 我希望你们能有所帮助。

GPMC_DEFAULT:GPMC_DEFAULT{
pinctrl-single、Pins =<

0x3c (PIN_INPUT_PULLUP | MUX_MODE0)/*(A11) GPMC_AD15.GPMC_AD15 */
0x38 (PIN_INPUT_PULLUP | MUX_MODE0)/*(B11) GPMC_ADEC_AD14
)/GPMC_ADM13 (GPMC_ADM13)/GPMC_INPUBL_13)/GPMC_AD13 (0xMC_ADMEC_13)/GPMC_ADMEC_13 (GPMC_AD13)/GPMC_IN_MODE14)/GPMC_PUBL_AD13 (GPMC_AD13)/GPMC_MODE14)/GPMC_AD13 (
0x
(PIN_INPUT_PULLUP | MUX_MODE0)/*(D11) GPMC_AD11.GPMC_AD11 */
0x28 (PIN_INPULLUP | MUX_MODE0)/*(F11) GPMC_AD10.GPMC_AD10 *
/ 0x24 (PIN_INPULLUM_PULLUP | MUX_AD0*)/GPMC_ADM8*

(GPMC_AD0*)/GPMC_ADM8*(0xMC_ADMC_ADMC_AD0*(GPMC_AD0*)/GPMC_ADMC_ADMC_ADMC_AD0*(GPMC_AD0_AD0*
(PIN_INPUT_PULLUP | MUX_MODE0)/*(C8) GPMC_AD6.GPMC_AD6 */
0x14 (PIN_INPULLUP | MUX_MODE0)/*(A7) GPMC_AD5.GPMC_AD5 *
/ 0x10 (PIN_INPULLUM_PULLUP | MUX_MODE0)/GPMC_AD4*

(GPMC_ADMC_ADM0*)/GPMC_ADMC_AD4*(0xMC_ADMC_AD4*(0xMC_ADMC_ADMC_AD4*)/GPMC_ADMC_AD4*(0xMC_ADMC_ADMC_AD4*
(PIN_INPUT_PULLUP | MUX_MODE0)/*(A5) GPMC_AD1.GPMC_AD1 */
0x0 (PIN_INPUT_PULLUP | MUX_MODE0)/*(B5) GPMC_AD0.GPMC_AD0 *
/ 0x70 (PIN_INPULL_MODE0
)/GPMC_AM848*(GPMC_MODE0
)/GPMC_GPMC_AD0)/GPMC_AMC.0*(GPMC_GPMC_AD0
(PIN_OUTPUT | MUX_MODE0)/*(B12) GPMC_csn3.GPMC_csn3 */
0x74 (PIN_OUTPUT | MUX_MODE2)/*(B3) GPMC_WPN.GPMC_csn5 *
/ 0x78 (PIN_OUTPUT | MUX_MODE2)/*(GPMC_EP_IN_IN_IN_IN_IN_EP0*
)/GPMC_IN_IN_IN_IN_IN_IN_IN_IN_IN_IN_EN.90*
(0xMC_IN_IN_IN_IN_IN_IN_EN_MODEN
(PIN_OUTPUT | MUX_MODE0)/*(D10) GPMC_Wen.GPMC_Wen */
0x9C (PIN_OUTPUT | MUX_MODE0)/*(C10) GPMC_be0n_cle。GPMC_be0n_cle */



>;
}

;&GPMC{
status ="确定";启用 GPMC_NAND_DEFAULT_ENTRL 时*="GPMC_ENTRLESD/禁用 GPMC_ENTRLICENTRLESD/ ENTRL
= GPMC_ENTRLESD/ ENTRL = 0;

范围=<3 0 0x02000000 0x00020000>


SRAM@3、0{
reg =<3 0 0x00100000 >;
组宽度=<1>;
GPMC、异步读取;
GPMC、异步写入;
GPMC、clk-activation-ns =<20>;
GPMC、突发长度=<16>;
GPMC、mux-add-data =<2>;
GPMC、SYNC-clk-ps =<10000>;
GPMC、cs-on-ns =<0>;
GPMC、cs-rd-Off-ns =<141>;
GPMC、cs-wr-off-ns =<141>;
GPMC、Adv-on-ns =<0>;
GPMC、Ad-rd -关闭-ns =<75>;
GPMC、AdV-wr-off-ns =<75>;
GPMC、WE-ON-ns =<85>;
GPMC、WE-OFF-ns =<123>;
GPMC、OE-ON-ns =<85>;
GPMC、OE-OFF-ns =<141>;
GPMC、PAGE-BURST-ACCESS ns =<10>;
GPMC、ACCESS ns =<50>;
GPMC、第周期-ns =<150>;
GPMC、功率周期-ns =<150>;
GPMC、wr 访问-ns =<0>;
GPMC、wr-data-mux-bus-ns =<85>;
GPMC、总线翻转-ns =<10>;
GPMC、cycle2cycle-samecsen;
GPMC、cycle2cycle-delay-ns =<10>;


}; 

以上是我的器件树时序。

#include 
#include 
#include 
#include 
#include 



#define GPMC_BASE 0x02000000
static int devmemfd =-1;

//映射长度为 len 且偏移量为"offset"
的存储器 static void* util_mapmemmemmemmemoryblock (off_t offset、size_t len)
{
devmemfd = open ("/dev/mem、O_RDWR | O_sync);
void *寄存器= mmap_write、PROt_read、PROmemt len、PROmemt read、PROmemd 偏移量);
if (寄存器=map_failed){
printf ("Map failed\n");
}
return 寄存器;
}

static void util_unmapmapyblock (void* block、size_t len)
{
munmap (void *) block、









void);if (devmemfd!=-1){ close (develt* block、size_membr>#gmund_unint32)

registers (static return inueln)= static 32 (static eMC_static retr2000n) n_static static ret_static r.e+ static r2000n = n.int_static static r.int_static r.e


静态空 GPMC_unmapregister()
{
util_unmapmemoryblock ((void*)寄存器,REGLEN);
}

void GPMC_setup (void)
{
GPMC_mapregister();
GPMC_unmapregister();
}

volatile uint8_t* extbus;

{GPMC_setup(void ){ uint8_datace+uint8_return)<int8_(uint8_datace)<int8_return)<uint8_(uint8_intbytes+(uint8_int8_datace)<int8_(uint8_return)<int_(u_int8_intbyte)











;}<int8_int8_int8_(uintbyte);void (uint8_int_dateum_int8_return)<int8_int8_int



void bus_shutdown (){
util_unmapmemoryblock ((void*) extbus、0x200);
}
int main (int argc、char const * argv[]){
int i、a、f;
int array[10];
bus_init ();
//for (i = 0;i < 10;i++){in
x


(byte = 0)、intx[如果 intx]、则为%/nbytesx (x]、intx](bytes= 1)、intx[)、intx](in = 1)、intbytesx (x](in)、intx[如果为1)、intx]、intbyte_intx]、intx]、intx](x[)
f = strtol (argv[3]、NULL、 0);
bus_writebyte (a、f);
}
if (strcmp ("read"、argv[1])=0){
a = strtol (argv[2]、NULL、0);
printf ("读取值:%x \n"、bus_readbyte (a));
}
if (strcmp ("argcmp"("i

= 0"、"i)= 1)


;(i)= 1);(i = 0)+(对于 inebyte (1)、I);(对于 inect = 1);(i = 1);(对于 inc = 1)= 1);(对于 inc = 1)、i = 1);(对于 e+(对于 e+);(对于 inc = 1)
i++){
array[i]=bus_readbyte (i);
printf ("地址%x 处的字节:%X\n"、i、array[i]);
}

bus_shutdown
();
return 0;
}

我现在面临的问题

  • 我的写入操作正常、当我执行./main 0x00 0x03等操作时、我可以看到地址和数据工作正常。
  • 但是、当我对寄存器执行读取操作时、读取操作始终返回 ASIC 的物理地址、而不是返回数据。
主写入0x02 0x04
./主写入0x03 0x05

./主读取0x02
读取值:0x02
./主读取0x03
读取值:0x03

我希望读操作返回本例中写入的实际值(0x04和0x05)我可以通过逻辑分析仪看到数据到达 CPU、但遗憾的是、我的返回结果与我在逻辑分析仪上看到的值不符。

请提出任何建议。

此致

-Parker

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    GPMC 地址映射支持地址/数据多路复用16位宽器件:

    •NOR 闪存控制器仍然支持非复用地址和数据存储器器件。
    •可通过 GPMC_CONFIG1_I[9-8] MUXADDATA 位字段选择多路复用模式。
    •多路复用地址和数据器件不支持异步页面模式。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Biser、

    表达您的意见:
    因此,根据您的说法,我将无法使用8位地址数据多路复用总线来执行异步读取或写入???

    如何从用户空间访问 GPMC 寄存器?

    我的上述理解是否正确?

    此致
    -Parker
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请参阅 AM437x TRM Rev. F 中的表9-4。GPMC_AD[15:0]引脚在 A/D 复用模式下输出 A[16:1]和 D[15:0]。 您只能对16位地址进行读/写操作。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    让我重新表述我的问题、

    我有16个地址数据引脚和我在上面的 DTS 文件中指定的控制引脚。

    我将2位 GPMC 存储器映射区域设置为2个 FPGA、将2个16位存储器映射区域设置为其他两个 FPGA。 如何在总线上执行单次读取和单次写入? 是否必须将 GPMC 设备配置为 NAND 或 NOR? 在 ASIC 内写入寄存器和从寄存器读回的过程是什么?

    我之前的 POST 多路复用"可通过 GPMC_CONFIG1_i[9-8] MUXADDATA 位字段选择多路复用模式"我的理解是我的 DTS 中的"GPMC、mux-add-data =<2>"定义也是如此。 如果我错了、请回答正确。

    此致
    -Parker
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    对于 A/D 多路复用模式、您的外设的行为应该为 NOR。 我想说的是、在这种模式下、GPMC 总线上不输出地址位0、这意味着写入地址 XXXX0b 和写入地址 XXXX1b 将寻址相同的外部存储器位置。 读取也是如此。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Biser、
    如果您看到我的 c 代码段、您会发现我将地址和数据移动了一个位、因此我根本不使用位0。 我还不明白为什么读数不起作用。 我再次仔细检查了计时、并尝试了我的所有测试。 读取仍然没有正结果。

    此致
    -Parker
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您读取/写入哪些地址? GPMC 是存储器映射的、因此您应该使用绝对地址。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Biser、

    我的基地址是0x02000000
    存储器映射区域的大小为0x00020000
    因此、从命令行中、如果我执行 devmem2 0x02000000 b 0x01 (我希望它写入到 FPGA 上的地址0值1)
    如果我读取来自命令行 devmem2 0x02000000 b (我希望回读我在前一条命令中写入的1)。

    回读总是返回物理地址、而不是物理地址中存储的值。

    您在上一条命令中的绝对地址是什么意思?

    此致
    -Parker
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    [引用]如果我读取 From 命令行 devmem2 0x02000000 b (我希望回读我在前一条命令中写入的1)。

    回读始终会返回物理地址、但不会返回物理地址中存储的值。

    这是一种非常奇怪的行为。 使用 devmem2进行读取时、您能否复制粘贴控制台输出?
    您还可以执行 cat /proc/iomem 并共享输出吗?

    此致、
    Yordan
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    另请参阅此主题、了解有关如何将 GPMC 与 SRAM 器件连接的更多信息:
    e2e.ti.com/.../512464

    此致、
    Yordan
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Yordan、您好!

    下面是我为您提出的问题的日志。

    root@
    
    
    
    
    
    @
    
    @
    @
    
    
    @@@
    @
    @AM437X-EVM:/bin/cat /proc/iomem /ocp/tscadc /ocp/rtc 40300000-4033ffff:40300000。ocmcram 44000000-443fff:/OCP 44800000-44bfff:/OCP 44d00000-44d34d03480fff:/OCP 44d4000-44d4000-44bfff:/ocp/gpio /ocp/l4_wkup /ocp/i2c e244000-44d4000-44d4000-ef:/ocp/wdt
    @/ocp/i2c
    /ocp/spi@48030000
    4804c000-4804cfff:/ocp/gpio@4804c000
    48060000-48060fff:/ocp/mmc@48060000
    48080000-48081fff:/ocp/elm
    
    
    
    /ocp/gpio
    
    
    /ocp/can
    
    
    /ocp/gpio@4800000 480c8000-480c81ff:/ocp/mailbox /ocp/gpio /ocp/epwmss
    /ocp/gpio@4808000 4808000 481a0100-481ffff:/ocp/spi@@@@@@@@@
    @4814848000148484000-4838000f:/ocp/can /ocp/rng /ocp/spi
    /ocp/omap_dwc3@48380000
    483c0000-483cffff:/ocp/omap_dwc3@483d0000-483d7fff
    :/ocp/omap_dwc3@483d0000
    483d0000-483d7fff:/ocp/omap_dwc3
    
    
    /ocp/ethernet
    
    
    /ocp/emif
    
    
    /ocp/aes@483d0000/USB@@@@@@@@@@@@@
    @483d0000 483d1000000_483dFFFF:/ocp/omap_dwc3 /ocp/ethernet /ocp/gpmc /ocp/des 483d0000.1004000-48100000f
    :/ocp/edma 10041004000-53100000f:/ocp/ethernet /ocp/sham
    
    内核数据
    根目录@AM437X-EVM:/bin# 

    使用 devmem2进行读取

    root@AM437X-EVM:/bin# devmem2 0x02000000 b
    /dev/mem 已打开。
    映射到地址 bb6fa6000的内存。
    读取地址0x02000000 (bb6fa6000):0x00
    root@AM437X-EVM:/bin/# devmem2 0x02000001 b
    /dev/mem 已打开。
    映射到地址 bb6f10000的内存。
    在地址0x02000001 (bb6f10001)处读取:0x00
    root@AM437X-EVM:/bin# devmem2 0x02000002 b
    /dev/mem 已打开。
    映射到地址 bb6fa8000的内存。
    在地址0x02000002 (bb6fa8002)处读取:0x01
    root@AM437X-EVM:/bin# devmem2 0x02000003 b
    /dev/mem 已打开。
    映射到地址 bb6fa6000的内存。
    在地址0x02000003 (bb6fa6003)处读取:0x01
    root@AM437X-EVM:/bin# devmem2 0x02000004 b
    /dev/mem 已打开。
    映射到地址 bb6ff6000的内存。
    在地址0x02000004 (bb6ff6004)处读取:0x02
    root@AM437X-EVM:/bin# devmem2 0x02000005 b
    /dev/mem 已打开。
    映射到地址 bb6f03000的内存。
    读取地址0x02000005 (bb6f03005):0x02
    root@AM437X-EVM:/bin/devmem2 0x02000006 b
    /dev/mem 已打开。
    映射到地址 bb6f42000的内存。
    读取地址0x02000006 (bb6f42006):0x03
    root@AM437X-EVM:/bin/devmem2 0x02000007 b
    /dev/mem 已打开。
    映射到地址 bb6f76000的内存。
    读取地址0x02000007 (bb6f76007):0x03
    root@AM437X-EVM:/bin/devmem2 0x02000000 b 0x01
    /dev/mem 已打开。
    映射到地址 bbb6fb3000的内存。
    在地址0x02000000 (bbbb63000)处读取:0x00
    在地址0x02000000 (bbb6b3000)处写入:0x01、回读0x01
    root@AM437X-EVM:/bin# devmem2 0x02000001 b 0x01
    /dev/mem 已打开。
    映射到地址 bb6f7a000的内存。
    在地址0x02000001 (bbb6f7a001)上读取:0x00
    在地址0x02000001 (bb6f7a001)上写入:0x01、回读0x01
    root@AM437X-EVM:/bin# devmem2 0x02000002 b 0x01
    /dev/mem 已打开。
    映射到地址 bb6fe6000的内存。
    在地址0x02000002 (bbb6fe6002)上读取:0x01
    在地址0x02000002 (bbb6fe6002)上写入:0x01、回读0x01
    root@AM437X-EVM:/bin# devmem2 0x02000003 b 0x01
    /dev/mem 已打开。
    映射到地址 bb6f4c000的内存。
    在地址0x02000003 (bbb6f4c003)处读取:0x01
    在地址0x02000003 (bb6f4c003)处写入:0x01、回读0x01
    root@AM437X-EVM:/bin# devmem2 0x02000004 b 0x01
    /dev/mem 已打开。
    映射到地址 bb6f55000的内存。
    在地址0x02000004 (bb6f55004)处读取:0x02
    在地址0x02000004 (bb6f55004)处写入:0x01、回读0x01
    root@AM437X-EVM:/bin# devmem2 0x02000005 b 0x01
    /dev/mem 已打开。
    映射到地址 bb6f23000的内存。
    在地址0x02000005 (bb6f23005)上读取:0x02
    在地址0x02000005 (bb6f23005)上写入:0x01、回读0x01
    root@AM437X-EVM:/bin# devmem2 0x02000005 h 0x01
    /dev/mem 已打开。
    映射到地址 bb6ff5000的内存。
    读取地址0x02000005 (bb6ff5004):0x0202
    写入地址0x02000005 (bb6ff5004):0x0001、回读0x0001
    root@AM437X-EVM:/bin# devmem2 0x02000005 b 0x01
    /dev/mem 已打开。
    映射到地址 bb6f24000的内存。
    在地址0x02000005 (bbb6f24005)处读取:0x02
    在地址0x02000005 (bb6f24005)处写入:0x01、回读0x01
    root@AM437X-EVM:/bin# devmem2 0x02000005 b
    /dev/mem 已打开。
    映射到地址 bb6f05000的内存。
    读取地址0x02000005 (bb6f05005):0x02
    root@AM437X-EVM:/bin/devmem2 0x02000004 b
    /dev/mem 已打开。
    映射到地址 bb6fcf000的内存。
    读取地址0x02000004 (bb6fcf004):0x02
    root@AM437X-EVM:/bin/devmem2 0x02000002 b
    /dev/mem 已打开。
    映射到地址 bb6fdd000的内存。
    在地址0x02000002 (bb6fdd002)处读取:0x01
    root@AM437X-EVM:/bin# devmem2 0x02000001 b
    /dev/mem 已打开。
    映射到地址 bb6efd000的内存。
    在地址0x02000001 (bb6efd001)处读取:0x00
    root@AM437X-EVM:/bin# devmem2 0x02000000 b
    /dev/mem 已打开。
    映射到地址 bb6f9d000的内存。
    在地址0x02000000 (bb6f9d000)处读取:0x00
    root@AM437X-EVM:/bin# 

    此致

    -Parker

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Yordan、您好!

    我最终得到了读取的总线

    GPMC、ACCESS ns =<50>; 

    总线上太短、因此 GPMC 读取地址的时间仍然存在于 AD 线路上、通过将地址扩展到

    GPMC、ACCESS ns =<123>; 

    我使回读工作正常

    非常感谢您的帮助

    此致

    -Parker

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!  

    感谢您更新该主题。  

    此致、  
    Yordan