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.

[参考译文] RTOS/TM4C123GH6PM:如何更改可能同时打开的 fatfs 文件的数量。

Guru**** 2613335 points
Other Parts Discussed in Thread: SYSBIOS, TM4C123GH6PM

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/770761/rtos-tm4c123gh6pm-how-to-change-the-number-of-fatfs-files-that-may-be-open-concurrently

器件型号:TM4C123GH6PM
Thread 中讨论的其他器件:SYSBIOS

工具/软件:TI-RTOS

使用 CCS、我编写了一个 C 语言程序来控制机器人/金属车床/切割锯。

所有 I/O 均由中断驱动、运行良好。

程序的核心由命令字符串解释器组成。

命令字符串可以通过串行端口到达、也可以从 SD 卡上的文件中读取。

解释器从多达10个打开的文件中以循环方式读取命令、并将每个文件的位置指针用作虚拟"程序计数器"、以便能够轻松实现 ONGOTO、GoSub、GOTO 等命令。

实际上、它是一个"多任务"解释器。 整个过程非常适合每秒解读5000条命令、速度足够快。

但是、每当我尝试打开7个以上的文件时、都会出现一个问题、即尝试打开第8个文件时返回 NULL。

在 .CFG (堆栈或堆、或者文件缓冲区所在的任何位置)中、我没有指定足够的正确 RAM 类型、或者

我在 ffconf.h 中更改_FS_SHARE 的尝试未生效、即使我单击"Build All"和"clear... 构建整个工作区"

我应该怎么做才能同时打开多达15个文件?

我们非常感谢您的帮助。 谢谢。 Dave

