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/AM3358:多线程可能存在高速缓存问题

Guru**** 2581345 points


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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/593518/rtos-am3358-possible-cache-issue-with-multi-threading

器件型号:AM3358

工具/软件:TI-RTOS

晚上都很好

我遇到了一个问题、即当 ISR 已启动时、128k 全局缓冲区阵列或已调用缓冲区的前56个字节会损坏。  但是、如果我将该缓冲区移动为局部缓冲区、问题就会消失。

所述代码是与 LWIP 一起运行的 FTP 客户端。  我们使用的是定制 AM335x PCB、CCS v6.1.1.00022、SYS/BIOS v642335、XDC 工具 v331024_CORE。  我已经尽量减少代码、我仍然可以看到错误、因此只运行 FTP 和 LWIP ISR、并且我可以告诉您、只有在 FTP 任务中的此代码期间触发 ISR 时才会发生损坏 GP_FTP_buffer 或 MlsdBuffer 类中的缓冲区会导致损坏。

fs_fread ((uint8_t *) gp_ftp_buffer、BTR、&br、ftp_instance->file_read);
//sys_prot_t hwi_state = sys_arch_protect ();
ftp_instance->mlsdBuffer->push (push_ftp_buffer、br);

if (gpgp_instance-=&trbt




)=&trbt 3&trbt
![fpf-ngpf-ngpf-ngpref!=&tract=&nbs=&trb&tract=&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb&trb %.2x %.2x"、(int)gp_ftp_buffer[3]、(int)buf[3];
ftp_instance->dbg_file_start = 1;
fp_instance->tx_state = sm_ftp_transfer_in_limbo;
}
//sys_arch_unprotect (hwi_state); 

正如我说过的、如果我将缓冲区移动到本地、问题就会发生、但这是一个非常大的应用、我们已经看到了其他可能与之相关或可能与之无关的损坏、因此我想了解这个问题的底部、并了解什么 发生的情况。  

我已排除:

  • 通过检测损坏发生的位置并引入延迟来使 ISR 调用在不同位置发生、任务代码的任何特定部分都是导致损坏的原因。
  • 堆栈或堆会通过其在存储器映射中的位置溢出、观察到它周围没有任何东西会损坏、并使所有堆栈和堆加倍以确保安全。

我剩下的是怀疑这与高速缓存相关、以及我如何设置高速缓存/使用高速缓存的方式不是线程安全的。  当我在 DDR3区域的 MMU 设置中禁用高速缓存或将可缓冲设置为 false 时、我没有观察到任何损坏、但是性能很差、LWIP 会保持报告断言并最终断开连接。  这种解释听起来是否可行?  如果是、我可以在不影响性能的情况下尝试阻止损坏吗?

以下是我在项目 cfg 文件中设置 MMU 和高速缓存的方法:

var 高速缓存= xdc.useModule('ti.sysbios.family.arm.a8.Cache');
var MMU = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');

//启用高速缓
存。enableCache = true;

//启用 MMU (L1/L2数据高速缓存所需)
MMU。enableMMU = true;

//强制外设段为不可高速缓存
var peripheralAttrs ={
键入:MMU.FirstLevelDesc_section,//段描述符
TEX:0、
可缓冲:false,//可缓冲
可高速缓存:false,//可高速缓存
可共享:false,//可共享
NoExecute:true,//不可执行
};

//为地址范围中的每个条目设置描述符
对于(var i=0x44000000;i < 0x8000000000;i = i + 0x00100000){
//每个“描述符”条目跨越1MB 地址范围
Mmu.setFirstLevelDescMeta(i、i、peripheralAttrs);
}

//描述符属性结构
VAR attrs ={
键入:MMU。FirstLevelDesc_section、//段描述符
TEX:0x1、
可缓冲:真、 //可缓冲
可高速缓存:true、 //可缓存
};

//为地址范围中的每个条目设置描述符
对于(var i=0x80000000;i < 0x90000000;i = i + 0x00100000){
//每个“描述符”条目跨越1MB 地址范围
Mmu.setFirstLevelDescMeta(i、i、atttrs);
} 

如果我现在不知道该去哪里、如果有任何关于我所做的错误的建议、我将不胜感激。

谢谢

