STM32CubeIDE HAL - Generated EXTI interrupts won't trigger - STM32F4 - arm

I've created (so far) simple project for STM32F411 MCU in STM32CubeIDE.
When using the GUI configurator to enable hardware interrupt EXTI for my pins (originally I wanted to use PB5, but added PB8 as it's just sticking out on my PCB and PA0, as it has button attached between it and ground) it generates configuration code to my main.cpp (for generation I rename it to main.c so configurator sees it), it created proper event handlers to which I added method HAL_GPIO_EXTI_Callback, according to instructions in stm32f4xx_hal_gpio.c, however, interrupts are not fired. Breakpoints are not hit, no output on serial.
I've set those pins to use EXTI, set their respective pull-ups/pull-downs etc. according to my needs (although tried to change it with no effect).
I've enabled those interrupts (EXTI line0 and EXTI line[9:5]) in NVIC page, followed countless tutorials on the issue (e.g. this one: https://www.waveshare.com/wiki/STM32CubeMX_Tutorial_Series:_EXTI, also official ST Electronics youtube channel).
My board is STM32F411CEU based chinese Black Pill.
Full code can be seen here: https://github.com/domints/LoadCellCWManipulator (latest commit, for future reference f4330cd6066f227f5cf3d3ea619adcc810025b72).
Might there be something I am missing? All other code I've tried so far works without a problem.
Might be that CubeIDE is missing something during generation and I need to write something by hand?
I'm trying to use C++ (although IDE supposedly has that options it makes it harder), as I am coming from higher level background.

Related

PIC16 microcontroller_ no output even after following tutorial

I am using PICKIT 4, PIC16F18446 microcontroller, and MPLAB X IDE. I am following an instruction provided from Microchip, Measuring frequency
Update:
I am not entirely sure what i needs to change but I am consistently getting an output of Frequency: 25536 whether there is an input signal or not. (Image of the output, and pin configuration shown below)
The Original Poster is using a PIC18 tutorial for a PIC16F target.
The MPLABX Code Configurator (MCC) tool is an awful thing for anyone new to the Microchip development tools to use.
An MPLABX project that does what I think this tutorial is about for the PIC16F18446 target is here in my git hub repository.
MCC was used to create most of this code so you should be able to see how it was done.
This code runs in the MPLABX simulator but that is a buggy hot mess. Use it with caution.

avr-gcc vs Arduino in PlatformIO

I'm using PlatformIO as an IDE for programming AVR MCUs. I'm beginning AVR programming (I have a background in C/C++ and programming on OS's, not embedded, although I have done some Arduino stuff in the past) and using PlatformIO gives me code completion for the registers/pins, which is why I use it.
It seems I can't switch framework from Arduino to avr-gcc in PlatformIO without losing code-completing.
I am wondering if there's any drawbacks in keeping Arduino as the
framework?
I know Arduino uses avr-gcc in the back, but I read that it still does a bit of setup without the users knowing it (such as Timer0 setting for delays, which I need since I'm using it as a clock source for USI on my ATTiny85).
Otherwise, is there anyway in PlatformIO to keep code completion and
use avr-gcc instead of Arduino?
Thanks!
EDIT: I'm on either OSX or linux (ubuntu).
As pointed out by ivankravets on the PlatformIO community platform (see: https://community.platformio.org/t/avr-programming-without-arduino-framework/525/4), it is as simple as removing the line framework = arduino from the platformio.ini file to get rid of the Arduino framework and work in bare C for avr-gcc.
I have never used PlatformIO, and my answer is only based on my (extended) knowledge of AVR development and the Arduino mess…err…framework.
The Arduino framework is using AVR-libc (the standard low level framework that gives you all the tools you need to program on AVR), and adds a layer of abstraction so you're not directly handling registers, but use a more easily understandable interface.
So when you write on a pin, instead of looking at the AVR's IC leg number, looking for the matching PORT address to configure it and mutate it, you're using digitalWrite() on the board's pin number. So, whatever the IC is, the pin will stay the same with consistent capabilities.
The pin definition is done using a header file that's given to the compiler depending on your target setting in your IDE (so whether you use an Arduino Mega or a Leonardo the matching between AVR port/pin and board pinout will change radically).
Given your description of PlatformIO, it's using that information to give you appropriate pinout completion based on the board configuration. It's also certainly taking advantage of the object oriented approach of the Arduino framework, so that you can easily have method completion when using singletons (like when you use Serial).
Using raw AVR-libc, on the other hand, it's harder to get any meaningful completion, because most of the operations are being done on registers which are being declared through preprocessors aliases, and the whole code is pure C, so code completion is not really helpful (you cannot list all the methods that applies to a given object… like with the Serial example).
Then, Arduino offers a nice high level approach to prototyping embedded code, that you can then curate when you need to optimise in time and/or space. And some projects (like the Marlin firmware for repraps) use some sort of hybrid approach, reimplementing many parts of the Arduino interface in a more optimised way (like digitalWrite or the Serial object).
In the end, my advice to you would be to drop platform.io or the arduino IDE, and switch to eclipse if you're really into IDE GUIs, or better, use your preferred powerful editor (like vim/nvim, emacs, atom, sublime…) to have it handle AVR code like any other C code.
If you work on an Arduino project including avr-gcc internals using VisualMicro plugin and VisualStudio (Community Edititon) all the code completion / syntax highlighting / goto declaration etc. works for anything in your project and all libraries.
Is this what you're looking for?
Of course, VisualMicro is annoying if you use them "for free"

Zynq Qspi Booting

I'm using Arm DS-5 and Xilinx SDK for developing programs on Zynq board.
I'm trying to boot Zynq 702 board from Qspi Flash.
What I've done so far is generating FSBL project from Xilinx SDK, and combining it with my application using Bootgen tool in SDK, then program it into the flash.
There are several questions in my mind.
DS-5 produces an .axf file, Bootgen requires an .elf file. Can I use
the .axf file by just changing its extension to .elf or do I require
some more steps?
Is there a tool that shows the inner structure of an .axf file?
Showing what is where?
And how can I debug if I managed to boot from QSPI. For example I want to debug my application from the beginning of FSBL, is it possible? Because in Qspi Boot, When I power on the board, my application would start running and when I connect with JTAG, it would be in somewhere in my application.
An AXF might have some extra ARM-toolchain magic in it (I'm not sure off-hand), but at heart it's an ELF file - the ARM toolchain provides fromelf for poking around inside them, but other tools like readelf and objdump also work.
I'm not familiar with the Zynq platform so I don't know any specific debugger tricks, but a general one is just to put an infinite loop at the start of your code (possibly using volatile or inline asm trickery if necessary to prevent optimisation) - once the debugger's connected and broken into it, you just move the PC past the loop and continue.
You can totally halt QSPI-booted Zynq via JTAG and do whatever you want with it. However, there are some quirks. Sometimes Zynq goes into some kind of lockup, and JTAG doesn't work at all, and you need to power-cycle before retrying. Some not-so-well-written peripherial might die after starting software over JTAG, so you might need to re-load bitstream first. And there are some Vivado-related bugs (like the one where you cannot re-flash the board unless you downgrade to 2017.2 or change MIO2-6 pulls or patch the FSBL) but i'm not sure if they apply in your case.

How to use I2C on a TM4C123GXL (TivaC) Launchpad

I am attempting to connect my Launchpad device to the Pololu MinIMU9v2 9DoF sensor via the I2C bus. I am working in a Linux environment, compiling with arm-none-eabi-gcc, and I have downloaded the sw-ek-tm4c123gxl zip file from the Texas Instruments website.
In digging through the drivers download, I identified a folder (examples/peripherals/i2c) that contains 3 demonstrations (each in a single C file) for using the I2C bus. One runs the Launchpad as a slave, the next configures it as a loopback, and finally, there is one that interfaces the Launchpad with an Atmel I2C-based memory device using what it refers to as "soft I2c".
I'm assuming that the "soft" part of this means that it's software based, utilizing interrupts and all. I'm looking for a simpler solution, preferably without interrupts. The loopback example worked like a charm, for instance, but in modifying it, I can't seem to get it to communicate with the MinIMU9, no matter what I try. The documentation for the MinIMU9 is pretty clear, but I think I'm just lacking an understanding on how to use this driver software.
Finally, I don't want to reinvent the wheel, but I can't seem to find any one else talking about I2C and the stellaris or tivac launchpads. Am I way off the mark in trying to implement this in this way? If not, is there an easier way to go about this? And, if not, where can I learn more about whatever it is that I'm missing?
I was able to figure it out after all. One thing that I hadn't noticed in the first place is that Texas Instruments provides a PDF peripherals resource that discusses the usage of their driver library. Unfortunately, this documentation is far from comprehensive, and probably would have still required someone to bury themselves in the code were it not for the examples.
Now, the peripheral examples required a bit of work to get going. To save some time and effort, I tried copying master_slave_loopback.c over the top of examples/project/project.c, modified it according to the comments within the file, and then I was able to compile the example and run it with immediate success.
Next, I attempted to convert the new project.c file into something that would allow me to communicate with the MiniIMU9v2. Everything seemed straight forward for the most part. I commented out anything that looked like it was related to loopback functionality, but when I would try to execute the program, it would hang on the following line:
while(I2CMasterBusy(I2C0_BASE)) { }
Overwhelmed with what I might have to do to begin troubleshooting this, I decided to post this question. Fortunately, the problem was a lot simpler and surprising to solve than I had suspected. A quick search revealed this page: http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/316580.aspx
I changed:
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3);
To:
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
And this solved my problem.

Testing Code for Embedded Application

Background:
I am developing a largish project using at Atmel AVR atmega2560. This project contains a lot of hardware based functions (7 SPI devices, 2 I2C, 2 RS485 MODBUS ports, lots of Analogue and Digital I/O). I have developed "drivers" for all of these devices which provide the main application loop with an interface to access the required data.
Question:
The project I am developing will eventually have to meet SIL standards.
I would like to be able to test the code and provide a good level of code coverage. However I am unable to find any information to get me started on how such a testing framework should be set up.
The idea is that I can have a suite of automated tests which will allow future bug fixes and feature additions to be tested to see if they break the code. The thing is I don't understand how the code can be tested on chip.
Do I require hardware to monitor the I/O on the device and emulate externally connected devices? Any pointers that could be provided would be highly appreciated.
--Steve
This is a very good question - a common concern for embedded developers. Unfortunately, most embedded developers aren't as concerned as you are and only test the code on real hardware. But as another answer pointed out, this can basically test just the nominal functionality of the code and not the corner/error cases.
There is no single and simple solution to this problem. Some guidelines and techniques exist, however, to do a relatively good job.
First, separate your code into layers. One layer should be "hardware agnostic" - i.e. function calls. Do not ask the user to write into HW registers directly. The other (lower) layer deals with the HW. This layer can be "mocked" in order to test the higher level. The lower level can not be really tested without the HW, but it's not going to change often and needs deep HW integration, so it's not an issue.
A "test harness" will be all your high-level HW agnostic code with a "fake" lower level specifically for testing. This can simulate the HW devices for correct and incorrect functionality and thus allow you to run automated tests on the PC.
Never run unit tests on or against the real hardware. Always mock your I/O interfaces. Otherwise, you can't simulate error conditions and, more importantly, you can't rely on the test to succeed.
So what you need is to split your app into various pieces that you can test independently. Simulator (or mock) all hardware that you need for those tests and run them on your development PC.
That should cover most of your code and leaves you with the drivers. Try to make as much of the driver code as possible work without the hardware. For the rest, you'll have to figure a way to make the code run on the hardware. This usually means you must create a test bed with external devices which respond to signals, etc. Since this is brittle (as in "your tests can't make this work automatically"), you must run these tests manually after preparing the hardware.
Vectorcast is a commercial tool to run unit tests on the hardware with code coverage.
Do you have a JTAG connector? You may be able to use JTAG to simulate error conditions on the chip.
I like to separate the tasks. For instance, when I made a circular buffer for my Atmel AVR I wrote it all in Code::Blocks and compiled it with the regular GCC compiler instead of the AVR GCC compiler, then I create a unit test for it. I used a special header file to provide the proper data types that I wanted to work with (uint8_t for example). I found errors with the unit tests, fixed them, then took the fixed code over to AVR Studio and integrated it. After that I used wrote support functions and ISRs to fit the buffer into useful code (ie, pop one byte off the buffer, push it into the UART data output register, append a string constant to the buffer for a printf function, etc). Then I used the AVR simulator to make sure that my ISRs and functions were being called and that the right data showed up in registers. After that I programmed it onto the chip and it worked perfectly.
I greatly prefer the debugging capabilities of Code::Blocks compared to AVR Studio so I use the above approach whenever I can. When I can't I'm usually dealing with hardware only. For instance I have a timer that automatically produces a square wave. The best I could do was see that the pin bit was being twiddled in the simulator. After that I just had to hook a scope up and make sure.
I like to use a multi-level approach when debugging problems. For instance with the clock the first layer is 'Put a probe on the clock pin and see if there's a signal there'. If not, probe out the pin on the uC and look for the signal. Then, I coded a debug interface in one of my UARTs where I can look at specific register values and make sure they are what they're supposed to be. So if it doesn't work the next step is 'call up the register value and ensure it's correct.'
Try to think ahead four steps or so whenever you're planning your debugging. There should be +5V here, but what if there isn't? Write into the debug interface a way to toggle the pin and see if that changes it. What if that doesn't work? Do something else, etc etc etc. You get to a point where you run into 'I HAVE NO IDEA WHY THIS DANG THING DOESN'T WORK!!!!' but hopefully you'll figure out the reason beforehand.

Resources