STM32H7 Instability?
Posted: Wed Apr 01, 2020 3:29 pm
Sorry for the vague topic, but I haven't been able to narrow this problem down to a specific system.
Since my last post(viewtopic.php?f=16&t=5441), I've started to get my devices up and running. I've got three serial ports, an SPI device (MPU6500), and two I2C devices (MS5611, QMC5883L) online. There are problems though. I suspect they're all related, but here are the symptoms I'm seeing:
Maybe the common thread in these is the DMA system? I have very little understanding of how that works. In my mcuconf.h, all DMA streams are set to STM32_DMA_STREAM_ID_ANY.
Any ideas on what might be going on? My basic task is to get device communications working reliably, without any possibility of lock-ups.
Things I've done:
My architecture:
Buffers are defined as globals in main.cpp:
Objects are defined as globals in main.cpp. Objects extend chibios_rt::BaseStaticThread. Each object creates one thread, which handles all of its communications to its device:
Objects are configured and started in main():
Within the device driver, the actual communication code looks like the following:
Since my last post(viewtopic.php?f=16&t=5441), I've started to get my devices up and running. I've got three serial ports, an SPI device (MPU6500), and two I2C devices (MS5611, QMC5883L) online. There are problems though. I suspect they're all related, but here are the symptoms I'm seeing:
- One I2C device often repeats the same set of samples many times in a row, and the other toggles between good data and some fixed and totally wrong data
- One I2C device only runs at 100khz, though the device itself is capable of high-speed mode. At 400khz, I get system lock-ups where the processor goes into an infinite loop of trying to service an I2C interrupt
- One I2C device gets a constant trickle of errors returned from i2cMasterTransmitTimeout. 1-2% of requests seem to generate something other than MSG_OK. Whenever this happens I stop the bus, sleep, reconfigure, start the bus again, and then run my device configuration.
- Sometimes after some minutes of operation, this will change to 100% errors. Resetting the MCU fixes this, even though the I2C device remains powered the whole time.
- I have a brittle set of memory buffers for the various devices. If I change the memory location for any of the communication buffers, either the error rate changes or I start getting lock-ups. (detail below)
Maybe the common thread in these is the DMA system? I have very little understanding of how that works. In my mcuconf.h, all DMA streams are set to STM32_DMA_STREAM_ID_ANY.
Any ideas on what might be going on? My basic task is to get device communications working reliably, without any possibility of lock-ups.
Things I've done:
- Verified through an o-scope that the I2C signals appear to be healthy and at the correct rate.
- Tried both the clock configuration from the H7 demo, and from ArduPilot. (Modified to use HSI rather than HSE)
- Swapped the physical devices.
- Swapped the board/processor that I'm developing on.
- Putting sleep(1) between all of the successive i2c calls.
- Increased the timeout value in i2cMasterTransmitTimeout to 20ms - way bigger than necessary.
- Followed the instructions in http://www.chibios.org/dokuwiki/doku.ph ... _dma_guide, having 32*x byte buffers in-32-byte aligned memory, and flushing TX and invalidating RX before/after communicating.
- Implemented basic load and stack-space monitoring. All debug options are turned on as well.
- Electrically, there is only one device per i2c bus. All SCL and SDA lines have 2.2k external pullup resistors. Internal pullups/pulldowns are disabled.
My architecture:
Buffers are defined as globals in main.cpp:
Code: Select all
__attribute__((__section__(".ram2"))) __attribute__((aligned (32))) static uint8_t mpu6500_tx_buffer[32];
__attribute__((__section__(".ram2"))) __attribute__((aligned (32))) static uint8_t mpu6500_rx_buffer[32];
__attribute__((__section__(".ram2"))) __attribute__((aligned (32))) static uint8_t ms5611_tx_buffer[32];
__attribute__((__section__(".ram2"))) __attribute__((aligned (32))) static uint8_t ms5611_rx_buffer[32];
__attribute__((__section__(".ram1"))) __attribute__((aligned (32))) static uint8_t qmc5883l_tx_buffer[32];
__attribute__((__section__(".ram1"))) __attribute__((aligned (32))) static uint8_t qmc5883l_rx_buffer[32];Objects are defined as globals in main.cpp. Objects extend chibios_rt::BaseStaticThread. Each object creates one thread, which handles all of its communications to its device:
Code: Select all
__attribute__((__section__(".ram0"))) MPU6500 mpu;
__attribute__((__section__(".ram0"))) MS5611 baro;
__attribute__((__section__(".ram0"))) QMC5883L mag;Objects are configured and started in main():
Code: Select all
mag.configure(&BUS_I2C_MAG);
mag.setI2CBuffers(qmc5883l_tx_buffer, qmc5883l_rx_buffer);
mag.start(NORMALPRIO);Within the device driver, the actual communication code looks like the following:
Code: Select all
void QMC5883L::read_registers(uint8_t first_register, uint8_t read_byte_count) {
tx_buffer[0] = first_register;
cacheBufferFlush(this->tx_buffer, 32);
msg_t res = i2cMasterTransmitTimeout(this->i2c, QMC5883L_ADDRESS, this->tx_buffer, 1, this->rx_buffer, read_byte_count, TIME_MS2I(20));
cacheBufferInvalidate(this->rx_buffer, 32);
if (res != MSG_OK) restart_bus();
}