Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
53 changes: 43 additions & 10 deletions boards/arm/disco_l475_iot1/disco_l475_iot1.dts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,code-partition = &slot0_partition;
zephyr,flash-controller = &mx25r6435f;
};

leds {
Expand Down Expand Up @@ -173,21 +174,13 @@

slot0_partition: partition@20000 {
label = "image-0";
reg = <0x00020000 0x0006C000>;
};
slot1_partition: partition@8c000 {
label = "image-1";
reg = <0x0008C000 0x0006C000>;
reg = <0x00020000 0x000D8000>;
};

scratch_partition: partition@f8000 {
label = "image-scratch";
reg = <0x000F8000 0x00004000>;
};

storage_partition: partition@fc000 {
label = "storage";
reg = <0x000fc000 0x00004000>;
};
};
};

Expand Down Expand Up @@ -228,3 +221,43 @@
&adc1_in14_pc5>;
status = "okay";
};

&dma1 {
status = "okay";
};

&quadspi {
pinctrl-0 = <&quadspi_clk_pe10 &quadspi_ncs_pe11
&quadspi_bk1_io0_pe12 &quadspi_bk1_io1_pe13
&quadspi_bk1_io2_pe14 &quadspi_bk1_io3_pe15>;
dmas = <&dma1 5 5 0x0000 0x03>;
dma-names = "tx_rx";

status = "okay";

mx25r6435f: qspi-nor-flash@0 {
compatible = "st,stm32-qspi-nor";
label = "MX25R6435F";
reg = <0>;
qspi-max-frequency = <50000000>;
/* 64 Megabits = 8 Megabytes */
size = <0x4000000>;
status = "okay";

partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;

slot1_partition: partition@0 {
label = "image-1";
reg = <0x00000000 0x000D8000>;
};

storage_partition: partition@D8000 {
label = "storage";
reg = <0x000D8000 DT_SIZE_M(7)>;
};
};
};
};
2 changes: 2 additions & 0 deletions boards/arm/disco_l475_iot1/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ The Zephyr Disco L475 IoT board configuration supports the following hardware fe
+-----------+------------+-------------------------------------+
| ADC | on-chip | adc |
+-----------+------------+-------------------------------------+
| QSPI NOR | on-chip | flash |
+-----------+------------+-------------------------------------+

Other hardware features are not yet supported on this Zephyr port.

Expand Down
1 change: 1 addition & 0 deletions doc/guides/kconfig/preprocessor-functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ while the ``*_hex`` version returns a hexadecimal value starting with ``0x``.
$(dt_compat_enabled,<compatible string>)
$(dt_chosen_enabled,<property in /chosen>)
$(dt_node_has_bool_prop,<node path>,<prop>)
$(dt_node_has_prop,<node path>,<prop>)


Example Usage
Expand Down
69 changes: 50 additions & 19 deletions drivers/clock_control/clock_stm32_ll_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,11 @@ static void config_bus_clk_init(LL_UTILS_ClkInitTypeDef *clk_init)
clk_init->APB1CLKDivider = apb1_prescaler(
CONFIG_CLOCK_STM32_APB1_PRESCALER);

#if !defined (CONFIG_SOC_SERIES_STM32F0X) && !defined (CONFIG_SOC_SERIES_STM32G0X)
#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
!defined (CONFIG_SOC_SERIES_STM32G0X)
clk_init->APB2CLKDivider = apb2_prescaler(
CONFIG_CLOCK_STM32_APB2_PRESCALER);
#endif /* CONFIG_SOC_SERIES_STM32F0X && CONFIG_SOC_SERIES_STM32G0X */
#endif
}

