Cannot setup Cortex M7 ITM properly on STM32H7 - debugging

I'm working on STM32H753 (STM32H753I-EVAL2 board) using STM32CubeIDE and I'm trying to setup the ITM.
I've started by enabling SWV in the Debugger setting (of course I selected SWD) with Core Clock 400MHz (my CPU clock) and SWO clock 2MHz.
Then in my code I defined the following macro:
#define ITM_Port(n) (*((volatile unsigned long *)(0xE0000000 + 4*n)))
and call this macro as follows, at the location of my code where I want to get a timestamp.
ITM_Port(20) = 0x10;
Finally, in the debug session, I enable ITM stimulus port number 20 and Timerstamp, and launch the SWV Trace Log.
However I don't understand the output:
If I remove the calls to ITM_Port, the trace is empty...
I checked the registers ITM_TCR and ITM_TER and they look correct. Stimulus port 20 is indeed enabled in TER. In TCR, bits ITMENA, TSENA, SYNCENA and TXENA are set.
I looked at assembly level (that looks correct) and I noticed that the store instruction that is supposed to write 0x10 into ITM_STIM20 has no effect,the register is not modified. Is there something to unlock / enable ?
I also configured the GPIO PB3 with alternate function SWO.
Any idea ?

[...] I noticed that the store instruction that is supposed to write 0x10 into ITM_STIM20 has no effect, the register is not modified.
Please re-check the read/write semantics of this register in the
Reference Manual, page 3222:
Write data is output on the trace bus as a software event packet. When reading, bit 0 is a
FIFOREADY indicator:
0: Stimulus port buffer is full (or port is disabled)
1: Stimulus port can accept new write data
Therefore, I don't believe that there must be a mistake around this register.
The trace log screenshot in the question shows plenty of ITM trace packets at other ports (24, 25, 26, 28, 29, 30, 31).
Please take care not to overdo the ITM trace packet creation:
The question refers to SWV Trace Log, so the trace packets of different ITM ports must all pass through the same SWO line.
That interface is not very fast (while the CPU of STM32H7 certainly is!), so software-triggered ITM packet creation can easily choke this bottleneck so that packets are discarded.
The question doesn't contain the surrounding code where trace packets are created, but my guess is that during the analysis, inserting additional ITM packet triggers at a finer level (inside loops or so) increased the port traffic until lost packets weren't even noticeable.
The easiest way out may be to remove parts of the ITM triggers (or, to activate only few ITM channels at a time, which will filter packets in ITM before they are transmitted through SWO) and measure different aspects at a time, repeating the measurement with different ITM channel selection.
The second easiest way is to spend a few k$ on a debug adapter that supports the synchronous trace port. This feature is only supported by high-end adapter variants such as J-Trace, Lauterbach, etc. - it is usually targeted at ETM tracing, but you can also use the parallel TPIU interface to output ITM data, probably at a higher rate.
This strategy isn't the most elegant in the described situation - please consider the other way first!

Related

What is the difference within the compiler between debugging and running the code? (STM32)

