STM32H7 SPI frozen during break? - stm32

In order to freeze a timer during a break in debug mode on a STM32H7, one has to set a bit in the DBGMCU. But I didn't find such a bit for SPI. Does it mean that the SPI is always frozen ? Or on the contrary never frozen ?

Short answer:
There is no such option for the SPI. SPI is always enabled, if used and proper configured.
Long answer:
There is no such option for SPI because this interface must be either actively served by the microcontroller. In this case the SPI transaction is automaticly stoped if your device is halted e.g in break mode. Any ongoing transaction of a word/fifo will be executed anyway.
Or the dma controler is configured to server the SPI. In this case data transmission is controlled by the dma controller. The dma controller itself has different trigger sources. As long this trigger source is not a timer depended one there is no way to implicitly halt the transfer.
See also: https://stackoverflow.com/a/43225545/5388805

Related

Why does the sequence of init calls matter in STM32CubeIDE?

Writing a simple UART program using CubeIDE 1.7.0 for a Nucleo-H723ZG board using DMA. A UART DMA receive call is issued waiting for input from a serial port app on the Mac OSX host (CoolTerm). A callback echoes the data received.
When a text message is sent to the board nothing but zeros is echoed back.
I noted that CubeMX had generated the DMΑ initialisation call (MX_DMA_Init()) AFTER the UART initialisation call (MX_USARTx_UART_Init()).
By Reversing the sequence of these two calls the code worked perfectly!
Is this my error, has something been missed in the setup, or is it an MX error?
This issue only affects CubeIDE 1.7.0 users on MacOSX Big Sur. Under Windows there is no problem and the code generator correctly positions the DMA initialisation call before that of the USART.
When using the MX configurator the peripheral initialisation calls are generated in the sequence in which they are entered. When setting up a USART to use DMA to perform the data transfer, two peripherals' initialisations need to be generated: the USART and the DMA device. As the USART was the first of the two peripherals selected the USART init call is generated before the DMA init call.
However, unknown to me at the time, the USART needs to set up a DMA register which must have its clock enabled. The DMA init must therefore be done BEFORE the USART init. Hence my problem.
Knowing this, in the MX Project Manager tab, the Advanced Settings tab provides the option to rearrange the sequence of these init calls and all is well!
So this is a bug. However, using a Nucleo-H743ZI2 with USART DMA there is no problem with out-of-sequence initialisation. Thus far the bug is limited to the Nucleo-H723ZG!
The firmware generated by CubeMX6.3.0 for Nucleo-G474RE does the same initialization inversion (UART before DMA) and leads to unresponsive code.

Watchpoint on STM32 GPIO register

using Keil µVision on a STM32F4 I am trying to add a watchpoint to a GPIO data register, which just does not trigger.
I want the watchpoint to be triggered as soon as output data gets writting into this register.
Setting the watchpoint to the os timer work fine.
Peripheral registers are memory mapped in STM32 F4, as far as I know.
Any (simple) explanation that I am missing here?
Any hint is very much appreciated.
While the ARM core can access the peripheral I/O registers in the same flat 32-bit address space as SRAM or flash, peripheral I/O registers are located in separate buses on the MCU, and not accessed by the same bus as the SRAM. For example, on the STM32F, there are the ABH bus which are usually further divided into the APB1 and APB2 buses, depending on the device. In any case, the debug controller unit defined by ARM ("CoreSight"), provides data watchpoint capability, and it only works on "real" data access.
Would be great if it did though ;-)
No source, or personal experience, but I can think of a few reasons why this wouldn't work.
Often value isn't "there" like in RAM, but is created when you access a peripheral register.
You could say periodic access could then solve this, but that wouldn't work for registers where reading has side effects (usually clearing some status flag).
I think you'll have to create an interrupt handler for GPIO, and a breakpoint for that.
there is a workaround if 12 cycles latency is a problem. Use Pin as a trigger which triggers memory to memory DMA transfer. Set the watchpoint on the destination (or source) RAM address.

The DMA support is needed to implement a device type interrupt driven?

From what I understand, interrupt-driven I / O and DMA are two separate mechanisms, but I need to answer this question. I think the answer is no for the fact that it is not necessary
If a device uses DMA (Direct Memory Access), it is able to read or/and write directly from/to the main memory.
If a device can generate interrupts, it is able to notify the CPU that it requires attention.
So, DMA and interrupts are principally completely independent.
They can of course be combined, e.g. a device can notify the CPU that it has finished a DMA.
So, you are right, the answer is NO.