P.S. 下面是我的解释器处理的代码示例。 当'load'尝试打开 Q.Bob 时、返回 NULL。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 David:
    您的问题描述比我对 FATFS 的了解要深得多。 您是否曾尝试先增加堆和堆栈大小、并将有所不同(即允许您打开第8个文件)?

    您能否澄清您是否正在使用 TI-RTOS FATFS 和 TI-RTOS SD 卡驱动程序? 如果是、我会将您的问题转交给我们的 TI-RTOS 专家以获取建议。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Charles、

    我首先尝试最大化堆、然后堆栈都差不多、但全部都没有效果。

    我将附加我的.cfg 文件。 也许你可以发现我搞砸了的东西。

    在 ffconf.h...中

    #ifndef _FFCONF
    #define _FFCONF 8255 /*修订 ID */

    我编辑了这些...


    #define _volumes 1
    /*要使用的卷数量(逻辑驱动器)。 *

    #define _FS_SHARE 15. /* 0:禁用或>=1:启用*/
    /*要启用文件共享功能,请将_FS_share 设置为1或更大。 值
    定义可以同时打开的文件数量。 *


    /cfs-file/__key/communityserver-components-multipleuploadfilemanager/3bfe50e9_2D00_41fa_2D00_4aec_2D00_be39_2D00_00708ddb1be3-150397-complete/BOB.cfg

    谢谢 Charles
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 David:
    如果您使用的是 TI-RTOS FATFS 和 TI-RTOS SD 卡驱动程序、您尚未回答我的问题。 如果您使用的是 TI-RTOS、您能否发送.cfg 文件? 谢谢。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Charles、

    这是.cfg 的副本和粘贴。

    /*
     *版权所有(c) 2014、德州仪器(TI)公司
     *保留所有权利。
     *
     *以源代码和二进制形式重新分发和使用、有无
     *如果满足以下条件、则允许进行修改
     符合*:
     *
     ** 源代码的重新分发必须保留上述版权
     *   注意、此条件列表和以下免责声明。
     *
     * *二进制形式的再发行必须复制上述版权
     *   请注意、中的此条件列表和以下免责声明
     *   随分发提供的文档和/或其他材料。
     *
     * *德州仪器公司的名称和名称均不相同
     *   其贡献者可用于认可或推广衍生产品
     *   未经特定的事先书面许可。
     *
     *本软件由版权所有者和贡献者"按原样"提供
     *以及任何明示或暗示的保证、包括但不限于:
     *特定适销性和适用性的隐含保证
     *不承认目的。 在任何情况下、版权所有者不得或
     *派遣国应对任何直接、间接、偶然、特殊、
     *典型或必然的损害(包括但不限于
     *采购替代货物或服务;丧失使用、数据或利润;
     *或业务中断)、无论原因是什么以及任何责任理论、
     *无论是合同、严格责任还是侵权行为(包括疏忽或)
     *否则)因使用本软件而以任何方式产生、
     *即使被告知可能会发生此类损坏。
     *

    /*
     * ==== fatsd.cfg ===========
     *

    /*========================= 常规配置=================== *
    VAR 默认值= xdc.useModule('xdc.runtime.Defaults');
    //var 诊断= xdc.useModule('xdc.runtime.Diags');
    //var 错误= xdc.useModule('xdc.runtime.Error');
    //var Log = xdc.useModule('xdc.runtime.Log');
    VAR Main = xdc.useModule('xdc.runtime.Main');
    VAR 内存= xdc.useModule('xdc.runtime.Memory');
    VAR 系统= xdc.useModule('xdc.runtime.System');
    VAR Swi = xdc.useModule('ti.sysbios.knl.Swi');
    VAR 时钟= xdc.useModule('ti.sysbios.knl.Clock');
    Clock.swiPriority = 7;
    clock.timerId = 0;
    VAR Hwi = xdc.useModule('ti.sysbios.family.arm.m3.Hwi');
    VAR 任务= xdc.useModule('ti.sysbios.knl.Task');
    VAR FatFs = xdc.useModule('ti.sysbios.fatfs.FatFS');
    VAR 秒= xdc.useModule('ti.sysbios.hal.Seconds');
    //var LoggerRunMode = xdc.useModule('ti.uia.loggers.LoggerRunMode');
    //var TimestampProvider = xdc.useModule('ti.sysbios.family.arm.lm4.TimestampProvider');
    //var ti_sysbios_hal_hwi = xdc.useModule('ti.sysbios.hal.Hwi');
    /*
     * IAR 会忽略 Program.stack。 使用中的项目选项
     * IAR Embedded Workbench 以更改系统堆栈大小。
     *
    if (!Program.build.target.$name.match (/IAR/)){
       /*
        * 减小系统堆栈大小(由 ISR 和 Swi 使用)以减小
         * RAM 使用情况。
        *
    program.stack = 4096;


    program.stack = 4096;
    /*
     *注释此行以允许在目标上加载模块名称。
     *模块名称字符串放置在.const 段中。 设置此值
     *将参数设置为 false 将节省.const 段中的空间。  误差和
     *断言消息将包含"未知模块"前缀
     实际模块名称的*。
     *
    Defaults.common$.namedModule = false;

    /*
     *最小化系统中的 EXIT 处理程序数组。  系统模块包括
     *向 System_atexit()注册的函数数数组
     *由 System_exit()调用。
     *
    System.maxAtexitHandlers = 2;

    /*========================= 系统配置=================== *
    VAR SysMin = xdc.useModule('xdc.runtime.SysMin');
    System.SupportProxy = SysMin;

    /*为 GNU 目标启用半主机功能以打印到 CCS 控制台*/
    if (Program.build.target.$name.match (/GNU/)){
       VAR SemiHost = xdc.useModule('ti.sysbios.rts.gnu.SemiHostSupport');

    system.extendedFormats ='%$L%$S%$F%f';
    /*========================= BIOS 配置=================== *
    /*
     *禁用未使用的 BIOS 功能以最大程度地减小占用空间。
     *
    VAR BIOS = xdc.useModule('ti.sysbios.BIOS');
    BIOS.libType = BIOS.LibType_Debug;
    /*减小堆大小*/
    BIOS.heapSize = 13540;
    // BIOS.logsEnabled = true;
    // BIOS.sertsEnabled = true;

    VAR TIRTOS = xdc.useModule('ti.tirtos.TIRTOS');
    TIRTOS.libType = TIRTOS.LibType_NonInstrumented;
    TIRTOS.useSDSPI = true;
    TIRTOS.useGPIO = false;
    TIRTOS.useI2C = false;
    TIRTOS.useSPI = false;
    var clock4Params0 =新的 Clock.Params();
    clock4Params0.instance.name ="clock_ArmServos_handle";
    clock4Params0.period = 10;
    clock4Params0.startFlag = false;
    program.global.clock_ArmServos_handle = Clock.create ("&clock_ArmServos"、2、clock4Params0);
    var clock5Params0 =新的 Clock.Params();
    clock5Params0.instance.name ="clock_ScanningServo_handle";
    clock5Params0.period = 50;
    clock5Params0.startFlag = false;
    clock5Params0.arg =空;
    program.global.clock_ScanningServo_handle = Clock.create ("&clock_ScanningServo"、5、clock5Params0);
    var clock5Params1 =新的 Clock.Params();
    clock5Params1.instance.name ="clock_Location_handle";
    clock5Params1.period = 100;
    clock5Params1.startFlag = false;
    program.global.clock_Location_handle = Clock.create ("&clock_Location"、4、clock5Params1);
    var clock6Params = new Clock.Params();
    clock6Params.instance.name ="clock_MillisecTimer_handle";
    clock6Params.period = 1;
    clock6Params.startFlag = false;
    program.global.clock_MillisecTimer_handle = Clock.create ("&clock_MillisecTimer"、1、clock6Params);
    var clock6Params0 =新的 Clock.Params();
    clock6Params0.instance.name ="clock_pid_handle";
    clock6Params0.period = 1;
    program.global.clock_PID_Handle = Clock.create ("&clock_PID"、1、clock6Params0);
    var clock7Params = new Clock.Params();
    clock7Params.instance.name ="clock_AtoDTimer_handle";
    clock7Params.period = 10;
    clock7Params.startFlag = false;
    program.global.clock_AtoDTimer_handle = Clock.create ("&clock_AtoDTimer"、3、clock7Params);
    var swi0Params = new swi.Params();
    swi0Params.instance.name ="swiConvertAnalogValues_handle";
    sw0Params.priority = 4;
    program.global.swiConvertAnalogValues_handle = Swi.create ("&swiConvertAnalogValues"、swi0Params);
    VAR task0Params = new Task.Params();
    task0Params.instance.name ="TheCoreTask_Handle";
    task0Params.STACKSIZE = 5000;
    task0Params.priority = 1;
    program.global.TheCoreTask_handle = Task.create ("&TheCoreTask"、task0Params);
    var hwi0Params = new hwi.Params();
    hwi0Params.instance.name ="UART1_ISR_Handle";
    hwi0Params.enableInt = true;
    hwi0Params.priority = 35;
    program.global.UART1_ISR_Handle = Hwi.create (22、"&UART1_ISR"、hwi0Params);
    var hwi1Params = new hwi.Params();
    hwi1Params.instance.name ="UART5_PIXYCAM_ISR_Handle";
    hwi1Params.priority = 34;
    hwi1Params.enableInt = true;
    program.global.UART5_PIXYCAM_ISR_Handle = Hwi.create (77、"&UART5_PIXYCAM_ISR"、hwi1Params);
    var hwi2Params = new hwi.Params();
    hwi2Params.instance.name ="ADC0_FIFO_FULL_ISR_Handle";
    hwi2Params.priority = 33;
    program.global.ADC0_FIFO_FULL_ISR_Handle = Hwi.create (30、"&hwi_ADC0_FIFO_FULL_ISR"、hwi2Params);
    var hwi3Params = new hwi.Params();
    hwi3Params.instance.name ="ADC1_FIFO_FULL_ISR_Handle";
    hwi3Params.priority = 33;
    program.global.ADC1_FIFO_FULL_ISR_Handle = Hwi.create (64、"&hwi_ADC1_FIFO_FULL_ISR"、hwi3Params);

    task.idleTaskVitalTaskFlag = false;
    task.enableIdleTask = false;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 David:
    感谢您提供.cfg 文件。 我会将您的问题转交给我们的 TI-RTOS 专家以寻求帮助。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 David:

    _fs_share 表示可以共享 file....no的线程数、而不是打开的唯一文件数。 这是无限的(根据 FatFS 网站)

    文件系统类型:fat、FAT32 (rev0.0)和 exFAT (rev1.0)。

    打开的文件数:不限。 (取决于可用内存)

    卷数:最多10个。

    卷大小:512字节/扇区时高达2 TB。

    文件大小:FAT 卷最多4 GB - 1个,exFAT 卷几乎不受限制。

    群集大小:FAT 卷上最多128个扇区,exFAT 卷上最多16 MB。

    扇区大小:512、1024、2048和4096字节。

    我认为还有其他事情在发生。 在任务中、您是否可以有一个循环来打开 N 个唯一文件并查看它是否起作用?

    Todd

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

    你好 Todd、你好:"在一个任务中、你是否可以有一个循环来打开 N 个唯一文件并查看它是否起作用?"

    是的、这是我的程序正在执行的操作...

    现在:

    program.stack = 2048;

    task0Params.STACKSIZE = 5000;(我的任务和唯一的任务)

    BIOS.heapSize = 15360;

    SRAM 内存分配为32、572 (99%)

    更可能相关...

    我可以将7个文件"加载"到 scriptList[]中。 尝试加载第8个命令会导致'fals'从 fileExists()返回。

    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    文件编号7的 TOKENPTRS[]数组中的文件名是否有错误(即拼写错误),并且文件系统中不存在?

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

    尊敬的 Alan:

    我通过在'load'参数列表中交换 P.Bob 和 Q.Bob 的顺序来测试这一点。

    在这种情况下,Q.Bob 被加载,fileExists()在尝试打开 P.Bob 时返回 false。

    我的堆使用实际上是不存在的。

    它的唯一用途是将每个脚本局部变量和标签存储在链接列表中。

    这是我尝试的内容的过时图像(但仍能捕捉到本质)...

    谢谢 Alan

    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    当您使用备用 C 库 API 时、我认为您将遇到 C RTS 库 FOPEN_MAX 限制。

    如果您可以找到所使用的 stdio.h 文件、请搜索 FOPEN_MAX 的定义。 这样您就可以了解需要执行哪些操作来增加可以同时打开的文件数量。 我认为可能是10。 在您的情况下、前3个由 STDIN、STDOUT 和 STDERR 执行。 剩下7个给你。 但这只是一个经过教育的猜测...

    我在此处找到了此信息:

    www.cplusplus.com/.../

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

    尊敬的 Alan:

    是的、FOPEN_MAX 设置为10。 我将其更改为15... 这是一张情况图片...

    我一直在努力解决问题、现在一切都很完美! (总是让我的好友笑的一个声明)。

    我知道、最终我们将解决这个问题。

    感谢您的建议。 我即将阅读您提供的"cplusplus "链接。

    谢谢

    Dave

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

    [引用 user="David genge">是的、FOPEN_MAX 设置为10。 我将其更改为15... 这是一张情况图片...我认为您必须更改 _NSTREAM 以及 _nfile - 请参阅 Compiler/TMS320C6674:RTFS File Descriptors > 17 open 一次?

    引用的线程适用于 TI C6000编译器、但认为相同的主体适用于 TI ARM 编译器。

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

    [引用 user="David genge">是的、FOPEN_MAX 设置为10。 我将其更改为15...[/quot]、因为图片显示_ftable 只有10个条目、看起来编译器运行时库在_nfile 更改后未重新构建。

    当编译器运行时库源目录中的源文件发生更改时、编译 CCS 工程时不会自动重新编译库。 要强制在增加_nfile 和_NSTREAM 后重建运行时库、请执行以下操作:

    a:在工程的链接器.map 文件中、找到以下形式的一行、该行标识了使用编译器中的库文件:

    /home/mr_halfword/ti/ccs830/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/lib/rtsv7M4_T_le_v4SPD16_eabi.lib 

    b.删除上述文件。

    c.重新编译 CCS 工程、链接器应输出以下形式的内容、指示正在编译该库:

    警告#10366-D:自动库构建:首次使用库"/home/mr_halfword/ti/ccs830/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/lib/rtsv7M4_T_le_v4SPD16_eabi.lib、因此必须进行构建。 这可能需要几分钟的时间。
    正在创建库/tmp/TI_MKLIB57mlHN/rtsv7M4_T_le_v4SPD16_eabi.lib 

    有关  如何构建运行时库的更多信息、请参阅 Mklib。

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

    切斯特、您好!
    太棒了! 那是可行的。 非常感谢切斯特。
    我所做的:
    在中找到包含文件'file.h'和'stdio.h'的目录
    C:\ti\ccsv6\tools\compiler\ti-cgt-arm_5.2.5\lib\src

    编辑了"stdio.h"、将_nfile 条目值从10更改为15。
    编辑了'file.h'、将_NSTREAM 条目值从10更改为15。
    在目录:C:\ti\ccsv6\tools\compiler\ti-cgt-arm_5.2.5\lib 中
    复制、重命名然后删除文件:
    tsv7M4_T_le_v4SPD16_eabi.lib
    在 Code Composer Studio.Project.Clean 中选择了我的项目、按下"Build the entire workspace"选项按钮、然后点击"OK"按钮。
    然后、我单击"调试"按钮将项目刻录到 TM4C123GH6PM 闪存中。
    当我打开内存浏览器并输入'_ftable'时、您会发现! 有15个条目。 惠赛。
    但是
    当我返回到编辑器并单击构建按钮时、发生了这种情况...

    "错误#10099-D:程序将无法装入可用内存。 对于“data_Group”size bbb9a,运行定位失败。 可用存储器范围:
    SRAM 大小:0x8000未使用:0xb48最大空洞:0xb48
    错误#10010:链接期间遇到错误;未生成"Rob0.out"
    >>编译失败
    gmake:***[Rob0.out]错误1.
    gmake:目标`全部'不会由于错误而重制。"

    我的下一个问题是:
    系统将15 x 512 = 7、680字节的文件缓冲区、系统堆栈、任务堆栈、堆或常规 RAM 分别放置在何处?
    感谢一百万 Chester、
    谢谢
    Dave

    更新:我触发了 RAM、因此它现在可以工作、至少第一个测试显示加载了7个以上的文件。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    切斯特、您好!
    一切都很棒。
    我将10个文件指针的数组移动到每个虚拟 CPU 中。
    "程序计数器"更合适的位置、是的。
    我现在单击"这解决了我的问题"。
    再次感谢您的出色帮助。
    谢谢
    Dave