Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Added raw QSPI functionality for the Arduino Giga#224

New issue

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

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

Already on GitHub?Sign in to your account

Open
cristidragomir97 wants to merge1 commit intoarduino:main
base:main
Choose a base branch
Loading
fromcristidragomir97:main
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletionslibraries/QSPI/CMakeLists.txt
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
zephyr_library()

zephyr_library_sources(QSPI.cpp)

zephyr_library_include_directories(.)
128 changes: 128 additions & 0 deletionslibraries/QSPI/QSPI.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
#include "QSPI.h"

// Define the QSPI flash device - will be available when overlay is active
#if DT_NODE_EXISTS(DT_NODELABEL(qspi_flash))
#define QSPI_FLASH_NODE DT_NODELABEL(qspi_flash)
#define QSPI_FLASH_DEVICE DEVICE_DT_GET(QSPI_FLASH_NODE)
#else
#define QSPI_FLASH_DEVICE NULL
#warning "QSPI flash device not found in device tree"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
#warning "QSPI flashdevice not found in device tree"
#warning "NoQSPI flashavailable on this board"

#endif

QSPIClass::QSPIClass() : flash_dev(nullptr), initialized(false) {
}

bool QSPIClass::begin() {
if (QSPI_FLASH_DEVICE == NULL) {
return false;
}

flash_dev = QSPI_FLASH_DEVICE;

if (!device_is_ready(flash_dev)) {
flash_dev = nullptr;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Use eitherNULL ornullptr in the file for consistency.

return false;
}

initialized = true;
return true;
}

bool QSPIClass::read(uint32_t address, void* data, size_t size) {
if (!initialized || !flash_dev) {
return false;
}

int ret = flash_read(flash_dev, address, data, size);
return (ret == 0);
}

bool QSPIClass::write(uint32_t address, const void* data, size_t size) {
if (!initialized || !flash_dev) {
return false;
}

int ret = flash_write(flash_dev, address, data, size);
return (ret == 0);
}

bool QSPIClass::erase(uint32_t address, size_t size) {
if (!initialized || !flash_dev) {
return false;
}

int ret = flash_erase(flash_dev, address, size);
return (ret == 0);
}

size_t QSPIClass::getFlashSize() {
if (!initialized || !flash_dev) {
return 0;
}

uint64_t size = 0;
int ret = flash_get_size(flash_dev, &size);
if (ret != 0) {
return 0;
}

return (size_t)size;
}

size_t QSPIClass::getSectorSize() {
if (!initialized || !flash_dev) {
return 0;
}

struct flash_pages_info page_info;
int ret = flash_get_page_info_by_offs(flash_dev, 0, &page_info);
if (ret != 0) {
return 0;
}

return page_info.size;
}

size_t QSPIClass::getPageSize() {
if (!initialized || !flash_dev) {
return 0;
}

const struct flash_parameters *flash_params = flash_get_parameters(flash_dev);
if (!flash_params) {
return 0;
}

return flash_params->write_block_size;
}

bool QSPIClass::isReady() {
if (!flash_dev) {
return false;
}

return device_is_ready(flash_dev);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This does not verify the device can accept more commands, but simply that it's enabled and has passedinit(). Since this is already tested inbegin, IMO it's better toreturn true here.

}

uint32_t QSPIClass::getFlashID() {
// This would require implementing JEDEC ID reading
// For now, return 0 as placeholder
return 0;
}

bool QSPIClass::isValidAddress(uint32_t address, size_t size) {
if (!initialized || !flash_dev) {
return false;
}

size_t flash_size = getFlashSize();
return (address + size <= flash_size);
}

void QSPIClass::end() {
flash_dev = nullptr;
initialized = false;
}

// Create global instance
QSPIClass QSPI;
51 changes: 51 additions & 0 deletionslibraries/QSPI/QSPI.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
#ifndef QSPI_H
#define QSPI_H

#include <Arduino.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/devicetree.h>

class QSPIClass {

public:
QSPIClass();

// Initialize QSPI flash
bool begin();

// Read data from QSPI flash
bool read(uint32_t address, void* data, size_t size);

// Write data to QSPI flash
bool write(uint32_t address, const void* data, size_t size);

// Erase sector/block
bool erase(uint32_t address, size_t size);

// Get flash information
size_t getFlashSize();
size_t getSectorSize();
size_t getPageSize();

// Check if flash is ready
bool isReady();

// Get flash ID
uint32_t getFlashID();

// Utility functions
bool isValidAddress(uint32_t address, size_t size = 1);

// End/deinitialize
void end();

private:
const struct device *flash_dev;
bool initialized;
};

extern QSPIClass QSPI;

#endif
50 changes: 50 additions & 0 deletionslibraries/QSPI/README.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
# QSPI Library

This library provides a simple Arduino-style interface for accessing QSPI (Quad SPI) flash memory on Arduino Zephyr boards.