Do we have to enable or disable PCI interrupts on every layer, or only at the closest to hardware?

I'm implementing a PCIe driver, and I'd like to understand at what level the interrupts can be or should be enabled/disabled. I intentionally do not specify OS, as I'm assuming it should be relevant for any platform. By levels I mean the following:
OS specific interrupts handling framework
Interrupts can be disabled or enabled in the PCI/PCIe configuration space registers, e.g. COMMAND register
Interrupts also can be masked at device level, for instance we can
configure device not trigger certain interrupts to the host
I understand that whatever interrupt type is being used on PCIe (INTx emulation, MSI or MSI-X), it has to be delivered to the host OS.
So my question is really -- do we actually have to enable or disable interrupts on every layer, or it's sufficient only at the closest to hardware, e.g. in relevant PCI registers?
Disabling interrupts at the various levels usually has completely different purposes.
Disabling interrupts:
In the OS (really, this means in the CPU) - This is generally about avoiding race conditions. In particular, if state/memory corruption could occur during a particular section of code if the CPU happened to be interrupted, then that section of code will need to disable interrupt handling. Interrupt handlers must not acquire normal locks (by definition they can't be suspended), and they must not attempt to acquire a spin-lock that is held by the thread currently scheduled on the same CPU (because that thread is blocked from progressing by the very same interrupt handler!) so ensuring data safety with interrupt handlers can be tricky. Handling interrupts promptly is generally a good thing, so you want to absolutely minimise such sections in any code you write. Do as much of your interrupt handling in secondary interrupt handlers as possible to avoid such situations. Secondary interrupt handlers are really just callbacks on a regular OS thread which doesn't have any of the restrictions of a primary interrupt handler.
PCI/PCIe configuration - It's my understanding this is mainly about routing interrupts, and is something you normally do once when your driver loads (or is activated by a client) and again when your driver unloads (or is deactivated). This may also be affected by power management events. In some OSes, the PCI(e) level is actually handled for you when you activate PCI device interrupts via higher-level APIs.
On-device - This is usually an optimisation to avoid interrupting the CPU when it doesn't need to be interrupted. The most common scenario is that an event happens on the device, so an interrupt is generated. The driver's primary interrupt handler checks the device registers if the driver needs to do any processing. If so, it disables interrupts on the device, and schedules the driver's secondary interrupt handler to run. The OS eventually runs the secondary handler, which processes whatever information the device has provided, until it runs out of things to do. Then it enables interrupts again, checks once more if there's any work pending from the device and if there are none, it terminates. (If there are items to process in this last check, it re-disables interrupts and starts over from the beginning.) The idea is that until the secondary interrupt handler has finished processing, there really is no point triggering the primary interrupt handler, and a waste of resources, if additional events arrive, because the driver is already busy processing the event queue. The final check after re-enabling interrupts is to avoid a race condition between an event arriving and re-enabling interrupts.
I hope that answers your question.

Power save mode STM32F205RG

I am using STM32F205RGT6 Cortex-M3 microcontroller and coding with IAR Embedded Workbench.
I plan to keep the microcontroller in a power saving mode most of the time except when an external component tries to either communicate via SPI (the STM32 microcontroller is meant to be a SP slave) or via USB.
One external compinent is connected via SPI (PB12-15) and PC is connected via USB (PA11-12).
The communication works fine - I have tested both the SPI as well as USB.
I figured that once I am done setting up SPI and USB I will call a power saving function and add the same function call at the end of interrupt service routines. I have found PWR_EnterSTANDBYMode and PWR_EnterSTOPMode (in stm32f2xx_pwr.h) both of which I tried using.
However with such arrangement I cannot establish any communication (SPI or USB) with the microcontroller.
Is there something extra that needs to be configured (for example which pins should wake the microcontroller up)?
Am I using wrong function? Or wrong header file?
Can you point me to an example resembling such case (I could not find anything similar on ST's website)?
Any constructive feedback would be welcome.
In the mean time I found the application note AN3430 (http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/DM00033348.pdf) which is somehow more digestible (only 38 pages) which gives an excellent overview on power saving in the microcontroller.
Since I don't have access to PA0-WKUP (the wake-up pin) I had to discard using stand-by. Seems that just a simple sleep mode in main loop - by calling __WMI(); - should lower current consumption enough in my case. I might consider stop mode if sleep mode isn't enough but I will have read fragments of datasheet on configuration of EXTI registers that the application notepoints to.