Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stm32: add STM32H7 series octospi storage support #12517

Open
nspsck opened this issue Sep 25, 2023 · 8 comments · May be fixed by #12523
Open

stm32: add STM32H7 series octospi storage support #12517

nspsck opened this issue Sep 25, 2023 · 8 comments · May be fixed by #12523

Comments

@nspsck
Copy link

nspsck commented Sep 25, 2023

This is a suggested solution to add octospi sotrage support to STM32H7 Series MCUs. Affecting STM32H723 and STM32H7B3 MCU.
The changes has been made to these lines of the octospi.c file located at ports/stm32/octospi.c.

STATIC_AF_OCTOSPI1_XXX has been changed to STATIC_AF_OCTOSPIM_P1_XXX, OCTOSPI_CR_MSEL_Pos has been changed to OCTOSPI_CR_FSEL_Pos and OCTOSPI_CR_DMM_Pos has been changed to OCTOSPI_CR_DQM_Pos for STM32H7 series, that is, if STM32H7 has been defined. These changes shall have no effects on other H7 MCUs since the others doesn't have Octo-SPI interfaces.

The changed section is as below:

    // Configure OCTOSPI pins (allows 1, 2, 4 or 8 line configuration).
    #if defined(STM32H7)
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_CS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_NCS);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_SCK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_CLK);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_IO0);
    #if defined(MICROPY_HW_OSPIFLASH_IO1)
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_IO1);
    #if defined(MICROPY_HW_OSPIFLASH_IO2)
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_IO2);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_IO3);
    #if defined(MICROPY_HW_OSPIFLASH_IO4)
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO4, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_IO4);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO5, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_IO5);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO6, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_IO6);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO7, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPIM_P1_IO7);
    #endif
    #endif
    #endif
    #else
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_CS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_NCS);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_SCK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_CLK);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO0);
    #if defined(MICROPY_HW_OSPIFLASH_IO1)
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO1);
    #if defined(MICROPY_HW_OSPIFLASH_IO2)
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO2);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO3);
    #if defined(MICROPY_HW_OSPIFLASH_IO4)
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO4, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO4);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO5, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO5);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO6, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO6);
    mp_hal_pin_config_alt_static_speed(MICROPY_HW_OSPIFLASH_IO7, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_OCTOSPI1_IO7);
    #endif
    #endif
    #endif
    #endif

    // Reset and turn on the OCTOSPI peripheral.
    __HAL_RCC_OSPI1_CLK_ENABLE();
    __HAL_RCC_OSPI1_FORCE_RESET();
    __HAL_RCC_OSPI1_RELEASE_RESET();

    // Configure the OCTOSPI peripheral.
    #if defined(STM32H7)
    OCTOSPI1->CR =
        3 << OCTOSPI_CR_FTHRES_Pos // 4 bytes must be available to read/write
            | 0 << OCTOSPI_CR_FSEL_Pos // FLASH 0 selected
            | 0 << OCTOSPI_CR_DQM_Pos // dual-memory mode disabled
    ;
    #else
    OCTOSPI1->CR =
        3 << OCTOSPI_CR_FTHRES_Pos // 4 bytes must be available to read/write
            | 0 << OCTOSPI_CR_MSEL_Pos // FLASH 0 selected
            | 0 << OCTOSPI_CR_DMM_Pos // dual-memory mode disabled
    ;
    #endif

Also if this solution is accepted, you might want to change something here located in ports/stm32/boards/STM32H7B3I_DK/mpconfigboard.h as well. A suggested change/fix for that section is provided according to the manual. After fixing the incorrect pins, the firmware could be built, but I do not own one of this board, so I couldn't test it.

#if 1
// 512MBit external OSPI flash, used for either the filesystem or XIP memory mapped
#define MICROPY_HW_OSPIFLASH_SIZE_BITS_LOG2 (29)
#define MICROPY_HW_OSPIFLASH_CS     (pin_G6)
#define MICROPY_HW_OSPIFLASH_SCK    (pin_B2)
#define MICROPY_HW_OSPIFLASH_DQS    (pin_C5)
#define MICROPY_HW_OSPIFLASH_IO0    (pin_D11) // changed from pin_P8
#define MICROPY_HW_OSPIFLASH_IO1    (pin_F9)
#define MICROPY_HW_OSPIFLASH_IO2    (pin_F7)
#define MICROPY_HW_OSPIFLASH_IO3    (pin_F6)
#define MICROPY_HW_OSPIFLASH_IO4    (pin_C1)
#define MICROPY_HW_OSPIFLASH_IO5    (pin_H3)
#define MICROPY_HW_OSPIFLASH_IO6    (pin_G9) // changed from pin_D6
#define MICROPY_HW_OSPIFLASH_IO7    (pin_D7) // changed from pin_G14
#endif

IMPORTANT NOTICE: These modifications has only been tested on a WeActStudio.MiniSTM32H723 board with only 4-pins used from the Octo-SPI1. The result has been validated through the following code:

# Code:
import gc
import os

#free disk
def df():
  s = os.statvfs('.')
  return ('{0} MB'.format((s[0]*s[3])/1048576))

