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.

CCS/PROCESSOR-SDK-AM437X: PROBLEM:Using fopen() with "rb" mode to read binary file

Part Number: PROCESSOR-SDK-AM437X
Other Parts Discussed in Thread: AM4378

Tool/software: Code Composer Studio

I'm developing a bare metal program based on  i2ctest in "processor_sdk_rtos_am437x_6_03_00_106".I want to read 256kbit binary file then write them to EEPROM by i2c. My file operation as follow:

test_file=fopen(filename,"rb");

char* txBuf32ByteFullSpace1;

txBuf32ByteFullSpace1=(char*)malloc(2+1024*32);//+2 for 2byte address

int fSize=0;

fSize=fread(txBuf32ByteFullSpace1+2,1,1024*32,test_file);

everytime fSize < the real file size,because of 0x1a

I can't solve this.it seems that "rb" is not be rightlydistinguished by progrom.

i even try test_file=fopen(filename,"rabbit"); CCS can pass the compile and debug it.

CCS version:9.3.0

c version :7.3.1(linaro)

  • My PC Operating System is Windows. the target is custom Am4378

  • The fopen and malloc calls both return NULL upon error.  Your code should check for that condition.

    Be sure you have not overflowed the stack or run out of heap memory.  

    Write a small program that opens and reads a simple ASCII text file.  Make sure that works.

    Please let me know what you see after taking these steps.

    Thanks and regards,

    -George

  • This is unlikely, but what size does malloc() take? could 32*1024 be overflowing?

  • Firstly,thank you sir for helping me solve my problem.

    I followed your advice. I check my function fopen() and malloc() their return value,I am sure their not NULL.And i check that  my heap size is 64000,i believe  it is enough for memary operation.

    This is my really code:

    char* filename="../TEST_CAT24C256.BIN";
    unsigned char *txBuf32ByteFullSpace1;
    char rxBuf32Byte[32] = {0x00, };
    txBuf32ByteFullSpace1 = (unsigned char*)malloc(2+1024*32);i
    if(txBuf32ByteFullSpace1==NULL)return;
    I2C_init();
    I2C_Params_init(&i2cParams);
    handle = I2C_open(I2C_EEPROM_INSTANCE, &i2cParams);
    I2C_transactionInit(&i2cTransaction);
    test_file  = fopen(filename, "rb");
    if(test_file == NULL) {
         UART_printf("can not open the file\n");
         fclose(test_file);
         I2C_close(handle);
         return NULL;
         }
    fseek(test_file, 0, SEEK_END);
    long fSize = ftell(test_file); //return length of file
    rewind(test_file); //return the point to head
    UART_printf("file_size:%d\n",fSize);
    *(txBuf32ByteFullSpace1)=0x00;
    *(txBuf32ByteFullSpace1+1)=0x00;
    int aaa=0;
    aaa=fread(txBuf32ByteFullSpace1+2,1,fSize ,test_file);
    if (aaa!=fSize) UART_printf("error read aaa=%d",aaa);
    UART_printf("read ok aaa=%d",aaa);

    It is a part of my encapsulation function.

    And when I test reading BINARY file ,I choose "rb" ;test reading .txt file I choose "r"

    The result printed by UART from XSHELL is

    BINARY FILE

    TXT FILE

  • 32*1024 is really a big size continuous memory. So i check the malloc() return value. I also try to use a 1024 byte char array,my program also does not work right.
    Sometimes I even think the C Library Function FOPEN is not right,but no doubt it is very absurd.

    It seems that I use MODE:rb/rb+/even RABBIT, the function just treat them as "r".

  • You might have to make your file name //Test since /T might be interpreted as an escape character.

  • OK,I will change the filename.

    But now, i can open the file.The file contain 32768 BYTE, i only fread() 128BYTE then close the file.

    This my file screen capture opened with Notepad++

  • One gotcha that I should have made clear in my other post is that even if the type for malloc() can handle 32x1024, the compiler might calculate with a smaller type - since you did not specify one - and use the wrong number.

    You can check this by storing 32x1024 into a variable before you use it and print the value before you call malloc().

    You can solve this by making your calculation 32L * 1024L to ensure that the calculation is carried out with long types.

  • Are you using the GCC ARM compiler that comes with CCS?  Are you using the semihosting feature built into the RTS libraries that come with that compiler?  

    Thanks and regards,

    -George

  • Yes,I used the the GCC ARM compiler that comes with CCS,the GCC ARM version is 7.3.1(linaro). But sorry,sir,I do no not know anything about the RTS libraries. I think I set that library default,because I do not change it.

    OH,sir today,i also use fopen(filename,"wb"),the program ever take "wb" as "w".So the result file contain many extra 0x0d.(‘’w“ open add 0x0d before 0x0a).

  • OH,bro today,i also use fopen(filename,"wb"),the program ever take "wb" as "w".So the result file contain many extra 0x0d.(‘’w“ open add 0x0d before 0x0a).

    This time i also use a large char array,it is okay.the result file is more than 32768 Byte. Just because the"0x0d",the other data is to totally right.

  • The extra characters are because windows uses cr/lf as an end of line marker rather than just lf.

  • Yes i know the reason,but i have no idea to solve it.

  • Hi, 

    Can you please try to use TI compiler and see if there is any difference? Create a CCS project as below: 

    I tried a simple program and the file I/O worked fine for me:

    #include <stdio.h>
    
    int main(void)
    {
        FILE *fp_bin_rd;
        FILE *fp_bin_wt;
        int array1[8] = {1,2,3,4,5,6,7,8};
        int array2[8] = {0};
    
        fp_bin_wt = fopen("test_bin1.bin", "wb");
        fwrite((void *)array1, 4, 8, fp_bin_wt);
        fclose(fp_bin_wt);
    
        fp_bin_rd = fopen("test_bin1.bin", "rb");
        fread((void *)array2, 4, 8, fp_bin_rd);
        fclose(fp_bin_rd);
    
        return 0;
    }
    

    Regards,

    Jianzhong

  • Sorry, the picture I uploaded in previous post didn't appear. Please see attached file for CCS project.

    ccs_project_fileio.docx

  • Sir, are you chinese? :D I am chinese too.所以如果可以的话我可以用中文和您交流!

    I tried your advice, it seems when I use TI compiler,"wb" really works. But I use the rtos-sdk TI provided,default compiler is arm-gcc.When I try to change it to TI compiler, there are some errors. Can you help me ? 

  • Hi,

    Can you try one of the following two methods:

    1. recreate the CCS project from scratch using TI compiler.

    2. compare the compiler options of the 2 configurations: Debug and Debug__TI. I believe Debug__TI must have missed some compiler flags. Try to add "-D" options and "-I" options which are in Debug but not in Debug__TI. For example,  -DSOC_AM437x -DEVM_AM437X -DevmAM437x -DAM43XX_FAMILY_BUILD -I"C:/ti/pdk_am437x_1_0_17/packages/". 

    Regards,

    Jianzhong

  • I have to say thank you for you spare no effort helping me.I also try your last advice,use your code,and add many include dictionaries;

    But this time I meet another problem,the error info is:"

    Description Resource Path Location Type
    Can't find the target named 'ti.targets.arm.elf.A8Fnv' along the path 'C:/ti/bios_6_76_03_01/packages;C:/ti/pdk_am437x_1_0_17/packages;C:/ti/ndk_3_61_01_01/packages;C:/ti/xdctools_3_55_02_22_core/packages;..;': please check the spelling of the target's name and that it exists along this path. .xdchelp /I2C_MULITYExample_Am437x_GeXinTec2 line 10 C/C++ Problem"

    Then I go to dir:C:\ti\bios_6_76_03_01\packages\ti\targets\arm\elf\

    I only find Arm9/IArm/IM3/IM4/IR4/IR5/M3/M4.....I tried Arm9, but it told me "

    Description Resource Path Location Type
    ti.platforms.evmAM437X.Platform : The build target ti.targets.arm.elf.Arm9 is incompatible with this platform. .xdchelp /I2C_MULITYExample_Am437x_GeXinTec2 line 80 C/C++ Problem"

    This is my first time to change compiler,so I maybe make many mistakes....

    SYS/BIOs version:bios_6_76_03_01

    TI compiler Version:TI v18.12.4LTS

  • Hi,

    It seems switching compiler in existing CCS project from GNU compiler to TI compiler is not working well. Let's not go this route.

    I tried the following:

    1. Imported the built-in RTOS CCS project from processor_sdk_rtos_am437x_6_03_00_106\demos\rtos_template_app\am437x\evmAM437x\A9\template_app\rtos without any modificatin. This project uses GNU 7.2.1 compiler.
    2. Built the project successfully
    3. Inserted the following code into main.c and validated file I/O worked fine:
          #define N 8192
          int array1[N] = {1,2,3,4,5,6,7,8};   // defined outside of main(), 32k bytes
          int array2[N] = {0};                        // defined outside of main(), 32k bytes
          
      FILE *fp_bin_rd; FILE *fp_bin_wt; int num_read; fp_bin_wt = fopen("test_bin1.bin", "wb"); fwrite((void *)array1, 4, N, fp_bin_wt); fclose(fp_bin_wt); fp_bin_rd = fopen("test_bin1.bin", "rasdfasf"); num_read = fread((void *)array2, 4, N, fp_bin_rd); if(num_read != N) { printf("Error in fread()\n"); } fclose(fp_bin_rd);

    So looks like the problem you had may have to do with your project configurations, especially RTS library as noted earlier in the thread.

    Also, I'm not sure about your application, but you can try to use CCS to directly load binary data into memory if that's okay. Choose Tools tab from CCS and select Load Memory. Then provide file path and specify File Type as Binary and then click Finish. It may take long time to load if your file is large, so you can try to validate this first by using a smaller file.

    Hope this can help.

    Regards,

    Jianzhong

  • Thank you very much sir!