static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler)
Expand All @@ -95,14 +96,25 @@ static inline int stm32_clock_control_on(const struct device *dev,
break;
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32L5X) || \
defined(CONFIG_SOC_SERIES_STM32F4X) && !defined(CONFIG_SOC_STM32F410RX) || \
defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB2_SUPPORT) || \
defined(CONFIG_SOC_SERIES_STM32F7X) || \
defined(CONFIG_SOC_SERIES_STM32F2X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G4X)
case STM32_CLOCK_BUS_AHB2:
LL_AHB2_GRP1_EnableClock(pclken->enr);
break;
#endif /* CONFIG_SOC_SERIES_STM32_* */
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32L5X) || \
defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB3_SUPPORT) || \
defined(CONFIG_SOC_SERIES_STM32F7X) || \
defined(CONFIG_SOC_SERIES_STM32F2X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G4X)
case STM32_CLOCK_BUS_AHB3:
LL_AHB3_GRP1_EnableClock(pclken->enr);
break;
#endif /* CONFIG_SOC_SERIES_STM32_* */
case STM32_CLOCK_BUS_APB1:
LL_APB1_GRP1_EnableClock(pclken->enr);
Expand All @@ -120,12 +132,13 @@ static inline int stm32_clock_control_on(const struct device *dev,
case STM32_CLOCK_BUS_APB2:
LL_APB2_GRP1_EnableClock(pclken->enr);
break;
#endif /* CONFIG_SOC_SERIES_STM32F0X */
#if defined (CONFIG_SOC_SERIES_STM32L0X) || defined (CONFIG_SOC_SERIES_STM32G0X)
#endif
#if defined (CONFIG_SOC_SERIES_STM32L0X) || \
defined (CONFIG_SOC_SERIES_STM32G0X)
case STM32_CLOCK_BUS_IOP:
LL_IOP_GRP1_EnableClock(pclken->enr);
break;
#endif /* CONFIG_SOC_SERIES_STM32L0X || CONFIG_SOC_SERIES_STM32G0X */
#endif
default:
return -ENOTSUP;
}
Expand All @@ -147,14 +160,25 @@ static inline int stm32_clock_control_off(const struct device *dev,
break;
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32L5X) || \
defined(CONFIG_SOC_SERIES_STM32F4X) && !defined(CONFIG_SOC_STM32F410RX) || \
defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB2_SUPPORT) || \
defined(CONFIG_SOC_SERIES_STM32F7X) || \
defined(CONFIG_SOC_SERIES_STM32F2X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G4X)
case STM32_CLOCK_BUS_AHB2:
LL_AHB2_GRP1_DisableClock(pclken->enr);
break;
#endif /* CONFIG_SOC_SERIES_STM32_* */
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32L5X) || \
defined(CONFIG_SOC_SERIES_STM32F4X) && defined(RCC_AHB3_SUPPORT) || \
defined(CONFIG_SOC_SERIES_STM32F7X) || \
defined(CONFIG_SOC_SERIES_STM32F2X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G4X)
case STM32_CLOCK_BUS_AHB3:
LL_AHB3_GRP1_EnableClock(pclken->enr);
break;
#endif /* CONFIG_SOC_SERIES_STM32_* */
case STM32_CLOCK_BUS_APB1:
LL_APB1_GRP1_DisableClock(pclken->enr);
Expand All @@ -172,12 +196,13 @@ static inline int stm32_clock_control_off(const struct device *dev,
case STM32_CLOCK_BUS_APB2:
LL_APB2_GRP1_DisableClock(pclken->enr);
break;
#endif /* CONFIG_SOC_SERIES_STM32F0X */
#if defined (CONFIG_SOC_SERIES_STM32L0X) || defined (CONFIG_SOC_SERIES_STM32G0X)
#endif
#if defined (CONFIG_SOC_SERIES_STM32L0X) || \
defined (CONFIG_SOC_SERIES_STM32G0X)
case STM32_CLOCK_BUS_IOP:
LL_IOP_GRP1_DisableClock(pclken->enr);
break;
#endif /* CONFIG_SOC_SERIES_STM32L0X || CONFIG_SOC_SERIES_STM32G0X */
#endif
default:
return -ENOTSUP;
}
Expand All @@ -200,19 +225,22 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
uint32_t ahb_clock = SystemCoreClock;
uint32_t apb1_clock = get_bus_clock(ahb_clock,
CONFIG_CLOCK_STM32_APB1_PRESCALER);
#if !defined (CONFIG_SOC_SERIES_STM32F0X) && !defined (CONFIG_SOC_SERIES_STM32G0X)
#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
!defined (CONFIG_SOC_SERIES_STM32G0X)
uint32_t apb2_clock = get_bus_clock(ahb_clock,
CONFIG_CLOCK_STM32_APB2_PRESCALER);
#endif /* CONFIG_SOC_SERIES_STM32F0X && CONFIG_SOC_SERIES_STM32G0X */
#endif

