15

背景

我一直在研究可能将MPC5200静态 ram 空间用作暂存器内存。我们有 16Kb 的未使用内存出现在处理器总线()上。

现在一些重要的实现说明是:

  1. 该内存由BestComm DMA控制器使用,在RTEMS此之下将在 SRAM 的开头设置一个任务表,其中包含一组 16 个任务,可以作为外围接口、I2C、以太网等的缓冲区运行。为了使用这个空间没有冲突并且知道我们的系统只使用了大约 2Kb 的以太网驱动程序缓冲区,我将 SRAM 的开始偏移了 8Kb,所以现在我们有 8Kb 的内存,我们知道系统不会使用它。

  2. RTEMS定义一个指向静态内存的数组,如下所示:

来源

typedef struct {
    ...
    ...
    volatile uint8_t    sram[0x4000];
 } mpc5200_t;

 extern volatile mpc5200_t mpc5200;

而且我知道 sram 数组指向静态内存,因为当我编辑第一部分并打印出内存块(MBAR + 0x8000 )时

所以从这里我可以说以下内容,我有 RTEMS 定义的对SRAMvia的访问mpc5200.sram[0 -> 0x2000]。这意味着我可以开始对我可以摆脱它的速度进行一些测试。


测试

为了评估速度,我设置了以下测试:

int a; // Global that is separate from the test. 

**TEST**

// Set up the data.
const unsigned int listSize = 0x1000;
uint8_t data1[listSize];
for (int k = 0; k < listSize; ++k) {
    data1[k] = k;
    mpc5200.sram[k] = k;
}

// Test 1, data on regular stack.
clock_t start = clock();
for (int x = 0; x < 5000; ++x) {
    for (int y = 0; y < 0x2000; ++y) {
        a = (data1[y]);
    }
}
double elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;
printf("elapsed dynamic: %f\n" ,elapsedTime);

// Test 2, get data from the static memory.
start = clock();
for (int x = 0; x < 5000; ++x) {
    for (int y = 0; y < 0x2000; ++y) {
        a = (mpc5200.sram[y]);
    }
}
elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;
printf("elapsed static: %f\n" ,elapsedTime);    

非常简单,概念是我们正在迭代可用空间并设置全局。我们应该期望静态内存应该有相同的近似时间。


结果

所以我们得到以下信息:

elapsedDynamic = 1.415
elapsedStatic = 6.348

所以这里发生了一些事情,因为静态几乎比缓存慢 6 倍。


假设

所以我对为什么会这样有 3 个想法:

  1. 缓存未命中,我想也许是因为我们正在混合动态和静态 ram,所以发生了一些奇怪的事情。所以我尝试了这个测试:

.

// Some pointers to use as incrementers
uint8_t *i = reinterpret_cast<uint8_t*>(0xF0000000+0x8000+0x1000+1);
uint8_t *j = reinterpret_cast<uint8_t*>(0xF0000000+0x8000+0x1000+2);
uint8_t *b = reinterpret_cast<uint8_t*>(0xF0000000+0x8000+0x1000+3);


// I replaced all of the potential memory accesses with the static ram
// variables. That way the tests have no interaction in terms of 
// memory locations. 
start = clock();
// Test 2, get data from the static memory.
for ((*i) = 0; (*i) < 240; ++(*i)) {
    for ((*j) = 0; (*j) < 240; ++(*j)) {
        (*b) = (mpc5200.sram[(*j)]);
    }
}
elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;
printf("elapsed static: %f\n" ,elapsedTime);

我们有以下结果:

elapsedDynamic = 0.0010
elapsedStatic = 0.2010

所以现在它慢了 200 倍?所以我想这与此无关?

  1. 与正常不同的静态内存,我想到的下一件事是,由于这条线,它可能不会像我想象的那样交互:

    MPC5200 包含 16KBytes 的片上 SRAM。BestComm DMA 单元可以直接访问该内存。它主要用作任务表和缓冲区描述符的存储,BestComm DMA 使用它来将外设数据移入和移出 SDRAM 或其他位置。这些描述符必须在启动时下载到 SRAM。该 SRAM 位于 MPC5200 内部寄存器空间中,也可由处理器内核访问。因此,它可以用于其他目的,例如便签本存储。16kBytes SRAM 从位置 MBAR + 0x8000 开始。

来源

