Compare commits

...

33 commits

Author SHA1 Message Date
Ha Thach
11e07c5a1b
Merge pull request #460 from sensebox/master
Add senseBox eye ESP32S3
2025-07-23 09:43:31 +07:00
Ha Thach
6c0c556436
Merge pull request #459 from UnexpectedCircuitPython/New_UM_boards
Added Unexpected Maker EdgeS3D
2025-07-23 09:42:10 +07:00
Mario Pesch
5c0e9b8f9b add favicon 2025-07-12 17:58:40 +02:00
Mario Pesch
55fede625d
update Neopixel Pin
update Neopixel Pin for Board Version v1.2
2025-07-12 17:52:44 +02:00
Seon Rozenblum
f4e9172f2f Added Unexpected Maker EdgeS3D 2025-07-12 14:25:11 +10:00
Mario Pesch
047e58f524
Merge branch 'adafruit:master' into master 2025-07-10 08:59:16 +02:00
Ha Thach
8542b474ff
Merge pull request #456 from adafruit/fix-release-esp
fix release asset with esp without combined-ota.bin
2025-07-03 17:32:00 +07:00
hathach
9c9a3328bd
fix release asset with esp without combined-ota.bin 2025-07-03 16:59:47 +07:00
Ha Thach
b250cb1408
Merge pull request #455 from adafruit/fix-release-asset
fix prepare release asset
2025-07-02 22:36:23 +07:00
hathach
c41356e5d8
fix prepare release asset 2025-07-02 21:27:03 +07:00
Dan Halbert
0e5f9f7be4
Merge pull request #454 from dhalbert/s3-upload-board-dirs
Upload Espressif bootloader .zip and combined*.bin to board-specific  dirs on S3
2025-06-30 10:06:17 -04:00
Dan Halbert
aabf153172 clean up workflow conditional; update to softprops/action-gh-release@v2 2025-06-30 09:10:23 -04:00
Ha Thach
9987ec807d
Merge pull request #453 from lyusupov/ESP32P4
add UF2 family ID for ESP32-P4
2025-06-30 09:34:09 +07:00
Dan Halbert
11e33c0a7d Upload Espressif bootloader .zip and combined*.bin to board-specific dirs on S3 2025-06-29 14:14:40 -04:00
Linar Yusupov
cb628c3411 add UF2 family ID for ESP32-P4 2025-06-29 08:58:45 +03:00
Ha Thach
d8185b8d2f
Merge pull request #439 from snkYmkrct/master
Add support for the Daisy Seed board - stm32H750
2025-06-13 20:37:41 +07:00
hathach
dd240b35b8
fix app build 2025-06-13 18:41:52 +07:00
hathach
bb49fbb469
Merge branch 'refs/heads/master' into fork/snkYmkrct/master
# Conflicts:
#	.github/workflows/build.yml
2025-06-13 17:01:22 +07:00
Ha Thach
07a6d75710
Merge pull request #446 from BrentK-ADI/add-max32-support
Add Port for ADI MCUs
2025-06-05 11:25:12 +07:00
hathach
2e1dc7fb69
re-enable espressif ci 2025-06-05 10:42:21 +07:00
Brent Kowal
00b57aa631 MAX32 OpenOCD cmake and README Updates
Updated the CMake rules for ADI/MAX32 parts using OpenOCD. This
corrects for some path mangling due to the MSDK being either Windows
or Linux based, and how MAXIM_PATH is set.

MAX32 README file updates to reflect the cmake build system updates.
2025-06-04 18:47:56 -04:00
hathach
2419f6512a
update Readme for cmake build system, remove all makefile 2025-06-04 16:46:45 +07:00
hathach
0805c2e70b
force CMAKE_BUILD_TYPE=MinSizeRel if not set 2025-06-04 15:52:50 +07:00
snkymkrct
822ec2aa30 disable log and change boot label 2025-03-30 20:36:14 +02:00
snkymkrct
81ec22f747 Add flash sector erase before page writes 2025-03-28 20:24:18 +01:00
snkymkrct
ef9729979c correct USB PID and VID 2025-03-28 20:06:27 +01:00
snkymkrct
924b7d86f0 self update is not yet properly implemented for the stm32h7 port 2025-03-28 20:06:27 +01:00
snkymkrct
998bedb57c add stm32h7 port to build workflow 2025-03-28 20:06:27 +01:00
snkymkrct
2ef7ccd2c4 pre-commit fixes 2025-03-28 20:06:27 +01:00
snkymkrct
a9dbffdfef Change Daisy board ID 2025-03-28 20:06:27 +01:00
snkymkrct
977e99e8a5 Add support for the Daisy Seed board - stm32H750 mcu 2025-03-28 20:06:27 +01:00
snkymkrct
0081b5ed06 fix stack address for dtcm 2025-03-28 20:06:27 +01:00
Mario Pesch
3ea0f24242 add senseBox-eye 2025-03-27 13:03:17 +00:00
46 changed files with 1603 additions and 617 deletions

View file

@ -65,6 +65,7 @@ jobs:
- 'lpc55' - 'lpc55'
- 'mimxrt10xx' - 'mimxrt10xx'
- 'stm32f3' - 'stm32f3'
- 'stm32h7'
- 'stm32l4' - 'stm32l4'
with: with:
port: ${{ matrix.port }} port: ${{ matrix.port }}

View file

