OpenNuvoton / MA35D1_Linux_Applications

MA35D1 Linux applications
0 stars 6 forks source link

get problem while implementing EBI's SRAM. #1

Closed shownb closed 1 year ago

shownb commented 1 year ago

Has anyone tested the code in ebi.c? The line

ioctl(fd, EBI_IOC_SPEED, &ebi);

seems to be ineffective, which makes me doubt if the driver is usable. because https://github.com/OpenNuvoton/MA35D1_linux-5.10.y/blob/896b79e89a81adfc28bae91759f53cca18b8edd8/drivers/misc/ma35d1-ebi.c#L101

I'm facing an issue where when I run

*(char *)(pEbiBuffer+i)=(char)85;

if i is an Even number, writing (char)85 and then reading it back gives me (char)84.

sch

here is my code

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <asm/ioctl.h>
#include <sys/mman.h>
#include "nua3500-ebi.h"

#define __CH        (0)//0~2

int main(int argc, char **argv)
{
    int fd,i,j;
    unsigned char *pEbiBuffer;
    unsigned long uEbiSize;
    unsigned int patterns[4]= {0x00000000,0x55555555,0xAAAAAAAA,0xFFFFFFFF};
    unsigned char *patternsSwaps[4] = {NULL, NULL, NULL, NULL};
    struct nua3500_set_ebi ebi;
    char dev[3][14] = {"/dev/ebi0",
            "/dev/ebi1",
            "/dev/ebi2"
            };

    if (sizeof(int) != 4) {
        printf("sizeof(int) != 4\n");
        exit(0);
    }

    i = __CH;
    fd = open(&dev[i][0], O_RDWR);
    if(fd < 0)
        printf("Open ebi%d error !!!\n", i);

    ebi.bank = i;
    ebi.base = 0x68000000 + (i * 0x100000);
    printf("EBI Bank %d Addr: 0x%08x\n", ebi.bank, ebi.base);

    ebi.busmode = EBI_OPMODE_ADSEPARATE;
    ebi.CSActiveLevel = EBI_CS_ACTIVE_LOW;
    ebi.width = EBI_BUSWIDTH_16BIT;

    //ioctl(fd, EBI_IOC_SET, &ebi);
    if (ioctl(fd, EBI_IOC_SET, &ebi) == -1) {
        printf("set errno %d\n", errno);
        close(fd);
        exit(EXIT_FAILURE);
    }

    //ioctl(fd, EBI_IOC_SPEED, &ebi);

    if (ioctl(fd, EBI_IOC_SPEED, &ebi) == -1) {
    printf("speed errno %d\n", errno);
        //close(fd);
        //exit(EXIT_FAILURE);
    }

    uEbiSize = 0x100000;
    printf("EbiSize: 0x%08x\n", uEbiSize);
    if (uEbiSize % 4) {
        printf("uEbiSize is not 4 bytes aligned\n");
        exit(0);
    }
    pEbiBuffer = mmap(NULL, uEbiSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (pEbiBuffer == MAP_FAILED) {
        printf("mmap() failed\n");
        exit(0);
    }

    printf("Start to Word Read/Write test\n");
    char tmp;
    for(i = 0; i < 20; i++) {
        *(char *)(pEbiBuffer+i)=(char)85;
        tmp=*(char *)(pEbiBuffer+i);
        printf("patterns=0x%08x, data[%d]=0x%08x\n",(char)85,i,*(char*)(pEbiBuffer+i));
    }

    close(fd);
    munmap(pEbiBuffer, uEbiSize);

    return 0;
}

result:

[root@ma35d1]~# ./ebi_demo
EBI Bank 0 Addr: 0x68000000
speed errno 25
EbiSize: 0x00100000
Start to Word Read/Write test
patterns=0x00000055, data[0]=0x00000054
patterns=0x00000055, data[1]=0x00000055
patterns=0x00000055, data[2]=0x00000054
patterns=0x00000055, data[3]=0x00000055
patterns=0x00000055, data[4]=0x00000054
patterns=0x00000055, data[5]=0x00000055
patterns=0x00000055, data[6]=0x00000054
patterns=0x00000055, data[7]=0x00000055
patterns=0x00000055, data[8]=0x00000054
patterns=0x00000055, data[9]=0x00000055
patterns=0x00000055, data[10]=0x00000054
patterns=0x00000055, data[11]=0x00000055
patterns=0x00000055, data[12]=0x00000054
patterns=0x00000055, data[13]=0x00000055
patterns=0x00000055, data[14]=0x00000054
patterns=0x00000055, data[15]=0x00000055
patterns=0x00000055, data[16]=0x00000054
patterns=0x00000055, data[17]=0x00000055
patterns=0x00000055, data[18]=0x00000054
patterns=0x00000055, data[19]=0x00000055

any idea is very welcome.

ychuang3 commented 1 year ago

The EBI data width is 16-bits. Please use (unsigned short ) instead of (char )

shownb commented 1 year ago

The EBI data width is 16-bits. Please use (unsigned short ) instead of (char )

Thank you very much for your response. In fact, I tried the code provided in the example as my first attempt.

[root@ma35d1]~# ./ebi_demo
EBI Bank 0 Addr: 0x68000000
EbiSize: 0x00100000
Start to Word Read/Write test
Read/Write test failed, patterns=0x55555555, data[0]=0x55545554

I have also tried many other possibilities, but things didn't go as expected. I'm really at a loss, so I thought I'd ask if you have any inspiration.

ychuang3 commented 1 year ago

The sample program seems not correct. It used 32-biits read/write. Please try use (short ) instead of (int ). And use 16-bits test pattern 0x5555.

shownb commented 1 year ago

The sample program seems not correct. It used 32-biits read/write. Please try use (short ) instead of (int ). And use 16-bits test pattern 0x5555.

it does not work. any more idea?

unsigned short patterns[4]= {0x5555,0x0000,0xFFFF,0xAAAA};
/*
skip not import code
*/
    printf("Start to Word Read/Write with short 0.001\n");
    for(i=0; i<uEbiSize; i+=4) {
        unsigned short tmp;
        for(j=0; j<4; j++) {
            *(unsigned short *)(pEbiBuffer+i)=patterns[j];
            tmp=*(unsigned short *)(pEbiBuffer+i);
            printf("Read/Write test failed, patterns=0x%04x, data[%d]=0x%04x\n",patterns[j],i,*(unsigned short*)(pEbiBuffer+i));
            if(tmp!=patterns[j]) {
                printf("Read/Write test failed, patterns=0x%04x, data[%d]=0x%04x\n",patterns[j],i,*(unsigned short*)(pEbiBuffer+i));
                return 0;
            }
        }
    }

[root@ma35d1]~# ./ebi_demo EBI Bank 0 Addr: 0x68000000 EbiSize: 0x00100000 Start to Word Read/Write with short 0.001 Read/Write test failed, patterns=0x5555, data[0]=0x5554 Read/Write test failed, patterns=0x5555, data[0]=0x5554

I would like to ask, 1 What was the hardware environment in your test code? What model of SRAM was being used? 2 which busmode was being used?

ychuang3 commented 1 year ago

How about other test patterns? 0x0000, 0xFFFF, 0xAAAA ... Can you get the waveform by a scope? Or, you can try to adjust the EBI timing by modify device tree .dts file.

shownb commented 1 year ago

How about other test patterns? 0x0000, 0xFFFF, 0xAAAA ... Can you get the waveform by a scope? Or, you can try to adjust the EBI timing by modify device tree .dts file.

unsigned short patterns[4]= {0x5555,0x7777,0xbbbb,0xffff};
//skip not import code
    printf("Start to Word Read/Write with short 0.002\n");
    for(i=0; i<5; i+=2) {
        short tmp;
        for(j=0; j<4; j++) {
            *(unsigned short *)(pEbiBuffer+i)=patterns[j];
            tmp=*(unsigned short *)(pEbiBuffer+i);
            printf("Read/Write, write=0x%04x, read=0x%04x\n",patterns[j],*(unsigned short*)(pEbiBuffer+i));
        }
    }

output

[root@ma35d1]~# ./ebi_demo
EBI Bank 0 Addr: 0x68000000
EbiSize: 0x00100000
Start to Word Read/Write with short 0.002
Read/Write, write=0x5555, read=0x5554
Read/Write, write=0x7777, read=0x7776
Read/Write, write=0xbbbb, read=0xbbba
Read/Write, write=0xffff, read=0xfffe
Read/Write, write=0x5555, read=0x5554
Read/Write, write=0x7777, read=0x7776
Read/Write, write=0xbbbb, read=0xbbba
Read/Write, write=0xffff, read=0xfffe
Read/Write, write=0x5555, read=0x5554
Read/Write, write=0x7777, read=0x7776
Read/Write, write=0xbbbb, read=0xbbba
Read/Write, write=0xffff, read=0xfffe
Compare data passed

and i found that if Even number at Even address,it will got problem.

i will try to ad the ebi timing,and how to do that?

        MCLKDIV = <2>;//0 ~ 7,EBI_CTL0[10:8]
        tALE = <1>;//0 ~ 7,EBI_CTL0[18:16]
        tACC = <1>;//0 ~ 31, EBI_TCTLx[7:3]
        tAHD = <1>;//0 ~ 7, EBI_TCTLx[10:9]
        IDLE  = <3>;//0 ~ 15, EBI_TCTLx[27:24] and EBI_TCTLx[15:12]
ychuang3 commented 1 year ago

The data bit 0 is consistently 0 in all test cases. Please check if there is any cold welding issue with the pin.

MCLKDIV represents the EBI clock divider. A value of 2 indicates that it is divided by 4 from the HCLK. MCLKDIV values 0, 1, 2, 3, 4... correspond to division factors of 1, 2, 4, 8, ...

For other timings, a higher value indicates a longer delay.

shownb commented 1 year ago

Finally found the reason, because of pin. thank you very much for your help.

shownb commented 1 year ago

By the way, I have a question. I'm using IS62WV51216BLL SRAM, which has a high-speed access time: 45ns , 55ns. In other words, the theoretical speed can reach 36M/s. However, when I tested it with the following code, I found that it couldn't reach the theoretical value. What could be the reason for this?

    // begin
    struct timespec time_start = { 0, 0 }, time_end = { 0, 0 };
    clock_gettime(CLOCK_REALTIME, &time_start);
    *(unsigned short *)pEbiBuffer = pattern;
    clock_gettime(CLOCK_REALTIME, &time_end);
    printf("Elapsed Time::%lds %ldns\n", time_end.tv_sec-time_start.tv_sec,
           time_end.tv_nsec-time_start.tv_nsec);

Elapsed Time: 0s 4334ns

ychuang3 commented 1 year ago

The current setting of EBI MCLK is HCLK divided by 4, which means it is running at 150MHz / 4. You can try modifying the device tree's MCLKDIV setting to either <0> or <1>. These values correspond to dividing by 1 and 2, respectively. The MCLK value determines the speed of the EBI. In addition, for performance testing, it is recommended to perform mass data access and calculate the average performance.

shownb commented 1 year ago

the default MCLK is: MCLKDIV = <2>; I changed the vaule like that: MCLKDIV = <0>; But looks like not too much Improve.

Can you tell me how fast you can reach? Do I still have an optimized place? For example, SRAM choices

ychuang3 commented 1 year ago

Did you modify your performance measurement code? It seems to have some issues. Invoking clock_gettime() itself cosume much more time than the EBI read command. It's recommend to have a loop, for example

clock_gettime(CLOCK_REALTIME, &time_start); for (i = 0; i < 100000; i++) (unsigned short )pEbiBuffer = pattern; clock_gettime(CLOCK_REALTIME, &time_end); printf("Elapsed Time::%lds %ldns\n", time_end.tv_sec-time_start.tv_sec, time_end.tv_nsec-time_start.tv_nsec);

And get the average time. Or, use a scope to meaure it.

ychuang3 commented 1 year ago

Additionally, may I ask for what purpose are you using EBI to interface with SRAM? What application does your product serve? Furthermore, may I inquire through which channel did you obtain the MA35D1 development board? Are you using an SOM or an IoT board?

shownb commented 1 year ago

MCLKDIV = <0>

MCLKDIV = <0> There will be random inconsistencies between what is written and what is read. MCLKDIV = <1> is ok.

My purpose of using ma35 is to develop a smart agriculture project. I got my SOM from taobao.

Thanks for your help, I'm going to close this issue.