肖恩

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我希望 LWIP 中的某些缓冲区不在高速缓存边界上。 "128k 全局缓冲器阵列的前56个字节"损坏之前是什么?

    好奇...我们不是在使用 TI 的 NDK?

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

    您好 Todd、

    两个损坏的缓冲区都不在 lwip 中、它们都在我们自己的 FTP 代码中。

    gp_ftp_buffer 之前是该文件中的其他全局变量、另外两个文件之后是堆、具体而言、信标和任务句柄直接位于前。  另一个缓冲器位于堆上、因此其他动态分配的存储器很可能会受到影响、但正如我说过的、我看到没有其他影响、只有在中断中有效使用的两个缓冲器、因此我不会看到这是相关的。

    据我所知、TI 的 NDK 不支持 am355x 处理器、这就是为什么我们被迫将 lwip 和驱动程序从 starterware 移植到 SYS/BIOS 项目中的原因。

    肖恩

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

    我已经做了一些进一步的调查、以下代码修复了缓冲区的损坏、同时将性能保持在可接受的水平。

    OxTS_fread (((uint8_t *) gp_ftp_buffer、BTR、&br、ftp_instance->file_read);
    CacheDataInvalidateBuff (unsigned int) gp_ftp_buffer、 gp_ftp_buffer_size);
    ftp_instance->MlsdBuffer->push (gp_ftp_buffer、br);
    
    if (fp_instance->bytes_read = 0)
    {
    char buf[4];
    ftp_instance->mlsdBuffer->pep (buf、4);
    if (gp_bad_buffer = 3)
    !(stofb!)|stofb!3!(stofb!)开始文件! %.2x %.2x"、(int)gp_ftp_buffer[3]、(int)buf[3];
    ftp_instance->TX_state = sm_ftp_transfer_in_limbo;
    } 

    但是、我现在从 lwip 中得到以下错误、并且大型传输失败

    lwip-1.4.1/src="/core/IPv4/IP.c,断言:P->ref =1.

    这与我在禁用高速缓存时遇到的相同错误、现在性能没有明显的影响。  如果有人了解 AM355x 中高速缓存的工作情况、请尽量让我们了解一下这里发生的情况、以及我可以尝试哪些方法来获得可行的解决方案?

    如果您能给我一个好的资源来了解它的工作原理、我也会非常感谢。

    谢谢

    肖恩  

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

    晚上好。

    我已经非常接近它的底部。  它似乎是由入门软件 mmcsd 库决定的、该库要求读取/写入数据的指针以进行缓存行对齐、因为它会使缓存无效并写回缓存、以便正确完成 DMA 修改的数据。  我在任何地方都没有看到此要求的记录、这将会有所帮助...

    为了解决这一问题、我计划添加一个检查、即为写入/读取而传递的指针是线对齐的、如果不将其复制到本地缓冲区、这样就不会在考虑了这一点的情况下降低写入效率、 在尚未考虑到读/写操作的情况下、读/写操作仍然有效、并将向调试器打印警告。  我还没有编写和测试其中的最后一部分、但希望它能正常工作。

    我曾尝试将数据从缓存行的开头向下舍入、并使另一行无效、但这会导致异常和其他问题、无论我是如何尝试的、我都想这是否可行?  例如、我尝试了:

    CacheDataCleanBuff (((unsigned int) ptr)& 0xffffffc0、(512 * nblks)+ SOC_CACHELINE_SIZE); 

    我尝试用 SYS/BIOS 替换缓存无效函数、但无法使它们正常工作、我更换了它们、如下所示、TI 的某个人可能会评论为什么?

    //CacheDataInvalidateBuff (((unsigned int) ptr)、(512 * nblks));
    cache_inv (ptr、(512 * nblks)+ 1、cache_Type_ALLD、true);
    
    和
    
    //CacheDataCleanBuff (((unsigned int) ptr)、(512 * nblks));
    cache_wb(ptr,(512 * nblks),cache_Type_alld, true); 

    欢迎对我的调查结果/理解发表任何评论,如果有人能够回答上述两个问题,我将不胜感激。

    非常感谢

    肖恩

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

    [引用 user="Sean Bedford"]我尝试用 SYS/BIOS 替换缓存无效函数,但无法使它们正常工作,我更换了它们,下面 TI 的某个人可能会评论为什么?

    哪些不起作用? cache_inv 或 cache_wd 或两者都是?  

    请注意、第二个参数是字节计数。 您的意思是执行(512 * nblks)+ 1个字节将失效吗? 注:高速缓存命令位于32位字上。 因此 、在 cache_inv 和 cache_wb 调用中、您的+ 1将四舍五入为4。

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

    很抱歉、我等了这么长时间才回复、我一直忙于其他问题。

    是的、我的意思是它(或者、您的意思是它、因为这是 TI 的库代码) 512是 AD 卡上的扇区大小、nblks 是正在写入或读取的数字;+1是我尝试通过向下舍入为高速缓存行并写入额外行来获取需要对齐的数据、因此它应该是64 我无法使其正常工作。

    无法使 SYS/BIOS 函数正常工作是因为我跳过了自己的调试代码、因此它们正常工作、而只是为了确保传递的数据是缓存行对齐的。 我现在修改了驱动程序、以警告和防止数据被错误地按顺序传递、因此问题似乎全部得到了解决。

    就像我说过的那样、如果记录下来的话、我会节省很多农业、因为这一点当然不明显。

    肖恩