@ -73,20 +73,22 @@ jobs:
- name: Prepare Release Asset - name: Prepare Release Asset
if: github.event_name == 'release' if: github.event_name == 'release'
run: | run: |
if [ ${{ inputs.toolchain }} == 'esp-idf' ]; then if [ ${{ inputs.toolchain }} == esp-idf ]; then
zip -jr tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.zip ${{ env.BIN_PATH }} zip -jr tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.zip ${{ env.BIN_PATH }}
cp ${{ env.BIN_PATH }}/combined.bin combined.bin
[ -f ${{ env.BIN_PATH }}/combined-ota.bin ] && cp ${{ env.BIN_PATH }}/combined-ota.bin combined-ota.bin
cp ${{ env.BIN_PATH }}/apps/update-tinyuf2.uf2 update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2 cp ${{ env.BIN_PATH }}/apps/update-tinyuf2.uf2 update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2
else else
if [[ ${{ inputs.build-system }} == cmake ]]; then if [[ ${{ inputs.build-system }} == cmake ]]; then
cp ${{ env.BIN_PATH }}/apps/update-tinyuf2.uf2 update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2 [ -f ${{ env.BIN_PATH }}/apps/update-tinyuf2.uf2 ] && cp ${{ env.BIN_PATH }}/apps/update-tinyuf2.uf2 update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2
else else
cp ${{ env.BIN_PATH }}/apps/update-tinyuf2-${{ matrix.board }}.uf2 update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2 [ -f ${{ env.BIN_PATH }}/apps/update-tinyuf2-${{ matrix.board }}.uf2] && cp ${{ env.BIN_PATH }}/apps/update-tinyuf2-${{ matrix.board }}.uf2 update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2
fi fi
zip -jr tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.zip ${{ env.BIN_PATH }} zip -jr tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.zip ${{ env.BIN_PATH }}
fi fi
- name: Upload Release Asset - name: Upload Release Asset
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v2
if: github.event_name == 'release' if: github.event_name == 'release'
with: with:
files: | files: |
@ -99,5 +101,11 @@ jobs:
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
if: github.event_name == 'release' && inputs.port == 'espressif' if: github.event_name == 'release' && inputs.port == 'espressif'
run: | run: |
[ -z \"$AWS_ACCESS_KEY_ID\" ] || aws s3 cp tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.zip s3://adafruit-circuit-python/bootloaders/esp32/tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.zip --no-progress --region us-east-1 if [ -n \"$AWS_ACCESS_KEY_ID\" ]; then
[ -z \"$AWS_ACCESS_KEY_ID\" ] || aws s3 cp update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2 s3://adafruit-circuit-python/bootloaders/esp32/update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2 --no-progress --region us-east-1 aws s3 cp tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.zip s3://adafruit-circuit-python/bootloaders/esp32/${{ matrix.board }}/tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.zip --no-progress --region us-east-1
aws s3 cp update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2 s3://adafruit-circuit-python/bootloaders/esp32/${{ matrix.board }}/update-tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}.uf2 --no-progress --region us-east-1
aws s3 cp combined.bin s3://adafruit-circuit-python/bootloaders/esp32/${{ matrix.board }}/tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}-combined.bin --no-progress --region us-east-1
if [ -f combined-ota.bin ]; then
aws s3 cp combined-ota.bin s3://adafruit-circuit-python/bootloaders/esp32/${{ matrix.board }}/tinyuf2-${{ matrix.board }}-${{ github.event.release.tag_name }}-combined-ota.bin --no-progress --region us-east-1
fi
fi

View file

@ -18,8 +18,8 @@ def set_matrix_json():
if b.is_dir(): if b.is_dir():
matrix[p.name]['board'].append(b.name) matrix[p.name]['board'].append(b.name)
# For quick testing by only build 1 espressif board # For quick testing by only build 1 espressif board
if p.name == 'espressif': # if p.name == 'espressif':
break # break
print(json.dumps(matrix)) print(json.dumps(matrix))

View file

@ -37,6 +37,8 @@
#define BOARD_UF2_FAMILY_ID 0xbfdd4eee #define BOARD_UF2_FAMILY_ID 0xbfdd4eee
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
#define BOARD_UF2_FAMILY_ID 0xc47e5767 #define BOARD_UF2_FAMILY_ID 0xc47e5767
#elif CONFIG_IDF_TARGET_ESP32P4
#define BOARD_UF2_FAMILY_ID 0x3d308e94
#else #else
#error unsupported MCUs #error unsupported MCUs
#endif #endif

View file

@ -0,0 +1,2 @@
# Apply board specific content here
set(IDF_TARGET "esp32s3")

View file

@ -0,0 +1,69 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Ha Thach (tinyusb.org) for Adafruit Industries
*
* 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 SENSEBOX_EYE_ESP32S3_H_
#define SENSEBOX_EYE_ESP32S3_H_
//--------------------------------------------------------------------+
// Button
//--------------------------------------------------------------------+
// Enter UF2 mode if GPIO is pressed while 2nd stage bootloader indicator
// is on e.g RGB = Purple. If it is GPIO0, user should not hold this while
// reset since that will instead run the 1st stage ROM bootloader
#define PIN_BUTTON_UF2 0
// GPIO that implement 1-bit memory with RC components which hold the
// pin value long enough for double reset detection.
// #define PIN_DOUBLE_RESET_RC
// GPIO connected to Neopixel data
#define NEOPIXEL_PIN 45
#define NEOPIXEL_POWER_STATE 1
// Brightness percentage from 1 to 255
#define NEOPIXEL_BRIGHTNESS 0x10
// Number of neopixels
#define NEOPIXEL_NUMBER 1
//--------------------------------------------------------------------+
// USB UF2
//--------------------------------------------------------------------+
#define USB_VID 0x303A
#define USB_PID 0x82D3
#define USB_MANUFACTURER "senseBox"
#define USB_PRODUCT "eye ESP32S3"
#define UF2_PRODUCT_NAME USB_MANUFACTURER " " USB_PRODUCT
#define UF2_BOARD_ID "ESP32S3-senseBox-eye"
#define UF2_VOLUME_LABEL "senseBox"
#define UF2_INDEX_URL "https://sensebox.de"
// Use favicon
#define TINYUF2_FAVICON_HEADER "favicon_sensebox_256.h"
#endif

View file

@ -0,0 +1,7 @@
# Board Specific Config
# Partition Table
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MB.csv"
# Serial flasher config
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y

View file

@ -0,0 +1,2 @@
# Apply board specific content here
set(IDF_TARGET "esp32s3")

View file

@ -0,0 +1,71 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Ha Thach (tinyusb.org) for Adafruit Industries
*
* 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 UNEXPECTEDMAKER_EDGE3SD_H_
#define UNEXPECTEDMAKER_EDGE3SD_H_
//--------------------------------------------------------------------+
// Button
//--------------------------------------------------------------------+
// Enter UF2 mode if GPIO is pressed while 2nd stage bootloader indicator
// is on e.g RGB = Purple. If it is GPIO0, user should not hold this while
// reset since that will instead run the 1st stage ROM bootloader
#define PIN_BUTTON_UF2 0
// GPIO that implement 1-bit memory with RC components which hold the
// pin value long enough for double reset detection.
// #define PIN_DOUBLE_RESET_RC 47
//--------------------------------------------------------------------+
// LED
//--------------------------------------------------------------------+
// GPIO connected to Neopixel data
// #define NEOPIXEL_PIN 35
// #define NEOPIXEL_POWER_PIN 34
// #define NEOPIXEL_POWER_STATE 1
// Brightness percentage from 1 to 255
// #define NEOPIXEL_BRIGHTNESS 0x64
// Number of neopixels
#define NEOPIXEL_NUMBER 0
//--------------------------------------------------------------------+
// USB UF2
//--------------------------------------------------------------------+
#define USB_VID 0x303A
#define USB_PID 0x82DE
#define USB_MANUFACTURER "Unexpected Maker"
#define USB_PRODUCT "EDGES3D"
#define UF2_PRODUCT_NAME USB_MANUFACTURER " " USB_PRODUCT
#define UF2_BOARD_ID "ESP32S3-EDGES3-01"
#define UF2_VOLUME_LABEL "EDGES3BOOT"
#define UF2_INDEX_URL "https://circuitpython.org/board/unexpectedmaker_edges3d/"
#endif

View file

@ -0,0 +1,7 @@
# Board Specific Config
# Partition Table
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MB.csv"
# Serial flasher config
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y

View file

@ -40,6 +40,8 @@
#define CFG_TUSB_MCU OPT_MCU_ESP32S2 #define CFG_TUSB_MCU OPT_MCU_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S3 #elif CONFIG_IDF_TARGET_ESP32S3
#define CFG_TUSB_MCU OPT_MCU_ESP32S3 #define CFG_TUSB_MCU OPT_MCU_ESP32S3
#elif CONFIG_IDF_TARGET_ESP32P4
#define CFG_TUSB_MCU OPT_MCU_ESP32P4
#endif #endif
#define CFG_TUSB_OS OPT_OS_FREERTOS #define CFG_TUSB_OS OPT_OS_FREERTOS

View file

@ -2,6 +2,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
set(UF2_FAMILY_ID_esp32s2 0xbfdd4eee) set(UF2_FAMILY_ID_esp32s2 0xbfdd4eee)
set(UF2_FAMILY_ID_esp32s3 0xc47e5767) set(UF2_FAMILY_ID_esp32s3 0xc47e5767)
set(UF2_FAMILY_ID_esp32p4 0x3d308e94)
set(UF2_FAMILY_ID ${UF2_FAMILY_ID_${IDF_TARGET}}) set(UF2_FAMILY_ID ${UF2_FAMILY_ID_${IDF_TARGET}})
# override default family_gen_uf2 # override default family_gen_uf2

View file

@ -33,6 +33,10 @@ if (NOT DEFINED TOOLCHAIN)
set(TOOLCHAIN gcc) set(TOOLCHAIN gcc)
endif () endif ()
if (NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Build type" FORCE)
endif ()
#------------------------------------------------------------- #-------------------------------------------------------------
# FAMILY and BOARD # FAMILY and BOARD
#------------------------------------------------------------- #-------------------------------------------------------------
@ -330,10 +334,17 @@ endfunction()
# Add flash openocd adi (Analog Devices) target # Add flash openocd adi (Analog Devices) target
# included with msdk or compiled from release branch of https://github.com/analogdevicesinc/openocd # included with msdk or compiled from release branch of https://github.com/analogdevicesinc/openocd
function(family_flash_openocd_adi TARGET) function(family_flash_openocd_adi TARGET)
if (DEFINED $ENV{MAXIM_PATH}) if (DEFINED MAXIM_PATH)
# use openocd from msdk # use openocd from msdk with MAXIM_PATH cmake variable first if the user
set(OPENOCD ENV{MAXIM_PATH}/Tools/OpenOCD/openocd) # specified it
set(OPENOCD_OPTION2 "-s $ENV{MAXIM_PATH}/Tools/OpenOCD/scripts") set(OPENOCD ${MAXIM_PATH}/Tools/OpenOCD/openocd)
set(OPENOCD_OPTION2 "-s ${MAXIM_PATH}/Tools/OpenOCD/scripts")
elseif (DEFINED ENV{MAXIM_PATH})
# use openocd from msdk with MAXIM_PATH environment variable. Normalize
# since msdk can be Windows (MinGW) or Linux
file(TO_CMAKE_PATH "$ENV{MAXIM_PATH}" MAXIM_PATH_NORM)
set(OPENOCD ${MAXIM_PATH_NORM}/Tools/OpenOCD/openocd)
set(OPENOCD_OPTION2 "-s ${MAXIM_PATH_NORM}/Tools/OpenOCD/scripts")
else() else()
# compiled from source # compiled from source
if (NOT DEFINED OPENOCD_ADI_PATH) if (NOT DEFINED OPENOCD_ADI_PATH)

View file

@ -1,3 +0,0 @@
# Ignore build logs
logs/
*.log

View file

@ -1,86 +0,0 @@
# List of git submodules that is included as part of the UF2 version
GIT_SUBMODULES = tinyusb
include ../make.mk
include port.mk
include ../rules.mk
################################################################################
# Optional Save Log Support
################################################################################
ifeq ($(SAVELOG),1)
TIMESTAMP := $(shell date +%Y%m%d_%H%M%S)
LOG_SUFFIX = _$(TIMESTAMP).log
endif
################################################################################
# Self-update
################################################################################
self-update:
@mkdir -p $(TOP)/$(PORT_DIR)/apps/self_update/logs/self-update
@echo "Building self-update application..."
ifeq ($(SAVELOG),1)
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update uf2 2>&1 | tee $(TOP)/$(PORT_DIR)/apps/self_update/logs/self-update/self-update$(LOG_SUFFIX)
else
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update uf2
endif
self-update-clean:
@mkdir -p $(TOP)/$(PORT_DIR)/apps/self_update/logs/self-update-clean
@echo "Cleaning self-update application..."
ifeq ($(SAVELOG),1)
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update clean 2>&1 | tee $(TOP)/$(PORT_DIR)/apps/self_update/logs/self-update-clean/self-update-clean$(LOG_SUFFIX)
else
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update clean
endif
################################################################################
# Erase Firmware
################################################################################
erase-firmware:
@mkdir -p $(TOP)/$(PORT_DIR)/apps/erase_firmware/logs/erase-firmware
@echo "Building erase-firmware application..."
ifeq ($(SAVELOG),1)
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/erase_firmware uf2 2>&1 | tee $(TOP)/$(PORT_DIR)/apps/erase_firmware/logs/erase-firmware/erase-firmware$(LOG_SUFFIX)
else
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/erase_firmware uf2
endif
erase-firmware-clean:
@mkdir -p $(TOP)/$(PORT_DIR)/apps/erase_firmware/logs/erase-firmware-clean
@echo "Cleaning erase-firmware application..."
ifeq ($(SAVELOG),1)
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/erase_firmware clean 2>&1 | tee $(TOP)/$(PORT_DIR)/apps/erase_firmware/logs/erase-firmware-clean/erase-firmware-clean$(LOG_SUFFIX)
else
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/erase_firmware clean
endif
################################################################################
# Blinky
################################################################################
blinky:
@mkdir -p $(TOP)/$(PORT_DIR)/apps/blinky/logs/blinky
@echo "Building blinky application..."
ifeq ($(SAVELOG),1)
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/blinky uf2 2>&1 | tee $(TOP)/$(PORT_DIR)/apps/blinky/logs/blinky/blinky$(LOG_SUFFIX)
else
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/blinky uf2
endif
blinky-clean:
@mkdir -p $(TOP)/$(PORT_DIR)/apps/blinky/logs/blinky-clean
@echo "Cleaning blinky application..."
ifeq ($(SAVELOG),1)
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/blinky clean 2>&1 | tee $(TOP)/$(PORT_DIR)/apps/blinky/logs/blinky-clean/blinky-clean$(LOG_SUFFIX)
else
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/blinky clean
endif
################################################################################
# Clean Logs
################################################################################
clean-logs:
@echo "Cleaning all log files..."
@rm -rf $(TOP)/$(PORT_DIR)/apps/self_update/logs
@rm -rf $(TOP)/$(PORT_DIR)/apps/erase_firmware/logs
@rm -rf $(TOP)/$(PORT_DIR)/apps/blinky/logs

View file

@ -1,6 +1,6 @@
# TinyUF2 - MAX32690 Port # TinyUF2 - MAX32690 Port
This folder contains the port of TinyUF2 for Analog Devices' MAX32690 MCU. This folder contains the port of TinyUF2 for Analog Devices' MAX32xxx/MAX78000 MCUs.
## Navigation ## Navigation
@ -17,16 +17,12 @@ This folder contains the port of TinyUF2 for Analog Devices' MAX32690 MCU.
- [J-Link vs OpenOCD](#j-link-vs-openocd) - [J-Link vs OpenOCD](#j-link-vs-openocd)
- [Flashing with J-Link](#1-j-link-default) - [Flashing with J-Link](#1-j-link-default)
- [Flashing with OpenOCD (MSDK)](#2-openocd-from-msdk-optional) - [Flashing with OpenOCD (MSDK)](#2-openocd-from-msdk-optional)
- [Notes on SAVELOG=1](#notes-on-savelog1)
- [Cleaning Logs](#cleaning-logs)
- [Flashing Example Applications](#flashing-example-applications) - [Flashing Example Applications](#flashing-example-applications)
- [Flashing via Drag-and-Drop](#flashing-via-drag-and-drop) - [Flashing via Drag-and-Drop](#flashing-via-drag-and-drop)
- [Re-Entering Bootloader Mode](#re-entering-bootloader-mode) - [Re-Entering Bootloader Mode](#re-entering-bootloader-mode)
- [Port Directory Structure](#port-directory-structure) - [Port Directory Structure](#port-directory-structure)
<br>
## Requirements ## Requirements
This guide focuses on building TinyUF2 for Analog Devices' MAX32 parts. This guide focuses on building TinyUF2 for Analog Devices' MAX32 parts.
@ -40,13 +36,13 @@ All you need is a basic toolchain:
- **GNU ARM Toolchain** (`arm-none-eabi-gcc`) available in your `PATH` - **GNU ARM Toolchain** (`arm-none-eabi-gcc`) available in your `PATH`
- **make** - **make**
- **CMake**
- **git** (required for submodules) - **git** (required for submodules)
- **SDK Dependencies** - **SDK Dependencies**
### Installing SDK Dependencies ### Installing SDK Dependencies
```bash ```bash
python tools/get_deps.py max32 python tools/get_deps.py maxim
``` ```
or or
```bash ```bash
@ -56,21 +52,13 @@ python tools/get_deps.py --board apard32690
#### macOS Dependency Install #### macOS Dependency Install
```bash ```bash
brew install arm-none-eabi-gcc make git brew install arm-none-eabi-gcc make cmake git
``` ```
#### Ubuntu Dependency Install #### Ubuntu Dependency Install
```bash ```bash
sudo apt update sudo apt update
sudo apt install gcc-arm-none-eabi make git sudo apt install gcc-arm-none-eabi make cmake git
```
<br><br>
```bash
# Example usage:
cd ports/max32690/
make BOARD=apard32690 all
``` ```
--- ---
@ -103,9 +91,6 @@ If needed, set `MAXIM_PATH` to point to your MSDK installation:
export MAXIM_PATH=/c/MaximSDK export MAXIM_PATH=/c/MaximSDK
``` ```
<br>
## MSDK (Windows) Environment Setup ## MSDK (Windows) Environment Setup
### 1. Using MSDK's MSYS2 ### 1. Using MSDK's MSYS2
@ -126,128 +111,122 @@ If you are using your own MSYS2 or mingw installation (not MSDKs MSYS2), you
export PATH="/c/MaximSDK/Tools/GNUTools/10.3/bin/:$PATH" export PATH="/c/MaximSDK/Tools/GNUTools/10.3/bin/:$PATH"
``` ```
Or in one-line command for building:
```bash
PATH="/c/MaximSDK/Tools/GNUTools/10.3/bin/:$PATH" make BOARD=apard32690 blinky erase-firmware self-update
```
(Adjust the path if your MSDK installation is in a different location.) (Adjust the path if your MSDK installation is in a different location.)
<br>
## Available Boards ## Available Boards
Each port supports multiple hardware platforms. Each port supports multiple hardware platforms.
The specific boards available for each device can be found inside: The specific boards available for each device can be found inside:
``` ```
ports/maxxxxxx/boards/ ports/maxim/boards/
``` ```
For example, for MAX32690: For example:
``` ```
tinyuf2/ports/max32690/boards/ tinyuf2/ports/maxim/boards/
apard32690 apard32690
max32650evkit
max32650fthr
max32666evkit
max32666fthr
max32690evkit max32690evkit
max78002evkit
``` ```
When building or flashing, make sure to specify a valid `BOARD` name from the available list: When initially configuring cmake, make sure to specify a valid `BOARD` name from the available list. Otherwise, the build will fail if an invalid board name is provided.
```bash ```bash
make BOARD=apard32690 all cmake -DBOARD=apard32690 ..
make BOARD=apard32690 flash
``` ```
Otherwise, the build will fail if an invalid board name is provided. Afterward, all the cmake/cmake commands can be run within the `build` directory without needing to specify the board again, as it will be cached.
<br> <br>
## Building the Bootloader ## Building the Bootloader and Applications
1. Open your MSYS2 terminal (preferably MSDKs). 1. Open your MSYS2 terminal (preferably MSDKs).
2. Navigate to the port folder for MAX32690: 2. Navigate to the maxim folder, create a build directory, and change into it:
```bash ```bash
cd ports/max32690 cd ports/maxim
mkdir build
cd build
``` ```
3. Build the TinyUF2 bootloader: 3. Configure cmake with correct BOARD and run make to build:
```bash ```bash
make BOARD=apard32690 all cmake -DBOARD=apard32690 ..
make
``` ```
It will build the TinyUF2 bootloader along with all supported application e.g blinky, update-tinyuf2, erase-firmware. Tinyuf2 binaries will appear in `build/` folder while application are created in `build/apps/$(APP)/`.
Output files will appear in `_build/` and build logs under `apps/$(APP)/logs/`. - **Blinky** (`apps/blinky`) is useful to quickly test the bootloader
- **Erase Firmware** (`apps/erase_firmware`) put the board into a clean state
- **Self-Update** (`apps/self_update`) allows updating the bootloader itself
To list all supported targets, run:
<br>
## Building Demo Applications
TinyUF2 for MAX32690 includes three demo applications:
- **Blinky** (`apps/blinky`)
- **Erase Firmware** (`apps/erase_firmware`)
- **Self-Update** (`apps/self_update`)
### To Build Individual Applications:
```bash ```bash
make BOARD=apard32690 blinky cmake --build . --target help
make BOARD=apard32690 erase-firmware
make BOARD=apard32690 self-update The following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
... edit_cache
... rebuild_cache
... blinky-uf2
... erase_firmware-uf2
... tinyuf2-erase-jlink
... tinyuf2-jlink
... tinyuf2-openocd
... update-tinyuf2-uf2
... blinky
... board_max32666fthr
... erase_firmware
... tinyuf2
... update-tinyuf2
``` ```
### To Clean Individual Applications: ### To Build Individual Targets
To build a specific target, you can specify it directly with `make` or using `cmake --build`:
```bash ```bash
make BOARD=apard32690 blinky-clean make blinky
make BOARD=apard32690 erase-firmware-clean cmake --build . --target blinky
make BOARD=apard32690 self-update-clean
```
You can add `SAVELOG=1` to any of these commands to generate a saved build log.
```bash
make BOARD=apard32690 SAVELOG=1 blinky erase-firmware self-update
``` ```
<br> <br>
## Flashing the Bootloader ## Flashing the Bootloader
### J-Link and OpenOCD
### J-Link vs OpenOCD
TinyUF2 supports two main ways to flash firmware: TinyUF2 supports two main ways to flash firmware:
- **J-Link** (default): Uses SEGGER's proprietary debug probe. Supports fast, reliable flashing and debugging over SWD or JTAG. Requires a J-Link device and SEGGER drivers. - **J-Link**: Uses SEGGER's proprietary debug probe. Supports fast, reliable flashing and debugging over SWD or JTAG. Requires a J-Link device and SEGGER drivers.
- **OpenOCD (MSDK)**: Open-source tool for programming/debugging via CMSIS-DAP or other adapters. - **OpenOCD (MSDK)**: Open-source tool for programming/debugging via CMSIS-DAP or other adapters.
The MSDK includes a custom version of OpenOCD that supports MAX32 devices, since official OpenOCD does not yet have MAX32 flash algorithm support. The MSDK includes a custom version of OpenOCD that supports MAX32 devices, since official OpenOCD does not yet have MAX32 flash algorithm support.
### 1. J-Link
<br>
`make flash` will use **J-Link** by default.
`make flash-msdk` to use the **OpenOCD** path with CMSIS-DAP.
### 1. J-Link (default)
To flash using a J-Link debugger: To flash using a J-Link debugger:
```bash ```bash
make BOARD=apard32690 flash make tinyuf2-jlink
``` ```
To erase before flashing: To erase before flashing:
```bash ```bash
make BOARD=apard32690 erase flash make tinyuf2-erase-jlink tinyuf2-jlink
``` ```
### 2. OpenOCD from MSDK (optional) ### 2. OpenOCD from MSDK (optional)
@ -255,77 +234,56 @@ make BOARD=apard32690 erase flash
If you prefer OpenOCD and you have it installed through MSDK: If you prefer OpenOCD and you have it installed through MSDK:
```bash ```bash
make BOARD=apard32690 flash-msdk make tinyuf2-openocd
``` ```
Make sure `MAXIM_PATH` is correctly set to the MSDK base folder. If your default installation of the MSDK is not `C:/MaximSDK` you can pass the MaximSDK directory's location... CMake will automatically leverage the MAXIM_PATH system environment variable if
a MAXIM_PATH is not manually specified. To manually specify a MSDK path,
you can pass the MaximSDK directory's location to cmake when configuring the
build:
```bash ```bash
make BOARD=apard32690 MAXIM_PATH=C:/MaximSDK flash-msdk cmake -DBOARD=apard32690 -DMAXIM_PATH=/path/to/MaximSDK ..
``` ```
or after initial configuration (in the build directory):
> ⚠️ **Note:**
> Optional flash option when running within an installed MSDK to use OpenOCD. Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated. If the MSDK is installed, flash-msdk can be run to utilize the the modified openocd with the algorithms.
<br>
## Notes on SAVELOG=1
Log export options are available for demo apps.
If `SAVELOG=1` is set during a build:
- Output logs are automatically saved into a `logs/` folder inside each application.
- Each application target (e.g., `blinky`, `blinky-clean`) has its own separate subfolder and timestamped `.log` files.
- Log files are ignored from Git version control.
Example:
```
apps/blinky/logs/blinky/blinky_20250425_134500.log
apps/blinky/logs/blinky-clean/blinky-clean_20250425_134512.log
```
<br>
## Cleaning Logs
You can remove all saved build logs across all apps by running:
```bash ```bash
make BOARD=apard32690 clean-logs cmake -DMAXIM_PATH=C:/MaximSDK .
``` ```
This deletes all `logs/` directories under `apps/blinky`, `apps/erase_firmware`, and `apps/self_update`.
<br>
## Flashing Example Applications ## Flashing Example Applications
After building any of the demo applications (Blinky, Erase Firmware, or Self-Update), a UF2 file will be generated in: After building any of the demo applications (Blinky, Erase Firmware, or Self-Update), a UF2 file will be generated in:
``` ```
apps/<application>/_build/<board>/<application>-<board>.uf2 build/apps/<application>/<application>.uf2
``` ```
For example: For example:
``` ```
apps/blinky/_build/<board>/blinky-<board>.uf2 apps/blinky/blinky.uf2
``` ```
### Flashing via Drag-and-Drop ### Flashing via Drag-and-Drop
1. **Enter bootloader mode** on your board: 1. **Enter bootloader mode** on your board:
- Typically, perform a **double-tap on the reset button** within **500 milliseconds**. - Typically, perform a **double-tap on the reset button** within **500 milliseconds**.
- The board will appear as a **USB mass storage device** (for example, named `TINYUF2`) in your operating system's **File Explorer** (Windows) or **Finder** (macOS) or **File Manager** (Linux). - The board will appear as a **USB mass storage device** (for example, named `3269BOOT`) in your operating system's **File Explorer** (Windows) or **Finder** (macOS) or **File Manager** (Linux).
2. **Using your file explorer**, locate the `.uf2` file you built, and **drag and drop** it onto the mounted TinyUF2 USB drive. 2. **Using your file explorer**, locate the `.uf2` file you built, and **drag and drop** it onto the mounted TinyUF2 USB drive.
3. The board will automatically reboot and begin running the new application. 3. The board will automatically reboot and begin running the new application.
### Flashing using make/cmake
To flash an application using the command line, you can use the `make` or `cmake` command:
```bash
make blinky-uf2
cmake --build . --target blinky-uf2
```
### Re-Entering Bootloader Mode ### Re-Entering Bootloader Mode
To flash a different application or return to bootloader mode: To flash a different application or return to bootloader mode:
@ -333,47 +291,32 @@ To flash a different application or return to bootloader mode:
- Perform another **double-tap** of the reset button within 500 milliseconds. - Perform another **double-tap** of the reset button within 500 milliseconds.
- The board will reappear as a USB mass storage device for new UF2 flashing. - The board will reappear as a USB mass storage device for new UF2 flashing.
<br>
> ⚠️ **Note:** > ⚠️ **Note:**
> If double-tap reset does not work (for example, if the running application has corrupted necessary flash metadata), you may need to manually reflash the TinyUF2 bootloader using a SWD debug tool such as J-Link or OpenOCD. > If double-tap reset does not work (for example, if the running application has corrupted necessary flash metadata), you may need to manually reflash the TinyUF2 bootloader using a SWD debug tool such as J-Link or OpenOCD.
> Refer to your board's documentation for additional recovery options if needed. > Refer to your board's documentation for additional recovery options if needed.
<br>
## Port Directory Structure ## Port Directory Structure
Example directory tree for the MAX32690 port:
``` ```
max32690 ├── app.cmake
├── Makefile
├── README.md
├── _build
├── apps
│ ├── blinky
│ │ ├── Makefile
│ │ └── _build
│ ├── erase_firmware
│ │ ├── Makefile
│ │ └── _build
│ └── self_update
│ ├── Makefile
│ └── _build
├── board_flash.c ├── board_flash.c
├── boards ├── boards
│ ├── apard32690 │ ├── apard32690
│ │ ├── board.h │ ├── max32650evkit
│ │ └── board.mk │ ├── max32650fthr
│ └── max32690evkit │ ├── max32666evkit
│ ├── board.h │ ├── max32666fthr
│ └── board.mk │ ├── max32690evkit
│ └── max78002evkit
├── boards.c ├── boards.c
├── boards.h ├── boards.h
├── CMakeLists.txt
├── family.cmake
├── linker ├── linker
│ ├── max32690_app.ld │ ├── max32650
│ ├── max32690_boot.ld │ ├── max32665
│ └── max32690_common.ld │ ├── max32690
├── port.mk │ └── max78002
├── README.md
└── tusb_config.h └── tusb_config.h
``` ```

View file

@ -1,19 +0,0 @@
PORT = max32690
OUTNAME = blinky-$(BOARD)
BUILD_APPLICATION = 1
BUILD_NO_TINYUSB = 1
include ../../../make.mk
include ../../port.mk
SRC_C += \
apps/blinky/blinky.c \
include ../../../rules.mk
uf2: $(BUILD)/$(OUTNAME).uf2
$(BUILD)/$(OUTNAME).uf2: $(BUILD)/$(OUTNAME).hex
@echo CREATE $@
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^

View file

@ -1,19 +0,0 @@
PORT = max32690
OUTNAME = erase_firmware-$(BOARD)
BUILD_APPLICATION = 1
BUILD_NO_TINYUSB = 1
include ../../../make.mk
include ../../port.mk
SRC_C += \
apps/erase_firmware/erase_firmware.c \
include ../../../rules.mk
uf2: $(BUILD)/$(OUTNAME).uf2
$(BUILD)/$(OUTNAME).uf2: $(BUILD)/$(OUTNAME).hex
@echo CREATE $@
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^

View file

@ -1,23 +0,0 @@
PORT = max32690
OUTNAME = self-update-$(BOARD)
BUILD_APPLICATION = 1
BUILD_NO_TINYUSB = 1
CFLAGS += -DTINYUF2_SELF_UPDATE
include ../../../make.mk
include ../../port.mk
SRC_C += \
apps/self_update/self_update.c \
$(TOP)/$(PORT_DIR)/apps/self_update/_build/bootloader_bin.c \
include ../../../rules.mk
uf2: $(BUILD)/$(OUTNAME).uf2
$(BUILD)/$(OUTNAME).uf2: $(BUILD)/$(OUTNAME).hex
@echo CREATE $@
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID) -c -o $@ $^

View file

@ -1 +0,0 @@
# No specific build requirements for the board.

View file

@ -1 +0,0 @@
# No specific build requirements for the board.

View file

@ -1 +0,0 @@
# No specific build requirements for the board.

View file

@ -1,6 +1,5 @@
set(MAX_DEVICE max32665) set(MAX_DEVICE max32665)
set(JLINK_DEVICE max32666) set(JLINK_DEVICE max32666)
#set(JLINK_OPTION "-USB 801011822")
function(update_board TARGET) function(update_board TARGET)
endfunction() endfunction()

View file

@ -1 +0,0 @@
# No specific build requirements for the board.

View file

@ -1,6 +1,5 @@
set(MAX_DEVICE max32665) set(MAX_DEVICE max32665)
set(JLINK_DEVICE max32666) set(JLINK_DEVICE max32666)
#set(JLINK_OPTION "-USB 801011822")
function(update_board TARGET) function(update_board TARGET)
endfunction() endfunction()

View file

@ -1 +0,0 @@
# No specific build requirements for the board.

View file

@ -1,6 +1,5 @@
set(MAX_DEVICE max32690) set(MAX_DEVICE max32690)
set(JLINK_DEVICE ${MAX_DEVICE}) set(JLINK_DEVICE ${MAX_DEVICE})
#set(JLINK_OPTION "-USB jtrace")
function(update_board TARGET) function(update_board TARGET)
endfunction() endfunction()

View file

@ -1 +0,0 @@
# No specific build requirements for the board.

View file

@ -1 +0,0 @@
# No specific build requirements for the board.

View file

@ -1,119 +0,0 @@
UF2_FAMILY_ID = 0x7410520a
CROSS_COMPILE = arm-none-eabi-
JLINK_DEVICE = MAX32690
# Important locations in the hw support for MCU
MAX32_CMSIS = lib/mcu/analog/msdk/Libraries/CMSIS
MAX32_PERIPH = lib/mcu/analog/msdk/Libraries/PeriphDrivers
PERIPH_SRC = $(MAX32_PERIPH)/Source
FLASH_BOOT_SIZE := 0x8000 #32K
# Port Compiler Flags
CFLAGS += \
-mthumb \
-mabi=aapcs \
-mcpu=cortex-m4 \
# Flags for TUSB features
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_MAX32690 \
-DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
# Flags for the MAX32690 SDK
CFLAGS += \
-DTARGET=MAX32690 \
-DTARGET_REV=0x4131 \
-DMXC_ASSERT_ENABLE \
-DMAX32690 \
-DIAR_PRAGMAS=0 \
-DFLASH_BOOT_SIZE=$(FLASH_BOOT_SIZE) \
-DMAX_PERIPH_ID=18 \
# mcu driver cause following warnings
CFLAGS += \
-Wno-error=unused-parameter \
-Wno-error=strict-prototypes \
-Wno-error=old-style-declaration \
-Wno-error=sign-compare \
-Wno-error=cast-qual \
-Wno-lto-type-mismatch \
# default linker file
ifdef BUILD_APPLICATION
LD_FILES ?= \
$(PORT_DIR)/linker/max32690/max32690_app.ld \
$(PORT_DIR)/linker/max32690/max32690_common.ld
else
LD_FILES ?= \
$(PORT_DIR)/linker/max32690/max32690_boot.ld \
$(PORT_DIR)/linker/max32690/max32690_common.ld
endif
LDFLAGS += -nostartfiles -Wl,--defsym=__FLASH_BOOT_SIZE=${FLASH_BOOT_SIZE} \
# Port source
SRC_C += \
$(PORT_DIR)/boards.c \
$(PORT_DIR)/board_flash.c \
$(MAX32_CMSIS)/Device/Maxim/MAX32690/Source/heap.c \
$(MAX32_CMSIS)/Device/Maxim/MAX32690/Source/system_max32690.c \
$(PERIPH_SRC)/SYS/mxc_assert.c \
$(PERIPH_SRC)/SYS/mxc_delay.c \
$(PERIPH_SRC)/SYS/mxc_lock.c \
$(PERIPH_SRC)/SYS/nvic_table.c \
$(PERIPH_SRC)/SYS/pins_me18.c \
$(PERIPH_SRC)/SYS/sys_me18.c \
$(PERIPH_SRC)/CTB/ctb_me18.c \
$(PERIPH_SRC)/CTB/ctb_reva.c \
$(PERIPH_SRC)/CTB/ctb_common.c \
$(PERIPH_SRC)/FLC/flc_common.c \
$(PERIPH_SRC)/FLC/flc_me18.c \
$(PERIPH_SRC)/FLC/flc_reva.c \
$(PERIPH_SRC)/GPIO/gpio_common.c \
$(PERIPH_SRC)/GPIO/gpio_me18.c \
$(PERIPH_SRC)/GPIO/gpio_reva.c \
$(PERIPH_SRC)/ICC/icc_me18.c \
$(PERIPH_SRC)/ICC/icc_reva.c \
$(PERIPH_SRC)/UART/uart_common.c \
$(PERIPH_SRC)/UART/uart_me18.c \
$(PERIPH_SRC)/UART/uart_revb.c \
ifndef BUILD_NO_TINYUSB
SRC_C += lib/tinyusb/src/portable/mentor/musb/dcd_musb.c
endif
SRC_S += $(MAX32_CMSIS)/Device/Maxim/MAX32690/Source/GCC/startup_max32690.S
# Port include
INC += \
$(TOP)/lib/CMSIS_5/CMSIS/Core/Include \
$(TOP)/$(MAX32_CMSIS)/Device/Maxim/MAX32690/Include \
$(TOP)/$(MAX32_PERIPH)/Include/MAX32690 \
$(TOP)/$(PERIPH_SRC)/SYS \
$(TOP)/$(PERIPH_SRC)/GPIO \
$(TOP)/$(PERIPH_SRC)/CTB \
$(TOP)/$(PERIPH_SRC)/ICC \
$(TOP)/$(PERIPH_SRC)/FLC \
$(TOP)/$(PERIPH_SRC)/UART
# By default use JLink to the flash the devices since OpenOCD requires ADI's
# OpenOCD fork until the part support can get mainlined. See flash-msdk below
# to use OpenOCD from ADI
flash: flash-jlink
erase: erase-jlink
# Optional flash option when running within an installed MSDK to use OpenOCD
# Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated.
# If the MSDK is installed, flash-msdk can be run to utilize the the modified
# openocd with the algorithms
# Convert Windows-style \ to /
MAXIM_PATH := $(subst \,/,$(MAXIM_PATH))
flash-msdk: $(BUILD)/$(OUTNAME).elf
$(MAXIM_PATH)/Tools/OpenOCD/openocd -s $(MAXIM_PATH)/Tools/OpenOCD/scripts \
-f interface/cmsis-dap.cfg -f target/max32690.cfg \
-c "program $(BUILD)/$(OUTNAME).elf verify; init; reset; exit"

View file

@ -22,11 +22,13 @@ include ../rules.mk
# This uf2 will be loaded into RAM # This uf2 will be loaded into RAM
# TODO: this needs to build the actual uf2 binary first # TODO: this needs to build the actual uf2 binary first
self-update: $(BUILD)/$(OUTNAME).bin self-update: $(BUILD)/$(OUTNAME).bin
$(PYTHON3) $(TOP)/lib/uf2/utils/uf2conv.py --carray $^ -o apps/self_update/_build/bootloader_bin.c @echo "not implemented yet"
$(MAKE) -C $(TOP)/$(PORT_DIR)/apps/self_update uf2 # $(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: 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 ---------- #---------- Erase app ----------
# Compile apps/erase_firmware/erase_firmware.c # Compile apps/erase_firmware/erase_firmware.c

View file

@ -4,12 +4,10 @@ OUTNAME = erase_firmware-$(BOARD)
BUILD_NO_TINYUSB = 1 BUILD_NO_TINYUSB = 1
SRC_C += \ SRC_C += \
apps/erase_firmware/erase_firmware.c \ apps/erase_firmware/src/erase_firmware.c \
$(TOP)/$(PORT_DIR)/boards.c \ $(PORT_DIR)/boards.c \
$(TOP)/$(PORT_DIR)/board_flash.c \ $(PORT_DIR)/board_flash.c \
$(TOP)/$(PORT_DIR)/board_irq.c \ $(PORT_DIR)/board_irq.c \
$(TOP)/$(PORT_DIR)/components/w25qxx/w25qxx.c \
$(TOP)/$(PORT_DIR)/components/w25qxx/w25qxx_qspi.c \
INC += \ INC += \
$(TOP)/src \ $(TOP)/src \

View file

@ -1,18 +1,21 @@
OUTNAME = self_update-$(BOARD) # OUTNAME = self_update-$(BOARD)
# skip tinyusb # # skip tinyusb
BUILD_NO_TINYUSB = 1 # BUILD_NO_TINYUSB = 1
CFLAGS += -DTINYUF2_SELF_UPDATE # CFLAGS += -DTINYUF2_SELF_UPDATE
SRC_C += \ # SRC_C += \
apps/self_update/self_update.c \ # apps/self_update/self_update.c \
$(TOP)/$(PORT_DIR)/apps/self_update/_build/bootloader_bin.c \ # $(TOP)/$(PORT_DIR)/apps/self_update/_build/bootloader_bin.c \
$(TOP)/$(PORT_DIR)/boards.c \ # $(TOP)/$(PORT_DIR)/boards.c \
$(TOP)/$(PORT_DIR)/board_hmi.c \ # $(TOP)/$(PORT_DIR)/board_hmi.c \
$(TOP)/$(PORT_DIR)/board_irq.c \ # $(TOP)/$(PORT_DIR)/board_irq.c \
INC += \ # INC += \
$(TOP)/src \ # $(TOP)/src \
include ../app.mk # include ../app.mk
all:
@echo "not implemented yet"

View file

@ -1,5 +1,6 @@
#include "board_api.h" #include "board_api.h"
#include "stm32h7xx_hal.h" #include "stm32h7xx_hal.h"
#include "qspi_status.h"
#ifdef W25Qx_SPI #ifdef W25Qx_SPI
#include "components/w25qxx/w25qxx.h" #include "components/w25qxx/w25qxx.h"
@ -9,11 +10,16 @@
#include "components/w25qxx/w25qxx_qspi.h" #include "components/w25qxx/w25qxx_qspi.h"
#endif // W25Qx_QSPI #endif // W25Qx_QSPI
#if BOARD_QSPI_FLASH_EN #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)
QSPI_HandleTypeDef _qspi_flash; QSPI_HandleTypeDef _qspi_flash;
#endif // BOARD_QSPI_FLASH_EN #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; SPI_HandleTypeDef _spi_flash;
#endif // BOARD_SPI_FLASH_EN #endif // BOARD_SPI_FLASH_EN
@ -53,6 +59,67 @@ extern volatile uint32_t _board_tmp_boot_magic[];
#define TMP_BOOT_ADDR _board_tmp_boot_addr[0] #define TMP_BOOT_ADDR _board_tmp_boot_addr[0]
#define TMP_BOOT_MAGIC _board_tmp_boot_magic[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 enabling 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) uint32_t board_get_app_start_address(void)
{ {
if (TMP_BOOT_MAGIC == 0xDEADBEEFU) if (TMP_BOOT_MAGIC == 0xDEADBEEFU)
@ -79,19 +146,19 @@ void board_clear_temp_boot_addr(void)
void board_flash_early_init(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 is initialized early to check for executable code
qspi_flash_init(&_qspi_flash); qspi_flash_init(&_qspi_flash);
// Initialize QSPI driver // Initialize QSPI driver
w25qxx_Init(); qspi_Init();
// SPI -> QPI // SPI -> QPI
w25qxx_EnterQPI(); qspi_EnterQPI();
#endif // BOARD_QSPI_FLASH_EN #endif // BOARD_QSPI_FLASH_EN
} }
void board_flash_init(void) void board_flash_init(void)
{ {
#if BOARD_SPI_FLASH_EN #if defined (BOARD_SPI_FLASH_EN) && (BOARD_SPI_FLASH_EN == 1)
// Initialize SPI peripheral // Initialize SPI peripheral
spi_flash_init(&_spi_flash); spi_flash_init(&_spi_flash);
// Initialize SPI drivers // Initialize SPI drivers
@ -101,10 +168,10 @@ void board_flash_init(void)
void board_flash_deinit(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 // Enable Memory Mapped Mode
// QSPI flash will be available at 0x90000000U (readonly) // QSPI flash will be available at 0x90000000U (readonly)
w25qxx_Startup(w25qxx_DTRMode); qspi_Startup();
#endif // BOARD_QSPI_FLASH_EN #endif // BOARD_QSPI_FLASH_EN
} }
@ -123,16 +190,16 @@ void board_flash_flush(void)
void board_flash_read(uint32_t addr, void * data, uint32_t len) 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); 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; // addr += QSPI_BASE_ADDR;
if (IS_QSPI_ADDR(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; return;
} }
#endif #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)) if (IS_AXISRAM_ADDR(addr) && IS_AXISRAM_ADDR(addr + len - 1))
{ {
memcpy(data, (void *) addr, len); memcpy(data, (void *) addr, len);
@ -156,11 +223,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); 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 // TODO: these should be configurable parameters
// Page size = 256 bytes // Page size = 256 bytes
// Sector size = 4K 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)) if (IS_SPI_ADDR(addr) && IS_SPI_ADDR(addr + len - 1))
{ {
W25Qx_Write((uint8_t *) data, (addr - SPI_BASE_ADDR), len); W25Qx_Write((uint8_t *) data, (addr - SPI_BASE_ADDR), len);
@ -168,20 +235,30 @@ bool board_flash_write(uint32_t addr, void const * data, uint32_t len)
} }
#endif #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)) if (IS_QSPI_ADDR(addr) && IS_QSPI_ADDR(addr + len - 1))
{ {
// SET_BOOT_ADDR(BOARD_AXISRAM_APP_ADDR); // SET_BOOT_ADDR(BOARD_AXISRAM_APP_ADDR);
// handles erasing internally // handles erasing internally
if (W25qxx_Write((uint8_t *)data, (addr - QSPI_BASE_ADDR), len) != w25qxx_OK) #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"); __asm("bkpt #9");
} }
return true; return true;
} }
#endif #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)) if (IS_AXISRAM_ADDR(addr) && IS_AXISRAM_ADDR(addr + len - 1))
{ {
// This memory is cached, DCache is cleaned in dfu_complete // This memory is cached, DCache is cleaned in dfu_complete
@ -211,13 +288,13 @@ void board_flash_erase_app(void)
{ {
board_flash_init(); 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"); TUF2_LOG1("Erasing QSPI Flash\r\n");
// Erase QSPI Flash // Erase QSPI Flash
(void) W25qxx_EraseChip(); (void) qspi_EraseChip();
#endif #endif
#if BOARD_SPI_FLASH_EN #if defined(BOARD_SPI_FLASH_EN) && (BOARD_SPI_FLASH_EN == 1)
TUF2_LOG1("Erasing SPI Flash\r\n"); TUF2_LOG1("Erasing SPI Flash\r\n");
// Erase QSPI Flash // Erase QSPI Flash
(void) W25Qx_Erase_Chip(); (void) W25Qx_Erase_Chip();

View file

@ -19,49 +19,44 @@ void ST7735_Delay(uint32_t ms)
{ {
HAL_Delay(ms); HAL_Delay(ms);
} }
#endif
void board_display_init(void) void board_display_init(void)
{ {
#if (TINYUF2_DISPLAY == 1U)
display_init(&_display_spi); display_init(&_display_spi);
ST7735_Init(); ST7735_Init();
// Clear previous screen // Clear previous screen
ST7735_FillScreen(ST7735_BLACK); ST7735_FillScreen(ST7735_BLACK);
#endif // TINYUF2_DISPLAY == 1U
} }
// The application draws a complete frame in memory and sends it // The application draws a complete frame in memory and sends it
// line-by-line to the display // line-by-line to the display
void board_display_draw_line(int y, uint16_t* pixel_color, uint32_t pixel_num) 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) { for (uint32_t x = 0; x < pixel_num; x += 1) {
ST7735_DrawPixel(y, x, pixel_color[x]); ST7735_DrawPixel(y, x, pixel_color[x]);
} }
#endif // TINYUF2_DISPLAY == 1U
} }
#endif // TINYUF2_DISPLAY == 1U
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// LED pattern // LED pattern
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
#if defined(TINYUF2_LED)
void board_led_write(uint32_t state) 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); HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? GPIO_PIN_SET : GPIO_PIN_RESET);
#endif // defined(LED_PIN)
} }
#endif // defined(LED_PIN)
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Button // Button
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
#if defined(BUTTON_PIN)
uint32_t board_button_read(void) uint32_t board_button_read(void)
{ {
#if defined(BUTTON_PIN)
return (BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN)) ? 1: 0; 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 // Neopixel color for status

View file

@ -1,8 +1,27 @@
#include "stm32h7xx_hal.h" #include "stm32h7xx_hal.h"
#include "board_api.h" #include "board_api.h"
#include <stdint.h>
#define STM32_UUID ((uint32_t *)0x1FF1E800) #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) void board_init(void)
{ {
SCB_EnableICache(); SCB_EnableICache();
@ -26,9 +45,31 @@ void board_init(void)
__HAL_RCC_GPIOI_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE();
__HAL_RCC_GPIOJ_CLK_ENABLE(); __HAL_RCC_GPIOJ_CLK_ENABLE();
__HAL_RCC_GPIOK_CLK_ENABLE(); __HAL_RCC_GPIOK_CLK_ENABLE();
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);
GPIO_InitTypeDef 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 #ifdef BUTTON_PIN
GPIO_InitStruct.Pin = BUTTON_PIN; GPIO_InitStruct.Pin = BUTTON_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
@ -53,8 +94,8 @@ void board_init(void)
void board_dfu_init(void) void board_dfu_init(void)
{ {
// Not quite sure what an RHPORT is :/ // Not quite sure what an RHPORT is :/
#if BOARD_TUD_RHPORT == 0 #if defined (BOARD_TUD_RHPORT) && (BOARD_TUD_RHPORT == 0)
GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitTypeDef GPIO_InitStruct = {0};
// Init USB Pins // Init USB Pins
// Configure DM DP 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_BVALOEN;
USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; 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 // TODO: implement whatever this is
#error "Sorry, not implemented yet" #error "Sorry, not implemented yet"
#endif #endif
@ -112,8 +153,8 @@ bool board_app_valid(void)
switch ((app_vector[0] & 0xFFFF0003u)) switch ((app_vector[0] & 0xFFFF0003u))
{ {
case 0x00000000u: // ITCM 64K [0x0000_0000u--0x0000_FFFFu] case 0x00000000u: // ITCM 64K [0x0000_0000u--0x0000_FFFFu]
case 0x20000000u: // DTCM 64K [0x2000_0000u--0x2000_FFFFu] case 0x20010000u: // DTCM 64K [0x2000_0000u--0x2000_FFFFu]
case 0x20010000u: // DTCM 64K [0x2001_0000u--0x2001_FFFFu] case 0x20020000u: // DTCM 64K [0x2001_0000u--0x2001_FFFFu]
case 0x24000000u: // AXI SRAM 512K [0x2400_0000u--0x2407_FFFFu] case 0x24000000u: // AXI SRAM 512K [0x2400_0000u--0x2407_FFFFu]
case 0x30010000u: // SRAM1 64K [0x3001_0000u--0x3001_FFFFu] case 0x30010000u: // SRAM1 64K [0x3001_0000u--0x3001_FFFFu]
case 0x30020000u: // SRAM2 64K [0x3002_0000u--0x3002_FFFFu] case 0x30020000u: // SRAM2 64K [0x3002_0000u--0x3002_FFFFu]
@ -170,16 +211,32 @@ void board_app_jump(void)
__HAL_RCC_GPIOJ_CLK_DISABLE(); __HAL_RCC_GPIOJ_CLK_DISABLE();
__HAL_RCC_GPIOK_CLK_DISABLE(); __HAL_RCC_GPIOK_CLK_DISABLE();
// Lotsa GPIOs // 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_DisableICache();
SCB_DisableDCache(); SCB_DisableDCache();
// Clear temporary boot address // Clear temporary boot address
board_clear_temp_boot_addr(); board_clear_temp_boot_addr();
// Setup VTOR to point to application vectors #ifdef UART_DEV
SCB->VTOR = (uint32_t) app_addr; HAL_UART_DeInit(&UartHandle);
HAL_GPIO_DeInit(UART_GPIO_PORT, UART_TX_PIN | UART_RX_PIN);
UART_CLOCK_DISABLE();
#endif
// Set stack pointer // Set stack pointer
__set_MSP(app_vector[0]); __set_MSP(app_vector[0]);
@ -187,6 +244,11 @@ void board_app_jump(void)
TUF2_LOG1("App address: %08lx\r\n", app_vector[1]); 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 // Jump to application reset vector
asm("bx %0" :: "r"(app_vector[1])); 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) 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) buf;
(void) len; (void) len;
return 0; return 0;
#endif
} }
#ifdef TINYUF2_SELF_UPDATE #ifdef TINYUF2_SELF_UPDATE

View file

@ -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 0x0483
#define USB_PID 0x5740
#define USB_MANUFACTURER "STM32"
#define USB_PRODUCT "STM32FH750IB"
#define UF2_PRODUCT_NAME USB_MANUFACTURER " " USB_PRODUCT
#define UF2_BOARD_ID "STM32FH750IB-DaisySeed"
#define UF2_VOLUME_LABEL "DaisyBOOT"
#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

View file

@ -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 = 0
SRC_S += \
$(ST_CMSIS)/Source/Templates/gcc/startup_stm32h750xx.s

View file

@ -1,6 +1,7 @@
SPI_FLASH = W25Qx_SPI SPI_FLASH = W25Qx_SPI
QSPI_FLASH = W25Qx_QSPI QSPI_FLASH = W25Qx_QSPI
DISPLAY_DRV = ST7735 DISPLAY_DRV = ST7735
JLINK_DEVICE = stm32h750vb
CFLAGS += \ CFLAGS += \
-DSTM32H750xx \ -DSTM32H750xx \

View file

@ -0,0 +1,130 @@
/*
* 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 (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) /* 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_ */

View file

@ -0,0 +1,567 @@
#include "is25lp064a_qspi.h"
#include "is25lp064a.h"
#include "qspi_status.h"
#include "stm32h7xx_hal.h"
#include <stdint.h>
#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, &reg, 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(&reg) != HAL_OK) {
return qspi_ERROR;
}
reg = reg | IS25LP064A_SR_QE;
if (HAL_QSPI_Transmit(&_qspi_flash, &reg, 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 */

View file

@ -0,0 +1,30 @@
#ifndef __IS25LP064A_QSPI_H
#define __IS25LP064A_QSPI_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
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

View file

@ -1,5 +1,7 @@
#include "board_api.h"
#include "w25qxx_qspi.h" #include "w25qxx_qspi.h"
#include "qspi_status.h"
#include "stm32h7xx_hal.h"
extern QSPI_HandleTypeDef _qspi_flash; 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, 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); 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]; uint8_t w25qxx_StatusReg[3];
uint16_t w25qxx_ID; uint16_t w25qxx_ID;
@ -30,7 +32,7 @@ uint16_t w25qxx_GetID(void)
uint8_t ID[6]; uint8_t ID[6];
uint16_t deviceID; 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)); 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 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)); 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 */ /* Reception of the data */
if (HAL_QSPI_Receive(&_qspi_flash, ID, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 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]; deviceID = (ID[0] << 8) | ID[1];
@ -48,7 +50,7 @@ uint16_t w25qxx_GetID(void)
uint8_t w25qxx_ReadSR(uint8_t SR) uint8_t w25qxx_ReadSR(uint8_t SR)
{ {
uint8_t byte=0; 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); 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 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); 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) 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); 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 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); 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[0] = w25qxx_ReadSR(W25X_ReadStatusReg1);
w25qxx_StatusReg[1] = w25qxx_ReadSR(W25X_ReadStatusReg2); w25qxx_StatusReg[1] = w25qxx_ReadSR(W25X_ReadStatusReg2);
w25qxx_StatusReg[2] = w25qxx_ReadSR(W25X_ReadStatusReg3); 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; uint8_t send;
send = (DummyClock/2 -1)<<4 | ((WrapLenth/8 - 1)&0x03); 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); 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) uint8_t w25qxx_EnterQPI(void)
{ {
/* Enter QSPI memory in QSPI mode */ /* 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); return w25qxx_SetReadParameters(8,8);
@ -116,14 +118,14 @@ uint8_t w25qxx_EnterQPI(void)
uint8_t w25qxx_Startup(uint8_t DTRMode) uint8_t w25qxx_Startup(uint8_t DTRMode)
{ {
/* Enable MemoryMapped mode */ /* 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); return QSPI_WriteEnable(&_qspi_flash);
} }
@ -132,20 +134,20 @@ uint8_t W25qxx_WriteEnable(void)
* @param SectorAddress: Sector address to erase * @param SectorAddress: Sector address to erase
* @retval QSPI memory status * @retval QSPI memory status
*/ */
uint8_t W25qxx_EraseSector(uint32_t SectorAddress) uint8_t w25qxx_EraseSector(uint32_t SectorAddress)
{ {
uint8_t result; uint8_t result;
W25qxx_WriteEnable(); w25qxx_WriteEnable();
W25QXX_Wait_Busy(); 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); 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 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); 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(); W25QXX_Wait_Busy();
return result; return result;
@ -156,20 +158,20 @@ uint8_t W25qxx_EraseSector(uint32_t SectorAddress)
* @param SectorAddress: Sector address to erase * @param SectorAddress: Sector address to erase
* @retval QSPI memory status * @retval QSPI memory status
*/ */
uint8_t W25qxx_EraseBlock(uint32_t BlockAddress) uint8_t w25qxx_EraseBlock(uint32_t BlockAddress)
{ {
uint8_t result; uint8_t result;
W25qxx_WriteEnable(); w25qxx_WriteEnable();
W25QXX_Wait_Busy(); 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); 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 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); 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(); W25QXX_Wait_Busy();
return result; return result;
@ -180,20 +182,20 @@ uint8_t W25qxx_EraseBlock(uint32_t BlockAddress)
* @param SectorAddress: Sector address to erase * @param SectorAddress: Sector address to erase
* @retval QSPI memory status * @retval QSPI memory status
*/ */
uint8_t W25qxx_EraseChip(void) uint8_t w25qxx_EraseChip(void)
{ {
uint8_t result; uint8_t result;
W25qxx_WriteEnable(); w25qxx_WriteEnable();
W25QXX_Wait_Busy(); 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); 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 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); 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(); W25QXX_Wait_Busy();
return result; return result;
@ -206,22 +208,22 @@ uint8_t W25qxx_EraseChip(void)
* @param Size Size of data to write. Range 1 ~ W25qxx page size * @param Size Size of data to write. Range 1 ~ W25qxx page size
* @retval QSPI memory status * @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; 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); 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 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); 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); result = HAL_QSPI_Transmit(&_qspi_flash,pData,HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
/* 等待写入完成 */ /* 等待写入完成 */
if(result == w25qxx_OK) if(result == qspi_OK)
W25QXX_Wait_Busy(); W25QXX_Wait_Busy();
return result; return result;
@ -232,7 +234,7 @@ uint8_t W25qxx_PageProgram(uint8_t *pData, uint32_t WriteAddr, uint32_t Size)
//pBuffer:数据存储区 //pBuffer:数据存储区
//ReadAddr:开始读取的地址(最大32bit) //ReadAddr:开始读取的地址(最大32bit)
//NumByteToRead:要读取的字节数(最大65535) //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; 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 */ /* 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.Instruction = W25X_QUAD_INOUT_FAST_READ_CMD;
s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 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); 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); result = HAL_QSPI_Receive(&_qspi_flash,pData,HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
return result; return result;
@ -285,7 +287,7 @@ uint8_t W25qxx_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size)
//WriteAddr:开始写入的地址(最大32bit) //WriteAddr:开始写入的地址(最大32bit)
//NumByteToWrite:要写入的字节数(最大65535) //NumByteToWrite:要写入的字节数(最大65535)
//CHECK OK //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; uint16_t pageremain;
pageremain = 256 - WriteAddr % 256; //单页剩余的字节数 pageremain = 256 - WriteAddr % 256; //单页剩余的字节数
@ -295,7 +297,7 @@ void W25qxx_WriteNoCheck(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t NumByteToW
} }
while(1) while(1)
{ {
W25qxx_PageProgram(pBuffer, WriteAddr, pageremain); w25qxx_PageProgram(pBuffer, WriteAddr, pageremain);
if (NumByteToWrite == pageremain) if (NumByteToWrite == pageremain)
{ {
break; //写入结束了 break; //写入结束了
@ -320,7 +322,7 @@ void W25qxx_WriteNoCheck(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t NumByteToW
//pBuffer:数据存储区 //pBuffer:数据存储区
//WriteAddr:开始写入的地址(最大32bit) //WriteAddr:开始写入的地址(最大32bit)
//NumByteToWrite:要写入的字节数(最大65535) //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; uint32_t secpos;
uint16_t secoff; 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个字节 if (NumByteToWrite <= secremain) secremain = NumByteToWrite; //不大于4096个字节
while(1) while(1)
{ {
if (W25qxx_Read(W25QXX_BUF, secpos * 4096, 4096) != w25qxx_OK) { if (w25qxx_Read(W25QXX_BUF, secpos * 4096, 4096) != qspi_OK) {
return w25qxx_ERROR; return qspi_ERROR;
} //读出整个扇区的内容 } //读出整个扇区的内容
for (i = 0;i < secremain; i++) //校验数据 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 (i < secremain) //需要擦除
{ {
if (W25qxx_EraseSector(secpos) != w25qxx_OK) { if (w25qxx_EraseSector(secpos) != qspi_OK) {
return w25qxx_ERROR; return qspi_ERROR;
} //擦除这个扇区 } //擦除这个扇区
for (i = 0; i < secremain; i++) //复制 for (i = 0; i < secremain; i++) //复制
{ {
W25QXX_BUF[i + secoff] = pBuffer[i]; W25QXX_BUF[i + secoff] = pBuffer[i];
} }
W25qxx_WriteNoCheck(W25QXX_BUF, secpos * 4096, 4096); //写入整个扇区 w25qxx_WriteNoCheck(W25QXX_BUF, secpos * 4096, 4096); //写入整个扇区
} }
else else
{ {
W25qxx_WriteNoCheck(pBuffer, WriteAddr, secremain); //写已经擦除了的,直接写入扇区剩余区间. w25qxx_WriteNoCheck(pBuffer, WriteAddr, secremain); //写已经擦除了的,直接写入扇区剩余区间.
} }
if (NumByteToWrite == secremain) if (NumByteToWrite == secremain)
{ {
@ -375,13 +377,13 @@ uint8_t W25qxx_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWri
secremain = NumByteToWrite; //下一个扇区可以写完了 secremain = NumByteToWrite; //下一个扇区可以写完了
} }
} }
return w25qxx_OK; return qspi_OK;
} }
/** /**
* @brief Configure the QSPI in memory-mapped mode QPI/SPI && DTR(DDR)/Normal Mode * @brief Configure the QSPI in memory-mapped mode QPI/SPI && DTR(DDR)/Normal Mode
* @param hqspi: QSPI handle * @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 * @retval QSPI memory status
*/ */
static uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *hqspi,uint8_t DTRMode) 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; QSPI_MemoryMappedTypeDef s_mem_mapped_cfg;
/* Configure the command for the read instruction */ /* Configure the command for the read instruction */
if(w25qxx_Mode == w25qxx_QPIMode) if(w25qxx_Mode == qspi_QPIMode)
s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES;
else else
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 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; 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.Instruction = W25X_QUAD_INOUT_FAST_READ_DTR_CMD;
s_command.DummyCycles = W25X_DUMMY_CYCLES_READ_QUAD_DTR; 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; 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; s_command.DummyCycles = W25X_DUMMY_CYCLES_READ_QUAD;
else else
s_command.DummyCycles = W25X_DUMMY_CYCLES_READ_QUAD-2; 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) 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 */ /* Send the command */
if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 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 */ /* Send the reset device command */
s_command.Instruction = W25X_ResetDevice; s_command.Instruction = W25X_ResetDevice;
if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 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; s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES;
@ -476,18 +478,18 @@ static uint32_t QSPI_ResetDevice(QSPI_HandleTypeDef *hqspi)
/* Send the command */ /* Send the command */
if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 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 */ /* Send the reset memory command */
s_command.Instruction = W25X_ResetDevice; s_command.Instruction = W25X_ResetDevice;
if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{ {
return w25qxx_ERROR; return qspi_ERROR;
} }
w25qxx_Mode = w25qxx_SPIMode; w25qxx_Mode = qspi_SPIMode;
return w25qxx_OK; 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 dataMode ; QSPI_DATA_NONE,QSPI_DATA_1_LINE,QSPI_DATA_2_LINES,QSPI_DATA_4_LINES
* @param dataSize * @param dataSize
* *
* @return uint8_t w25qxx_OK: * @return uint8_t qspi_OK:
* w25qxx_ERROR: * qspi_ERROR:
*/ */
static uint8_t QSPI_Send_CMD(QSPI_HandleTypeDef *hqspi,uint32_t instruction, uint32_t address,uint32_t addressSize,uint32_t dummyCycles, 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) 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; Cmdhandler.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
if(HAL_QSPI_Command(hqspi, &Cmdhandler, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 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; s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Enable write operations */ /* Enable write operations */
if (QSPI_WriteEnable(hqspi) != w25qxx_OK) if (QSPI_WriteEnable(hqspi) != qspi_OK)
{ {
return w25qxx_ERROR; return qspi_ERROR;
} }
/* Send the command */ /* Send the command */
if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 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 */ /* 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; QSPI_AutoPollingTypeDef s_config;
/* Enable write operations */ /* Enable write operations */
if(w25qxx_Mode == w25qxx_QPIMode) if(w25qxx_Mode == qspi_QPIMode)
s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES;
else else
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; 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) 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 */ /* 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; s_command.Instruction = W25X_ReadStatusReg1;
if(w25qxx_Mode == w25qxx_QPIMode) if(w25qxx_Mode == qspi_QPIMode)
s_command.DataMode = QSPI_DATA_4_LINES; s_command.DataMode = QSPI_DATA_4_LINES;
else else
s_command.DataMode = QSPI_DATA_1_LINE; s_command.DataMode = QSPI_DATA_1_LINE;
if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) 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 */ /* 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; s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
else else
s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES; 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.AddressSize = QSPI_ADDRESS_8_BITS;
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
if(w25qxx_Mode == w25qxx_SPIMode) if(w25qxx_Mode == qspi_SPIMode)
s_command.DataMode = QSPI_DATA_1_LINE; s_command.DataMode = QSPI_DATA_1_LINE;
else else
s_command.DataMode = QSPI_DATA_4_LINES; s_command.DataMode = QSPI_DATA_4_LINES;
@ -685,19 +687,19 @@ static uint8_t QSPI_EnterQPI(QSPI_HandleTypeDef *hqspi)
stareg2 = w25qxx_ReadSR(W25X_ReadStatusReg2); stareg2 = w25qxx_ReadSR(W25X_ReadStatusReg2);
if((stareg2 & 0X02) == 0) //QE位未使能 if((stareg2 & 0X02) == 0) //QE位未使能
{ {
W25qxx_WriteEnable(); w25qxx_WriteEnable();
stareg2 |= 1<<1; //使能QE位 stareg2 |= 1<<1; //使能QE位
w25qxx_WriteSR(W25X_WriteStatusReg2,stareg2); 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); 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 */ /* 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;
} }

View file

@ -7,21 +7,6 @@
#include <stdint.h> #include <stdint.h>
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 ================ */ /* =============== W25Qxx CMD ================ */
#define W25X_WriteEnable 0x06 #define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04 #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_SetReadParameters(uint8_t DummyClock,uint8_t WrapLenth);
uint8_t w25qxx_EnterQPI(void); uint8_t w25qxx_EnterQPI(void);
uint8_t w25qxx_Startup(uint8_t DTRMode); uint8_t w25qxx_Startup(uint8_t DTRMode);
uint8_t W25qxx_WriteEnable(void); uint8_t w25qxx_WriteEnable(void);
uint8_t W25qxx_EraseSector(uint32_t SectorAddress); uint8_t w25qxx_EraseSector(uint32_t SectorAddress);
uint8_t W25qxx_EraseBlock(uint32_t BlockAddress); uint8_t w25qxx_EraseBlock(uint32_t BlockAddress);
uint8_t W25qxx_EraseChip(void); uint8_t w25qxx_EraseChip(void);
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 W25qxx_Read(uint8_t *pData, uint32_t ReadAddr, 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); 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_Write(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -24,27 +24,29 @@ endif
CFLAGS += -Wno-error=cast-align -Wno-error=unused-parameter -Wno-error=unused-but-set-variable -Wno-error=unused-function CFLAGS += -Wno-error=cast-align -Wno-error=unused-parameter -Wno-error=unused-but-set-variable -Wno-error=unused-function
ifeq ($(SPI_FLASH),W25Qx_SPI) ifeq ($(SPI_FLASH),W25Qx_SPI)
INC += \ INC += ${TOP}/$(PORT_DIR)/components/w25qxx
$(CURRENT_PATH)/components/w25qxx/ \
SRC_C += \ SRC_C += \
$(TOP)/$(PORT_DIR)/components/w25qxx/w25qxx.c $(PORT_DIR)/components/w25qxx/w25qxx.c
endif endif
ifeq ($(QSPI_FLASH),W25Qx_QSPI) ifeq ($(QSPI_FLASH),W25Qx_QSPI)
INC += \ INC += ${TOP}/$(PORT_DIR)/components/w25qxx
$(CURRENT_PATH)/components/w25qxx/ \
SRC_C += \ SRC_C += \
$(TOP)/$(PORT_DIR)/components/w25qxx/w25qxx_qspi.c $(PORT_DIR)/components/w25qxx/w25qxx_qspi.c
endif
ifeq ($(QSPI_FLASH),IS25LP064A)
INC += ${TOP}/$(PORT_DIR)/components/is25lp064a
SRC_C += \
$(PORT_DIR)/components/is25lp064a/is25lp064a_qspi.c
endif endif
ifeq ($(DISPLAY_DRV),ST7735) ifeq ($(DISPLAY_DRV),ST7735)
INC += \ INC += ${TOP}/$(PORT_DIR)/components/st7735/
$(CURRENT_PATH)/components/w25qxx/ \
SRC_C += \ SRC_C += \
$(TOP)/$(PORT_DIR)/components/st7735/st7735.c $(PORT_DIR)/components/st7735/st7735.c \
$(PORT_DIR)/components/st7735/fonts.c
endif endif
# Source # Source
@ -63,8 +65,6 @@ SRC_C += \
$(ST_HAL_DRIVER)/Src/stm32h7xx_hal_qspi.c \ $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_qspi.c \
$(ST_HAL_DRIVER)/Src/stm32h7xx_hal_mdma.c \ $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_mdma.c \
$(ST_HAL_DRIVER)/Src/stm32h7xx_hal_pwr_ex.c \ $(ST_HAL_DRIVER)/Src/stm32h7xx_hal_pwr_ex.c \
$(TOP)/$(PORT_DIR)/components/st7735/fonts.c \
ifndef BUILD_NO_TINYUSB ifndef BUILD_NO_TINYUSB
SRC_C += lib/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c SRC_C += lib/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c
@ -75,8 +75,6 @@ endif
INC += \ INC += \
$(TOP)/$(BOARD_PATH) \ $(TOP)/$(BOARD_PATH) \
$(TOP)/$(CMSIS_5)/CMSIS/Core/Include \ $(TOP)/$(CMSIS_5)/CMSIS/Core/Include \
$(CURRENT_PATH)/components/st7735/ \
$(CURRENT_PATH)/components/w25qxx/ \
$(TOP)/$(PORT_DIR)/ \ $(TOP)/$(PORT_DIR)/ \
$(TOP)/$(BOARD_DIR) \ $(TOP)/$(BOARD_DIR) \
$(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_CMSIS)/Include \

View file

@ -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