somehow when i am running my code, it seems like one GPIO Port isn't being initialized, meanwhile if i am debugging, it is.
I am initializing two sensors:
struct MAX31856_t max31856_temperature_sensor_heater_1 = MAX31856_TPL( SPI_DEV_TPL( IO_PIN_TPL(
TEMP_SENSOR_0_CS_GPIO_Port, TEMP_SENSOR_0_CS_Pin), &spi1));
struct MAX31856_t max31856_temperature_sensor_heater_2 = MAX31856_TPL( SPI_DEV_TPL( IO_PIN_TPL(
TEMP_SENSOR_1_CS_GPIO_Port, TEMP_SENSOR_1_CS_Pin), &spi1));
Sensor Heater 1 is not getting any Information, Sensor Heater 2 is getting Informations. Now if i swap the Name of the Heaters:
struct MAX31856_t max31856_temperature_sensor_heater_2 = MAX31856_TPL( SPI_DEV_TPL( IO_PIN_TPL(
TEMP_SENSOR_0_CS_GPIO_Port, TEMP_SENSOR_0_CS_Pin), &spi1));
struct MAX31856_t max31856_temperature_sensor_heater_1 = MAX31856_TPL( SPI_DEV_TPL( IO_PIN_TPL(TEMP_SENSOR_1_CS_GPIO_Port, TEMP_SENSOR_1_CS_Pin), &spi1));
and run the code in the debugger, Sensor Heater 1 and 2 are getting Informations.
How can this happen? I was thinking about a timing problem, but since it is working in the debugger, i don't really know what to do.
Provided that you are debugging and/or running the same binary. Debugging is mostly the same as running except if you halt the processor (es breakpoints).
In that case...
some peripherals could continue to run or be halted togheder with the cpu, the behaviour is some cases can be configured. (timers, watchdog...)
some interrupts can be lost.
some hardware buffers can overflow and data can be lost (if you don't use any flow control in your IO)
How do you run the code in debug mode? Do you have breakpoints somewhere?
You (OP) are right about it being most likely a timing problem, and probably related to physical SPI transmission. Because your line of code to send/receive something over SPI has already executed in the MCU, but physically the bits and bytes are still being transmitted on the line, while MCU is already calling the next SPI function, so one of the transmissions will fail. Try adding some delay after SPI transmission code. If things work after that, then it's the timing of SPI peripheral, and you need to add a check that there is no SPI transmission already in place before you call a functions to send/receive something.
You can do while(transmission) (pseudocode, replace with actual check if SPI transmission is going on) to wait until the previous transmission ends to call the next one.

Dismiss or Handle Data Abort when AXI transaction replies an error

Background
I have an ZynqMP system which has four Cortex-A53 cores (PS) along with FPGA logic (PL). They transfer data via AXI bus.
I've placed some Xilinx AXI Quad SPI in my design. Linux which runs on PS successfully probes them, and starts a daemons which periodically (333 Hz) ask MCUs on SPIs to reply their data chunk (~ up to around 500 bytes, split in every 64 bytes.)
They works nicely for a while (median 50 minutes) but suddenly the readl_relaxed() in SPI driver causes Synchronous External Abort which leads an Kernel Panic. It seems to be an AXI's error reply according to ARM TRM, and might be recoverable because it's "synchronous" which means the registers are not corrupted (in my understanding.)
After some search I found the do_sea() func that handles SEA and also found that there's no chance to recover from it according to the implementation.
I want the AXI error to be handled like: discard the read, return SIGBUS and lead the process to be killed, etc.
Of course I'm debugging the Abort and finding why it occurs but at present I have no clue.
Question
So my questions are:
Why SEAs are not recoverable in Linux arm64 implementation?
If I can "handle" or "ignore" it, how do I modify Linux kernel code (I know it's stupid but I'd like to know if there's a way.)
What can reply error in Quad SPI IP? The readl_relaxed I mentioned above reads Rx data FIFO.
1) I’ve never ventured down this path, but it looks to me like they are recoverable if the inf->fn returns 0; which means that ghes_notify_sea() must return 0; thus one of the SEA error sources successfully reported an error.
2) I think you need a bit more info. I would start by changing
drivers/acpi/apei/ghes.c:732
from:
rc = ghes_read_estatus(ghes, 0);
to:
rc = ghes_read_estatus(ghes, 1);
which should get you a bit more information when the error happens.
Armed with that information, you need to find out if you have a malfunctioning handler, or a missing one. Either way, this is the place to address it.
3) You are dealing with an ACPI implementation. There are 155 kloc in the kernel plus unknown quantity in the firmware and hardware. The kernel code doesn’t appear to handle whichever condition you are running into. First you need to determine which of these suspects is involved and what interactions are failing before you can dig out the root cause.
Happy Digging!

Is it possible to query serial port tx pin status (signal low / high) in windows?