ARG_UNUSED(clock);

switch (pclken->bus) {
case STM32_CLOCK_BUS_AHB1:
case STM32_CLOCK_BUS_AHB2:
#if defined (CONFIG_SOC_SERIES_STM32L0X) || defined (CONFIG_SOC_SERIES_STM32G0X)
case STM32_CLOCK_BUS_AHB3:
#if defined (CONFIG_SOC_SERIES_STM32L0X) || \
defined (CONFIG_SOC_SERIES_STM32G0X)
case STM32_CLOCK_BUS_IOP:
#endif /* (CONFIG_SOC_SERIES_STM32L0X) || defined (CONFIG_SOC_SERIES_STM32G0X) */
#endif
*rate = ahb_clock;
break;
case STM32_CLOCK_BUS_APB1:
Expand All @@ -232,11 +260,12 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock,
#endif /* CONFIG_SOC_SERIES_STM32G0X */
*rate = apb1_clock;
break;
#if !defined (CONFIG_SOC_SERIES_STM32F0X) && !defined (CONFIG_SOC_SERIES_STM32G0X)
#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
!defined (CONFIG_SOC_SERIES_STM32G0X)
case STM32_CLOCK_BUS_APB2:
*rate = apb2_clock;
break;
#endif /* CONFIG_SOC_SERIES_STM32F0X && CONFIG_SOC_SERIES_STM32G0X */
#endif
default:
return -ENOTSUP;
}
Expand Down Expand Up @@ -450,9 +479,10 @@ static int stm32_clock_control_init(const struct device *dev)

/* Set APB1 & APB2 prescaler*/
LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider);
#if !defined (CONFIG_SOC_SERIES_STM32F0X) && !defined (CONFIG_SOC_SERIES_STM32G0X)
#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
!defined (CONFIG_SOC_SERIES_STM32G0X)
LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider);
#endif /* CONFIG_SOC_SERIES_STM32F0X && CONFIG_SOC_SERIES_STM32G0X */
#endif

/* If freq not increased, set flash latency after all clock setting */
if (new_hclk_freq <= old_hclk_freq) {
Expand Down Expand Up @@ -543,7 +573,8 @@ static int stm32_clock_control_init(const struct device *dev)

/* Set APB1 & APB2 prescaler*/
LL_RCC_SetAPB1Prescaler(s_ClkInitStruct.APB1CLKDivider);
#if !defined (CONFIG_SOC_SERIES_STM32F0X) && !defined (CONFIG_SOC_SERIES_STM32G0X)
#if !defined (CONFIG_SOC_SERIES_STM32F0X) && \
!defined (CONFIG_SOC_SERIES_STM32G0X)
LL_RCC_SetAPB2Prescaler(s_ClkInitStruct.APB2CLKDivider);
#endif /* CONFIG_SOC_SERIES_STM32F0X && CONFIG_SOC_SERIES_STM32G0X */

Expand Down
29 changes: 25 additions & 4 deletions drivers/dma/dma_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <init.h>
#include <drivers/clock_control.h>
#include <drivers/dma/dma_stm32.h>

#include <logging/log.h>
LOG_MODULE_REGISTER(dma_stm32, CONFIG_DMA_LOG_LEVEL);
Expand Down Expand Up @@ -101,14 +102,21 @@ static void dma_stm32_irq_handler(const struct device *dev, uint32_t id)
}

