From 0081b5ed064b6ac0ae6c983446fe7b7ba35a0a10 Mon Sep 17 00:00:00 2001 From: snkymkrct Date: Tue, 25 Feb 2025 22:02:58 +0100 Subject: [PATCH 1/9] fix stack address for dtcm --- ports/stm32h7/boards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32h7/boards.c b/ports/stm32h7/boards.c index 11c12f262..90b7ef588 100644 --- a/ports/stm32h7/boards.c +++ b/ports/stm32h7/boards.c @@ -112,8 +112,8 @@ bool board_app_valid(void) switch ((app_vector[0] & 0xFFFF0003u)) { case 0x00000000u: // ITCM 64K [0x0000_0000u--0x0000_FFFFu] - case 0x20000000u: // DTCM 64K [0x2000_0000u--0x2000_FFFFu] - case 0x20010000u: // DTCM 64K [0x2001_0000u--0x2001_FFFFu] + case 0x20010000u: // DTCM 64K [0x2000_0000u--0x2000_FFFFu] + case 0x20020000u: // DTCM 64K [0x2001_0000u--0x2001_FFFFu] case 0x24000000u: // AXI SRAM 512K [0x2400_0000u--0x2407_FFFFu] case 0x30010000u: // SRAM1 64K [0x3001_0000u--0x3001_FFFFu] case 0x30020000u: // SRAM2 64K [0x3002_0000u--0x3002_FFFFu] From 977e99e8a52604811526bd8b76b72b8ced9eb361 Mon Sep 17 00:00:00 2001 From: snkymkrct Date: Sun, 2 Mar 2025 23:14:23 +0100 Subject: [PATCH 2/9] Add support for the Daisy Seed board - stm32H750 mcu --- ports/stm32h7/board_flash.c | 106 +++- ports/stm32h7/board_hmi.c | 15 +- ports/stm32h7/boards.c | 85 ++- ports/stm32h7/boards/daisy_seed/board.h | 240 ++++++++ ports/stm32h7/boards/daisy_seed/board.mk | 18 + .../components/is25lp064a/is25lp064a.h | 131 ++++ .../components/is25lp064a/is25lp064a_qspi.c | 567 ++++++++++++++++++ .../components/is25lp064a/is25lp064a_qspi.h | 30 + ports/stm32h7/components/w25qxx/w25qxx_qspi.c | 158 ++--- ports/stm32h7/components/w25qxx/w25qxx_qspi.h | 31 +- ports/stm32h7/port.mk | 16 +- ports/stm32h7/qspi_status.h | 26 + 12 files changed, 1278 insertions(+), 145 deletions(-) create mode 100644 ports/stm32h7/boards/daisy_seed/board.h create mode 100644 ports/stm32h7/boards/daisy_seed/board.mk create mode 100644 ports/stm32h7/components/is25lp064a/is25lp064a.h create mode 100644 ports/stm32h7/components/is25lp064a/is25lp064a_qspi.c create mode 100644 ports/stm32h7/components/is25lp064a/is25lp064a_qspi.h create mode 100644 ports/stm32h7/qspi_status.h diff --git a/ports/stm32h7/board_flash.c b/ports/stm32h7/board_flash.c index 6221d50a0..92e6a2a4d 100644 --- a/ports/stm32h7/board_flash.c +++ b/ports/stm32h7/board_flash.c @@ -1,5 +1,6 @@ #include "board_api.h" #include "stm32h7xx_hal.h" +#include "qspi_status.h" #ifdef W25Qx_SPI #include "components/w25qxx/w25qxx.h" @@ -9,11 +10,15 @@ #include "components/w25qxx/w25qxx_qspi.h" #endif // W25Qx_QSPI -#if BOARD_QSPI_FLASH_EN +#ifdef IS25LP064A +#include "components/is25lp064a/is25lp064a_qspi.h" +#endif + +#if defined (BOARD_QSPI_FLASH_EN) && (BOARD_QSPI_FLASH_EN == 1) QSPI_HandleTypeDef _qspi_flash; #endif // BOARD_QSPI_FLASH_EN -#if BOARD_SPI_FLASH_EN +#if defined (BOARD_SPI_FLASH_EN) && (BOARD_SPI_FLASH_EN == 1) SPI_HandleTypeDef _spi_flash; #endif // BOARD_SPI_FLASH_EN @@ -53,6 +58,67 @@ extern volatile uint32_t _board_tmp_boot_magic[]; #define TMP_BOOT_ADDR _board_tmp_boot_addr[0] #define TMP_BOOT_MAGIC _board_tmp_boot_magic[0] +static void qspi_Init(void) { + #ifdef W25Qx_QSPI + w25qxx_Init(); + #endif + #ifdef IS25LP064A + CSP_QSPI_DisableMemoryMappedMode(); + CSP_QSPI_ExitQPIMODE(); + if (CSP_QUADSPI_Init() != qspi_OK) { + TUF2_LOG1("Error initializing QSPI Flash\r\n"); + } + #endif + +} + +static void qspi_EnterQPI(void) { + #ifdef W25Qx_QSPI + w25qxx_EnterQPI(); + #endif +} + +static void qspi_Startup(void) { + #ifdef W25Qx_QSPI + w25qxx_Startup(qspi_DTRMode); + #endif + #ifdef IS25LP064A + if (CSP_QSPI_EnableMemoryMappedMode() != qspi_OK) { + TUF2_LOG1("Error enabing memory map for QSPI Flash\r\n"); + } + #endif +} + +static uint8_t qspi_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size) { + #ifdef W25Qx_QSPI + return w25qxx_Read(pData,ReadAddr,Size); + #endif + #ifdef IS25LP064A + return CSP_QSPI_Read(pData, ReadAddr, Size); + #endif + return qspi_OK; +} + +static uint8_t qspi_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) { + #ifdef W25Qx_QSPI + return w25qxx_Write(pData,WriteAddr,Size); + #endif + #ifdef IS25LP064A + return CSP_QSPI_Write(pData,WriteAddr,Size); + #endif + return qspi_OK; +} + + +static void qspi_EraseChip(void) { + #ifdef W25Qx_QSPI + w25qxx_EraseChip(); + #endif + #ifdef IS25LP064A + CSP_QSPI_Erase_Chip(); + #endif +} + uint32_t board_get_app_start_address(void) { if (TMP_BOOT_MAGIC == 0xDEADBEEFU) @@ -79,19 +145,19 @@ void board_clear_temp_boot_addr(void) void board_flash_early_init(void) { -#if BOARD_QSPI_FLASH_EN +#if defined (BOARD_QSPI_FLASH_EN) && (BOARD_QSPI_FLASH_EN == 1) // QSPI is initialized early to check for executable code qspi_flash_init(&_qspi_flash); // Initialize QSPI driver - w25qxx_Init(); + qspi_Init(); // SPI -> QPI - w25qxx_EnterQPI(); + qspi_EnterQPI(); #endif // BOARD_QSPI_FLASH_EN } void board_flash_init(void) { -#if BOARD_SPI_FLASH_EN +#if defined (BOARD_SPI_FLASH_EN) && (BOARD_SPI_FLASH_EN == 1) // Initialize SPI peripheral spi_flash_init(&_spi_flash); // Initialize SPI drivers @@ -101,10 +167,10 @@ void board_flash_init(void) void board_flash_deinit(void) { -#if BOARD_QSPI_FLASH_EN +#if defined (BOARD_QSPI_FLASH_EN) && (BOARD_QSPI_FLASH_EN == 1) // Enable Memory Mapped Mode // QSPI flash will be available at 0x90000000U (readonly) - w25qxx_Startup(w25qxx_DTRMode); + qspi_Startup(); #endif // BOARD_QSPI_FLASH_EN } @@ -123,16 +189,16 @@ void board_flash_flush(void) void board_flash_read(uint32_t addr, void * data, uint32_t len) { TUF2_LOG1("Reading %lu byte(s) from 0x%08lx\r\n", len, addr); -#if BOARD_QSPI_FLASH_EN +#if defined (BOARD_QSPI_FLASH_EN) && (BOARD_QSPI_FLASH_EN == 1) // addr += QSPI_BASE_ADDR; if (IS_QSPI_ADDR(addr)) { - (void) W25qxx_Read(data, addr - QSPI_BASE_ADDR, len); + (void) qspi_Read(data, addr - QSPI_BASE_ADDR, len); return; } #endif -#if BOARD_AXISRAM_EN +#if defined (BOARD_AXISRAM_EN) && (BOARD_AXISRAM_EN == 1) if (IS_AXISRAM_ADDR(addr) && IS_AXISRAM_ADDR(addr + len - 1)) { memcpy(data, (void *) addr, len); @@ -156,11 +222,11 @@ bool board_flash_write(uint32_t addr, void const * data, uint32_t len) { TUF2_LOG1("Programming %lu byte(s) at 0x%08lx\r\n", len, addr); - // For external flash, W25Qx + // For external flash // TODO: these should be configurable parameters // Page size = 256 bytes // Sector size = 4K bytes -#if (BOARD_SPI_FLASH_EN == 1U) +#if defined (BOARD_SPI_FLASH_EN) && (BOARD_SPI_FLASH_EN == 1U) if (IS_SPI_ADDR(addr) && IS_SPI_ADDR(addr + len - 1)) { W25Qx_Write((uint8_t *) data, (addr - SPI_BASE_ADDR), len); @@ -168,12 +234,12 @@ bool board_flash_write(uint32_t addr, void const * data, uint32_t len) } #endif -#if (BOARD_QSPI_FLASH_EN == 1) +#if defined (BOARD_QSPI_FLASH_EN) && (BOARD_QSPI_FLASH_EN == 1) if (IS_QSPI_ADDR(addr) && IS_QSPI_ADDR(addr + len - 1)) { // SET_BOOT_ADDR(BOARD_AXISRAM_APP_ADDR); // handles erasing internally - if (W25qxx_Write((uint8_t *)data, (addr - QSPI_BASE_ADDR), len) != w25qxx_OK) + if (qspi_Write((uint8_t *)data, (addr - QSPI_BASE_ADDR), len) != qspi_OK) { __asm("bkpt #9"); } @@ -181,7 +247,7 @@ bool board_flash_write(uint32_t addr, void const * data, uint32_t len) } #endif -#if BOARD_AXISRAM_EN +#if defined (BOARD_AXISRAM_EN) && (BOARD_AXISRAM_EN == 1) if (IS_AXISRAM_ADDR(addr) && IS_AXISRAM_ADDR(addr + len - 1)) { // This memory is cached, DCache is cleaned in dfu_complete @@ -211,13 +277,13 @@ void board_flash_erase_app(void) { board_flash_init(); -#if BOARD_QSPI_FLASH_EN +#if defined (BOARD_QSPI_FLASH_EN) && (BOARD_QSPI_FLASH_EN == 1) TUF2_LOG1("Erasing QSPI Flash\r\n"); // Erase QSPI Flash - (void) W25qxx_EraseChip(); + (void) qspi_EraseChip(); #endif -#if BOARD_SPI_FLASH_EN +#if defined(BOARD_SPI_FLASH_EN) && (BOARD_SPI_FLASH_EN == 1) TUF2_LOG1("Erasing SPI Flash\r\n"); // Erase QSPI Flash (void) W25Qx_Erase_Chip(); @@ -225,4 +291,4 @@ void board_flash_erase_app(void) // TODO: Implement PFLASH erase for non-tinyuf2 sectors board_reset(); -} +} \ No newline at end of file diff --git a/ports/stm32h7/board_hmi.c b/ports/stm32h7/board_hmi.c index 11881803a..77323f196 100644 --- a/ports/stm32h7/board_hmi.c +++ b/ports/stm32h7/board_hmi.c @@ -19,49 +19,44 @@ void ST7735_Delay(uint32_t ms) { HAL_Delay(ms); } -#endif void board_display_init(void) { -#if (TINYUF2_DISPLAY == 1U) display_init(&_display_spi); ST7735_Init(); // Clear previous screen ST7735_FillScreen(ST7735_BLACK); -#endif // TINYUF2_DISPLAY == 1U } // The application draws a complete frame in memory and sends it // line-by-line to the display void board_display_draw_line(int y, uint16_t* pixel_color, uint32_t pixel_num) { -#if (TINYUF2_DISPLAY == 1U) for (uint32_t x = 0; x < pixel_num; x += 1) { ST7735_DrawPixel(y, x, pixel_color[x]); } -#endif // TINYUF2_DISPLAY == 1U } - +#endif // TINYUF2_DISPLAY == 1U //--------------------------------------------------------------------+ // LED pattern //--------------------------------------------------------------------+ +#if defined(TINYUF2_LED) void board_led_write(uint32_t state) { -#if defined(TINYUF2_LED) HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? GPIO_PIN_SET : GPIO_PIN_RESET); -#endif // defined(LED_PIN) } +#endif // defined(LED_PIN) //--------------------------------------------------------------------+ // Button //--------------------------------------------------------------------+ +#if defined(BUTTON_PIN) uint32_t board_button_read(void) { -#if defined(BUTTON_PIN) return (BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN)) ? 1: 0; -#endif // defined(BUTTON_PIN) } +#endif // defined(BUTTON_PIN) //--------------------------------------------------------------------+ // Neopixel color for status diff --git a/ports/stm32h7/boards.c b/ports/stm32h7/boards.c index 90b7ef588..fa1d149e3 100644 --- a/ports/stm32h7/boards.c +++ b/ports/stm32h7/boards.c @@ -1,8 +1,27 @@ #include "stm32h7xx_hal.h" #include "board_api.h" +#include #define STM32_UUID ((uint32_t *)0x1FF1E800) +#ifdef UART_DEV +static UART_HandleTypeDef UartHandle; +#endif + +// fixes for linker warnings: _syscall is not implemented and will always fail +void __weak _close(void) { +} +void __weak _lseek(void) { +} +void __weak _read(void) { +} +void __weak _write(void) { +} +void __weak _fstat(void) { +} +void __weak _isatty(void) { +} + void board_init(void) { SCB_EnableICache(); @@ -26,9 +45,31 @@ void board_init(void) __HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOJ_CLK_ENABLE(); __HAL_RCC_GPIOK_CLK_ENABLE(); - - GPIO_InitTypeDef GPIO_InitStruct; - + GPIO_InitTypeDef GPIO_InitStruct = {0}; + // UART + #ifdef UART_DEV + UART_CLOCK_ENABLE(); + GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = UART_GPIO_AF; + HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct); + + UartHandle.Instance = UART_DEV; + UartHandle.Init.BaudRate = 115200; + UartHandle.Init.WordLength = UART_WORDLENGTH_8B; + UartHandle.Init.StopBits = UART_STOPBITS_1; + UartHandle.Init.Parity = UART_PARITY_NONE; + UartHandle.Init.Mode = UART_MODE_TX_RX; + UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; + UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; + UartHandle.Init.ClockPrescaler = UART_PRESCALER_DIV1; + UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + HAL_UART_Init(&UartHandle); + #endif + memset(&GPIO_InitStruct,0,sizeof(GPIO_InitStruct)); #ifdef BUTTON_PIN GPIO_InitStruct.Pin = BUTTON_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; @@ -53,8 +94,8 @@ void board_init(void) void board_dfu_init(void) { // Not quite sure what an RHPORT is :/ -#if BOARD_TUD_RHPORT == 0 - GPIO_InitTypeDef GPIO_InitStruct; +#if defined (BOARD_TUD_RHPORT) && (BOARD_TUD_RHPORT == 0) + GPIO_InitTypeDef GPIO_InitStruct = {0}; // Init USB Pins // Configure DM DP pins @@ -81,7 +122,7 @@ void board_dfu_init(void) USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; -#elif BOARD_TUD_RHPORT == 1 +#elif defined (BOARD_TUD_RHPORT) && (BOARD_TUD_RHPORT == 1) // TODO: implement whatever this is #error "Sorry, not implemented yet" #endif @@ -170,16 +211,32 @@ void board_app_jump(void) __HAL_RCC_GPIOJ_CLK_DISABLE(); __HAL_RCC_GPIOK_CLK_DISABLE(); // Lotsa GPIOs +uint8_t allow_rcc_deinit = 1; + +// rcc clock needs to be enabled when executing code from external flash +#if defined(BOARD_QSPI_FLASH_EN) && (BOARD_QSPI_FLASH_EN == 1) + allow_rcc_deinit = 0; +#endif + +#if defined(BOARD_SPI_FLASH_EN) && (BOARD_SPI_FLASH_EN == 1) + allow_rcc_deinit = 0; +#endif + + if (allow_rcc_deinit) { + HAL_RCC_DeInit(); + } - HAL_RCC_DeInit(); SCB_DisableICache(); SCB_DisableDCache(); // Clear temporary boot address board_clear_temp_boot_addr(); - // Setup VTOR to point to application vectors - SCB->VTOR = (uint32_t) app_addr; +#ifdef UART_DEV + HAL_UART_DeInit(&UartHandle); + HAL_GPIO_DeInit(UART_GPIO_PORT, UART_TX_PIN | UART_RX_PIN); + UART_CLOCK_DISABLE(); +#endif // Set stack pointer __set_MSP(app_vector[0]); @@ -187,6 +244,11 @@ void board_app_jump(void) TUF2_LOG1("App address: %08lx\r\n", app_vector[1]); + // Setup VTOR to point to application vectors + __DMB(); //ARM says to use a DMB instruction before relocating VTOR */ + SCB->VTOR = (uint32_t) app_addr; + __DSB(); //ARM says to use a DSB instruction just after relocating VTOR */ + // Jump to application reset vector asm("bx %0" :: "r"(app_vector[1])); @@ -217,9 +279,14 @@ void board_timer_stop(void) int board_uart_write(void const * buf, int len) { +#ifdef UART_DEV + HAL_UART_Transmit(&UartHandle, (uint8_t*) buf, len, 0xFFFFFFFFU); + return len; +#else (void) buf; (void) len; return 0; +#endif } #ifdef TINYUF2_SELF_UPDATE diff --git a/ports/stm32h7/boards/daisy_seed/board.h b/ports/stm32h7/boards/daisy_seed/board.h new file mode 100644 index 000000000..c2a8b8fbc --- /dev/null +++ b/ports/stm32h7/boards/daisy_seed/board.h @@ -0,0 +1,240 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 @snkYmkrct + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// LED +//--------------------------------------------------------------------+ + +#define LED_PORT GPIOC +#define LED_PIN GPIO_PIN_7 +#define LED_STATE_ON 1 + +//--------------------------------------------------------------------+ +// BUTTON +//--------------------------------------------------------------------+ + +#define BUTTON_PORT GPIOG +#define BUTTON_PIN GPIO_PIN_3 +#define BUTTON_STATE_ACTIVE 0 + +//--------------------------------------------------------------------+ +// Flash +//--------------------------------------------------------------------+ + +// Flash size of the board +#define BOARD_FLASH_SIZE (128 * 1024) +#define BOARD_FLASH_SECTORS 1 + +//--------------------------------------------------------------------+ +// External QSPI Flash +//--------------------------------------------------------------------+ +#define BOARD_QSPI_FLASH_SIZE (8 * 1024 * 1024) // 8MB + +//--------------------------------------------------------------------+ +// USB UF2 +//--------------------------------------------------------------------+ + +#define USB_VID 0x239A +#define USB_PID 0x005D +#define USB_MANUFACTURER "STM32" +#define USB_PRODUCT "STM32FH750IB" + +#define UF2_PRODUCT_NAME USB_MANUFACTURER " " USB_PRODUCT +#define UF2_BOARD_ID "DaisySeed" +#define UF2_VOLUME_LABEL "DaisySeed" +#define UF2_INDEX_URL "https://electro-smith.com/products/daisy-seed" + +#define USB_NO_VBUS_PIN 1 +#define BOARD_TUD_RHPORT 0 + +//--------------------------------------------------------------------+ +// UART +//--------------------------------------------------------------------+ + +#define UART_DEV UART4 +#define UART_CLOCK_ENABLE __HAL_RCC_UART4_CLK_ENABLE +#define UART_CLOCK_DISABLE __HAL_RCC_UART4_CLK_DISABLE +#define UART_GPIO_PORT GPIOB +#define UART_GPIO_AF GPIO_AF8_UART4 +#define UART_TX_PIN GPIO_PIN_9 +#define UART_RX_PIN GPIO_PIN_8 + +static void Error_Handler(void) { + __disable_irq(); + while (1) { + } +} + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ +static inline void clock_init(void) { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + + // Set voltage scaling in accordance with system clock speed + HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0); + while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) { + } + + // Configure LSE Drive + HAL_PWR_EnableBkUpAccess(); + __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); + + // Set up primary PLL and HSE clocks + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.OscillatorType |= RCC_OSCILLATORTYPE_LSI; + RCC_OscInitStruct.LSIState = RCC_LSI_ON; + RCC_OscInitStruct.OscillatorType |= RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 1; + RCC_OscInitStruct.PLL.PLLN = 50; + RCC_OscInitStruct.PLL.PLLP = 2; + RCC_OscInitStruct.PLL.PLLQ = 4; + RCC_OscInitStruct.PLL.PLLR = 2; + RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3; + RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; + RCC_OscInitStruct.PLL.PLLFRACN = 0; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + Error_Handler(); + } + + // Configure bus clock sources and divisors + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | + RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | + RCC_CLOCKTYPE_D3PCLK1 | RCC_CLOCKTYPE_D1PCLK1; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; + RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; + RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2); + + // Set up non-bus peripherals + PeriphClkInitStruct.PeriphClockSelection = + RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_USB; + // UART4 + PeriphClkInitStruct.Usart234578ClockSelection = + RCC_USART234578CLKSOURCE_D2PCLK1; + // USB + PeriphClkInitStruct.PLL3.PLL3M = 1; + PeriphClkInitStruct.PLL3.PLL3N = 12; + PeriphClkInitStruct.PLL3.PLL3P = 2; + PeriphClkInitStruct.PLL3.PLL3Q = 4; + PeriphClkInitStruct.PLL3.PLL3R = 2; + PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_3; + PeriphClkInitStruct.PLL3.PLL3FRACN = 0; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3; + + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + Error_Handler(); + } + // Enable USB Voltage detector + HAL_PWREx_EnableUSBVoltageDetector(); +} + +//--------------------------------------------------------------------+ +// QSPI and SPI FLash +//--------------------------------------------------------------------+ + +static inline void qspi_flash_init(QSPI_HandleTypeDef *qspiHandle) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_QSPI; + PeriphClkInitStruct.QspiClockSelection = RCC_QSPICLKSOURCE_PLL; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + Error_Handler(); + } + + /* QUADSPI clock enable */ + __HAL_RCC_QSPI_CLK_ENABLE(); + + __HAL_RCC_GPIOG_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + /**QUADSPI GPIO Configuration + PG6 ------> QUADSPI_BK1_NCS + PF7 ------> QUADSPI_BK1_IO2 + PF6 ------> QUADSPI_BK1_IO3 + PF10 ------> QUADSPI_CLK + PF9 ------> QUADSPI_BK1_IO1 + PF8 ------> QUADSPI_BK1_IO0 + */ + GPIO_InitStruct.Pin = GPIO_PIN_6; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI; + HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI; + HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI; + HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + qspiHandle->Instance = QUADSPI; + qspiHandle->Init.ClockPrescaler = 1; + qspiHandle->Init.FifoThreshold = 1; + qspiHandle->Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; + qspiHandle->Init.FlashSize = 22; + qspiHandle->Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE; + qspiHandle->Init.ClockMode = QSPI_CLOCK_MODE_0; + qspiHandle->Init.FlashID = QSPI_FLASH_ID_1; + qspiHandle->Init.DualFlash = QSPI_DUALFLASH_DISABLE; + if (HAL_QSPI_Init(qspiHandle) != HAL_OK) { + Error_Handler(); + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ports/stm32h7/boards/daisy_seed/board.mk b/ports/stm32h7/boards/daisy_seed/board.mk new file mode 100644 index 000000000..d2eed84c1 --- /dev/null +++ b/ports/stm32h7/boards/daisy_seed/board.mk @@ -0,0 +1,18 @@ +QSPI_FLASH = IS25LP064A + +CFLAGS += \ + -DSTM32H750xx \ + -DHSE_VALUE=16000000U \ + -DTINYUF2_LED=1 \ + -DBOARD_QSPI_FLASH_EN=1 \ + -DBOARD_AXISRAM_EN=1 \ + -D$(QSPI_FLASH)\ + -DBOARD_FLASH_APP_START=0x90000000 \ + -DTRAP_EXC \ + +MCU = h750xx + +LOG = 1 + +SRC_S += \ + $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h750xx.s diff --git a/ports/stm32h7/components/is25lp064a/is25lp064a.h b/ports/stm32h7/components/is25lp064a/is25lp064a.h new file mode 100644 index 000000000..e289df0e3 --- /dev/null +++ b/ports/stm32h7/components/is25lp064a/is25lp064a.h @@ -0,0 +1,131 @@ +/* + * IS25LP064A.h + * + * Adapted from https://github.com/electro-smith/libDaisy/blob/master/src/dev/flash_IS25LP064A.h + * + */ + + #ifndef INC_FLASH_IS25LP064A_H_ + #define INC_FLASH_IS25LP064A_H_ + + #ifdef __cplusplus + extern "C" { + #endif + + #define IS25LP064A_FLASH_SIZE 0x800000 /* 8 MBytes*/ + #define IS25LP064A_BLOCK_SIZE 0x10000 /* 64 KBytes */ + #define IS25LP064A_SECTOR_SIZE 0x1000 /* 4 KBytes */ + #define IS25LP064A_PAGE_SIZE 0x100 /* 256 bytes */ + + #define IS25LP064A_SECTOR_COUNT 2048 + + + #define IS25LP064A_DUMMY_CYCLES_READ_QUAD 6 /* & */ + #define IS25LP064A_DUMMY_CYCLES_READ 6 /* & */ + //#define IS25LP064A_DUMMY_CYCLES_READ_DTR 6 /* & */ + //#define IS25LP064A_DUMMY_CYCLES_READ_QUAD_DTR 6 /* & */ + + + #define IS25LP064A_DIE_ERASE_MAX_TIME 46000 /* 45 max seconds in datasheet */ + #define IS25LP064A_BLOCK_ERASE_MAX_TIME 1100 /* 1000 ms max in datasheet */ + #define IS25LP064A_SECTOR_ERASE_MAX_TIME 350 /* 300 ms max in datasheet */ + + + /* Low Power Modes */ + #define ENTER_DEEP_POWER_DOWN 0XB9 /* & */ + #define EXIT_DEEP_POWER_DOWN 0XAB /* Release from Power-down/Read Device ID instruction */ + + /* Software Reset Operation commands */ + #define RESET_ENABLE_CMD 0x66 + #define RESET_MEMORY_CMD 0x99 /* & */ + + /* Identification Operations */ + #define READ_ID_CMD 0xAB /* Release from Power-down/Read Device ID instruction */ + #define READ_ID_CMD2 0x9F /* JEDEC ID READ command in SPI mode */ + #define MULTIPLE_IO_READ_ID_CMD 0xAF /* JEDEC ID READ command in QPI mode */ + #define READ_SERIAL_FLASH_DISCO_PARAM_CMD 0x5A /* Serial Flash Discoverable Parameters (SFDP) */ + #define READ_MANUFACT_AND_ID 0x90 /* Read Product Identification (RDID) instruction */ + #define READ_UNIQUE_ID 0x4B /* Read Unique ID Number (RDUID) */ + + #define NO_OP 0x00 /* Cancels Reset Enable */ + + /* Sector LOCK/UNLOCK Operations */ + #define SECTOR_UNLOCK 0x26 /**< & */ + #define SECTOR_LOCK 0x24 /**< & */ + + /* Security Information Row */ + #define INFO_ROW_ERASE_CMD 0x64 /* Information Row Erase (IRER) instruction */ + #define INFO_ROW_PROGRAM_CMD 0x62 /* Information Row Program (IRP) instruction */ + #define INFO_ROW_READ_CMD 0x68 /* Information Row Read (IRRD) instruction */ + + /* Read Operations */ + #define READ_CMD 0x03 /* NORMAL READ (NORD) instruction */ + + #define FAST_READ_CMD 0x0B /* FAST READ (FRD) instruction for both 1 line and QPI modes */ + #define FAST_READ_DTR_CMD 0x0D /* FRDTR instruction */ + + #define DUAL_OUT_FAST_READ_CMD 0x3B /* FAST READ DUAL OUTPUT OPERATION (FRDO) */ + + #define DUAL_INOUT_FAST_READ_CMD 0xBB /* FAST READ DUAL I/O OPERATION (FRDIO) */ + #define DUAL_INOUT_FAST_READ_DTR_CMD 0xBD /* FAST READ DUAL IO DTR MODE OPERATION (FRDDTR) */ + + #define QUAD_OUT_FAST_READ_CMD 0x6B /* FAST READ QUAD OUTPUT OPERATION (FRQO) */ + + #define QUAD_INOUT_FAST_READ_CMD 0xEB /* FAST READ QUAD I/O OPERATION (FRQIO) - can be used to enable memory mapped mode */ + #define QUAD_INOUT_FAST_READ_DTR_CMD 0xED /* FAST READ QUAD IO DTR MODE OPERATION (FRQDTR) */ + + /* Write Operations */ + #define WRITE_ENABLE_CMD 0x06 /* WRITE ENABLE OPERATION (WREN) */ + #define WRITE_DISABLE_CMD 0x04 /* WRITE DISABLE OPERATION (WRDI) */ + + /* Register Operations */ + #define READ_STATUS_REG_CMD 0x05 /* READ STATUS REGISTER OPERATION (RDSR) */ + #define WRITE_STATUS_REG_CMD 0x01 /* WRITE STATUS REGISTER OPERATION (WRSR) */ + + #define READ_FUNCTION_REGISTER 0X48 /* READ FUNCTION REGISTER OPERATION (RDFR) */ + #define WRITE_FUNCTION_REGISTER 0x42 /* WRITE FUNCTION REGISTER OPERATION (WRFR) */ + + #define WRITE_READ_PARAM_REG_CMD 0xC0 /* SET READ PARAMETERS OPERATION (SRP) */ + + /* Page Program Operations */ + #define PAGE_PROG_CMD 0x02 /* PAGE PROGRAM OPERATION (PP) */ + + /* QUAD INPUT PAGE PROGRAM OPERATION (PPQ) */ + #define QUAD_IN_PAGE_PROG_CMD 0x32 + #define EXT_QUAD_IN_PAGE_PROG_CMD 0x38 + + /* Erase Operations */ + #define SECTOR_ERASE_CMD 0xd7 /* SECTOR ERASE OPERATION (SER) on SPI */ + #define SECTOR_ERASE_QPI_CMD 0x20 /* SECTOR ERASE OPERATION (SER) QPI */ + + #define BLOCK_ERASE_CMD 0xD8 /* BLOCK ERASE OPERATION (BER64K) */ + #define BLOCK_ERASE_32K_CMD 0x52 /* BLOCK ERASE OPERATION (BER32K) */ + + #define CHIP_ERASE_CMD 0xC7 /* CHIP ERASE OPERATION (CER) on SPI */ + #define EXT_CHIP_ERASE_CMD 0x60 /* CHIP ERASE OPERATION (CER) on QPI*/ + + #define PROG_ERASE_RESUME_CMD 0x7A /* Resume program/erase (PERRSM) on SPI */ + #define EXT_PROG_ERASE_RESUME_CMD 0x30 /* Resume program/erase (PERRSM) on QPI */ + + #define PROG_ERASE_SUSPEND_CMD 0x75 /* Suspend during program/erase (PERSUS) on SPI */ + #define EXT_PROG_ERASE_SUSPEND_CMD 0xB0 /* Suspend during program/erase (PERSUS) on QPI */ + + /** Quad Operations */ + #define ENTER_QUAD_CMD 0x35 /* ENTER QUAD PERIPHERAL INTERFACE (QPI) MODE OPERATION (QIOEN) */ + #define EXIT_QUAD_CMD 0xF5 /* EXIT QUAD PERIPHERAL INTERFACE (QPI) MODE OPERATION (QIODI) */ + + + /* Status Register */ + #define IS25LP064A_SR_WIP ((uint8_t)0x01) /* WIP Write in progress */ + #define IS25LP064A_SR_WREN ((uint8_t)0x02) /* WEL Write enable latch */ + //#define IS25LP064A_SR_BLOCKPR ((uint8_t)0x5C) /*!< Block protected against program and erase operations */ + //#define IS25LP064A_SR_PRBOTTOM ((uint8_t)0x20) /*!< Protected memory area defined by BLOCKPR starts from top or bottom */ + #define IS25LP064A_SR_QE ((uint8_t)0x40) /* QE Quad Enable */ + #define IS25LP064A_SR_SRWREN ((uint8_t)0x80) /* SRWD Status Register Write Disable*/ + + #ifdef __cplusplus + } + #endif + + #endif /* INC_FLASH_IS25LP064A_H_ */ + \ No newline at end of file diff --git a/ports/stm32h7/components/is25lp064a/is25lp064a_qspi.c b/ports/stm32h7/components/is25lp064a/is25lp064a_qspi.c new file mode 100644 index 000000000..4413d74e6 --- /dev/null +++ b/ports/stm32h7/components/is25lp064a/is25lp064a_qspi.c @@ -0,0 +1,567 @@ +#include "is25lp064a_qspi.h" +#include "is25lp064a.h" +#include "qspi_status.h" +#include "stm32h7xx_hal.h" +#include + +#define MEMORY_FLASH_SIZE 0x800000 /* 8 MBytes*/ +#define MEMORY_SECTOR_SIZE 0x1000 /* 4 KBytes */ +#define MEMORY_PAGE_SIZE 0x100 /* 256 bytes */ + +extern QSPI_HandleTypeDef _qspi_flash; + +static uint8_t qspi_enabled = 0; + +static uint8_t QSPI_Wait(QSPI_AutoPollingTypeDef *config, uint32_t timeout) { + + QSPI_CommandTypeDef sCommand = {0}; + + if (qspi_enabled) { + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + sCommand.DataMode = QSPI_DATA_4_LINES; + // Based on Reference manual RM0433 for the STM32H750 Value line, + // dummy cycles needed on all read operations in QUAD mode + sCommand.DummyCycles = IS25LP064A_DUMMY_CYCLES_READ_QUAD; + } else { + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.DataMode = QSPI_DATA_1_LINE; + sCommand.DummyCycles = 0; + } + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + ; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + if (HAL_QSPI_AutoPolling(&_qspi_flash, &sCommand, config, timeout) != + HAL_OK) { + return qspi_ERROR; + } + + return qspi_OK; +} + + +static uint8_t QSPI_ReadStatusRegister(uint8_t *status) { + QSPI_CommandTypeDef sCommand = {0}; + + if (qspi_enabled) { + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + sCommand.DataMode = QSPI_DATA_4_LINES; + // Based on Reference manual RM0433 for the STM32H750 Value line, + // dummy cycles needed on all read operations in QUAD mode + sCommand.DummyCycles = IS25LP064A_DUMMY_CYCLES_READ_QUAD; + + } else { + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.DataMode = QSPI_DATA_1_LINE; + sCommand.DummyCycles = 0; + } + sCommand.Instruction = READ_STATUS_REG_CMD; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.Address = 0; + sCommand.NbData = 1; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + if (HAL_QSPI_Receive(&_qspi_flash, status, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != + HAL_OK) { + return qspi_ERROR; + } + return qspi_OK; +} + +static uint8_t QSPI_ResetChip(void) { + QSPI_CommandTypeDef sCommand = {0}; + QSPI_AutoPollingTypeDef sConfig = {0}; + + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.Instruction = RESET_ENABLE_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.Address = 0; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + sCommand.Instruction = RESET_MEMORY_CMD; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + sConfig.Match = 0; + sConfig.Mask = IS25LP064A_SR_WIP; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + sConfig.Interval = 0x10; + + if (QSPI_Wait(&sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + return qspi_OK; +} + +static uint8_t QSPI_WriteEnable(void) { + QSPI_CommandTypeDef sCommand = {0}; + QSPI_AutoPollingTypeDef sConfig = {0}; + + /* Enable write / erase operations */ + if (qspi_enabled) { + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + } else { + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + } + sCommand.Instruction = WRITE_ENABLE_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + /* Configure automatic polling mode to wait for write enabling */ + sConfig.Match = IS25LP064A_SR_WREN; + sConfig.Mask = IS25LP064A_SR_WREN; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + sConfig.Interval = 0x10; + + if (QSPI_Wait(&sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + return qspi_OK; +} + +/*Enable quad mode and set dummy cycles count*/ +static uint8_t QSPI_Configuration(void) { + + QSPI_CommandTypeDef sCommand = {0}; + QSPI_AutoPollingTypeDef sConfig = {0}; + uint8_t reg = 0; + + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.Instruction = WRITE_READ_PARAM_REG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.DataMode = QSPI_DATA_1_LINE; + sCommand.DummyCycles = 0; + sCommand.NbData = 1; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + /* Minimum necessary dummy cycles for memory mapped mode at 100 MHz = 6 + * Setting in Read Register P4 P3 bits as 0 0, so full reg = 11100000 0xE0 + * see IS25LP064A data sheet section 6.3 READ REGISTER */ + reg = 0xE0; + if (HAL_QSPI_Transmit(&_qspi_flash, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != + HAL_OK) { + return qspi_ERROR; + } + + sConfig.Match = 0; + sConfig.Mask = IS25LP064A_SR_WIP; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + sConfig.Interval = 0x10; + + if (QSPI_Wait(&sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + /*----- Setting the QSPI mode ----*/ + + /* Set the non-volatile Quad Enable bit in status register */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = WRITE_STATUS_REG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_1_LINE; + sCommand.DummyCycles = 0; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.NbData = 1; + + if (QSPI_WriteEnable() != HAL_OK) { + return qspi_ERROR; + } + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + reg = 0; + if (QSPI_ReadStatusRegister(®) != HAL_OK) { + return qspi_ERROR; + } + reg = reg | IS25LP064A_SR_QE; + if (HAL_QSPI_Transmit(&_qspi_flash, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != + HAL_OK) { + return qspi_ERROR; + } + /* Configure automatic polling mode to wait for quad enable complete */ + sConfig.Match = IS25LP064A_SR_QE; + sConfig.Mask = IS25LP064A_SR_QE; + + if (QSPI_Wait(&sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + /* Wait to make sure controller is done with writing */ + sConfig.Match = 0; + sConfig.Mask = IS25LP064A_SR_WIP; + + if (QSPI_Wait(&sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + /* Enter QPI mode */ + sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; + sCommand.Instruction = ENTER_QUAD_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.NbData = 0; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + qspi_enabled = 1; /* qpi mode ON */ + + return qspi_OK; +} + +uint8_t CSP_QSPI_Erase_Chip(void) { + QSPI_CommandTypeDef sCommand = {0}; + QSPI_AutoPollingTypeDef sConfig = {0}; + + if (QSPI_WriteEnable() != HAL_OK) { + return qspi_ERROR; + } + + sCommand.Instruction = EXT_CHIP_ERASE_CMD; + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + sCommand.Address = 0; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + // Poll until the max chip erase time + sConfig.Match = 0; + sConfig.Mask = IS25LP064A_SR_WIP; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + sConfig.Interval = 0x10; + + if (QSPI_Wait(&sConfig, IS25LP064A_DIE_ERASE_MAX_TIME) != HAL_OK) { + return qspi_ERROR; + } + + return qspi_OK; +} + +uint8_t CSP_QSPI_EraseSector(uint32_t EraseStartAddress, + uint32_t EraseEndAddress) { + + QSPI_CommandTypeDef sCommand = {0}; + QSPI_AutoPollingTypeDef sConfig = {0}; + + /* Erasing Sequence -------------------------------------------------- */ + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.Instruction = SECTOR_ERASE_QPI_CMD; + sCommand.AddressMode = QSPI_ADDRESS_4_LINES; + sCommand.DataMode = QSPI_DATA_NONE; + sCommand.DummyCycles = 0; + + sConfig.Match = 0; + sConfig.Mask = IS25LP064A_SR_WIP; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + sConfig.Interval = 0x10; + + EraseStartAddress = + EraseStartAddress - EraseStartAddress % IS25LP064A_SECTOR_SIZE; + + while (EraseEndAddress >= EraseStartAddress) { + sCommand.Address = (EraseStartAddress & 0x7FFFFF); + + if (QSPI_WriteEnable() != HAL_OK) { + return qspi_ERROR; + } + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + EraseStartAddress += IS25LP064A_SECTOR_SIZE; + + if (QSPI_Wait(&sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + } + return qspi_OK; +} + +uint8_t CSP_QSPI_EnableMemoryMappedMode(void) { + + QSPI_CommandTypeDef sCommand = {0}; + QSPI_MemoryMappedTypeDef sMemMappedCfg = {0}; + + /* Enable Memory-Mapped mode + The FRQIO instruction allows the address bits to be input four bits at a time. + This may allow for code to be executed directly from the SPI in some + applications. Sending the mode bits as AX (X = doesn't matter) will set the + flash controller in memory mapped mode. + */ + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + sCommand.Instruction = QUAD_INOUT_FAST_READ_CMD; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AddressMode = QSPI_ADDRESS_4_LINES; + sCommand.DataMode = QSPI_DATA_4_LINES; + sCommand.NbData = 0; + sCommand.Address = 0; + + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; + sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; + sCommand.AlternateBytes = 0x000000A0; + sCommand.DummyCycles = IS25LP064A_DUMMY_CYCLES_READ_QUAD - 2; + sCommand.SIOOMode = QSPI_SIOO_INST_ONLY_FIRST_CMD; + + sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; + + if (HAL_QSPI_MemoryMapped(&_qspi_flash, &sCommand, &sMemMappedCfg) != + HAL_OK) { + return qspi_ERROR; + } + return HAL_OK; +} + +uint8_t CSP_QSPI_DisableMemoryMappedMode(void) { + + QSPI_CommandTypeDef sCommand = {0}; + uint8_t data; + + // Need to first stop the host controller's access to flash + if (HAL_QSPI_Abort(&_qspi_flash) != HAL_OK) { + return qspi_ERROR; + } + + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + sCommand.Instruction = QUAD_INOUT_FAST_READ_CMD; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AddressMode = QSPI_ADDRESS_4_LINES; + sCommand.DataMode = QSPI_DATA_4_LINES; + sCommand.NbData = 1; + sCommand.Address = 0; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES; + sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; + sCommand.AlternateBytes = 0x00000000; + sCommand.DummyCycles = IS25LP064A_DUMMY_CYCLES_READ_QUAD; + sCommand.SIOOMode = QSPI_SIOO_INST_ONLY_FIRST_CMD; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + if (HAL_QSPI_Receive(&_qspi_flash, &data, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != + HAL_OK) { + return qspi_ERROR; + } + + return qspi_OK; +} + +uint8_t CSP_QSPI_Write(uint8_t *buffer, uint32_t address, + uint32_t buffer_size) { + + QSPI_CommandTypeDef sCommand = {0}; + QSPI_AutoPollingTypeDef sConfig = {0}; + uint32_t end_addr = 0, current_size = 0, current_addr = 0; + + /* Calculation of the size between the write address and the end of the page + */ + current_addr = 0; + + while (current_addr <= address) { + current_addr += IS25LP064A_PAGE_SIZE; + } + current_size = current_addr - address; + + /* Check if the size of the data is less than the remaining place in the page + */ + if (current_size > buffer_size) { + current_size = buffer_size; + } + + /* Initialize the address variables */ + current_addr = address; + end_addr = address + buffer_size; + + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.Instruction = PAGE_PROG_CMD; + sCommand.AddressMode = QSPI_ADDRESS_4_LINES; + sCommand.DataMode = QSPI_DATA_4_LINES; + sCommand.NbData = buffer_size; + sCommand.Address = address; + sCommand.DummyCycles = 0; + + sConfig.Match = 0; + sConfig.Mask = IS25LP064A_SR_WIP; + sConfig.MatchMode = QSPI_MATCH_MODE_AND; + sConfig.StatusBytesSize = 1; + sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + sConfig.Interval = 0x10; + + /* Perform the write page by page */ + do { + sCommand.Address = current_addr; + sCommand.NbData = current_size; + + if (current_size == 0) { + return HAL_OK; + } + + /* Enable write operations */ + if (QSPI_WriteEnable() != HAL_OK) { + return qspi_ERROR; + } + + /* Configure the command */ + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + + return qspi_ERROR; + } + + /* Transmission of the data */ + if (HAL_QSPI_Transmit(&_qspi_flash, buffer, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + + return qspi_ERROR; + } + + /* Configure automatic polling mode to wait for end of program */ + if (QSPI_Wait(&sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + + /* Update the address and size variables for next page programming */ + current_addr += current_size; + buffer += current_size; + current_size = ((current_addr + IS25LP064A_PAGE_SIZE) > end_addr) + ? (end_addr - current_addr) + : IS25LP064A_PAGE_SIZE; + } while (current_addr <= end_addr); + + return qspi_OK; +} + +uint8_t CSP_QSPI_Read(uint8_t *buffer, uint32_t address, uint32_t buffer_size) { + + QSPI_CommandTypeDef sCommand = {0}; + + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.Instruction = QUAD_INOUT_FAST_READ_CMD; + sCommand.AddressMode = QSPI_ADDRESS_4_LINES; + sCommand.DataMode = QSPI_DATA_4_LINES; + sCommand.NbData = buffer_size; + sCommand.Address = address; + sCommand.DummyCycles = IS25LP064A_DUMMY_CYCLES_READ_QUAD; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + + return qspi_ERROR; + } + + if (HAL_QSPI_Receive(&_qspi_flash, buffer, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != + HAL_OK) { + + return qspi_ERROR; + } + + return qspi_OK; +} + +//------------------------------------------------------ +uint8_t CSP_QSPI_ExitQPIMODE(void) { + QSPI_CommandTypeDef sCommand = {0}; + + sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES; + sCommand.AddressSize = QSPI_ADDRESS_24_BITS; + sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + sCommand.Instruction = EXIT_QUAD_CMD; + sCommand.AddressMode = QSPI_ADDRESS_NONE; + + if (HAL_QSPI_Command(&_qspi_flash, &sCommand, + HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + return qspi_ERROR; + } + qspi_enabled = 0; + + return qspi_OK; +} + +/* QUADSPI init function */ +uint8_t CSP_QUADSPI_Init(void) { + + if (QSPI_ResetChip() != HAL_OK) { + return qspi_ERROR; + } + + if (QSPI_Configuration() != HAL_OK) { + return qspi_ERROR; + } + + return qspi_OK; +} + +/* USER CODE END 1 */ diff --git a/ports/stm32h7/components/is25lp064a/is25lp064a_qspi.h b/ports/stm32h7/components/is25lp064a/is25lp064a_qspi.h new file mode 100644 index 000000000..6f59845fa --- /dev/null +++ b/ports/stm32h7/components/is25lp064a/is25lp064a_qspi.h @@ -0,0 +1,30 @@ +#ifndef __IS25LP064A_QSPI_H +#define __IS25LP064A_QSPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +uint8_t CSP_QUADSPI_Init(void); +uint8_t CSP_QSPI_Erase_Chip(void); +uint8_t CSP_QSPI_EraseSector(uint32_t EraseStartAddress, + uint32_t EraseEndAddress); +uint8_t CSP_QSPI_EnableMemoryMappedMode(void); +uint8_t CSP_QSPI_DisableMemoryMappedMode(void); +uint8_t CSP_QSPI_Write(uint8_t *buffer, uint32_t address, uint32_t buffer_size); +uint8_t CSP_QSPI_Read(uint8_t *buffer, uint32_t address, uint32_t buffer_size); +//--------------------------------------------- +uint8_t CSP_QSPI_ExitQPIMODE(void); + +/* USER CODE END Private defines */ + + +/* USER CODE BEGIN Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ports/stm32h7/components/w25qxx/w25qxx_qspi.c b/ports/stm32h7/components/w25qxx/w25qxx_qspi.c index a609d2734..3d3bd06bc 100644 --- a/ports/stm32h7/components/w25qxx/w25qxx_qspi.c +++ b/ports/stm32h7/components/w25qxx/w25qxx_qspi.c @@ -1,5 +1,7 @@ -#include "board_api.h" #include "w25qxx_qspi.h" +#include "qspi_status.h" +#include "stm32h7xx_hal.h" + extern QSPI_HandleTypeDef _qspi_flash; @@ -13,7 +15,7 @@ static uint32_t QSPI_EnterFourBytesAddress(QSPI_HandleTypeDef *hqspi); static uint8_t QSPI_Send_CMD(QSPI_HandleTypeDef *hqspi,uint32_t instruction, uint32_t address,uint32_t addressSize,uint32_t dummyCycles, uint32_t instructionMode,uint32_t addressMode, uint32_t dataMode, uint32_t dataSize); -w25qxx_StatusTypeDef w25qxx_Mode = w25qxx_SPIMode; +qspi_StatusTypeDef w25qxx_Mode = qspi_SPIMode; uint8_t w25qxx_StatusReg[3]; uint16_t w25qxx_ID; @@ -30,7 +32,7 @@ uint16_t w25qxx_GetID(void) uint8_t ID[6]; uint16_t deviceID; - if(w25qxx_Mode == w25qxx_SPIMode) + if(w25qxx_Mode == qspi_SPIMode) QSPI_Send_CMD(&_qspi_flash,W25X_QUAD_ManufactDeviceID,0x00,QSPI_ADDRESS_24_BITS,6,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_4_LINES, QSPI_DATA_4_LINES, sizeof(ID)); else QSPI_Send_CMD(&_qspi_flash,W25X_ManufactDeviceID,0x00,QSPI_ADDRESS_24_BITS,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_4_LINES, QSPI_DATA_4_LINES, sizeof(ID)); @@ -38,7 +40,7 @@ uint16_t w25qxx_GetID(void) /* Reception of the data */ if (HAL_QSPI_Receive(&_qspi_flash, ID, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } deviceID = (ID[0] << 8) | ID[1]; @@ -48,7 +50,7 @@ uint16_t w25qxx_GetID(void) uint8_t w25qxx_ReadSR(uint8_t SR) { uint8_t byte=0; - if(w25qxx_Mode == w25qxx_SPIMode) + if(w25qxx_Mode == qspi_SPIMode) QSPI_Send_CMD(&_qspi_flash,SR,0x00,QSPI_ADDRESS_8_BITS,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_NONE, QSPI_DATA_1_LINE, 1); else QSPI_Send_CMD(&_qspi_flash,SR,0x00,QSPI_ADDRESS_8_BITS,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_NONE, QSPI_DATA_4_LINES, 1); @@ -62,7 +64,7 @@ uint8_t w25qxx_ReadSR(uint8_t SR) uint8_t w25qxx_WriteSR(uint8_t SR,uint8_t data) { - if(w25qxx_Mode == w25qxx_SPIMode) + if(w25qxx_Mode == qspi_SPIMode) QSPI_Send_CMD(&_qspi_flash,SR,0x00,QSPI_ADDRESS_8_BITS,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_NONE, QSPI_DATA_1_LINE, 1); else QSPI_Send_CMD(&_qspi_flash,SR,0x00,QSPI_ADDRESS_8_BITS,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_NONE, QSPI_DATA_4_LINES, 1); @@ -75,7 +77,7 @@ uint8_t w25qxx_ReadAllStatusReg(void) w25qxx_StatusReg[0] = w25qxx_ReadSR(W25X_ReadStatusReg1); w25qxx_StatusReg[1] = w25qxx_ReadSR(W25X_ReadStatusReg2); w25qxx_StatusReg[2] = w25qxx_ReadSR(W25X_ReadStatusReg3); - return w25qxx_OK; + return qspi_OK; } //等待空闲 @@ -90,7 +92,7 @@ uint8_t w25qxx_SetReadParameters(uint8_t DummyClock,uint8_t WrapLenth) uint8_t send; send = (DummyClock/2 -1)<<4 | ((WrapLenth/8 - 1)&0x03); - W25qxx_WriteEnable(); + w25qxx_WriteEnable(); QSPI_Send_CMD(&_qspi_flash,W25X_SetReadParam,0x00,QSPI_ADDRESS_8_BITS,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_NONE, QSPI_DATA_4_LINES, 1); @@ -100,9 +102,9 @@ uint8_t w25qxx_SetReadParameters(uint8_t DummyClock,uint8_t WrapLenth) uint8_t w25qxx_EnterQPI(void) { /* Enter QSPI memory in QSPI mode */ - if(QSPI_EnterQPI(&_qspi_flash) != w25qxx_OK) + if(QSPI_EnterQPI(&_qspi_flash) != qspi_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } return w25qxx_SetReadParameters(8,8); @@ -116,14 +118,14 @@ uint8_t w25qxx_EnterQPI(void) uint8_t w25qxx_Startup(uint8_t DTRMode) { /* Enable MemoryMapped mode */ - if( QSPI_EnableMemoryMappedMode(&_qspi_flash,DTRMode) != w25qxx_OK ) + if( QSPI_EnableMemoryMappedMode(&_qspi_flash,DTRMode) != qspi_OK ) { - return w25qxx_ERROR; + return qspi_ERROR; } - return w25qxx_OK; + return qspi_OK; } -uint8_t W25qxx_WriteEnable(void) +uint8_t w25qxx_WriteEnable(void) { return QSPI_WriteEnable(&_qspi_flash); } @@ -132,20 +134,20 @@ uint8_t W25qxx_WriteEnable(void) * @param SectorAddress: Sector address to erase * @retval QSPI memory status */ -uint8_t W25qxx_EraseSector(uint32_t SectorAddress) +uint8_t w25qxx_EraseSector(uint32_t SectorAddress) { uint8_t result; - W25qxx_WriteEnable(); + w25qxx_WriteEnable(); W25QXX_Wait_Busy(); - if(w25qxx_Mode == w25qxx_SPIMode) + if(w25qxx_Mode == qspi_SPIMode) result = QSPI_Send_CMD(&_qspi_flash,W25X_SectorErase,SectorAddress,QSPI_ADDRESS_24_BITS,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_1_LINE,QSPI_DATA_NONE,0); else result = QSPI_Send_CMD(&_qspi_flash,W25X_SectorErase,SectorAddress,QSPI_ADDRESS_24_BITS,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_4_LINES,QSPI_DATA_NONE,0); /* 等待擦除完成 */ - if(result == w25qxx_OK) + if(result == qspi_OK) W25QXX_Wait_Busy(); return result; @@ -156,20 +158,20 @@ uint8_t W25qxx_EraseSector(uint32_t SectorAddress) * @param SectorAddress: Sector address to erase * @retval QSPI memory status */ -uint8_t W25qxx_EraseBlock(uint32_t BlockAddress) +uint8_t w25qxx_EraseBlock(uint32_t BlockAddress) { uint8_t result; - W25qxx_WriteEnable(); + w25qxx_WriteEnable(); W25QXX_Wait_Busy(); - if(w25qxx_Mode == w25qxx_SPIMode) + if(w25qxx_Mode == qspi_SPIMode) result = QSPI_Send_CMD(&_qspi_flash,W25X_BlockErase,BlockAddress,QSPI_ADDRESS_24_BITS,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_1_LINE,QSPI_DATA_NONE,0); else result = QSPI_Send_CMD(&_qspi_flash,W25X_BlockErase,BlockAddress,QSPI_ADDRESS_24_BITS,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_4_LINES,QSPI_DATA_NONE,0); /* 等待擦除完成 */ - if(result == w25qxx_OK) + if(result == qspi_OK) W25QXX_Wait_Busy(); return result; @@ -180,20 +182,20 @@ uint8_t W25qxx_EraseBlock(uint32_t BlockAddress) * @param SectorAddress: Sector address to erase * @retval QSPI memory status */ -uint8_t W25qxx_EraseChip(void) +uint8_t w25qxx_EraseChip(void) { uint8_t result; - W25qxx_WriteEnable(); + w25qxx_WriteEnable(); W25QXX_Wait_Busy(); - if(w25qxx_Mode == w25qxx_SPIMode) + if(w25qxx_Mode == qspi_SPIMode) result = QSPI_Send_CMD(&_qspi_flash,W25X_ChipErase,0x00,QSPI_ADDRESS_8_BITS,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_NONE,QSPI_DATA_NONE,0); else result = QSPI_Send_CMD(&_qspi_flash,W25X_ChipErase,0x00,QSPI_ADDRESS_8_BITS,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_NONE,QSPI_DATA_NONE,0); /* 等待擦除完成 */ - if(result == w25qxx_OK) + if(result == qspi_OK) W25QXX_Wait_Busy(); return result; @@ -206,22 +208,22 @@ uint8_t W25qxx_EraseChip(void) * @param Size Size of data to write. Range 1 ~ W25qxx page size * @retval QSPI memory status */ -uint8_t W25qxx_PageProgram(uint8_t *pData, uint32_t WriteAddr, uint32_t Size) +uint8_t w25qxx_PageProgram(uint8_t *pData, uint32_t WriteAddr, uint32_t Size) { uint8_t result; - W25qxx_WriteEnable(); + w25qxx_WriteEnable(); - if(w25qxx_Mode == w25qxx_SPIMode) + if(w25qxx_Mode == qspi_SPIMode) result = QSPI_Send_CMD(&_qspi_flash,W25X_QUAD_INPUT_PAGE_PROG_CMD,WriteAddr,QSPI_ADDRESS_24_BITS,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_1_LINE,QSPI_DATA_4_LINES,Size); else result = QSPI_Send_CMD(&_qspi_flash,W25X_PageProgram,WriteAddr,QSPI_ADDRESS_24_BITS,0,QSPI_INSTRUCTION_4_LINES,QSPI_ADDRESS_4_LINES,QSPI_DATA_4_LINES,Size); - if(result == w25qxx_OK) + if(result == qspi_OK) result = HAL_QSPI_Transmit(&_qspi_flash,pData,HAL_QPSI_TIMEOUT_DEFAULT_VALUE); /* 等待写入完成 */ - if(result == w25qxx_OK) + if(result == qspi_OK) W25QXX_Wait_Busy(); return result; @@ -232,7 +234,7 @@ uint8_t W25qxx_PageProgram(uint8_t *pData, uint32_t WriteAddr, uint32_t Size) //pBuffer:数据存储区 //ReadAddr:开始读取的地址(最大32bit) //NumByteToRead:要读取的字节数(最大65535) -uint8_t W25qxx_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size) +uint8_t w25qxx_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size) { uint8_t result; @@ -240,7 +242,7 @@ uint8_t W25qxx_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size) /* Configure the command for the read instruction */ - if(w25qxx_Mode == w25qxx_QPIMode) + if(w25qxx_Mode == qspi_QPIMode) { s_command.Instruction = W25X_QUAD_INOUT_FAST_READ_CMD; s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; @@ -271,7 +273,7 @@ uint8_t W25qxx_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size) result = HAL_QSPI_Command(&_qspi_flash, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE); - if(result == w25qxx_OK) + if(result == qspi_OK) result = HAL_QSPI_Receive(&_qspi_flash,pData,HAL_QPSI_TIMEOUT_DEFAULT_VALUE); return result; @@ -285,7 +287,7 @@ uint8_t W25qxx_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size) //WriteAddr:开始写入的地址(最大32bit) //NumByteToWrite:要写入的字节数(最大65535) //CHECK OK -void W25qxx_WriteNoCheck(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite) +void w25qxx_WriteNoCheck(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite) { uint16_t pageremain; pageremain = 256 - WriteAddr % 256; //单页剩余的字节数 @@ -295,7 +297,7 @@ void W25qxx_WriteNoCheck(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t NumByteToW } while(1) { - W25qxx_PageProgram(pBuffer, WriteAddr, pageremain); + w25qxx_PageProgram(pBuffer, WriteAddr, pageremain); if (NumByteToWrite == pageremain) { break; //写入结束了 @@ -320,7 +322,7 @@ void W25qxx_WriteNoCheck(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t NumByteToW //pBuffer:数据存储区 //WriteAddr:开始写入的地址(最大32bit) //NumByteToWrite:要写入的字节数(最大65535) -uint8_t W25qxx_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) +uint8_t w25qxx_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { uint32_t secpos; uint16_t secoff; @@ -335,8 +337,8 @@ uint8_t W25qxx_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWri if (NumByteToWrite <= secremain) secremain = NumByteToWrite; //不大于4096个字节 while(1) { - if (W25qxx_Read(W25QXX_BUF, secpos * 4096, 4096) != w25qxx_OK) { - return w25qxx_ERROR; + if (w25qxx_Read(W25QXX_BUF, secpos * 4096, 4096) != qspi_OK) { + return qspi_ERROR; } //读出整个扇区的内容 for (i = 0;i < secremain; i++) //校验数据 { @@ -344,18 +346,18 @@ uint8_t W25qxx_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWri } if (i < secremain) //需要擦除 { - if (W25qxx_EraseSector(secpos) != w25qxx_OK) { - return w25qxx_ERROR; + if (w25qxx_EraseSector(secpos) != qspi_OK) { + return qspi_ERROR; } //擦除这个扇区 for (i = 0; i < secremain; i++) //复制 { W25QXX_BUF[i + secoff] = pBuffer[i]; } - W25qxx_WriteNoCheck(W25QXX_BUF, secpos * 4096, 4096); //写入整个扇区 + w25qxx_WriteNoCheck(W25QXX_BUF, secpos * 4096, 4096); //写入整个扇区 } else { - W25qxx_WriteNoCheck(pBuffer, WriteAddr, secremain); //写已经擦除了的,直接写入扇区剩余区间. + w25qxx_WriteNoCheck(pBuffer, WriteAddr, secremain); //写已经擦除了的,直接写入扇区剩余区间. } if (NumByteToWrite == secremain) { @@ -375,13 +377,13 @@ uint8_t W25qxx_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWri secremain = NumByteToWrite; //下一个扇区可以写完了 } } - return w25qxx_OK; + return qspi_OK; } /** * @brief Configure the QSPI in memory-mapped mode QPI/SPI && DTR(DDR)/Normal Mode * @param hqspi: QSPI handle - * @param DTRMode: w25qxx_DTRMode DTR mode ,w25qxx_NormalMode Normal mode + * @param DTRMode: qspi_DTRMode DTR mode ,qspi_NormalMode Normal mode * @retval QSPI memory status */ static uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *hqspi,uint8_t DTRMode) @@ -390,7 +392,7 @@ static uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *hqspi,uint8_t DT QSPI_MemoryMappedTypeDef s_mem_mapped_cfg; /* Configure the command for the read instruction */ - if(w25qxx_Mode == w25qxx_QPIMode) + if(w25qxx_Mode == qspi_QPIMode) s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; else s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; @@ -405,7 +407,7 @@ static uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *hqspi,uint8_t DT s_command.DataMode = QSPI_DATA_4_LINES; - if(DTRMode == w25qxx_DTRMode) + if(DTRMode == qspi_DTRMode) { s_command.Instruction = W25X_QUAD_INOUT_FAST_READ_DTR_CMD; s_command.DummyCycles = W25X_DUMMY_CYCLES_READ_QUAD_DTR; @@ -415,7 +417,7 @@ static uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *hqspi,uint8_t DT { s_command.Instruction = W25X_QUAD_INOUT_FAST_READ_CMD; - if(w25qxx_Mode == w25qxx_QPIMode) + if(w25qxx_Mode == qspi_QPIMode) s_command.DummyCycles = W25X_DUMMY_CYCLES_READ_QUAD; else s_command.DummyCycles = W25X_DUMMY_CYCLES_READ_QUAD-2; @@ -432,10 +434,10 @@ static uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *hqspi,uint8_t DT if (HAL_QSPI_MemoryMapped(hqspi, &s_command, &s_mem_mapped_cfg) != HAL_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } - return w25qxx_OK; + return qspi_OK; } /** @@ -461,14 +463,14 @@ static uint32_t QSPI_ResetDevice(QSPI_HandleTypeDef *hqspi) /* Send the command */ if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } /* Send the reset device command */ s_command.Instruction = W25X_ResetDevice; if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; @@ -476,18 +478,18 @@ static uint32_t QSPI_ResetDevice(QSPI_HandleTypeDef *hqspi) /* Send the command */ if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } /* Send the reset memory command */ s_command.Instruction = W25X_ResetDevice; if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } - w25qxx_Mode = w25qxx_SPIMode; - return w25qxx_OK; + w25qxx_Mode = qspi_SPIMode; + return qspi_OK; } /** @@ -502,8 +504,8 @@ static uint32_t QSPI_ResetDevice(QSPI_HandleTypeDef *hqspi) * @param dataMode 数据模式; QSPI_DATA_NONE,QSPI_DATA_1_LINE,QSPI_DATA_2_LINES,QSPI_DATA_4_LINES * @param dataSize 待传输的数据长度 * - * @return uint8_t w25qxx_OK:正常 - * w25qxx_ERROR:错误 + * @return uint8_t qspi_OK:正常 + * qspi_ERROR:错误 */ static uint8_t QSPI_Send_CMD(QSPI_HandleTypeDef *hqspi,uint32_t instruction, uint32_t address,uint32_t addressSize,uint32_t dummyCycles, uint32_t instructionMode,uint32_t addressMode, uint32_t dataMode, uint32_t dataSize) @@ -530,9 +532,9 @@ static uint8_t QSPI_Send_CMD(QSPI_HandleTypeDef *hqspi,uint32_t instruction, uin Cmdhandler.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; if(HAL_QSPI_Command(hqspi, &Cmdhandler, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) - return w25qxx_ERROR; + return qspi_ERROR; - return w25qxx_OK; + return qspi_OK; } /** @@ -556,24 +558,24 @@ static uint32_t QSPI_EnterFourBytesAddress(QSPI_HandleTypeDef *hqspi) s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* Enable write operations */ - if (QSPI_WriteEnable(hqspi) != w25qxx_OK) + if (QSPI_WriteEnable(hqspi) != qspi_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } /* Send the command */ if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } /* Configure automatic polling mode to wait the memory is ready */ - if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != w25qxx_OK) + if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != qspi_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } - return w25qxx_OK; + return qspi_OK; } /** @@ -587,7 +589,7 @@ static uint32_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) QSPI_AutoPollingTypeDef s_config; /* Enable write operations */ - if(w25qxx_Mode == w25qxx_QPIMode) + if(w25qxx_Mode == qspi_QPIMode) s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; else s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; @@ -603,7 +605,7 @@ static uint32_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } /* Configure automatic polling mode to wait for write enabling */ @@ -616,17 +618,17 @@ static uint32_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi) s_command.Instruction = W25X_ReadStatusReg1; - if(w25qxx_Mode == w25qxx_QPIMode) + if(w25qxx_Mode == qspi_QPIMode) s_command.DataMode = QSPI_DATA_4_LINES; else s_command.DataMode = QSPI_DATA_1_LINE; if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } - return w25qxx_OK; + return qspi_OK; } /** @@ -642,7 +644,7 @@ static uint32_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Tim /* Configure automatic polling mode to wait for memory ready */ - if(w25qxx_Mode == w25qxx_SPIMode) + if(w25qxx_Mode == qspi_SPIMode) s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; else s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; @@ -654,7 +656,7 @@ static uint32_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Tim s_command.AddressSize = QSPI_ADDRESS_8_BITS; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; - if(w25qxx_Mode == w25qxx_SPIMode) + if(w25qxx_Mode == qspi_SPIMode) s_command.DataMode = QSPI_DATA_1_LINE; else s_command.DataMode = QSPI_DATA_4_LINES; @@ -685,19 +687,19 @@ static uint8_t QSPI_EnterQPI(QSPI_HandleTypeDef *hqspi) stareg2 = w25qxx_ReadSR(W25X_ReadStatusReg2); if((stareg2 & 0X02) == 0) //QE位未使能 { - W25qxx_WriteEnable(); + w25qxx_WriteEnable(); stareg2 |= 1<<1; //使能QE位 w25qxx_WriteSR(W25X_WriteStatusReg2,stareg2); } QSPI_Send_CMD(hqspi,W25X_EnterQSPIMode,0x00,QSPI_ADDRESS_8_BITS,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_NONE,QSPI_DATA_NONE,0); /* Configure automatic polling mode to wait the memory is ready */ - if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != w25qxx_OK) + if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != qspi_OK) { - return w25qxx_ERROR; + return qspi_ERROR; } - w25qxx_Mode = w25qxx_QPIMode; + w25qxx_Mode = qspi_QPIMode; - return w25qxx_OK; + return qspi_OK; } diff --git a/ports/stm32h7/components/w25qxx/w25qxx_qspi.h b/ports/stm32h7/components/w25qxx/w25qxx_qspi.h index 57c63e4d7..2622f1556 100644 --- a/ports/stm32h7/components/w25qxx/w25qxx_qspi.h +++ b/ports/stm32h7/components/w25qxx/w25qxx_qspi.h @@ -7,21 +7,6 @@ #include -typedef enum -{ - w25qxx_OK = 0x00, - w25qxx_ERROR = 0x01, - w25qxx_BUSY = 0x02, - w25qxx_TIMEOUT = 0x03, - - w25qxx_QPIMode = 0x04, - w25qxx_SPIMode = 0x05, - - w25qxx_DTRMode = 0x06, - w25qxx_NormalMode = 0x07, - -} w25qxx_StatusTypeDef; - /* =============== W25Qxx CMD ================ */ #define W25X_WriteEnable 0x06 #define W25X_WriteDisable 0x04 @@ -84,14 +69,14 @@ uint8_t w25qxx_WriteSR(uint8_t SR,uint8_t data); uint8_t w25qxx_SetReadParameters(uint8_t DummyClock,uint8_t WrapLenth); uint8_t w25qxx_EnterQPI(void); uint8_t w25qxx_Startup(uint8_t DTRMode); -uint8_t W25qxx_WriteEnable(void); -uint8_t W25qxx_EraseSector(uint32_t SectorAddress); -uint8_t W25qxx_EraseBlock(uint32_t BlockAddress); -uint8_t W25qxx_EraseChip(void); -uint8_t W25qxx_PageProgram(uint8_t *pData, uint32_t WriteAddr, uint32_t Size); -uint8_t W25qxx_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size); -void W25qxx_WriteNoCheck(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite); -uint8_t W25qxx_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); +uint8_t w25qxx_WriteEnable(void); +uint8_t w25qxx_EraseSector(uint32_t SectorAddress); +uint8_t w25qxx_EraseBlock(uint32_t BlockAddress); +uint8_t w25qxx_EraseChip(void); +uint8_t w25qxx_PageProgram(uint8_t *pData, uint32_t WriteAddr, uint32_t Size); +uint8_t w25qxx_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size); +void w25qxx_WriteNoCheck(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t NumByteToWrite); +uint8_t w25qxx_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); #ifdef __cplusplus } diff --git a/ports/stm32h7/port.mk b/ports/stm32h7/port.mk index 1f51fca86..81bc507bd 100644 --- a/ports/stm32h7/port.mk +++ b/ports/stm32h7/port.mk @@ -39,12 +39,21 @@ SRC_C += \ $(TOP)/$(PORT_DIR)/components/w25qxx/w25qxx_qspi.c endif +ifeq ($(QSPI_FLASH),IS25LP064A) +INC += \ + $(CURRENT_PATH)/components/is25lp064a/ \ + +SRC_C += \ + $(TOP)/$(PORT_DIR)/components/is25lp064a/is25lp064a_qspi.c +endif + ifeq ($(DISPLAY_DRV),ST7735) INC += \ - $(CURRENT_PATH)/components/w25qxx/ \ + $(CURRENT_PATH)/components/st7735/ \ SRC_C += \ - $(TOP)/$(PORT_DIR)/components/st7735/st7735.c + $(TOP)/$(PORT_DIR)/components/st7735/st7735.c \ + $(TOP)/$(PORT_DIR)/components/st7735/fonts.c endif # Source @@ -63,7 +72,6 @@ SRC_C += \ $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_qspi.c \ $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_mdma.c \ $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_pwr_ex.c \ - $(TOP)/$(PORT_DIR)/components/st7735/fonts.c \ ifndef BUILD_NO_TINYUSB @@ -75,8 +83,6 @@ endif INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/$(CMSIS_5)/CMSIS/Core/Include \ - $(CURRENT_PATH)/components/st7735/ \ - $(CURRENT_PATH)/components/w25qxx/ \ $(TOP)/$(PORT_DIR)/ \ $(TOP)/$(BOARD_DIR) \ $(TOP)/$(ST_CMSIS)/Include \ diff --git a/ports/stm32h7/qspi_status.h b/ports/stm32h7/qspi_status.h new file mode 100644 index 000000000..cb249bb6a --- /dev/null +++ b/ports/stm32h7/qspi_status.h @@ -0,0 +1,26 @@ +#ifndef QSPI_STATUS_H_ +#define QSPI_STATUS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + qspi_OK = 0x00, + qspi_ERROR = 0x01, + qspi_BUSY = 0x02, + qspi_TIMEOUT = 0x03, + + qspi_QPIMode = 0x04, + qspi_SPIMode = 0x05, + + qspi_DTRMode = 0x06, + qspi_NormalMode = 0x07, + +} qspi_StatusTypeDef; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file From a9dbffdfef514461e07efee6dd6281b3d436bc9d Mon Sep 17 00:00:00 2001 From: snkymkrct Date: Sun, 2 Mar 2025 23:23:10 +0100 Subject: [PATCH 3/9] Change Daisy board ID --- ports/stm32h7/boards/daisy_seed/board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32h7/boards/daisy_seed/board.h b/ports/stm32h7/boards/daisy_seed/board.h index c2a8b8fbc..6ba56e359 100644 --- a/ports/stm32h7/boards/daisy_seed/board.h +++ b/ports/stm32h7/boards/daisy_seed/board.h @@ -68,7 +68,7 @@ extern "C" { #define USB_PRODUCT "STM32FH750IB" #define UF2_PRODUCT_NAME USB_MANUFACTURER " " USB_PRODUCT -#define UF2_BOARD_ID "DaisySeed" +#define UF2_BOARD_ID "STM32FH750IB-DaisySeed" #define UF2_VOLUME_LABEL "DaisySeed" #define UF2_INDEX_URL "https://electro-smith.com/products/daisy-seed" From 2ef7ccd2c4edd99e9332ab0bd28e1a2439872c7f Mon Sep 17 00:00:00 2001 From: snkymkrct Date: Mon, 3 Mar 2025 00:21:13 +0100 Subject: [PATCH 4/9] pre-commit fixes --- ports/stm32h7/board_flash.c | 4 +- .../components/is25lp064a/is25lp064a.h | 79 +++++++++---------- ports/stm32h7/qspi_status.h | 2 +- 3 files changed, 42 insertions(+), 43 deletions(-) diff --git a/ports/stm32h7/board_flash.c b/ports/stm32h7/board_flash.c index 92e6a2a4d..12fec8522 100644 --- a/ports/stm32h7/board_flash.c +++ b/ports/stm32h7/board_flash.c @@ -84,7 +84,7 @@ static void qspi_Startup(void) { #endif #ifdef IS25LP064A if (CSP_QSPI_EnableMemoryMappedMode() != qspi_OK) { - TUF2_LOG1("Error enabing memory map for QSPI Flash\r\n"); + TUF2_LOG1("Error enabling memory map for QSPI Flash\r\n"); } #endif } @@ -291,4 +291,4 @@ void board_flash_erase_app(void) // TODO: Implement PFLASH erase for non-tinyuf2 sectors board_reset(); -} \ No newline at end of file +} diff --git a/ports/stm32h7/components/is25lp064a/is25lp064a.h b/ports/stm32h7/components/is25lp064a/is25lp064a.h index e289df0e3..2106b94d7 100644 --- a/ports/stm32h7/components/is25lp064a/is25lp064a.h +++ b/ports/stm32h7/components/is25lp064a/is25lp064a.h @@ -7,38 +7,38 @@ #ifndef INC_FLASH_IS25LP064A_H_ #define INC_FLASH_IS25LP064A_H_ - + #ifdef __cplusplus extern "C" { #endif - + #define IS25LP064A_FLASH_SIZE 0x800000 /* 8 MBytes*/ #define IS25LP064A_BLOCK_SIZE 0x10000 /* 64 KBytes */ #define IS25LP064A_SECTOR_SIZE 0x1000 /* 4 KBytes */ #define IS25LP064A_PAGE_SIZE 0x100 /* 256 bytes */ - + #define IS25LP064A_SECTOR_COUNT 2048 - - + + #define IS25LP064A_DUMMY_CYCLES_READ_QUAD 6 /* & */ #define IS25LP064A_DUMMY_CYCLES_READ 6 /* & */ //#define IS25LP064A_DUMMY_CYCLES_READ_DTR 6 /* & */ //#define IS25LP064A_DUMMY_CYCLES_READ_QUAD_DTR 6 /* & */ - - + + #define IS25LP064A_DIE_ERASE_MAX_TIME 46000 /* 45 max seconds in datasheet */ #define IS25LP064A_BLOCK_ERASE_MAX_TIME 1100 /* 1000 ms max in datasheet */ #define IS25LP064A_SECTOR_ERASE_MAX_TIME 350 /* 300 ms max in datasheet */ - - + + /* Low Power Modes */ #define ENTER_DEEP_POWER_DOWN 0XB9 /* & */ #define EXIT_DEEP_POWER_DOWN 0XAB /* Release from Power-down/Read Device ID instruction */ - + /* Software Reset Operation commands */ #define RESET_ENABLE_CMD 0x66 #define RESET_MEMORY_CMD 0x99 /* & */ - + /* Identification Operations */ #define READ_ID_CMD 0xAB /* Release from Power-down/Read Device ID instruction */ #define READ_ID_CMD2 0x9F /* JEDEC ID READ command in SPI mode */ @@ -46,86 +46,85 @@ #define READ_SERIAL_FLASH_DISCO_PARAM_CMD 0x5A /* Serial Flash Discoverable Parameters (SFDP) */ #define READ_MANUFACT_AND_ID 0x90 /* Read Product Identification (RDID) instruction */ #define READ_UNIQUE_ID 0x4B /* Read Unique ID Number (RDUID) */ - + #define NO_OP 0x00 /* Cancels Reset Enable */ - + /* Sector LOCK/UNLOCK Operations */ #define SECTOR_UNLOCK 0x26 /**< & */ #define SECTOR_LOCK 0x24 /**< & */ - + /* Security Information Row */ #define INFO_ROW_ERASE_CMD 0x64 /* Information Row Erase (IRER) instruction */ #define INFO_ROW_PROGRAM_CMD 0x62 /* Information Row Program (IRP) instruction */ #define INFO_ROW_READ_CMD 0x68 /* Information Row Read (IRRD) instruction */ - + /* Read Operations */ #define READ_CMD 0x03 /* NORMAL READ (NORD) instruction */ - + #define FAST_READ_CMD 0x0B /* FAST READ (FRD) instruction for both 1 line and QPI modes */ #define FAST_READ_DTR_CMD 0x0D /* FRDTR instruction */ - + #define DUAL_OUT_FAST_READ_CMD 0x3B /* FAST READ DUAL OUTPUT OPERATION (FRDO) */ - + #define DUAL_INOUT_FAST_READ_CMD 0xBB /* FAST READ DUAL I/O OPERATION (FRDIO) */ #define DUAL_INOUT_FAST_READ_DTR_CMD 0xBD /* FAST READ DUAL IO DTR MODE OPERATION (FRDDTR) */ - + #define QUAD_OUT_FAST_READ_CMD 0x6B /* FAST READ QUAD OUTPUT OPERATION (FRQO) */ - + #define QUAD_INOUT_FAST_READ_CMD 0xEB /* FAST READ QUAD I/O OPERATION (FRQIO) - can be used to enable memory mapped mode */ #define QUAD_INOUT_FAST_READ_DTR_CMD 0xED /* FAST READ QUAD IO DTR MODE OPERATION (FRQDTR) */ - + /* Write Operations */ #define WRITE_ENABLE_CMD 0x06 /* WRITE ENABLE OPERATION (WREN) */ #define WRITE_DISABLE_CMD 0x04 /* WRITE DISABLE OPERATION (WRDI) */ - + /* Register Operations */ #define READ_STATUS_REG_CMD 0x05 /* READ STATUS REGISTER OPERATION (RDSR) */ #define WRITE_STATUS_REG_CMD 0x01 /* WRITE STATUS REGISTER OPERATION (WRSR) */ - + #define READ_FUNCTION_REGISTER 0X48 /* READ FUNCTION REGISTER OPERATION (RDFR) */ #define WRITE_FUNCTION_REGISTER 0x42 /* WRITE FUNCTION REGISTER OPERATION (WRFR) */ - + #define WRITE_READ_PARAM_REG_CMD 0xC0 /* SET READ PARAMETERS OPERATION (SRP) */ - + /* Page Program Operations */ #define PAGE_PROG_CMD 0x02 /* PAGE PROGRAM OPERATION (PP) */ - + /* QUAD INPUT PAGE PROGRAM OPERATION (PPQ) */ #define QUAD_IN_PAGE_PROG_CMD 0x32 #define EXT_QUAD_IN_PAGE_PROG_CMD 0x38 - + /* Erase Operations */ - #define SECTOR_ERASE_CMD 0xd7 /* SECTOR ERASE OPERATION (SER) on SPI */ - #define SECTOR_ERASE_QPI_CMD 0x20 /* SECTOR ERASE OPERATION (SER) QPI */ - + #define SECTOR_ERASE_CMD 0xd7 /* SECTOR ERASE OPERATION (S E R) on SPI */ + #define SECTOR_ERASE_QPI_CMD 0x20 /* SECTOR ERASE OPERATION (S E R) QPI */ + #define BLOCK_ERASE_CMD 0xD8 /* BLOCK ERASE OPERATION (BER64K) */ #define BLOCK_ERASE_32K_CMD 0x52 /* BLOCK ERASE OPERATION (BER32K) */ - + #define CHIP_ERASE_CMD 0xC7 /* CHIP ERASE OPERATION (CER) on SPI */ #define EXT_CHIP_ERASE_CMD 0x60 /* CHIP ERASE OPERATION (CER) on QPI*/ - + #define PROG_ERASE_RESUME_CMD 0x7A /* Resume program/erase (PERRSM) on SPI */ #define EXT_PROG_ERASE_RESUME_CMD 0x30 /* Resume program/erase (PERRSM) on QPI */ - + #define PROG_ERASE_SUSPEND_CMD 0x75 /* Suspend during program/erase (PERSUS) on SPI */ #define EXT_PROG_ERASE_SUSPEND_CMD 0xB0 /* Suspend during program/erase (PERSUS) on QPI */ - + /** Quad Operations */ #define ENTER_QUAD_CMD 0x35 /* ENTER QUAD PERIPHERAL INTERFACE (QPI) MODE OPERATION (QIOEN) */ #define EXIT_QUAD_CMD 0xF5 /* EXIT QUAD PERIPHERAL INTERFACE (QPI) MODE OPERATION (QIODI) */ - - + + /* Status Register */ #define IS25LP064A_SR_WIP ((uint8_t)0x01) /* WIP Write in progress */ - #define IS25LP064A_SR_WREN ((uint8_t)0x02) /* WEL Write enable latch */ + #define IS25LP064A_SR_WREN ((uint8_t)0x02) /* W E L Write enable latch */ //#define IS25LP064A_SR_BLOCKPR ((uint8_t)0x5C) /*!< Block protected against program and erase operations */ //#define IS25LP064A_SR_PRBOTTOM ((uint8_t)0x20) /*!< Protected memory area defined by BLOCKPR starts from top or bottom */ #define IS25LP064A_SR_QE ((uint8_t)0x40) /* QE Quad Enable */ #define IS25LP064A_SR_SRWREN ((uint8_t)0x80) /* SRWD Status Register Write Disable*/ - + #ifdef __cplusplus } #endif - + #endif /* INC_FLASH_IS25LP064A_H_ */ - \ No newline at end of file diff --git a/ports/stm32h7/qspi_status.h b/ports/stm32h7/qspi_status.h index cb249bb6a..1bb7791d6 100644 --- a/ports/stm32h7/qspi_status.h +++ b/ports/stm32h7/qspi_status.h @@ -23,4 +23,4 @@ typedef enum { } #endif -#endif \ No newline at end of file +#endif From 998bedb57c32e62412d5b0f6f4f7e5b104a369c4 Mon Sep 17 00:00:00 2001 From: snkymkrct Date: Mon, 3 Mar 2025 00:40:26 +0100 Subject: [PATCH 5/9] add stm32h7 port to build workflow --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fe4a3f101..0e638c12e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,6 +68,7 @@ jobs: - 'stm32f4' - 'stm32h5' - 'stm32l4' + - 'stm32h7' with: port: ${{ matrix.port }} boards: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.port].board) }} From 924b7d86f03779d54e898a2b79d6b51b1c15649e Mon Sep 17 00:00:00 2001 From: snkymkrct Date: Mon, 3 Mar 2025 12:22:09 +0100 Subject: [PATCH 6/9] self update is not yet properly implemented for the stm32h7 port --- ports/stm32h7/Makefile | 8 +++--- ports/stm32h7/apps/erase_firmware/Makefile | 13 ++++++++-- ports/stm32h7/apps/self_update/Makefile | 29 ++++++++++++---------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/ports/stm32h7/Makefile b/ports/stm32h7/Makefile index 16f41a035..659eab2bc 100644 --- a/ports/stm32h7/Makefile +++ b/ports/stm32h7/Makefile @@ -22,11 +22,13 @@ include ../rules.mk # This uf2 will be loaded into RAM # TODO: this needs to build the actual uf2 binary first self-update: $(BUILD)/$(OUTNAME).bin - $(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py --carray $^ -o apps/self_update/_build/bootloader_bin.c - $(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update uf2 + @echo "not implemented yet" +# $(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py --carray $^ -o apps/self_update/_build/bootloader_bin.c +# $(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update uf2 self-update-clean: - $(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update clean + @echo "not implemented yet" +# $(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update clean #---------- Erase app ---------- # Compile apps/erase_firmware/erase_firmware.c diff --git a/ports/stm32h7/apps/erase_firmware/Makefile b/ports/stm32h7/apps/erase_firmware/Makefile index 9a2907779..1abfb4fd6 100644 --- a/ports/stm32h7/apps/erase_firmware/Makefile +++ b/ports/stm32h7/apps/erase_firmware/Makefile @@ -8,8 +8,17 @@ SRC_C += \ $(TOP)/$(PORT_DIR)/boards.c \ $(TOP)/$(PORT_DIR)/board_flash.c \ $(TOP)/$(PORT_DIR)/board_irq.c \ - $(TOP)/$(PORT_DIR)/components/w25qxx/w25qxx.c \ - $(TOP)/$(PORT_DIR)/components/w25qxx/w25qxx_qspi.c \ + +ifeq ($(QSPI_FLASH),W25Qx_QSPI) +SRC_C += \ + $(TOP)/$(PORT_DIR)/components/w25qxx/w25qxx.c \ + $(TOP)/$(PORT_DIR)/components/w25qxx/w25qxx_qspi.c +endif + +ifeq ($(QSPI_FLASH),IS25LP064A) +SRC_C += \ + $(TOP)/$(PORT_DIR)/components/is25lp064a/is25lp064a_qspi.c +endif INC += \ $(TOP)/src \ diff --git a/ports/stm32h7/apps/self_update/Makefile b/ports/stm32h7/apps/self_update/Makefile index 700e8e61f..7c7c6d568 100644 --- a/ports/stm32h7/apps/self_update/Makefile +++ b/ports/stm32h7/apps/self_update/Makefile @@ -1,18 +1,21 @@ -OUTNAME = self_update-$(BOARD) +# OUTNAME = self_update-$(BOARD) -# skip tinyusb -BUILD_NO_TINYUSB = 1 +# # skip tinyusb +# BUILD_NO_TINYUSB = 1 -CFLAGS += -DTINYUF2_SELF_UPDATE +# CFLAGS += -DTINYUF2_SELF_UPDATE -SRC_C += \ - apps/self_update/self_update.c \ - $(TOP)/$(PORT_DIR)/apps/self_update/_build/bootloader_bin.c \ - $(TOP)/$(PORT_DIR)/boards.c \ - $(TOP)/$(PORT_DIR)/board_hmi.c \ - $(TOP)/$(PORT_DIR)/board_irq.c \ +# SRC_C += \ +# apps/self_update/self_update.c \ +# $(TOP)/$(PORT_DIR)/apps/self_update/_build/bootloader_bin.c \ +# $(TOP)/$(PORT_DIR)/boards.c \ +# $(TOP)/$(PORT_DIR)/board_hmi.c \ +# $(TOP)/$(PORT_DIR)/board_irq.c \ -INC += \ - $(TOP)/src \ +# INC += \ +# $(TOP)/src \ -include ../app.mk +# include ../app.mk + +all: + @echo "not implemented yet" From ef9729979c8e429fa53a7850985120ddc5fad9ff Mon Sep 17 00:00:00 2001 From: snkymkrct Date: Mon, 3 Mar 2025 13:05:27 +0100 Subject: [PATCH 7/9] correct USB PID and VID --- .github/workflows/build.yml | 2 +- ports/stm32h7/boards/daisy_seed/board.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0e638c12e..c9f998abe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -67,8 +67,8 @@ jobs: - 'stm32f3' - 'stm32f4' - 'stm32h5' - - 'stm32l4' - 'stm32h7' + - 'stm32l4' with: port: ${{ matrix.port }} boards: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.port].board) }} diff --git a/ports/stm32h7/boards/daisy_seed/board.h b/ports/stm32h7/boards/daisy_seed/board.h index 6ba56e359..0b5f3f111 100644 --- a/ports/stm32h7/boards/daisy_seed/board.h +++ b/ports/stm32h7/boards/daisy_seed/board.h @@ -62,8 +62,8 @@ extern "C" { // USB UF2 //--------------------------------------------------------------------+ -#define USB_VID 0x239A -#define USB_PID 0x005D +#define USB_VID 0x0483 +#define USB_PID 0x5740 #define USB_MANUFACTURER "STM32" #define USB_PRODUCT "STM32FH750IB" From 81ec22f747d6d03268371a209becf12e04d1a8dd Mon Sep 17 00:00:00 2001 From: snkymkrct Date: Fri, 28 Mar 2025 20:24:18 +0100 Subject: [PATCH 8/9] Add flash sector erase before page writes --- ports/stm32h7/board_flash.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ports/stm32h7/board_flash.c b/ports/stm32h7/board_flash.c index 12fec8522..3dbd6e494 100644 --- a/ports/stm32h7/board_flash.c +++ b/ports/stm32h7/board_flash.c @@ -12,6 +12,7 @@ #ifdef IS25LP064A #include "components/is25lp064a/is25lp064a_qspi.h" +#include "components/is25lp064a/is25lp064a.h" #endif #if defined (BOARD_QSPI_FLASH_EN) && (BOARD_QSPI_FLASH_EN == 1) @@ -239,8 +240,18 @@ bool board_flash_write(uint32_t addr, void const * data, uint32_t len) { // SET_BOOT_ADDR(BOARD_AXISRAM_APP_ADDR); // handles erasing internally + #ifdef IS25LP064A + // flash needs to be erased before writing + if (addr % IS25LP064A_SECTOR_SIZE == 0) { + // erase 4k sector ahead of next page writes + if (CSP_QSPI_EraseSector(addr, addr+IS25LP064A_SECTOR_SIZE) != qspi_OK) { + TUF2_LOG1("Error erasing sector at address: %lx \r\n",addr); + } + } + #endif if (qspi_Write((uint8_t *)data, (addr - QSPI_BASE_ADDR), len) != qspi_OK) { + TUF2_LOG1("Error QSPI Flash write\r\n"); __asm("bkpt #9"); } return true; From 822ec2aa304ca389d555977c2ca0a36bc93671ec Mon Sep 17 00:00:00 2001 From: snkymkrct Date: Sun, 30 Mar 2025 20:36:14 +0200 Subject: [PATCH 9/9] disable log and change boot label --- ports/stm32h7/boards/daisy_seed/board.h | 2 +- ports/stm32h7/boards/daisy_seed/board.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32h7/boards/daisy_seed/board.h b/ports/stm32h7/boards/daisy_seed/board.h index 0b5f3f111..c7e1691c0 100644 --- a/ports/stm32h7/boards/daisy_seed/board.h +++ b/ports/stm32h7/boards/daisy_seed/board.h @@ -69,7 +69,7 @@ extern "C" { #define UF2_PRODUCT_NAME USB_MANUFACTURER " " USB_PRODUCT #define UF2_BOARD_ID "STM32FH750IB-DaisySeed" -#define UF2_VOLUME_LABEL "DaisySeed" +#define UF2_VOLUME_LABEL "DaisyBOOT" #define UF2_INDEX_URL "https://electro-smith.com/products/daisy-seed" #define USB_NO_VBUS_PIN 1 diff --git a/ports/stm32h7/boards/daisy_seed/board.mk b/ports/stm32h7/boards/daisy_seed/board.mk index d2eed84c1..0770d255f 100644 --- a/ports/stm32h7/boards/daisy_seed/board.mk +++ b/ports/stm32h7/boards/daisy_seed/board.mk @@ -12,7 +12,7 @@ CFLAGS += \ MCU = h750xx -LOG = 1 +LOG = 0 SRC_S += \ $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h750xx.s