Is it possible to query serial port tx (send) pin status if it is active or not ?
For example when issuin break command (SetCommBreak) tx pin is set to active (low). I'd like to know when it is active or not. Thanks.
No. (at least not likely)
If you are using the "16550" family of UARTs, then I am confident that you can not query the serial port tx pin status. Of course, if you are using some new version or other UART family, maybe.
You can assume that the TX pin is in the SPACE state ('0', +Volts) whilst performing SetCommBreak(), but I suspect that is not enough for you.
If you are look to debug your code to know if a break occurred, you can short pins 2 & 3 on a 9-pin D-sub, thus loop backing the transmit to the receive. A paper clip will do. Your receive code would detect the incoming BREAK. Shorting to the incorrect pin does not cause a lasting problem with a conforming serial port, but be careful. Try this first with simple data, before testing BREAK condition.
If you have a "16550"-like UART.
You can put the UART into loop-back mode and see if you receiving you own outgoing BREAK signal. Its somewhat complicated in current PCs. Other UART type may support loop-back.

CAN Bus Protocol Implementation

I want to learn and implement CAN BUS protocol. I have implemented UART,SPI,I2C and One Wire Bus protocol using MSP430 Launchpad in software. Now I want to learn about CAN Bus protocol. I have mBed LPC 1768 Cortex M3 Development board. mBed has Can Bus Library but I want to write my own library so that I can learn it in detail, i.e. the way I did for other communication protocols.
I am not able to find suitable resources to start with and the material appears to be scattered on net. Can any one guide how do i write and implement CAN Bus protocol with the development boards available with me.
Thanks
Developing CAN library is relatively easy as compared to I2C or SPI. This is because CAN Controller of your Cortex will take care of most of complex things.
To transmit the data, You have to write ID and Data in designated registers and set bit to transmit data.
This Application note from NXP can be very useful for you.
I would recommend you to implement following functions:
InitCAN - This should set specified Baud Rate of CAN.
SetFilters - Most CAN Controllers come with Acceptance Filters, So it's good to have that
SendData - Make sure you accept Parameters like ID_Type and RTRs etc.
RecieveData - This can be blocking or Interrupt based.
Before beginning, do read CAN Basics to understand. Application notes AN713 and AN754 from Microchip is a good source. Also Vector's site and Wikipedia Article.
Plus, You can always post your doubts here or on Electronics.StackExchange.com :)
Okay so this post is quite old but people may look at it again so:
First of all Can bus is not user friendly protocol like USART or IC2 at all so you have to be very precise about your can bit timing there are tools for that but I suggest you to calculate them by hand. For a microcontroller I would suggest STM32 and be away from PIC series in my opinion. If it's only CAN-BUS without higher level protocols such as SAE J1939, steps are pretty simple and straight forward:
1)Initialize Can
2)Put CAN to configuration mode and remember that you can set baudrate, mask and filters only in configuration mode!
3) Set the baud rate registers.
4) Set the mask and filters. If you need to receive all messages just simply set mask to 0x00. Then filter will be do not care.
5) Set the CAN to the normal or loopback mode. (loopback mode is used for debugging purposes mostly.)
Some remarkable points people try to implement can at the beginning may miss:
*** You need at least 2 working CAN nodes for successfull transmission. (of course with matching baud rate). So if you want to send some data via CAN with 1 node it will not be succesfull. Because your transmitter node will not receive ACK.
*** Most likely you will need a CAN tranciever. Do not forget to put a 100 ohm or similar value resistor between Tx and Rx pins of your tranciever.
I used the software canking to talk to a mcp25050 when I learned how to implement can protocol using an hcs12 dragonboard. It helped a lot because canking will initialize everything for you when u go on the bus and all you have to do is learn how to write and recieve. If you want to learn how to initialize the steps are:
Enables can bus by setting bit on CAN Control Register 1
Enable can initialization Control Register 0
wait until can bus is in initialization mode by checking control register 1 bit
Enables can bus by setting bit on CAN Control Register 1 again and set clock source - Ethier bus clock or eclock
set prescaler baudrate and Tq with Bus timing register
set sample time and prop_seg1, prop_seg2, and phase_seg
set acceptance id on Identifier acceptance register 0-3 or 0-7 - to set your can to recieve everything set those to 00 because when doing a compare the can bus does a ones complement compare with the id coming in
set Identifier mask register 0-3 or 0-7, if you want to not care about any of the bits set them all to FF
set identifier acceptance control register to 32 bit extended or 11 bit - i use 32
set Control Register 0 back to normal mode
wait until bus is normal mode by checking Control Register 1
after this you can start changing registers or reading data to do this you must select the empty can buffer, write your id to write or request data, and then input the address, mask, and value in the 3 transmitter registers if writing and then specify the dlc (3 if writing and 8-1 if reading). to transmit the id and data you then have to set the can transmit flag to equal the can Transmit buffer selection.
** depending on what id you use bit shifting can be tedious so if you are having a problem I would suggest debugging and looking at what your Transmit buffer selection registers are holding. I had this error because i did not shift correctly when i was sending messages to the mcp25050
If your MCU supports CAN Bus, you should start from the related datasheet.