我不确定如何确认或否认这一点?

  1. 较慢的静态时钟,也许静态内存运行在较慢的时钟上,就像在某些系统中一样?

这可以通过查看手册来反驳:

在此处输入图像描述

来源

SRAM 和处理器在同一个时钟上,XLB_CLK以处理器基频运行(来源


问题

什么可能导致这种情况,一般有理由不使用 SRAM 进行暂存器存储吗?我知道在现代处理器上这甚至不会被考虑,但这是一个较旧的嵌入式处理器,我们正在为速度和空间而奋斗。


额外测试

所以在下面的评论之后,我进行了一些额外的测试:

  1. 添加volatile到堆栈成员以查看速度是否更相等:

.

elapsedDynamic = 0.98
elapsedStatic = 5.97

所以仍然快得多,并且与volatile没有任何变化??

  1. 反汇编代码看看发生了什么

.

// original code
int a = 0;
uint8_t data5[0x2000];
void assemblyFunction(void) {
    int * test = (int*) 0xF0008000;
    mpc5200.sram[0] = a;
    data5[0] = a;
    test[0] = a;
}

void assemblyFunction(void) {
// I think this is to load up A
0:  3d 20 00 00     lis     r9,0
8:  80 09 00 00     lwz     r0,0(r9)
 14:    54 0a 06 3e     clrlwi  r10,r0,24

    mpc5200.sram[0] = a;   
    1c: 3d 60 00 00     lis     r11,0
  20:   39 6b 00 00     addi    r11,r11,0
  28:   3d 6b 00 01     addis   r11,r11,1 // Where do these come from?
  2c:   99 4b 80 00     stb     r10,-32768(r11)

test[0] = a;
   c:   3d 20 f0 00     lis     r9,-4096 // This should be the same as above??
  10:   61 29 80 00     ori     r9,r9,32768
  24:   90 09 00 00     stw     r0,0(r9)

    data5[0] = a;
    4:  3d 60 00 00     lis     r11,0
    18: 99 4b 00 00     stb     r10,0(r11)

我不是特别擅长互穿汇编程序,但也许我们这里有问题?从全局访问和设置内存似乎需要更多的指令SRAM

  1. 从上面的测试看来,指针的指令较少,所以我添加了这个:

.

uint8_t *p = (uint8_t*)0xF0008000;

// Test 3, get data from static with direct pointer.
for (int x = 0; x < 5000; ++x) {
    for (int y = 0; y < 0x2000; ++y) {
        a = (p[y]);
    }
}

我得到以下结果:

elapsed dynamic: 0.952750
elapsed static: 5.160250
elapsed pointer: 5.642125

所以指针需要更长的时间!我会认为它会完全一样?这只是越来越陌生。

4

1 回答 1

1

所以看起来有几个因素可能会导致这种情况。

  1. 我不再确定 SRAM 是否以与处理器相同的时钟速度运行。正如@user58697 所指出的,SRAM即使看起来总线在 XLB 时间上,它也在 IPB 时钟时间上。最重要的是有这个图表:

在此处输入图像描述来源

这似乎表明内存时钟位于 XLB 路径上,但 XLB 路径的频率低于 CORE 时钟。这可以在这里确认:

在此处输入图像描述

来源

这表明 XLB_Bus 的运行速度比处理器慢。

  1. 为了测试 SRAM 至少比动态 ram 快,我进行了以下测试:

.

// Fill up the cache with pointless stuff
for (int i = 0; i < 4097; ++i) {
    a = (int)TSin[i];
}

// 1. Test the dynamic RAM access with a cache miss every time. 
ticks = timer_now();
// += 16 to ensure a cache line miss.
for (int y = 0; y < listSize; y += 16) {
    a = (data1[y]);
}
elapsedTicks = timer_now() - ticks;

// Fill up the cache with pointless stuff again ...

ticks = timer_now();
// Test 2, do the same cycles but with static memory.
for (int y = 0; y < listSize; y += 16) {
    a = (mpc5200.sram[y]);
}
elapsedTicks = timer_now() - ticks;

有了这个,我们得到以下结果:

elapsed dynamic:  294.84 uS
elapsed static:  57.78 uS

所以我们在这里可以说的是静态 RAM 比动态 RAM 快(预期),但是当动态 RAM 加载到缓存中时,访问静态 RAM 要慢得多,因为缓存访问是处理器速度,而静态 RAM 速度是远少于此。

于 2015-04-02T17:38:02.080 回答