Browse Source
This set of changes adds support for QSPI-based external flash and Bluetooth to the device tree. This make it possible to correctly build and execute the fatfs and several Bluetooth samples out of the box. Also added a function to read the external flash OTP to extract information about the Opta model and hardware features and a second function to retrieve the "official" Opta serial number. Signed-off-by: Federico Di Gregorio <fog@dndg.it>pull/90956/merge
8 changed files with 278 additions and 16 deletions
@ -1,4 +1,5 @@
@@ -1,4 +1,5 @@
|
||||
# Copyright (c) 2021 STMicroelectronics |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
|
||||
zephyr_sources(board_gpio_init.c) |
||||
zephyr_sources(board_gpio_init.c board_info.c) |
||||
zephyr_include_directories(.) |
||||
|
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
/* |
||||
* Copyright (c) 2024 DNDG srl |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
&quadspi { |
||||
qspi_flash: qspi-nor-flash@90000000 { |
||||
|
||||
/delete-node/ partitions; |
||||
|
||||
partitions { |
||||
compatible = "fixed-partitions"; |
||||
#address-cells = <1>; |
||||
#size-cells = <1>; |
||||
|
||||
/* Partition 1: WiFi firmware and certificates 1MB - 4kB */ |
||||
wlan_partition: partition@1000 { |
||||
label = "wlan"; |
||||
reg=<0x001000 DT_SIZE_K(1020)>; |
||||
}; |
||||
|
||||
/* Partition 2: OTA 5MB */ |
||||
ota_partition: partition@100000 { |
||||
label = "ota"; |
||||
reg=<0x100000 DT_SIZE_M(5)>; |
||||
}; |
||||
|
||||
/* Partition 3: Provisioning KVStore 1MB */ |
||||
kvs_partition: partition@600000 { |
||||
label = "kvs"; |
||||
reg=<0x600000 DT_SIZE_M(1)>; |
||||
}; |
||||
|
||||
/* Partition 4: User data / OPTA PLC runtime 7MB (littlefs) */ |
||||
user_partition: partition@700000 { |
||||
label = "user"; |
||||
reg=<0x00000 DT_SIZE_M(7)>; |
||||
}; |
||||
}; |
||||
}; |
||||
}; |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2024 DNDG srl |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
#ifndef __ARDUINO_OPTA_BOARD_H |
||||
#define __ARDUINO_OPTA_BOARD_H |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#define OPTA_OTP_MAGIC 0xB5 |
||||
|
||||
#define OPTA_SERIAL_NUMBER_SIZE 24 |
||||
|
||||
struct __packed opta_board_info { |
||||
uint8_t magic; |
||||
uint8_t version; |
||||
union { |
||||
uint16_t board_functionalities; |
||||
struct { |
||||
uint8_t wifi: 1; |
||||
uint8_t rs485: 1; |
||||
uint8_t ethernet: 1; |
||||
} _board_functionalities_bits; |
||||
}; |
||||
uint16_t revision; |
||||
uint8_t external_flash_size; |
||||
uint16_t vid; |
||||
uint16_t pid; |
||||
uint8_t mac_address[6]; |
||||
uint8_t mac_address_wifi[6]; |
||||
}; |
||||
|
||||
const struct opta_board_info *const opta_get_board_info(void); |
||||
|
||||
const char *const opta_get_serial_number(void); |
||||
|
||||
#endif /* __ARDUINO_OPTA_BOARD_H */ |
@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2024 DNDG srl |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
#include <zephyr/kernel.h> |
||||
#include <zephyr/devicetree.h> |
||||
#include <zephyr/device.h> |
||||
#include <zephyr/init.h> |
||||
#include <zephyr/drivers/flash.h> |
||||
#include <zephyr/drivers/flash/stm32_flash_api_extensions.h> |
||||
#include <soc.h> |
||||
#include <errno.h> |
||||
#include <stdint.h> |
||||
#include "board.h" |
||||
|
||||
#define AT25SF128_READ_SECURITY_REGISTERS 0x48 |
||||
|
||||
static struct opta_board_info info; |
||||
static char serial_number[OPTA_SERIAL_NUMBER_SIZE + 1]; |
||||
|
||||
#if defined(CONFIG_FLASH_STM32_QSPI_GENERIC_READ) |
||||
|
||||
const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(qspi_flash)); |
||||
|
||||
static int board_info(void) |
||||
{ |
||||
QSPI_CommandTypeDef cmd = { |
||||
.Instruction = AT25SF128_READ_SECURITY_REGISTERS, |
||||
.InstructionMode = QSPI_INSTRUCTION_1_LINE, |
||||
.Address = (1 << 13), |
||||
.AddressSize = QSPI_ADDRESS_24_BITS, |
||||
.AddressMode = QSPI_ADDRESS_1_LINE, |
||||
.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE, |
||||
.DataMode = QSPI_DATA_1_LINE, |
||||
.NbData = sizeof(struct opta_board_info), |
||||
.DummyCycles = 8, |
||||
}; |
||||
|
||||
if (!device_is_ready(dev)) { |
||||
return -ENODEV; |
||||
} |
||||
|
||||
int ret = flash_ex_op(dev, FLASH_STM32_QSPI_EX_OP_GENERIC_READ, (uintptr_t)&cmd, &info); |
||||
|
||||
if (ret != 0) { |
||||
return -EIO; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
SYS_INIT(board_info, APPLICATION, 0); |
||||
|
||||
#endif /* CONFIG_FLASH_STM32_QSPI_GENERIC_READ */ |
||||
|
||||
static void uint32tohex(char *dst, uint32_t value) |
||||
{ |
||||
int v; |
||||
|
||||
for (int i = 0; i < 8; i++) { |
||||
v = (value >> ((8 - i - 1) * 4)) & 0x0F; |
||||
dst[i] = v <= 9 ? (0x30 + v) : (0x40 + v - 9); |
||||
} |
||||
} |
||||
|
||||
const struct opta_board_info *const opta_get_board_info(void) |
||||
{ |
||||
if (info.magic == OPTA_OTP_MAGIC) { |
||||
return &info; |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
const char *const opta_get_serial_number(void) |
||||
{ |
||||
if (serial_number[0] == 0) { |
||||
uint32tohex(&serial_number[0], HAL_GetUIDw0()); |
||||
uint32tohex(&serial_number[8], HAL_GetUIDw1()); |
||||
uint32tohex(&serial_number[16], HAL_GetUIDw2()); |
||||
} |
||||
return serial_number; |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
# |
||||
# Copyright (c) 2025 DNDG srl |
||||
# |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
# |
||||
|
||||
# Usually, some files are already present on the first partition, |
||||
# don't create new ones or format the partition in case of failure. |
||||
CONFIG_FILE_SYSTEM_MKFS=n |
||||
CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES=n |
||||
CONFIG_FS_FATFS_MOUNT_MKFS=n |
||||
|
||||
# Arduino format FAT volumes using a 4096 bytes sector size. |
||||
CONFIG_FS_FATFS_MAX_SS=4096 |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
/* |
||||
* Copyright (c) 2025 DNDG srl |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
/ { |
||||
flash_disk0 { |
||||
status="okay"; |
||||
compatible = "zephyr,flash-disk"; |
||||
partition = <&wlan_partition>; |
||||
disk-name = "SD"; |
||||
/* A sector size of 4096 is needed to correctly operate on partitions |
||||
* formatted by Arduino example sketches. It is possible to reformat |
||||
* the external flash and use a different sector size if needed. |
||||
*/ |
||||
sector-size = <4096>; |
||||
cache-size = <4096>; |
||||
}; |
||||
}; |
Loading…
Reference in new issue