Creating new task in FreeRTOS for USART reception

I am using EVK1105 development board with AVR Studio 5 as development IDE for my AVR project.
I am using FreeRTOS in it. I have 3 USART ports on this board. One external module is connected to my AVR32 board via USART-RS232 mode. It sends me continuous serial data to my board on USART0 with 19230 baudrate, 7-databits, odd parity, stopbit-1 and normal-channel mode. I created a new task for this purpose. After each 9 data bytes it sends '\n' and '\r'. So in my task I keep on collecting the 9 databytes in a string buffer and then transmit it on USART1. I am using polling method to collect data from USAR0 which is receiving port. But I am facing problem in receiving data. I don't know if its timing issue or something or the scheduler switches the task while collects the data. But I don't get the required data.
Following are things I have already checked as troubleshooting
1. Connected my external module to my PC hyper-terminal which gives me perfect result.
2. Implemented the same thing of using receiving from USART0 and whatever received is transmitted to USART1 as without FreeRTOS. Its works fine.
Please suggest some idea what may be wrong. I am using a queue to communicate between Tx and Rx task to pass the string buffer from USART0 to USART1. Is it problem in handling queue? How can I troubleshoot the queue?
I am using a delay of 50ms in my infinite task loop in Rx Task. Can it create a problem? If I don't use any delay the OS crashes. Please suggest some good practices to create a new task in FreeRTOS so that I will not get any timing issue.
For such a use case, I would not use a polling method with 50ms delay to retrieve data from UART peripheral. You can easily lose received data depending on the system load and UART reception buffer size.
At least use an interrupt on UART data reception that copies every received byte into a local buffer that will be read by your TX thread.
You can have an even better solution using a DMA channel to receive your data frame and be notified when 9 bytes have been received. I don't know if your AVR device has a DMA peripheral or not.
Are you still working on this? The statement of your problem is vague, but there I have several suggestions/leading questions.
1) You may want some documents to see what the registers are
Get the giant datasheet pdfs at
http://www.atmel.com/dyn/products/product_docs.asp?category_id=163&family_id=607&subfamily_id=2138&part_id=4117
2) In this and an earlier post you state that you have, in some cases, been able to RX data. You will need to find the USART HW initialization code from those example projects and get them into the freeRTOS example project. In particular calls to
gpio_enable_module() with {AVR32_USART0_RXD_0_0_PIN, AVR32_USART0_RXD_0_0_FUNCTION}
To connect to USART to CPU
and i believe
InitRs232()
Just doing this requires poking around a lot of code - there's alot of dependencies.
2) What function are you calling to retrieve data from USART0? 19kbaud is approximately 2000bytes/sec or 1 byte/0.5ms, so 50ms polling is not nearly enough. I'd suggest that your RX task poll continuously (never sleep explicitly) but at a lower priority than the TX task.
3) Concentrate on debugging the RX task at the call to retrieve data. Use the debugger to look at the hardware registers for the usart. In particular
USART0 cr register AVR32_USART_CR_RXEN_MASK should be set to enable RX
USART0 csr register AVR32_USART_CSR_RXRDY_MASK will indicate if there is new data there
You can also check the overlow flag to see if you have missed some data.
When the read of USART0 rhr occurs it should be a byte that you sent.
If you are still working on this I can look into this a bit more.

Resources