## Features

- Initialize and configure QSPI flash
- Read data from QSPI flash memory
- Write data to QSPI flash memory
- Erase sectors/blocks
- Get flash information (size, sector size, page size)


### Device Tree Setup

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Not sure the following part is relevant for Arduino users, only a selected few know about any of this 🙂
Maybe you can move this info to a more specific file, such asREADME.zephyr.md?


Added to `arduino_giga_r1_stm32h747xx_m7.overlay` file:

```dts
&quadspi {
pinctrl-0 = <&quadspi_clk_pf10 &quadspi_bk1_ncs_pb6
&quadspi_bk1_io0_pf8 &quadspi_bk1_io1_pf9
&quadspi_bk1_io2_pf7 &quadspi_bk1_io3_pf6>;
pinctrl-names = "default";
status = "okay";

qspi_flash: qspi-nor-flash@90000000 {
compatible = "st,stm32-qspi-nor";
reg = <0x90000000 DT_SIZE_M(16)>;
qspi-max-frequency = <80000000>;
size = <DT_SIZE_M(16) * 8>;
spi-bus-width = <4>;
status = "okay";
};
};
```

### Configuration Setup

Added to the `arduino_giga_r1_stm32h747xx_m7.conf`:

```kconfig
CONFIG_SPI_STM32_QSPI=y
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_SFDP_DEVICETREE=y
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y
```

No changes were needed to the llext.
101 changes: 101 additions & 0 deletionslibraries/QSPI/examples/BasicQSPI.ino
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
/*
Basic QSPI Flash Example

This example demonstrates how to use the QSPI library to read and write
data to external QSPI flash memory on Arduino boards with QSPI support.

Note: QSPI flash must be configured in the board's device tree overlay.
*/

#include <QSPI.h>

void setup() {
Serial.begin(115200);
while (!Serial) {
delay(10);
}

Serial.println("QSPI Flash Test");

// Initialize QSPI flash
if (!QSPI.begin()) {
Serial.println("Failed to initialize QSPI flash!");
while (1) {
delay(1000);
}
}

Serial.println("QSPI flash initialized successfully");

// Get flash information
Serial.print("Flash size: ");
Serial.print(QSPI.getFlashSize());
Serial.println(" bytes");

Serial.print("Sector size: ");
Serial.print(QSPI.getSectorSize());
Serial.println(" bytes");

Serial.print("Page size: ");
Serial.print(QSPI.getPageSize());
Serial.println(" bytes");

// Test write and read
testWriteRead();
}

void loop() {
// Nothing to do in loop
delay(5000);

Serial.println("Running periodic test...");
testWriteRead();
}

void testWriteRead() {
const uint32_t test_address = 0x1000; // Test address (4KB offset)
const char test_data[] = "Hello QSPI Flash!";
char read_buffer[32];

Serial.println("\n--- Testing Write/Read ---");

// Erase sector first
Serial.print("Erasing sector at 0x");
Serial.print(test_address, HEX);
Serial.print("... ");

if (QSPI.erase(test_address, QSPI.getSectorSize())) {
Serial.println("OK");
} else {
Serial.println("FAILED");
return;
}

// Write test data
Serial.print("Writing data... ");
if (QSPI.write(test_address, test_data, strlen(test_data) + 1)) {
Serial.println("OK");
} else {
Serial.println("FAILED");
return;
}

// Read back data
Serial.print("Reading data... ");
memset(read_buffer, 0, sizeof(read_buffer));
if (QSPI.read(test_address, read_buffer, sizeof(read_buffer))) {
Serial.println("OK");

Serial.print("Read data: ");
Serial.println(read_buffer);

// Verify data
if (strcmp(test_data, read_buffer) == 0) {
Serial.println("Data verification: PASSED");
} else {
Serial.println("Data verification: FAILED");
}
} else {
Serial.println("FAILED");
}
}
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,3 +64,9 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_BT_RX_STACK_SIZE=4096

CONFIG_STM32H7_BOOT_M4_AT_INIT=n

# QSPI Flash Support
CONFIG_FLASH=y
CONFIG_FLASH_STM32_QSPI=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -334,6 +334,23 @@
};


&quadspi {
pinctrl-0 = <&quadspi_clk_pf10 &quadspi_bk1_ncs_pg6
&quadspi_bk1_io0_pd11 &quadspi_bk1_io1_pd12
&quadspi_bk1_io2_pe2 &quadspi_bk1_io3_pf6>;
pinctrl-names = "default";
status = "okay";

qspi_flash: qspi-nor-flash@0 {
compatible = "st,stm32-qspi-nor";
reg = <0>;
size = <DT_SIZE_M(128)>; /* 128 Mbits (16 MB) */
qspi-max-frequency = <72000000>;
spi-bus-width = <4>;
status = "okay";
};
};

&flash0 {
partitions {
user_sketch: partition@e0000 {
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp