Here's a very small overview of how to get DMA and FreeRTOS running on an STM32 MCU. Only scratching the surface in this video, as there is quite a bit more to it all! We'll be using this basic firmware to look at things such as how to implement digital filters (IIR, FIR) and (extended) Kalman filters in real-time in future videos. Also note: The txBuf (passed to the DMA) should be either declared static or also made more global/persistent (e.g. stored in the IMU struct). I'm getting away with it here, since the majority of the txBuf is not important - only the first byte - and the data is being pushed out on the bus quick enough. I have updated the code in the repo.
I've found very few STM32 FreeRTOS videos that get you started in simple & clear steps without diving headlong into the RTOS innards. You struck just the right balance here.
I'm just starting out with STM32 programming for my thesis and this series has cleared so many things up that other STM32 series on YT have just brushed over. Please keep doing these they are so informative!
Thanks. Maybe one quick note on data consistency: If you want the IMU data in the printing to be consistent (all from the same sample), you should copy the data onto the USB task stack (local variables) inside of a critical section before printing. That protects against the IMU data from being partially updated by the interrupt during printing. This is naturally also true for using the data in other contexts: A Kalman filter would also want consistent samples. I am sure that you are aware, just thought I add that for your audience as such stuff can lead to extended head scratching :).
As a beginner who just started in electronics, your videos are so informative and completed. Starting from the schematics, designing, software implementation and even debugging. I wish there were more content out there like yours! Keep the videos coming! They are super valuable. Thank you!
Oh dear! That's what I was looking for a long time! Thanks a lot Phil! Your content is great! I wish I had a time to share my thoughts and experience 😊
Great video Phil you are setting high standards for the electronics video community here on RU-vid. I would love to see a short video on how to create custom footprints in KiCad e.g a USB connector by reading the mechanical diagram from the vendor
Thank you very much, Odysseas! That sounds like a good idea for a new video, I'll probably incorporate that 'how-to' in a design video. Just working on a six-layer board for the STM32MP1 series, so hopefully can make a video about that sometime in the near future.
Phil, your work is amazing! I'm learning so much from your channel. It has helped me tremendously! Thank you for getting FreeRTOS video out there. I think your tutorial is the best one I've seen. Simple. To the point. Easy to duplicate. Thanks so much for all you do!
Good tip, when you do "if (some_var == some_const)" I write it the other way around, so, "if (some_const == some_var)" so that if you have a typo and only put one = by mistake you get a compiler error for trying to assign to a constant. I also like using zero as success, rather than 1, so that you can have many error codes that can be handled higher up if needed. I that's how the HAL works as well, HAL_OK === 0 Great video as always by the way!
Thank you Phil for taking the time to make these great videos. They're concise and to the point. You're doing an absolutely superb job to the community and just wanted you to know it's greatly appreciated!
Can you explain me how you are reading my mind? :) Every time I try something PCB or STM32 related a couple of days later you upload that specific video..Seems magic👍
Haha, that does seem rather peculiar :D I’m glad it always seems to be the right topic though. I wonder if you can guess what the next video will be on?
Great content, Phil! Just wondering if you would consider doing a bootloader example next whether it is using STM bootloader or custom bootloader. Thanks for the contents and keep up the good work.
Phil, I'm stupid as fuck about electronics still 'cause I have no background or study in any of it - I'm a programmer - but God damn man, your channel has the coolest videos in the world and you explain things that actually have me saying "ohhhhhhh". Keep it up, I'll back you on Patreon soon!
Hey Bart, Thank you very much for your kind words! I'm sure you're more than decent at electornics haha. I'm very glad to hear that you like the videos, thanks again!
Super excited for the upcoming videos on digital filters! Currently in a DSP class and we're using a K22F uC based board (FRDM board from NXP) and we're close to finishing up our book's chapters on IIR and FIR filters. Then we have a sort of class competition to implement the highest order filter we can using our given uC. Professor says so far the record's been something close to 1000 (an FIR one) from previous semesters!
Thank you, Abdullah! Awesome haha, well to win you're probably going to have to do an FFT-based FIR implementation, which I won't be covering in the next video. For DSP in general, I'd highly recommend this book/site: www.dspguide.com/whatdsp.htm
@@PhilsLab Oh indeed wasn't expecting you to cover filter design necessarily. Was more interested in the implementation of a given design. The competition is something more like: alright here's the nth order filter (however way it was designed); now get the hardware to do it, and knowing there's x amount of multiplies and y amount of memory accesses and so on, and we're operating at a fixed sample rate of f (for us it's assigned 10kHz), write the code so the uC is able to manage all those operations in the time between samples (so 100us). The uC is also fixed to operate at 120MHz. Exciting! I haven't started on this yet but I imagined that efficient memory accesses would be done DMA-style (still not super familiar with it tho) and efficient arithmetic done by choosing the smallest word-length fixed-point representation of the coefficients in the filter's design that would still satisfy the desired character (also haven't really done fixed-point black magic). There are other choices; like if we make the FIR filter linear phase, we get symmetric coefficients, and by grouping together appropriate delay terms, we can cut in half (or almost half) the number of multiplies needed. Finally, we're writing everything in C, but if we wanted even more of an edge, we'd bite the bullet and go assembly this mf, but yeah. Anyways, I'm excited to see whatever you got! Also, thanks for the book recommendation! The book we're using is "Essentials of DSP, Lathi Green, 3rd Ed" and my professor is Green, hence the choice of textbook. I do enjoy the book. It's got a lot of humor mixed in.
Thanks so much for all these videos Phil, I've been somewhat binge-watching them during my travel-induced quarantine and they've really made me think about doing another electronics project over the summer. One thing I would be interested in is the dual-core capabilities of the STM32WL55 family (with the secondary chip for offloading certain tasks) and their LoRa capabilities. Obviously it's a bit too much to ask for a full Start to Finish tutorial, but if you could consider covering the topic a bit I would be most grateful! Thanks again
You should add it from scratch to really learn it. These "click to add" type tools really hide SO MUCH implimentation. And it's not that hard to set up the interrupt timer, and init the OS.
@PhilsLab I know this video is a couple years old, but I am just watching to learn about some STM32. Thanks so much for all the videos! Granted, I have never even used a STM32 or it's HAL, but it seems to me that the txBuf at 13:15 being passed to HAL_SPI_TransmitRececeiveDMA() is on the stack. And seeing how the DMA version of the function is non-blocking, it may return before ever reading that memory.
The callback functions can be generated by CubeIDE but writing the function in main also works. You skipped the Systick timer thing when using FreeRTOS. FreeRTOS uses that timer to know when to schedule other tasks, but it's your video, you decide how you do it. It's a small detail but I find it important. Anyway, great video, really liked it and nice PCB design!
Your videos are great, thanks. A request for future content that might be a good fit down the line: FreeRTOS inter task -signaling, -memory protection and -data sharing. Probably with a concept of how to organize responsibilities. E.g. Kalman Filter operates on top of data from multiple sensors without having to lock for access. But an intermediary might be required if the multiple sensor inputs have to be consistent with each other. Something like that :).
Great job! Appreciating your work! Are you planning to cover firmware update via wireless module or some software client by usb connection? Always wanted to know about it.
Thank you! I’ve written some custom USB DFU programs that’ll flash firmware from a host PC, nothing wireless yet though. But good idea, I’ll see if I can make a video on that at some point.
Excellent! Thank you so much. And thanks for the tutorial on how to order boards. Of course it was on the rights of advertising, but still it is also very necessary and useful.
Definitely would love to see some DMA circular sampling (perhaps for audio or control system application?) and some more RTOS stuff. Can't wait for IIR and FIR filters. Thanks for all the effort :D
Thank you for the suggestions, Marco! Yeah, I've used circular DMA with audio (codecs) a fair bit. Would be good to make a video on that. Hope to get the digital filtering video out in about two weeks :)
Thanks again for sharing Phil! I was just wondering though: you opted to use the SPI RxTx Complete interrupt to call your 'DMA Complete' function. However, there's also a DMA transfer complete interrupt callback. Is there a specific reason you chose the SPI interrupt over the DMA interrupt? Also (without having checked the Github repo), did you implement something like a mutex to safely read the sensor values from the logging/usb task? Because in theory the task might try to read it, while the DMA is still in the process of writing it, isn't it?
Thanks for your comment, Bastiaan! No particular reason for using the SPI callback instead of the DMA one. I believe both should do the job in this case. And yes, ideally some form of read/write protection (e.g. via mutexes, as you said) should be added to avoid potential access problems. Should probably have mentioned that in the video, but I guess I just ‘flew through’ it to give a rough overview! Will be adding more firmware code to this project, as this will be used in videos on filtering, Kalman filtering, etc. :)
question about sensor fusion, if you have an IMU that has different polling rates for the different sensors, how would sensor fusion work? Sure if it were a multiple you could I guess just use the lowest multiple sampling rate and subsample the other sensors or maybe average out the samples to some degree if a bit of phase delay is acceptable. What about when it is a non-integer value? Is the best solution to simply read whatever happens to be the most current value in the FIFO and read all the sensors at periodic intervals determined by a timer in your MCU?
I wonder if the "impedance control" option means that they will use a suitable prepeg material (that is, one that is electrically more uniform in every direction). I can't find any specifications about that option. Anyway, this video of yours should have more views and likes. It is as if RU-vid does not promote videos that are technical and in depth. I find your content accessible, very well explained and nicely presented.
Yeah, that’s a good point. I’ve assumed that it should mean something along those lines, but I’ll send them an email to check. Thank you also for your very kind comment!
Phil, about how you are accessing the imu struct, I thought this data isn't accessible from the task context. It's like you are using it as a global variable. Each task doesn't have it own context variables? How the imu's struct was accessible? I'm sure that it should be done with a queue or other mechanism. Can you give a hint about data exchange within tasks? Thank you
Hey Phil - I've just discovered your channel and it's fantastic. Aside from watching all of your videos on the subject, do you know of any good books, channels, or other resources that discuss techniques and patterns for writing firmware (and maybe more specifically drivers)? Thanks for taking the time to make these kinds of videos, at this level of quality - they seem to be in short supply!
Thank you so much for another excellent video! I have one question - could you explain a little bit why did you use a timer instead of systick for FreeRTOS? On ST forum I read that systick should be preferred, but unfortunately no explanation why there is a choice and any pros and cons .
Another great video, Phil. I want to get hold of a board but only want one for now. Do you sell through anyone? Thanks for all the hard work, Phil. I enjoy every video!
Thanks, Terry! I believe I have one or two more of these boards lying around (no connectors populated, however). I also have the new version of this board (LittleBrain++) with some improvements. Please send me an email (www.phils-lab.net/contact) and let's see if we can figure something out!
Isn't txBuf is going out of scope, and should be declared static; unless the HAL actually copies the buffer contents out? Given only the first value is important, you will probably get away with it, but if more data was being sent it probably wouldn't work.
Yeah, I’m being a bit naughty doing it without static or not declaring txBuf more globally/persistent but in this case one gets away with it, since only the first value is important. You’re right though that it isn’t good practice, so I’ll update the code - thanks for your comment :)
If it completes some time in future then tx buffer should also outlive the function. Or "TransmissionReceive" is guaranteed not to return until data is sent? Why is the difference in send/deceive logic then (should be symmetric, I suppose)?
Awesome video Phil. You should certianly continue STM32 FreeRTOS videos in relation to you FLight control system. Have you made much progress on that project in the past few months ? Cheers
Thank you very much! Yeah, unfortunately I haven't had time and/or a place to test the flight control system, so had to let that slide a bit. I do hope I can get back to that sometime in the (near?) future :/
Possible bug... Phil please confirm that txBuf on the stack is OK. Being DMA, i suspect that the command in the txBuf is queued leading to unpredictable results. Let us know what you find.
Very informative video! I have a question. Does anyone know how to enable autocomplete suggestions in CubeIDE? Currently, I have to press Ctlr+Space to get the suggestion list. I am hoping that someone has figured out this setting in their IDE. Thanks!!
Hi Phil, great video! I'm definitely going to build one of these boards and Explore. I have one question about the content of this video: how so you control the synchronization between the thread collecting the IMU data into the global struct and the thread reading the global struct and transmitting out the USB port? thanks dale
Thank you, William! I haven't done any synchronisation-control between the various threads, other than letting the FreeRTOS scheduler do its thing. Ideally, one would do that via some form of mutex, etc.. I'll probably be showing that in a future video on something like Kalman filters!
I'm new to STM32 MCU-s and I'm working on a project that will use inter-MCU communication over SPIs. My plan was to use SPI interrupts so I was wondering why do you use external interrupts to initiate DMA transfer? Can't you rely on SPI RX interrupts instead?
Would it be possible to design a board using mostly smt parts from the jlcpcb catalog, that is capable of running "ordinary" Linux, preferably with X11 and a connected USB mouse and keyboard? We seem to be so close with some of the more advanced embedded SoCs, but there seem to be very few processors in the JLCPCB catalog with an MMU.
Excellent content! Edit: You already answered my first question in your comment :) But I have another one: how is the main loop synchronized with the DMA read?
There is no synchronization - There are issues of possible "half values" in memories during reads - so called race conditions. To solve this you should wrap access to the data in a mutex - but you have to be careful of priority inversion.
Thanks for this vid, I only learned CMSIS way of doing thins this is very useful. More of this kind of vids on youtube will be useful, anyone has any books for topics like this to recommend?
If you set 'osDelay(500)', does it mean that the loop runs the user code first and then waits for 500ms, which results in a total duration longer than 500ms? Or does the RTOS wait for only the remaining time of the 500ms, which would result precisely in 500ms period?
Thank you phil! Glad i found a channel to help with my future projects! I wonder if the board iactually only need, is to read logic signals around 833us per bit, do I need to set up FreeRTOS? Thanks again
As always very helpful video with great explanations! I'm usually trying to use FOSS tools, but now I'm tempted to give this IDE a whirl since the graphical setup tools seem really nice for getting to know the STM32-family. In your experience, is this IDE/toolchain mature enough to use for production? I read some horror stories about bugs in the HAL/code-generation, but these might have been fixed already.
Hi, sorry for the late reply! Thanks for your comment :) I believe you could use STM32CubeIDE in a production environment. There have been bugs with HAL in the past but they are being ironed out over time, so I'd say give it a shot!
@@PhilsLab No worries. I've had a small project coming up that needed a pretty gui for our client so I tried out the tools and really like touchGFX and its no-cost license. I'm new to STM32s, FreeRTOS and touchGFX, so I use only basic features and should be absolutely fine using the free vendor tools. I learned that touchGFX and the CubeIDE is meant to play nice together when generating a project in touchGFX and then importing it into CubeIDE. This way is easy and works great. There is a tutorial on yt that starts a project in the IDE, generates a second project in touchGFX and then merges everything manually and is definitely not recommended for beginners. Fortunately this convoluted mess is not necessary anymore with the current version of tools, which is great.
Absolutely great video, mybe only small remark: When function return status that everything is ok. Should that be 0, because 1 or any other number mean some kind of error code.
Hi Phil, thank you for your videos! I have a question about connection using SPI but also any other interface, what kind of countermeasures do you program in case of error? I'm currently working in an application where I use the UART port in DMA mode, using cables between the STM32 and a Raspberry. According to the manual, if there is a framing, parity or noise error during a transmission, the DMA transference is aborted. The way I use to react to this: in case of error, UART error callback is called, I then write an Error state to a variable. A timer, every 3ms, calls an error_check() function on period elapsed. This function restarts the transmission on error. I don't know if there are better ways to overcome errors. I don't know either if all this is worth the code and time if the two devices connected by UART, SPI, etc are in the same PCB, where there is no possibility of cables getting disconnected.
Few days ago i ordered my own pcbs. I'm going to build advanced e-cig(smth like DNA) and I'm wondering if is it better to use these stm32cubeide than stm32duino in platformio. Im already familiar with normal atmega. Idk which one I should use to my project. At this moment stm tools are a bit confusing to me. I love yours videos 😍 You helped me a lot
Awesome, glad the videos have been helping! :) There is a bit of a steep learning curve with the STM32 environment but it is definitely worth it - once you've gotten to grips with all of it, you will never want to go back to Arduino!
Hi Phil! Thanks for this video. Are you planning to record something about exchange data beetween tasks (use of Queus, Memory Pool, Mail )..? I didn't found nothing well explained , because the FreeRTOS is wrapped by a CMSIS layer by STM32CubeIDE, there is less examples avaliable than pure FreeRTOS implementations. Specially exchanging structures of data instead of a single integer. Please.. thanks!
Hi Fernando, Yes, I plan on doing that for later videos, when I go into more detail on something like Extended Kalman Filters, digital signal processing, and so on. Got a few different things lined up! :)
Hey sorry for the late reply, there are two basic parts at JLCPCB for ferrite beads, see: jlcpcb.com/parts/componentSearch?searchTxt=bead The 600R @ 100 MHz ferrite bead (0805) has LCSC part number: C1017