Commit 22210724 authored by Federico Di Gregorio's avatar Federico Di Gregorio Committed by Daniel DeGrasse
Browse files

boards: opta: external flash and BLE support



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: default avatarFederico Di Gregorio <fog@dndg.it>
parent fc3cdb8a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
#  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(.)
+42 −0
Original line number Diff line number Diff line
/*
 * 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)>;
			};
		};
	};
};
+67 −15
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
		zephyr,sram = &sram0;
		zephyr,flash = &flash0;
		zephyr,code-partition = &slot0_partition;
		zephyr,bt-hci = &bt_hci_uart;
	};
};

@@ -123,33 +124,84 @@ zephyr_udc0: &usbotg_fs {
	};
};

/* Assign Bluetooth to M7 by default */
&uart4 {
	pinctrl-0 = <
		&uart4_tx_pb9
		&uart4_rx_ph14
		&uart4_cts_pb15
		&uart4_rts_pa15
	>;
	pinctrl-names = "default";
	current-speed = <115200>;
	hw-flow-control;
	status = "okay";

	bt_hci_uart: bt_hci_uart {
		compatible = "zephyr,bt-hci-uart";
		status = "okay";

		murata-1dx {
			compatible = "infineon,cyw43xxx-bt-hci";
			bt-reg-on-gpios = <&gpioj 12 GPIO_ACTIVE_HIGH>;
			bt-host-wake-gpios = <&gpioj 13 GPIO_ACTIVE_HIGH>;
			bt-dev-wake-gpios = <&gpioj 14 GPIO_ACTIVE_HIGH>;
		};
	};
};

/* Assign external flash to M7 by default */
&quadspi {
	pinctrl-0 = < &quadspi_bk1_io0_pd11
	pinctrl-0 = <
		&quadspi_bk1_io0_pd11
		&quadspi_bk1_io1_pd12
		&quadspi_bk1_io2_pe2
		&quadspi_bk1_io3_pd13
		&quadspi_bk1_ncs_pg6
		      &quadspi_clk_pb2 >;
		&quadspi_clk_pb2
	>;
	pinctrl-names = "default";
	status = "okay";

	at25sf128a: qspi-nor-flash@0 {
	qspi_flash: qspi-nor-flash@0 {
		compatible = "st,stm32-qspi-nor";
		reg = <0>;
		size = <DT_SIZE_M(128)>; /* 128 MBits */
		qspi-max-frequency = <DT_FREQ_M(70)>;
		qspi-max-frequency = <80000000>;
		jedec-id = [01 1f 89];
		spi-bus-width = <4>;
		quad-enable-requirements = "NONE";
		status = "okay";
		spi-bus-width = <2>;
		st,read-id-dummy-cycles = <16>;

		/* The following partitions are valid only if the Opta external flash
		 * has never been reformatted or repartitioned. Note the offset of the
		 * first partition, due to the presence of the MBR.
		 */
		partitions {
			compatible = "fixed-partitions";
			#address-cells = <1>;
			#size-cells = <1>;

			storage_partition: partition@0 {
				label = "storage";
				reg=< 0x0 DT_SIZE_K(15872) >;
			/* WiFi firmware and TLS certificates: 1MB - 4K for MBR using LBA */
			wlan_partition: partition@1000 {
				label = "wlan";
				reg=<0x001000 DT_SIZE_K(1020)>;
			};

			/* Arduino OTA partition: 13MB */
			fs_partition: partition@100000 {
				label = "fs";
				reg=<0x100000 DT_SIZE_M(13)>;
			};

			/* The final 2MB is used to keep a memory-mapped copy of the WiFi
			 * firmware. The address of the firmware blob is 0xF80000 and the
			 * size of the partition in the MBR is 0 but, given that we can't
			 * specify a zero size in `reg` we just give the "correct" one.
			 */
			wifi_partition: partition@e00000 {
				label = "4343WA1";
				reg=<0xE00000 DT_SIZE_M(2)>;
			};
		};
	};
+39 −0
Original line number Diff line number Diff line
/*
 * 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 */
+84 −0
Original line number Diff line number Diff line
/*
 * 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;
}
Loading