#free ram
def free():
  F = gc.mem_free() / 1024
  A = gc.mem_alloc() / 1024
  T = F+A
  P = '{0:.2f}%'.format(F/T*100)
  return ('Total:%dKB Free:%dKB (%s)' % (T, F, P))
  
print(df())
print(free())

# Output:
7.96484375 MB
Total:69KB Free:67KB (96.96%)

# Input:
Ctrl + D

# Output:
MPY: sync filesystems
MPY: soft reboot
MicroPython v1.20.0-489-ga3862e726-dirty on 2023-09-25; WeAct Studio MiniSTM32H7xx with STM32H723VGT6
Type "help()" for more information.
@jimmo
Copy link
Member

jimmo commented Sep 26, 2023

Thanks @nspsck would you be willing to put this into a pull request please?

@nspsck
Copy link
Author

nspsck commented Sep 26, 2023

@jimmo I'd love to! I tried to create a pull request but it failed the Check commit message formatting / build (pull_request) check.

@nspsck
Copy link
Author

nspsck commented Sep 26, 2023

My appologies to not following the Git commit conventions, after carefully read Sending pull requests through, I am still not sure how to properly send a pull request, please help me! Thank you very much in advance!

@jimmo
Copy link
Member

jimmo commented Sep 26, 2023

My appologies to not following the Git commit conventions, after carefully read Sending pull requests through, I am still not sure how to properly send a pull request, please help me! Thank you very much in advance!

Your commit messages need to be reformatted and signed-off. See https://github.com/jimmo/git-and-micropython#i-forgot-to-sign-off-a-commit (which is about fixing the sign-off, but will also help you adjust the commit messages)

Note that the sign off requires a valid email address.

@nspsck
Copy link
Author

nspsck commented Sep 26, 2023

Hi, after a extensive trial period, I've reached at the poin Creating a new PR, which then I realise, that I've used github website to modify the code and create the PR, there are also no branches beside origine/master. Is it better to close the pull request and start new according to the guide at this point?

@nspsck nspsck linked a pull request Sep 26, 2023 that will close this issue
@nspsck
Copy link
Author

nspsck commented Sep 26, 2023

So, I've started it all over again and this should work now!

@jimmo
Copy link
Member

jimmo commented Sep 27, 2023

@nspsck You didn't need to close and re-open the PR as you can just keep working on the same branch in your local checkout, but that's fine. Thanks for making the PR.

@nspsck
Copy link
Author

nspsck commented Sep 27, 2023

Hi, may I also suggest to add a flag called MICROPY_HW_RCC_OSPI_CLKSOURCE corresponding to MICROPY_HW_RCC_QSPI_CLKSOURCE? This allows the user to choose a clock source for the OSPI flash. This involves adding the following codes to roughly line 463 in the ports/stm32/system_stm32.c.

    #if defined(MICROPY_HW_RCC_OSPI_CLKSOURCE)
    PeriphClkInitStruct.PeriphClockSelection |= RCC_PERIPHCLK_OSPI;
    PeriphClkInitStruct.OspiClockSelection = MICROPY_HW_RCC_OSPI_CLKSOURCE;
    #endif

I have tested this on my port for the STM32H723. The OSPI clock related settings are as below:

//PLL1 550MHz system clock.
#define MICROPY_HW_CLK_PLLM             (5)
#define MICROPY_HW_CLK_PLLN             (110)
#define MICROPY_HW_CLK_PLLP             (1)
// This gives 25 / 5 * 110 / 4 =137.5 MHz on PLL1Q.
#define MICROPY_HW_CLK_PLLQ             (4) 
#define MICROPY_HW_CLK_PLLR             (2)
#define MICROPY_HW_CLK_PLLVCI           (RCC_PLL1VCIRANGE_2)
#define MICROPY_HW_CLK_PLLVCO           (RCC_PLL1VCOWIDE)
#define MICROPY_HW_CLK_PLLFRAC          (0)

// PLL2 200MHz for FMC and OSPI. HSE is 25 MHz.
#define MICROPY_HW_CLK_PLL2M            (5)
#define MICROPY_HW_CLK_PLL2N            (80)
#define MICROPY_HW_CLK_PLL2P            (2)
#define MICROPY_HW_CLK_PLL2Q            (2)
// OSPI1 can get clock from PLL1Q or PLL2R, this gives 25 / 5 * 80 / 2 = 200 MHz on PLL2R。
#define MICROPY_HW_CLK_PLL2R            (2) 
#define MICROPY_HW_CLK_PLL2VCI          (RCC_PLL2VCIRANGE_2)
#define MICROPY_HW_CLK_PLL2VCO          (RCC_PLL2VCOWIDE)
#define MICROPY_HW_CLK_PLL2FRAC         (0)

// Source the clock from PLL2R。
#define MICROPY_HW_RCC_OSPI_CLKSOURCE   (RCC_OSPICLKSOURCE_PLL2)

// Divide PLL2R by 2. Hence 100 Mhz for the W25Q64 Flash. This worked flawlessly.
#define MICROPY_HW_OSPI_PRESCALER           (2) 

According to the datasheet of the W25Q64 , it can run up to 104 MHz. So I have changed the PLL2N to 96, this gives roughly 120MHz clock for OSPI flash. And the OSPI flash stopped working. Hence I assume this modification actually allows the user to control clock source for the OSPI flash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants