Documentation/arm/tcm.txt

ARM 112浏览

Chinese translated version of Documentation/arm/tcm.txt

 

If you have any comment or update to the content, please contact the

original document maintainer directly.  However, if you have a problem

communicating in English you can also ask the Chinese maintainer for

help.  Contact the Chinese maintainer if this translation is outdated

or if there is a problem with the translation.

Chinese maintainer: 屠鹏  285585997@qq.com

---------------------------------------------------------------------

Documentation/arm/tcm.txt 的中文翻译

如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文

交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻

译存在问题,请联系中文版维护者。

中文版维护者: 屠鹏  285585997@qq.com

中文版翻译者: 屠鹏  285585997@qq.com

中文版校译者: 屠鹏  285585997@qq.com

 

以下为正文

---------------------------------------------------------------------

ARM TCM (Tightly-Coupled Memory) handling in Linux

----

Written by Linus Walleij <linus.walleij@stericsson.com>

Some ARM SoC:s have a so-called TCM (Tightly-Coupled Memory).

This is usually just a few (4-64) KiB of RAM inside the ARM

Processor.

ARM TCM (Tightly-Coupled Memory)在linux中的处理

-----

由Linus Walleij <linus.walleij@stericsson.com>编写

Some ARM SoC:一些有所谓的TCM (Tightly-Coupled Memory).

这通常是几个(4 - 64)前字节的RAMARM处理器

Due to being embedded inside the CPU The TCM has a

Harvard-architecture, so there is an ITCM (instruction TCM)

and a DTCM (data TCM). The DTCM can not contain any

instructions, but the ITCM can actually contain data.

The size of DTCM or ITCM is minimum 4KiB so the typical

minimum configuration is 4KiB ITCM and 4KiB DTCM.

由于嵌入CPU TCM有一个哈佛架构,所以有一个ITCM(指令TCM)和一个DTCM(数据TCM)DTCM不能包含任何的指令,ITCM实际上可以包含数据。DTCMITCM的大小最低4千字节,所以典型的最低配置是4千字节ITCM4千字节DTCM

 

ARM CPU:s have special registers to read out status, physical

location and size of TCM memories. arch/arm/include/asm/cputype.h

defines a CPUID_TCM register that you can read out from the

system control coprocessor. Documentation from ARM can be found

at http://infocenter.arm.com, search for "TCM Status Register"

to see documents for all CPUs. Reading this register you can

determine if ITCM (bits 1-0) and/or DTCM (bit 17-16) is present

in the machine.

ARM CPU:一些有特殊寄存器读出状态、物理位置和大小TCM的记忆。arch/arm/include/asm/cputype.h定义一个你可以从系统控制协处理器读出的CPUID_TCMARM文档可以在http://infocenter.arm.com找到,搜索TCM状态寄存器看到对于所有的cpu的文档。读这个寄存器可以确定ITCM(0 - 1)/DTCM(钻头17 16)是否存在于机器。

There is further a TCM region register (search for "TCM Region

Registers" at the ARM site) that can report and modify the location

size of TCM memories at runtime. This is used to read out and modify

TCM location and size. Notice that this is not a MMU table: you

actually move the physical location of the TCM around. At the

place you put it, it will mask any underlying RAM from the

CPU so it is usually wise not to overlap any physical RAM with

the TCM.

有进一步的一个TCM Region

Registers(搜索TCM Region

RegistersARM的网站),可以报告和修改位置尺寸在运行时的TCM。这是用于读取和修改TCM位置和大小。注意,这不是一个MMU:你实际上移动的TCM物理位置。在这个你所的地方,它将匹配任何潜在的CPU内存所以它通常是智能的不重叠的任何物理RAMTCM

 

The TCM memory can then be remapped to another address again using

the MMU, but notice that the TCM if often used in situations where

the MMU is turned off. To avoid confusion the current Linux

implementation will map the TCM 1 to 1 from physical to virtual

memory in the location specified by the kernel. Currently Linux

will map ITCM to 0xfffe0000 and on, and DTCM to 0xfffe8000 and

on, supporting a maximum of 32KiB of ITCM and 32KiB of DTCM.

TCM存储器可以重新映射到另一个地址的MMU再次使用,但请注意,TCM是否在MMU关闭的情况下经常使用。为了避免内核混淆当前的Linux实现将映射TCM11从物理到虚拟内存中指定的位置。目前Linux断断续续映射xfffe0000 ITCM,xfffe8000 DTCM,支持最大值为32千字节ITCM32千字节DTCM

Newer versions of the region registers also support dividing these

TCMs in two separate banks, so for example an 8KiB ITCM is divided

into two 4KiB banks with its own control registers. The idea is to

be able to lock and hide one of the banks for use by the secure

world (TrustZone).

新版本的地区寄存器也支持划分这些TCM两个单独的部分,比如一个8千字节的ITCM分为两个有自己的控制寄存器的4千字节部分。这个想法是为了被secure

world 锁定和隐藏一部分。

TCM is used for a few things:

 - FIQ and other interrupt handlers that need deterministic

   timing and cannot wait for cache misses.

 

 - Idle loops where all external RAM is set to self-refresh

   retention mode, so only on-chip RAM is accessible by

   the CPU and then we hang inside ITCM waiting for an

   interrupt.

 

  - Other operations which implies shutting off or reconfiguring

the external RAM controller.

TCM是用于一些事情:

- FIQ和其他中断处理程序,需要确定的时间和不能等待缓存未命中。

-在所有外部RAM空闲循环设置为自动刷新保留模式,所以只有芯片上的RAM访问CPU然后我们挂在ITCM等待一个中断。

-其他操作这意味着关闭或重新配置外部RAM控制器。

  

  There is an interface for using TCM on the ARM architecture

 in <asm/tcm.h>. Using this interface it is possible to:

  

  - Define the physical address and size of ITCM and DTCM.

  

  - Tag functions to be compiled into ITCM.

  

  - Tag data and constants to be allocated to DTCM and ITCM.

  

  - Have the remaining TCM RAM added to a special

    allocation pool with gen_pool_create() and gen_pool_add()

    and provice tcm_alloc() and tcm_free() for this

    memory. Such a heap is great for things like saving

    device state when shutting off device power domains.

  

  A machine that has TCM memory shall select HAVE_TCM from

  arch/arm/Kconfig for itself. Code that needs to use TCM shall

  #include <asm/tcm.h>

  

  Functions to go into itcm can be tagged like this:

  int __tcmfunc foo(int bar);

  

  Since these are marked to become long_calls and you may want

  to have functions called locally inside the TCM without

  wasting space, there is also the __tcmlocalfunc prefix that

  will make the call relative.

  

  Variables to go into dtcm can be tagged like this:

  int __tcmdata foo;

  

  Constants can be tagged like this:

  int __tcmconst foo;

  

  To put assembler into TCM just use

  .section ".tcm.text" or .section ".tcm.data"

  respectively.

  

  Example code:

  

 #include <asm/tcm.h>

 

 /* Uninitialized data */

 static u32 __tcmdata tcmvar;

 /* Initialized data */

 static u32 __tcmdata tcmassigned = 0x2BADBABEU;

 /* Constant */

 static const u32 __tcmconst tcmconst = 0xCAFEBABEU;

 

 static void __tcmlocalfunc tcm_to_tcm(void)

 {

         int i;

         for (i = 0; i < 100; i++)

                 tcmvar ++;

 }

 

 static void __tcmfunc hello_tcm(void)

 {

         /* Some abstract code that runs in ITCM */

         int i;

         for (i = 0; i < 100; i++) {

                 tcmvar ++;

         }

         tcm_to_tcm();

 }

 

 static void __init test_tcm(void)

 {

         u32 *tcmem;

         int i;

 

         hello_tcm();

         printk("Hello TCM executed from ITCM RAMn");

 

         printk("TCM variable from testrun: %u @ %pn", tcmvar, &tcmvar);

         tcmvar = 0xDEADBEEFU;

         printk("TCM variable: 0x%x @ %pn", tcmvar, &tcmvar);

 

         printk("TCM assigned variable: 0x%x @ %pn", tcmassigned, &tcmassigned);

 

         printk("TCM constant: 0x%x @ %pn", tcmconst, &tcmconst);

 

         /* Allocate some TCM memory from the pool */

         tcmem = tcm_alloc(20);

         if (tcmem) {

                 printk("TCM Allocated 20 bytes of TCM @ %pn", tcmem);

                 tcmem[0] = 0xDEADBEEFU;

                 tcmem[1] = 0x2BADBABEU;

                 tcmem[2] = 0xCAFEBABEU;

                 tcmem[3] = 0xDEADBEEFU;

                 tcmem[4] = 0x2BADBABEU;

                 for (i = 0; i < 5; i++)

                         printk("TCM tcmem[%d] = %08xn", i, tcmem[i]);

                 tcm_free(tcmem, 20);

         }

 }