gpt4 book ai didi

stm32 - 为什么即使禁用时钟,D2 RAM 也能正常工作?

转载 作者:行者123 更新时间:2023-12-03 14:37:28 28 4
gpt4 key购买 nike

TL;DR: 文档指出,我必须先在微 Controller 中启用特定的内存区域,然后才能使用它。但是,我可以在启用它之前使用它,甚至在禁用它之后使用它。这怎么可能?

我目前正在为 STM32H743 微 Controller 开发一个应用程序。我不明白在时钟被禁用时 RAM 是如何正常工作的。
该 MCU 具有多个存储器,分布在多个电源域中:

  • 在 D1 域中,它具有 ITCMRAM + DTCMRAM + AXI SRAM (64 + 128 + 512 kB)
  • 在 D2 域中,它具有 SRAM1 + SRAM2 + SRAM3 (128 + 128 + 32 kB)
  • 在 D3 域中,它具有 SRAM4 + 备份 SRAM (64 + 4 kB)

  • 我想使用SRAM1。在引用手册( RM0433 Rev. 7)中,第 366 页指出:

    If the CPU wants to use memories located into D2 domain (SRAM1, SRAM2 and SRAM3), it has to enable them.


    在第 452 页的寄存器设置中描述了如何执行此操作:

    RCC AHB2 Clock Register (RCC_AHB2ENR):

    SRAM1EN: SRAM1 block enable
    Set and reset by software.When set, this bit indicates that the SRAM1 is allocated by the CPU. It causes the D2 domain totake into account also the CPU operation modes, i.e. keeping D2 domain in DRun when the CPU isin CRun.
    0: SRAM1 interface clock is disabled. (default after reset)
    1: SRAM1 interface clock is enabled.


    因此,默认值(复位后)为 0,表示 SRAM1 接口(interface)被禁用。
    this thread在 STM 社区论坛上,问题是为什么 D2 RAM 不能正常工作,解决方案是启用 D2 RAM 时钟。执行此操作的“正确”方法是 SystemInit() (STM32H7 HAL 的一部分)。在 system_stm32h7xx.c 我们可以找到以下代码部分:
    /************************* Miscellaneous Configuration ************************/
    /*!< Uncomment the following line if you need to use initialized data in D2 domain SRAM (AHB SRAM)
    */
    // #define DATA_IN_D2_SRAM

    (...)

    void SystemInit(void)
    {
    (...)
    #if defined(DATA_IN_D2_SRAM)
    /* in case of initialized data in D2 SRAM (AHB SRAM) , enable the D2 SRAM clock (AHB SRAM clock)
    */
    # if defined(RCC_AHB2ENR_D2SRAM3EN)
    RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
    # elif defined(RCC_AHB2ENR_D2SRAM2EN)
    RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN);
    # else
    RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN);
    # endif /* RCC_AHB2ENR_D2SRAM3EN */

    tmpreg = RCC->AHB2ENR;
    (void)tmpreg;
    #endif /* DATA_IN_D2_SRAM */
    (...)
    }
    所以,要使用 D2 SRAM,宏 DATA_IN_D2_SRAM应该定义(或者您必须使用 __HAL_RCC_D2SRAM1_CLK_ENABLE() 手动启用时钟)。
    但是,我没有定义这个宏,即使我手动禁用时钟,RAM 似乎工作得很好。
    我的主要任务(我正在运行 FreeRTOS,这是目前唯一的任务)是这样的:
    void main_task(void * argument)
    {
    __HAL_RCC_D2SRAM1_CLK_DISABLE();
    __HAL_RCC_D2SRAM2_CLK_DISABLE();
    __HAL_RCC_D2SRAM3_CLK_DISABLE();
    mem_test(); // expected to fail, but runs successfully
    for (;;) {}
    }
    内存测试用已知数据完全填充 D2 SRAM,然后计算一个 CRC。 CRC 是正确的。我已经验证过缓冲区确实放置在 D2 SRAM 中(内存地址 0x30000400 在 SRAM1 的 0x30000000-0x3001FFFF 范围内)。 RCC->AHB2ENR 的值确认为 0(禁用所有时钟)。我也确认了 RCC->AHB2ENR的地址如数据表中所述,为 0x580244DC。
    数据缓存被禁用。
    我在这里想念什么?为什么时钟被禁用时这个内存是可读写的?

    更新:根据要求,这是我的内存测试的代码,从中我得出的结论是内存可以成功写入和读取:
    // NB: The sections are defined in the linker script.
    static char test_data_d1[16] __attribute__((section(".RAM_D1_data"))) = "Test data in D1";
    static char test_data_d2[16] __attribute__((section(".RAM_D2_data"))) = "Test data in D2";
    static char test_data_d3[16] __attribute__((section(".RAM_D3_data"))) = "Test data in D3";

    static char buffer_d1[256 * 1024ul] __attribute__((section(".RAM_D1_bss")));
    static char buffer_d2[256 * 1024ul] __attribute__((section(".RAM_D2_bss")));
    static char buffer_d3[ 32 * 1024ul] __attribute__((section(".RAM_D3_bss")));

    static void mem_test(void)
    {
    // Fill the buffers each with a different test pattern.
    fill_buffer_with_test_data(buffer_d1, sizeof(buffer_d1), test_data_d1);
    fill_buffer_with_test_data(buffer_d2, sizeof(buffer_d2), test_data_d2);
    fill_buffer_with_test_data(buffer_d3, sizeof(buffer_d3), test_data_d3);

    uint32_t crc_d1 = crc32b((uint8_t const *)buffer_d1, sizeof(buffer_d1));
    uint32_t crc_d2 = crc32b((uint8_t const *)buffer_d2, sizeof(buffer_d2));
    uint32_t crc_d3 = crc32b((uint8_t const *)buffer_d3, sizeof(buffer_d3));

    printf("CRC buffer_d1 = 0x%08lX\n", crc_d1);
    printf("CRC buffer_d2 = 0x%08lX\n", crc_d2);
    printf("CRC buffer_d3 = 0x%08lX\n", crc_d3);

    assert(0xC29DFAED == crc_d1); // Python: hex(binascii.crc32(16384 * b'Test data in D1\0'))
    assert(0x73B70C2A == crc_d2); // Python: hex(binascii.crc32(16384 * b'Test data in D2\0'))
    assert(0xC30AE71E == crc_d3); // Python: hex(binascii.crc32(2048 * b'Test data in D3\0'))
    }

    最佳答案

    经过大量测试和调查后,我发现 D2 SRAM 在使用 SysTick 的最小应用程序中被禁用(如记录和预期的那样),并且只有几个 LED 使测试结果可见。然而,当使用定时器 (TIM1) 而不是 SysTick 时,或者启用 USART 时,D2 SRAM 也被启用,即使我没有在我的代码中启用它。事实上,添加以下任一代码行都会隐式启用 D2 SRAM:

    __HAL_RCC_TIM1_CLK_ENABLE();
    __HAL_RCC_USART3_CLK_ENABLE();
    STM 支持已确认此行为:

    D2 SRAM is activated as soon as any peripheral in D2 is activated. It means that If you enable clock for any peripheral located in D2 domain (AHB1, AHB2, APB1 and APB2), D2 SRAM is active even if RCC->AHB2ENR is 0.


    我仍在寻找记录此行为的可靠来源(引用手册),但这似乎是一个合理的解释。
    实际上,我认为这意味着 D2 SRAM 几乎总是会自动启用,因此您不必关心它,至少对于最常见的用例(例如,使用任何外围设备或 DMA Controller 时)。只有当您想使用 D2 SRAM 但不使用任何 D2 外设时,您才必须手动启用 SRAM 时钟。启动代码也是如此,其中(如果您选择实现此功能)将在启用任何外设之前初始化 D2 SRAM。

    关于stm32 - 为什么即使禁用时钟,D2 RAM 也能正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64908765/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com