/* the dma stream id is in range from STREAM_OFFSET..<dma-requests> */
if (dma_stm32_is_tc_active(dma, id)) {
dma_stm32_clear_tc(dma, id);
if (dma_stm32_is_ht_active(dma, id)) {
/* Let HAL DMA handle flags on its own */
if (!stream->hal_override) {
dma_stm32_clear_ht(dma, id);
}
stream->dma_callback(dev, stream->user_data, callback_arg, 0);
} else if (dma_stm32_is_tc_active(dma, id)) {
#ifdef CONFIG_DMAMUX_STM32
stream->busy = false;
#endif
/* Let HAL DMA handle flags on its own */
if (!stream->hal_override) {
dma_stm32_clear_tc(dma, id);
}
stream->dma_callback(dev, stream->user_data, callback_arg, 0);
} else if (dma_stm32_is_ht_active(dma, id)) {
dma_stm32_clear_ht(dma, id);
} else if (stm32_dma_is_unexpected_irq_happened(dma, id)) {
LOG_ERR("Unexpected irq happened.");
stream->dma_callback(dev, stream->user_data,
Expand Down Expand Up @@ -255,6 +263,19 @@ DMA_STM32_EXPORT_API int dma_stm32_configure(const struct device *dev,
/* give channel from index 0 */
id = id - STREAM_OFFSET;

/* Check potential DMA override */
if (config->linked_channel == STM32_DMA_HAL_OVERRIDE) {
/* DMA channel is overridden by HAL DMA
* Retain that the channel is busy and proceed to the minimal
* configuration to properly route the IRQ
*/
stream->busy = true;
stream->hal_override = true;
stream->dma_callback = config->dma_callback;
stream->user_data = config->user_data;
return 0;
}

if (id >= dev_config->max_streams) {
LOG_ERR("cannot configure the dma stream %d.", id);
return -EINVAL;
Expand Down
1 change: 1 addition & 0 deletions drivers/dma/dma_stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct dma_stm32_stream {
int mux_channel; /* stores the dmamux channel */
#endif /* CONFIG_DMAMUX_STM32 */
bool source_periph;
bool hal_override;
volatile bool busy;
uint32_t src_size;
uint32_t dst_size;
Expand Down
1 change: 1 addition & 0 deletions drivers/flash/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SAM flash_sam.c)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NIOS2_QSPI soc_flash_nios2_qspi.c)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_GECKO flash_gecko.c)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_RV32M1 soc_flash_rv32m1.c)
zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_QSPI flash_stm32_qspi.c)

if(CONFIG_SOC_FLASH_STM32)
if(CONFIG_SOC_SERIES_STM32H7X)
Expand Down
2 changes: 2 additions & 0 deletions drivers/flash/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ source "drivers/flash/Kconfig.nor"

source "drivers/flash/Kconfig.stm32"

source "drivers/flash/Kconfig.stm32_qspi"

source "drivers/flash/Kconfig.sam0"

source "drivers/flash/Kconfig.sam"
Expand Down
22 changes: 22 additions & 0 deletions drivers/flash/Kconfig.stm32_qspi
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# STM32 Quad SPI flash driver configuration options

# Copyright (c) 2020 Piotr Mienkowski
# Copyright (c) 2020 Linaro Limited
# SPDX-License-Identifier: Apache-2.0

DT_COMPAT_ST_STM32_QSPI_NOR := st,stm32-qspi-nor
DT_STM32_QUADSPI_HAS_DMA := $(dt_node_has_prop,quadspi,dmas)

config FLASH_STM32_QSPI
bool "STM32 Quad SPI Flash driver"
depends on SOC_FAMILY_STM32
default $(dt_compat_enabled,$(DT_COMPAT_ST_STM32_QSPI_NOR))
select USE_STM32_HAL_QSPI
select FLASH_HAS_DRIVER_ENABLED
select FLASH_JESD216
select FLASH_PAGE_LAYOUT
select FLASH_HAS_PAGE_LAYOUT
select DMA if $(DT_STM32_QUADSPI_HAS_DMA)
select USE_STM32_HAL_DMA if $(DT_STM32_QUADSPI_HAS_DMA)
help
Enable QSPI-NOR support on the STM32 family of processors.
Loading