Rant... Why I dumped Platform IO IDE after a week - Page 1
Forum section: electronics / general

author: jnz
author_rank: Frequent Contributor
timestamp: September 07, 2022, 05:16:05 pm
content: Aside from odd projects here and there... Microchip whatevers >>> Rowley Crossworks >>> Kiel uVision >>> Segger Embedded Studio >>> Eclipse CDT and STM32CubeIDE >>> VS Code + PlatformIO >>> VS Code CMake.I recently decided to dump Eclipse / STM32CubeIDE. While it's a TON better than my previous (Segger Embedded Studio, seriously, that can go to hell), I wanted VS Code but still wanted "support". I wanted tools that were made and maintained by someone. Someone to call on if there was an issue. I'm not paid to play with tooling all day, I'm paid to make things.My first and last week with PlatformIO...-There is pretty literally one guy answering questionson their forum. I hope Max is paid, because if he isn't I imagine there is an end to his generosity. This does not count as having someone to call on. Paid support for PIO is absurdly expensive at $250/mo with a 12 month use it or lose it contract. This iirc on the prices, is more than a year of IAR, Keil, and CLion together. That's some lunatic pricing.(EDIT I swear last week they had a $500 per month no contract, but it's gone now)-Good luck manually adding a floating point flag.I spent a two days trying to figure out how to get an STM32 to build with floating point. Any other system you click a button, or add -fpv4-16 or some other flag. No, not PIO!! You need to add the flag to the compiler, as well as the linker, but In PIO the config .ini only allows for editing the compiler flags. So... What you need to do is create a python script that will add the flags in a backend way, and then call that flag from the ini file. Complete backwards BS. Why are there no linker arguments in the ini? F U is why, I assume.-You'll have no options and be happy about it.Similarly, you have access to flags they thought you would want access to. I wanted to add context RTOS awareness to the JLink debugger. Despite a guide saying you can easily to it, adding the "-rtos freertos" didn't work.-What do you mean multiple ram sections!?A ton of new chips have multiple ram sections like STM32's tightly coupled memory. You can place things in these sections using the linker and gcc compiler options, but PIO is hard coded to only should a build usage percentage chart of RAM and FLASH. Not all ram, or all flash, just one "main" section they per-determine. This is 1990s thinking, at best. No great way to fix it, and it's been on their open issues for at least a year.-"Will you be able to build the project in 10 years?". EEV Members warn/warned others about this. I say no. I could barely build today, and that was not using any of their tooling, just bringing my own files in like a big boy. I initially scoffed this warning, but I recant. Their package manager looks nice, but it's trying to do too much. For STM32, they have a hard coded "platform" build script that tries to replace CubeMX and select the files you might need. I don't trust they will maintain it. I decided early to bring my own files in and it was also trouble.-It probably works well if you still to absolute basics. Using their tools the way they intended. However... At it's root, they're using python scripts to interpret an ini file, then make a SCons config, which makes me wonder why not just use a Makefile or CMake to existing standards? PIO is a build system helper for SCons. I guess when something goes wrong, I'd rather have the millions deep CMake community to ask instead of hoping Max is around.-It's still vendor lock in.Despite big bullet points saying it isn't. You're in their system or you aren't. You do get the source, but that doesn't mean it's portable or your changes would be maintainable. You're paying for it with your time. They're a vendor, and their system is exclusive. It's not the hardest lock-in I've ever seen. But there was nothing stopping me from dumping Keil and taking my code to GCC, just a couple flags to change here and there.-Inexplicable limitations. You are forced root source folder for your code. They build from multiple folders and libraries, but give you access to only one root folder. If you have configurations for two micros, and one folder must be excluded, you are expected to add both to the root source folder, then add a build flag to explicitly exclude the "wrong" folder per build. Backwards and they easily could have selected an "opt-in" system for source files, like every other build tool ever.-.C or .S files, pick one.You can not have both with the same name, ever, anywhere. Annoying that in STM32 you may have a .C or .S option with the same name. Startup is one example but in the CMSIS folders there are a few more. PIO just can't handle this. Goes back to the single root source folder, and that everything inside will try and be compiled whether you want it to or not.Takeaways...1.They're trying to be Arduino. I would only rank it slightly above.2.I don't think the current development is very active. Blame the war in Ukraine if you want.3.It took me longer to try and learn PIO and it's odd .ini system and workaround than it did to open VSCode, install all the extensions I wanted, and create a CMake file. That's the worst thing I can say about PIO and why I'll probably never recommend it.I don't regret trying it. I have a great setup now in VS Code. I finally feel like my embedded tooling isn't perpetually 15 years in the past.

author: hans
author_rank: Super Contributor
timestamp: September 07, 2022, 06:26:30 pm
content: My personal favorite: CLion + CMake. But CLion is not free. And their embedded support is far from done (still waiting for disassembly listing panes and live CPU register views -- need to debug with gcc objdump and gdb commands). But their C/C++/general programming tool suite is very well regarded/supported..I agree with your findings. And I can rant along too. PIO... I've tried it, and my first impression: it's a steaming pile of ****. I like the Arduino IDE more because it does less things and doesn't get in the way. I hate when embedded tools try to be "automagic" but then get it wrong. It's a general theme IMO in your comments. It's a 1-size-fits-all approach which only works in the software world where you can say "this software runs on any Windows 7 or later system".I've tried to build a custom IOT application based on the Tasmota project, and I don't think I can fault the Tasmota guys for how crappy PIO is. For mysterious reasons, the upload_port will never change even when I manually set it in ALL the .ini files with CTRL+F search in the project folders and brute-force replaced them all. It still defaults to COM5. I'm not even on Windows(!), and there is absolutely no mention in ANY file of "COM5".Eventually I gave up on trying to fix PIO, so I hacked in the correct serial port right at the exception line in one of those python scripts. It worked.. but then rebuilding a project takes forever. Now this may be because of the large Tasmota project size, but I was really not amused by an almost 2 min build/upload cycle... IIRC it kept rebuilding libraries and trying to link this huge 1MB final binary. I rather spend my energy on writing an Arduino sketch with a basic MQTT library and handing over data via a handful of published/subscribed topics.

author: JPortici
author_rank: Super Contributor
timestamp: September 07, 2022, 07:51:59 pm
content: why i dumped platform io after one hour: it should be self explanatory. How do people stand that pile of garbage? I couldn't make sense of anything, the workflow, how to know when things are being done, everything seems like an hack upon another hack.

author: JPortici
author_rank: Super Contributor
timestamp: September 07, 2022, 07:53:50 pm
content: I'd rather have poor documentation, but at least one hello world C project that actually builds and works so i can make sense of things one little step at a time

author: Sal Ammoniac
author_rank: Super Contributor
timestamp: September 07, 2022, 09:34:54 pm
content: Quote from: jnz on September 07, 2022, 05:16:05 pmI'm curious...what did you not like about Segger Embedded Studio (and presumably Rowley CrossWorks)?

author: thm_w
author_rank: Super Contributor
timestamp: September 07, 2022, 09:37:39 pm
content: If you are paid for your work and want support, PIO is not something I'd really consider. I would be looking at paid software.My choice isVisualGDB, but many may not like it, especially if software is your strong suite.You can setup a project as msbuild, gnumake, cmake.Its NOT lightweight, and windows only.

author: jnz
author_rank: Frequent Contributor
timestamp: September 08, 2022, 12:17:55 am
content: Quote from: Sal Ammoniac on September 07, 2022, 09:34:54 pmWithout derail... Besides the straight up crashes, besides the goofball menus that try and hide options way deep down, besides the download/install size and that updates are manual with entirely new binary folders, besides the find/find-in-files sucking, besides the awful theme options, and besides the bugs I had to work with Segger on....It's just old. It doesn't support a modern CTRL+CLICK to get a definition of. It doesn't support any extensions for complex or trivial things. It just feels like it's 20 years old, because it is and no one ever considered to go through it again.Compared to a version of VS Code that is set up how I like it, it's just a joke to use. I'm still stuck with it for a legacy product, but I honestly wonder how I got anything done in there.Like I said above, I finally feel like I have modern tools that do actually helpful things. As I write this, I have VS Code open with a text file set to PlantUML and I'm doing a state machine diagram that is automatically updating when I change the text. I don't need to leave my IDE to work in Notepad++ and run the PlantUML jar elsewhere. It's all just right here, and works so well. I can switch to C or Python just by opening a file and build/debug either just as easily.

author: jnz
author_rank: Frequent Contributor
timestamp: September 08, 2022, 12:19:37 am
content: Quote from: thm_w on September 07, 2022, 09:37:39 pmYea, well.... Been there too! I had a short stint with IAR, and a long stint with Keil.At least for all of Keil's awfulness and an editor that rival Segger for old tech... At least their compiler is very very fast.

author: jnz
author_rank: Frequent Contributor
timestamp: September 08, 2022, 12:22:18 am
content: Quote from: JPortici on September 07, 2022, 07:53:50 pmI guess to be fair, PIO's documentation isn't the worst. But it looks a lot better than it is on the surface. Once you need something, you get in this loop of"I need this thing (build tools) so I click a link and it takes me to a page that has another link that looks like what I want that takes me to another page that definitely says it has what I want... And now I'm back at the first page again." I'll check the forum or GIT close issues and see if Max answered this already.

author: PatrickCPE
author_rank: Newbie
timestamp: September 08, 2022, 12:30:33 am
content: I can vouch I enjoyed CLion when I did STM32 Development. They let you import the IOC files and generate a CMake file for you.I'm also a fan of just doing a CMake or make file if the project is anything serious that I'll be using for a long time. GUIs are great until something doesn't work or you need to do something weird/dumb. I've been opting for just Emacs and a terminal when needed as of late

author: JPortici
author_rank: Super Contributor
timestamp: September 08, 2022, 05:56:55 am
content: Quote from: jnz on September 08, 2022, 12:22:18 amI am starting to ventilate

author: SpacedCowboy
author_rank: Frequent Contributor
timestamp: September 08, 2022, 03:50:28 pm
content: Perhaps I was lucky, but I got platform io working pretty quickly with the RP2040. Thought it was quite nice and easy to use, actually.

author: jnz
author_rank: Frequent Contributor
timestamp: September 08, 2022, 05:54:21 pm
content: Quote from: JPortici on September 08, 2022, 05:56:55 amI get it. Hence the reason for this whole post.However... still sadly, not even remotely the worst.

author: jnz
author_rank: Frequent Contributor
timestamp: September 08, 2022, 05:57:35 pm
content: Quote from: SpacedCowboy on September 08, 2022, 03:50:28 pmYea, well, that's the thing isn't it? If it's something we all recognize even vaguely as a thing, there are obviously people out there using it. I have no doubts that if you stay within the box and with very popular hardware, that there has been enough work to be successful using it.I like some of the things they did, they just made odd choices that I feel long term have boxed themselves in. Unless they PIO2 as a complete re-write to drop old decisions, I don't see it going much further. But, I shit on bitcoin back when it was $100, so what do I know anyhow!?The overall point is when you want to step outside the box even a little, or you want to build the project years later... Your time is probably better spent doing it "the hard way" (may be easier) with CMake and modular tools.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 08, 2022, 06:02:29 pm
content: Vendor frameworks, IDEs and whatever have always been pure shit, and so are third party replacements.Even if some are remotely acceptable, learning them is wasted time because they have short lifespans, or narrow scope (some specific brand).If you use ARM, RISCV, AVR or any other MCU with GCC and GNU toolchain available, just learn these command line tools. They have been the same from 1980's, maybe evolved a bit but never aggressively. As you have witnessed trying to adjust compiler flags in a GUI, you usually need to understand how the underlying tools work anyway, so working with them directly removes one layer of indirection.End result: less wasted time, stable workflow, you being able to quickly switch between different manufacturers without installing anything, deeper understanding, better results. No downsides.So just say no and don't waste a week, don't waste a day, not even an hour.

author: wek
author_rank: Frequent Contributor
timestamp: September 08, 2022, 06:08:32 pm
content: We all have strong opinions about toolsets, cars and beverages.Maybe it's good.Thanks jnz for the overview.JW

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 08, 2022, 06:14:33 pm
content: I agree with Siwastaja here, and more generally speaking, don't fall into the trap of quick-and-easy, "instant-gratification" tools and approaches. You will almost always regret it at some point.

author: jnz
author_rank: Frequent Contributor
timestamp: September 08, 2022, 06:51:18 pm
content: Quote from: SiliconWizard on September 08, 2022, 06:14:33 pmI can steelman that... I said it in the top post. "I'm not paid to play with tooling all day, I'm paid to make things."Jupiter Notebooks and Python have replaced MathCad for me. VS Code + Extensions has replaced like... almost everything. But if you hold a gun to my head and tell me I have 5 days to make a CAN to Ethernet bridge on a micro I've never used before - I'm not running to VS Code or CMake or my ability to screw up a for loop in python because I do them so rarely.Similar to the comments to SpacedCowboy, obviously these things work for some people depending on the task. Let's not pretend that "instant gratification" is a bad thing if it works.Let's also not pretend that "the big boy tools" always Just Work (tm).... But yea, I agree overall and it's where I'm at now.

author: agehall
author_rank: Frequent Contributor
timestamp: September 08, 2022, 07:18:35 pm
content: I found that it did take a bit of work to get into how PIO does things but once you start reading up on things, it was pretty trivial to beat it into submission and make it do whatever I desired. Probably spent a day or so figuring things out but I thought that was time well invested for my little project.

author: ozcar
author_rank: Frequent Contributor
timestamp: September 08, 2022, 10:09:22 pm
content: Quote from: SpacedCowboy on September 08, 2022, 03:50:28 pmPIO worked for me as a casual tinkerer for STM32. I do remember having some trouble with a compiler option, when I had to "unset" something that PIO was doing.PIO does RP2040? I did eventually get RP2040 working with VS code, but as far as I could see, what I did had nothing to do with PIO.

author: thm_w
author_rank: Super Contributor
timestamp: September 08, 2022, 10:27:24 pm
content: Quote from: jnz on September 08, 2022, 12:19:37 amSure, I never said all paid software is good, just that paid would be the only ones I'd be looking at trialing.Compiler being fast could be related to build options, caching, multi-core use, etc.

author: SpacedCowboy
author_rank: Frequent Contributor
timestamp: September 09, 2022, 01:01:01 am
content: Quote from: ozcar on September 08, 2022, 10:09:22 pmGah. Wrong micro. I was alsousing VSCodefor the RP2040. I used PIO for theGD32F450(Chinese STM32 "clone").As I recall, there was a little to do - create a definition file basically because the specific chip I had wasn't supported, but it was pretty straightforward.

author: Sal Ammoniac
author_rank: Super Contributor
timestamp: September 09, 2022, 06:33:40 pm
content: Quote from: jnz on September 08, 2022, 06:51:18 pmI remember looking into doing STM32 development using VSCode about a year ago. There are several sites describing how to do this, and they all require tying together a bunch of bits and pieces from different sources. And they require using STM32CubeMX to create the makefiles. After futzing with it for a week, I finally got things going, but it felt like a kludge that would break anytime one of the components changed and became incompatible with some other component.I prefer an integrated solution that includes everything, properly integrated. Hell, I'll even use something like Keil or IAR over some hodge podge solution cobbled together from parts. I' more than willing to give up some cute editing features for an all-in-one solution thatjust works.

author: jnz
author_rank: Frequent Contributor
timestamp: September 09, 2022, 11:46:55 pm
content: Quote from: Sal Ammoniac on September 09, 2022, 06:33:40 pmI think the weak point in your path was being convinced to use CubeMX for the makefile.You'll need to add your own files to the make process anyhow... So I would recommend just using CMake and then adding the cube files. The way I look at it is, how often do you really add files to the project? You will spend much more time working with what you have after an initial set up. I still use Cube for generation of inits and clock, but if Cube adds a new file, I just add it to CMake and away I go. I haven't used CLion, and just CAN'T imagine the editor is nearly as good as VSCode, but that would be my backup before having to go back to Eclipse which I would fine also painful.My extension list is primarily:Language and Syntax:ARMCCMakePythonPlantUMLMarkdownGNU LinkerTools:CMake ToolsCortex-Debug (and SVD packs)Serial MonitorEmbedded Tools (RTOS monitor)That's 99% of everything I need. Everything else are themes, tools I find handy (like errorlens and rainbow brackets).I just had to got from my "cobbled together" solution back to Keil and it nearly killed me. Such a productivity drag.If anyone wants a decent guide, I used this and it worked pretty well.https://mcuoneclipse.com/2021/05/01/visual-studio-code-for-c-c-with-arm-cortex-m-part-1/

author: uliano
author_rank: Regular Contributor
timestamp: September 10, 2022, 06:52:22 am
content: Quote from: jnz on September 09, 2022, 11:46:55 pmQuoteI had already stumbled on that link, however all the workflow there is based on j-link (expeeensive!!) and NXP devices. As an absolute beginner in the ARM realm I'm not able to "translate" it for st-link and stm devices. That's why I have been an easy pray for PlatformIO, which at least let me blink a led even if I strongly dislike it in almost every aspect.

author: Whales
author_rank: Super Contributor
timestamp: September 10, 2022, 11:20:35 am
content: Quote from: jnz on September 07, 2022, 05:16:05 pmMy current PIO work codebase: we commit the whole .pio folder to git, because it's easier to keep a working setup going than fix things all of the time when doing a fresh clone and build.

author: peter-h
author_rank: Super Contributor
timestamp: September 10, 2022, 12:41:22 pm
content: QuoteI agree with the 1st but not with the 2nd. Stuff like a graphic IDE, with breakpoints, etc, is a real productivity enhancer. Even if it crashes quite a lot.Actually I don't get why the 1st is true but it seems to be. The money made on chips (ST = $14BN sales) is so huge. They could do great tools. The mfgs are just taking the piss.

author: hans
author_rank: Super Contributor
timestamp: September 10, 2022, 01:53:31 pm
content: I think HAL's are also a way to lure beginners and intermediaries to a vendor lock in.If you look at hardware on a RTL level, then most operate almost identically. Where each bit is implementation details. Virtually any peripheral is structured the same: control registers, status registers, interrupt status/clear flag registers, and some data and auxillary registers.. for many many peripherals.If I need to set up something new, I just set everything to zero and begin bringing in the stuff I need 1 by 1. That often works pretty well. Sometimes I will need to read some software description manual, e.g. how to set up the correct interrupts, DMA channels, FIFO's, initialization locks and delays, etc. But those are again implementation details..Imagine if the manufacturer writes their HAL wrapper around it and immensely invest into frameworks, code generators, etc. Whoila you have an eco-system that should be great beginners or to get something done quickly (if there are no quirks and bugs, of course).The problem is:A) Eco-system is synonym a prison, especially in the enterprise world.B) Backporting new HALs and frameworks could be a mess if the mfgr doesn't care about breaking changesIn software dev world you would seriously consider each dependency you add to a project, for the same reason as B, but also potentially if the project gets shitcanned by a company or OSS community and you're stuck with a soon-to-be outdated dependency.Now in embedded this is often less of a problem. Many projects used a custom design/MCU. If the code works and is done (no more feature development), then eventually enough bugs have been squashed and in a few years time, the project has become 'legacy'.Concerning point A): manufacturers will never have an interest in developing a compatible API of peripherals between devices. That's not an imprisonment for their customers, and so in the chance of e.g. a huge chip shortage it would be too easy/cheap for a customer to run to NXP/Microchip/SiLabs/etc. In contrast, ecosystems like Arduino, mbed, etc. are the closest to succeed in "compatible" APIs, however, but in those paradigms you will need to look up which ports have been assigned for various functions. E.g. on Arduino: which timer is used for ms timebase? Which serial port is reserved for using the bootloader and the default Serial object? Which I2C peripheral is used for the default Wire object? Which GPIOs are assigned to which analog/digital pinout on the original Arduino Uno form factor? And what if they conflict with an 'alternate' peripheral you need? Bad luck?Now IMO ecosystems like Arduino are still some kind of imprisonment. Similar to how you can see many people ask about to use STM32 HAL's, or change over to a different chip/brand, etc. You see the similar thing happen for people moving away from Arduino. I get why it's attractive to use these paradigms to start learning or get something done (as I occasionally also do for quick projects), but in terms of control I think ecosystems will never deliver.

author: peter-h
author_rank: Super Contributor
timestamp: September 10, 2022, 02:20:18 pm
content: I don't think one could develop a serious commercial product using the Cube MX type of code generation. No way.MX is OK to get you started (the standard flashing LED) and it is very handy for generating example code which you can copy into your real project and then discard the original, together with other obvious junk code. I have done that with a lot of ex MX code generated in the early days of my project.I also don't think that changing CPU vendors is a real proposition in manufacturing. The current chip shortage is affecting everybody, at different times, like the carousel with wooden horses which go up and down. The proper solution is not to redesign with a different CPU (which involves a massive amount of work and so much retesting, unless the product is trivial) but to keep large stocks of strategic items. Forget JIT, which is just a fancy phrase for bending your small suppliers over a barrel and screwing them (and only large companies can do that). By all means use JIT for teabags, bog rolls, resistors, PCBs, etc. But not single sourced key items. At work I have at least 5 years' worth of CPU stock at all times (H8/3xx, now obsolete) and have probably a first year's production qty of the 32F417.I know anything from Atmel is dodgy. I used the 90S1200 for years, and when I replaced it, by the time I went to buy some they had dropped those as well. But ST, like Hitachi, is a long term production company. They will probably run their chips for 20 years, and after that you can do a huge last time buy, and for a bit of time after that they come up on the US cowboy 2nd tier disti scene as companies dispose of dead stock. I bought tens of k of the H8s on that scene, for peanuts. Eventually the chinese found out there was a demand and started "printing" fake ones. That was the end, practically speaking. In the long run, it will pay you to a) stick with one big CPU company and b) hold strategically appropriate stock levels.And then you can stick to the same software tools and not waste your time going up learning curves.Well, it depends on whether you work for yourself or a company. If the latter, wasteful learning curves are ideal for putting bread on the table at home.-----------------------------------------------------------------------------------Simon edited to insert chinese instead of a term that apparently offends.

author: Simon
author_rank: Unknown
timestamp: September 10, 2022, 04:31:43 pm
content: I have done the same, I have 1'000 SAMC chips in stock. They are a pain in the arse to work with as the datasheet is never clear about anything and the microchip code generator is a joke, but they were available and in time have potential. We will now be using them as general purpose port expanders and external ADC's as my colleague who I left to sort out the software side of things has fallen for the ESP32's which I have agreed to although somewhat nervous given that they are chinese and I always think long term. I'm interested in how the PI microcontroller type things turn out in comparison as perhaps a more stable alternative in the future.

author: peter-h
author_rank: Super Contributor
timestamp: September 10, 2022, 05:55:12 pm
content: This is digressing but I would never use a chinese CPU. Incredibly risky politically - as well as their committment to anything to do with customers is only as long as a $100 bill. The ESP32 is a good package if you want a working out of the box TCP/IP + WIFI solution.

author: JPortici
author_rank: Super Contributor
timestamp: September 10, 2022, 06:56:50 pm
content: And yet GigaDevice has the only other mcu i could find, other than dsPIC33CK, that has CAN/CAN-FD in 28pin QFN (or other equally small package that isn't a massive pain to work with). Unfortunately they are not available either, but i was mentally ready to dive in.

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 10, 2022, 07:02:58 pm
content: Given how much of a hell it is right now to find MCUs, that's understandable.I'm really considering making my own MCUs.(Of course that wouldn't solve the problem, as I would have even less access to foundries than the big ones, and sure, unit cost would be way higher unless I made millions of them.)So that's just a musing right now more than a practical thought. But I do have a working RV32/RV64 core, a small set of peripherals (that I could easily expand), working I/D cache, a decent interrupt controller. For now it's fun on FPGAs, but that could be made on silicon. I dont have the cash though.

author: Simon
author_rank: Unknown
timestamp: September 10, 2022, 07:57:10 pm
content: Oh just turn to indigogo, they will fund anything

author: Sal Ammoniac
author_rank: Super Contributor
timestamp: September 10, 2022, 11:20:40 pm
content: I'll take another look at getting a VSCode development environment set up with the link jnz posted. I use STM32 rather than NXP, but the translation should be straightforward. In the meantime I'll continue using Segger Embedded Studio. Despite what others have said about it, it works well for me and I haven't had it crash for many years now--it's very stable, at least on my development system. I like it not because it has a great editor (it doesn't) or the newest, coolest features (it doesn't) but because it was the easiest of the graphical IDEs to get working with my projects from scratch. Much easier than STM32CubeIDE (and Atollic before that) or Keil and itjust works. For debugging I mostly use Ozone.I tried Keil a few months ago right after ARM removed the 32K code size limitation, but getting it working was a real pain in the ass, and I remember (although my memory of this is fading) issues with the C compiler version and associated assembler where I needed to compile C code with one version and assembly code with another because the assembly syntax changed (and I didn't want to convert all of my assembly to the new syntax).Regarding MCU availability, yes, that's a problem for some, but I do this as a hobby and only do 3-4 projects a year, so my needs are modest. I was fortunate to anticipate a possible MCU shortage at the beginning of the pandemic and order a five year supply of the STM32F7 and H7 MCUs I use in projects, so I'm set (at least for now).

author: artag
author_rank: Super Contributor
timestamp: September 10, 2022, 11:25:49 pm
content: Quote from: hans on September 10, 2022, 01:53:31 pmThat's not the intention : it's a (L)ayer supposed to (A)bstract the (H)ardware. But it's what ST's HAL does - it isn't really a HAL, it's more like an OS or an API for devices .. that's so comprehensive that only other (ST) devices have it available. And also slugs the performance by using dreadful 'universal' code, so that you lose all the advantages of a bare-metal microcontroller.

author: peter-h
author_rank: Super Contributor
timestamp: September 11, 2022, 06:13:28 am
content: ST "HAL" is automatically generated code from Cube MX. It is a kind of hardware abstraction layer but really it is a load of code which you don't need to write yourself after reading the 2000 page RMThis is an example of ST HAL. Each function was written by somebody originally, and when you specify what you want in your project, it drops these functions into a file.Code:/********************************************************************************* @file usbd_msc_scsi.c* @author MCD Application Team* @brief This file provides all the USBD SCSI layer functions.******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2015 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under Ultimate Liberty license* SLA0044, the "License"; You may not use this file except in compliance with* the License. You may obtain a copy of the License at:* [url=http://www.st.com/SLA0044]www.st.com/SLA0044********************************************************************************//* BSPDependencies- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"- "stm32xxxxx_{eval}{discovery}_io.c"- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c"EndBSPDependencies *//* Includes ------------------------------------------------------------------*/#include "usbd_msc_bot.h"#include "usbd_msc_scsi.h"#include "usbd_msc.h"#include "usbd_msc_data.h"/** @addtogroup STM32_USB_DEVICE_LIBRARY* @{*//** @defgroup MSC_SCSI* @brief Mass storage SCSI layer module* @{*//** @defgroup MSC_SCSI_Private_TypesDefinitions* @{*//*** @}*//** @defgroup MSC_SCSI_Private_Defines* @{*//*** @}*//** @defgroup MSC_SCSI_Private_Macros* @{*//*** @}*//** @defgroup MSC_SCSI_Private_Variables* @{*//*** @}*//** @defgroup MSC_SCSI_Private_FunctionPrototypes* @{*/static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_RequestSense(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_AllowPreventRemovable(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_Write12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_Read12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun,uint32_t blk_offset, uint32_t blk_nbr);static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun);static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun);static int8_t SCSI_UpdateBotData(USBD_MSC_BOT_HandleTypeDef *hmsc,uint8_t *pBuff, uint16_t length);/*** @}*//** @defgroup MSC_SCSI_Private_Functions* @{*//*** @brief SCSI_ProcessCmd* Process SCSI commands* @param pdev: device instance* @param lun: Logical unit number* @param params: Command parameters* @retval status*/int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd){int8_t ret;USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;switch (cmd){case SCSI_TEST_UNIT_READY:ret = SCSI_TestUnitReady(pdev, lun, cmd);break;case SCSI_REQUEST_SENSE:ret = SCSI_RequestSense(pdev, lun, cmd);break;case SCSI_INQUIRY:ret = SCSI_Inquiry(pdev, lun, cmd);break;case SCSI_START_STOP_UNIT:ret = SCSI_StartStopUnit(pdev, lun, cmd);break;case SCSI_ALLOW_MEDIUM_REMOVAL:ret = SCSI_AllowPreventRemovable(pdev, lun, cmd);break;case SCSI_MODE_SENSE6:ret = SCSI_ModeSense6(pdev, lun, cmd);break;case SCSI_MODE_SENSE10:ret = SCSI_ModeSense10(pdev, lun, cmd);break;case SCSI_READ_FORMAT_CAPACITIES:ret = SCSI_ReadFormatCapacity(pdev, lun, cmd);break;case SCSI_READ_CAPACITY10:ret = SCSI_ReadCapacity10(pdev, lun, cmd);break;case SCSI_READ_CAPACITY16:ret = SCSI_ReadCapacity16(pdev, lun, cmd);break;case SCSI_READ10:ret = SCSI_Read10(pdev, lun, cmd);break;case SCSI_READ12:ret = SCSI_Read12(pdev, lun, cmd);break;case SCSI_WRITE10:ret = SCSI_Write10(pdev, lun, cmd);break;case SCSI_WRITE12:ret = SCSI_Write12(pdev, lun, cmd);break;case SCSI_VERIFY10:ret = SCSI_Verify10(pdev, lun, cmd);break;default:SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB);hmsc->bot_status = USBD_BOT_STATUS_ERROR;ret = -1;break;}return ret;}/*** @brief SCSI_TestUnitReady* Process SCSI Test Unit Ready Command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){UNUSED(params);USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;/* case 9 : Hi > D0 */if (hmsc->cbw.dDataLength != 0U){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);hmsc->bot_state = USBD_BOT_NO_DATA;return -1;}if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsReady(lun) != 0){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);hmsc->bot_state = USBD_BOT_NO_DATA;return -1;}hmsc->bot_data_length = 0U;return 0;}/*** @brief SCSI_Inquiry* Process Inquiry command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){uint8_t *pPage;uint16_t len;USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;if (hmsc->cbw.dDataLength == 0U){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}if ((params & 0x01U) != 0U) /* Evpd is set */{if (params == 0U) /* Request for Supported Vital Product Data Pages*/{(void)SCSI_UpdateBotData(hmsc, MSC_Page00_Inquiry_Data, LENGTH_INQUIRY_PAGE00);}else if (params == 0x80U) /* Request for VPD page 0x80 Unit Serial Number */{(void)SCSI_UpdateBotData(hmsc, MSC_Page80_Inquiry_Data, LENGTH_INQUIRY_PAGE80);}else /* Request Not supported */{SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST,INVALID_FIELED_IN_COMMAND);return -1;}}else{pPage = (uint8_t *)&((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN];len = (uint16_t)pPage + 5U;if (params <= len){len = params;}(void)SCSI_UpdateBotData(hmsc, pPage, len);}return 0;}/*** @brief SCSI_ReadCapacity10* Process Read Capacity 10 command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){UNUSED(params);int8_t ret;USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;ret = ((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size);if ((ret != 0) || (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED)){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);return -1;}hmsc->bot_data = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 24);hmsc->bot_data = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 16);hmsc->bot_data = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 8);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_nbr - 1U);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_size >> 24);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_size >> 16);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_size >> 8);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_size);hmsc->bot_data_length = 8U;return 0;}/*** @brief SCSI_ReadCapacity16* Process Read Capacity 16 command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_ReadCapacity16(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){UNUSED(params);uint8_t idx;int8_t ret;USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;ret = ((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size);if ((ret != 0) || (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED)){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);return -1;}hmsc->bot_data_length = ((uint32_t)params << 24) |((uint32_t)params << 16) |((uint32_t)params << 8) |(uint32_t)params;for (idx = 0U; idx < hmsc->bot_data_length; idx++){hmsc->bot_data = 0U;}hmsc->bot_data = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 24);hmsc->bot_data = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 16);hmsc->bot_data = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 8);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_nbr - 1U);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_size >> 24);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_size >> 16);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_size >> 8);hmsc->bot_data = (uint8_t)(hmsc->scsi_blk_size);hmsc->bot_data_length = ((uint32_t)params << 24) |((uint32_t)params << 16) |((uint32_t)params << 8) |(uint32_t)params;return 0;}/*** @brief SCSI_ReadFormatCapacity* Process Read Format Capacity command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){UNUSED(params);uint16_t blk_size;uint32_t blk_nbr;uint16_t i;int8_t ret;USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;ret = ((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->GetCapacity(lun, &blk_nbr, &blk_size);if ((ret != 0) || (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED)){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);return -1;}for (i = 0U; i < 12U ; i++){hmsc->bot_data = 0U;}hmsc->bot_data = 0x08U;hmsc->bot_data = (uint8_t)((blk_nbr - 1U) >> 24);hmsc->bot_data = (uint8_t)((blk_nbr - 1U) >> 16);hmsc->bot_data = (uint8_t)((blk_nbr - 1U) >> 8);hmsc->bot_data = (uint8_t)(blk_nbr - 1U);hmsc->bot_data = 0x02U;hmsc->bot_data = (uint8_t)(blk_size >> 16);hmsc->bot_data = (uint8_t)(blk_size >> 8);hmsc->bot_data = (uint8_t)(blk_size);hmsc->bot_data_length = 12U;return 0;}/*** @brief SCSI_ModeSense6* Process Mode Sense6 command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){UNUSED(lun);USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;uint16_t len = MODE_SENSE6_LEN;if (params <= len){len = params;}(void)SCSI_UpdateBotData(hmsc, MSC_Mode_Sense6_data, len);return 0;}/*** @brief SCSI_ModeSense10* Process Mode Sense10 command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){UNUSED(lun);USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;uint16_t len = MODE_SENSE10_LEN;if (params <= len){len = params;}(void)SCSI_UpdateBotData(hmsc, MSC_Mode_Sense10_data, len);return 0;}/*** @brief SCSI_RequestSense* Process Request Sense command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_RequestSense(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){UNUSED(lun);uint8_t i;USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;if (hmsc->cbw.dDataLength == 0U){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++){hmsc->bot_data = 0U;}hmsc->bot_data = 0x70U;hmsc->bot_data = REQUEST_SENSE_DATA_LEN - 6U;if ((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)){hmsc->bot_data = (uint8_t)hmsc->scsi_sense[hmsc->scsi_sense_head].Skey;hmsc->bot_data = (uint8_t)hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC;hmsc->bot_data = (uint8_t)hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ;hmsc->scsi_sense_head++;if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH){hmsc->scsi_sense_head = 0U;}}hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN;if (params <= REQUEST_SENSE_DATA_LEN){hmsc->bot_data_length = params;}return 0;}/*** @brief SCSI_SenseCode* Load the last error code in the error list* @param lun: Logical unit number* @param sKey: Sense Key* @param ASC: Additional Sense Code* @retval none*/void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC){UNUSED(lun);USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey;hmsc->scsi_sense[hmsc->scsi_sense_tail].w.b.ASC = ASC;hmsc->scsi_sense[hmsc->scsi_sense_tail].w.b.ASCQ = 0U;hmsc->scsi_sense_tail++;if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH){hmsc->scsi_sense_tail = 0U;}}/*** @brief SCSI_StartStopUnit* Process Start Stop Unit command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){UNUSED(lun);USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;if ((hmsc->scsi_medium_state == SCSI_MEDIUM_LOCKED) && ((params & 0x3U) == 2U)){SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);return -1;}if ((params & 0x3U) == 0x1U) /* START=1 */{hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;}else if ((params & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */{hmsc->scsi_medium_state = SCSI_MEDIUM_EJECTED;}else if ((params & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */{hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;}else{/* .. */}hmsc->bot_data_length = 0U;return 0;}/*** @brief SCSI_AllowPreventRemovable* Process Allow Prevent Removable medium command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_AllowPreventRemovable(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){UNUSED(lun);USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;if (params == 0U){hmsc->scsi_medium_state = SCSI_MEDIUM_UNLOCKED;}else{hmsc->scsi_medium_state = SCSI_MEDIUM_LOCKED;}hmsc->bot_data_length = 0U;return 0;}/*** @brief SCSI_Read10* Process Read10 command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */{/* case 10 : Ho <> Di */if ((hmsc->cbw.bmFlags & 0x80U) != 0x80U){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);return -1;}if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsReady(lun) != 0){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);return -1;}hmsc->scsi_blk_addr = ((uint32_t)params << 24) |((uint32_t)params << 16) |((uint32_t)params << 8) |(uint32_t)params;hmsc->scsi_blk_len = ((uint32_t)params << 8) | (uint32_t)params;if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr,hmsc->scsi_blk_len) < 0){return -1; /* error */}/* cases 4,5 : Hi <> Dn */if (hmsc->cbw.dDataLength != (hmsc->scsi_blk_len * hmsc->scsi_blk_size)){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}hmsc->bot_state = USBD_BOT_DATA_IN;}hmsc->bot_data_length = MSC_MEDIA_PACKET;return SCSI_ProcessRead(pdev, lun);}/*** @brief SCSI_Read12* Process Read12 command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_Read12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */{/* case 10 : Ho <> Di */if ((hmsc->cbw.bmFlags & 0x80U) != 0x80U){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}if (hmsc->scsi_medium_state == SCSI_MEDIUM_EJECTED){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);return -1;}if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsReady(lun) != 0){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);return -1;}hmsc->scsi_blk_addr = ((uint32_t)params << 24) |((uint32_t)params << 16) |((uint32_t)params << 8) |(uint32_t)params;hmsc->scsi_blk_len = ((uint32_t)params << 24) |((uint32_t)params << 16) |((uint32_t)params << 8) |(uint32_t)params;if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr,hmsc->scsi_blk_len) < 0){return -1; /* error */}/* cases 4,5 : Hi <> Dn */if (hmsc->cbw.dDataLength != (hmsc->scsi_blk_len * hmsc->scsi_blk_size)){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}hmsc->bot_state = USBD_BOT_DATA_IN;}hmsc->bot_data_length = MSC_MEDIA_PACKET;return SCSI_ProcessRead(pdev, lun);}/*** @brief SCSI_Write10* Process Write10 command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;uint32_t len;if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */{if (hmsc->cbw.dDataLength == 0U){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}/* case 8 : Hi <> Do */if ((hmsc->cbw.bmFlags & 0x80U) == 0x80U){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}/* Check whether Media is ready */if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsReady(lun) != 0){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);return -1;}/* Check If media is write-protected */if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsWriteProtected(lun) != 0){SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED);return -1;}hmsc->scsi_blk_addr = ((uint32_t)params << 24) |((uint32_t)params << 16) |((uint32_t)params << 8) |(uint32_t)params;hmsc->scsi_blk_len = ((uint32_t)params << 8) |(uint32_t)params;/* check if LBA address is in the right range */if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr,hmsc->scsi_blk_len) < 0){return -1; /* error */}len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;/* cases 3,11,13 : Hn,Ho <> D0 */if (hmsc->cbw.dDataLength != len){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}len = MIN(len, MSC_MEDIA_PACKET);/* Prepare EP to receive first data packet */hmsc->bot_state = USBD_BOT_DATA_OUT;(void)USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len);}else /* Write Process ongoing */{return SCSI_ProcessWrite(pdev, lun);}return 0;}/*** @brief SCSI_Write12* Process Write12 command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_Write12(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;uint32_t len;if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */{if (hmsc->cbw.dDataLength == 0U){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}/* case 8 : Hi <> Do */if ((hmsc->cbw.bmFlags & 0x80U) == 0x80U){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}/* Check whether Media is ready */if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsReady(lun) != 0){SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT);hmsc->bot_state = USBD_BOT_NO_DATA;return -1;}/* Check If media is write-protected */if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->IsWriteProtected(lun) != 0){SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED);hmsc->bot_state = USBD_BOT_NO_DATA;return -1;}hmsc->scsi_blk_addr = ((uint32_t)params << 24) |((uint32_t)params << 16) |((uint32_t)params << 8) |(uint32_t)params;hmsc->scsi_blk_len = ((uint32_t)params << 24) |((uint32_t)params << 16) |((uint32_t)params << 8) |(uint32_t)params;/* check if LBA address is in the right range */if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr,hmsc->scsi_blk_len) < 0){return -1; /* error */}len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;/* cases 3,11,13 : Hn,Ho <> D0 */if (hmsc->cbw.dDataLength != len){SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB);return -1;}len = MIN(len, MSC_MEDIA_PACKET);/* Prepare EP to receive first data packet */hmsc->bot_state = USBD_BOT_DATA_OUT;(void)USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len);}else /* Write Process ongoing */{return SCSI_ProcessWrite(pdev, lun);}return 0;}/*** @brief SCSI_Verify10* Process Verify10 command* @param lun: Logical unit number* @param params: Command parameters* @retval status*/static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params){USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;if ((params & 0x02U) == 0x02U){SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND);return -1; /* Error, Verify Mode Not supported*/}if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0){return -1; /* error */}hmsc->bot_data_length = 0U;return 0;}/*** @brief SCSI_CheckAddressRange* Check address range* @param lun: Logical unit number* @param blk_offset: first block address* @param blk_nbr: number of block to be processed* @retval status*/static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun,uint32_t blk_offset, uint32_t blk_nbr){USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr){SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE);return -1;}return 0;}/*** @brief SCSI_ProcessRead* Handle Read Process* @param lun: Logical unit number* @retval status*/static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun){USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;len = MIN(len, MSC_MEDIA_PACKET);if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->Read(lun, hmsc->bot_data,hmsc->scsi_blk_addr,(len / hmsc->scsi_blk_size)) < 0){SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR);return -1;}(void)USBD_LL_Transmit(pdev, MSC_EPIN_ADDR, hmsc->bot_data, len);hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size);hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size);/* case 6 : Hi = Di */hmsc->csw.dDataResidue -= len;if (hmsc->scsi_blk_len == 0U){hmsc->bot_state = USBD_BOT_LAST_DATA_IN;}return 0;}/*** @brief SCSI_ProcessWrite* Handle Write Process* @param lun: Logical unit number* @retval status*/static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun){USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataMSC;uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size;len = MIN(len, MSC_MEDIA_PACKET);if (((USBD_StorageTypeDef *)pdev->pClassSpecificInterfaceMSC)->Write(lun, hmsc->bot_data,hmsc->scsi_blk_addr,(len / hmsc->scsi_blk_size)) < 0){SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, WRITE_FAULT);return -1;}hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size);hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size);/* case 12 : Ho = Do */hmsc->csw.dDataResidue -= len;if (hmsc->scsi_blk_len == 0U){MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED);}else{len = MIN((hmsc->scsi_blk_len * hmsc->scsi_blk_size), MSC_MEDIA_PACKET);/* Prepare EP to Receive next packet */(void)USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len);}return 0;}/*** @brief SCSI_UpdateBotData* fill the requested Data to transmit buffer* @param hmsc handler* @param params: Data buffer* @param length: Data length* @retval status*/static int8_t SCSI_UpdateBotData(USBD_MSC_BOT_HandleTypeDef *hmsc,uint8_t *pBuff, uint16_t length){uint16_t len = length;hmsc->bot_data_length = len;while (len != 0U){len--;hmsc->bot_data = pBuff;}return 0;}/*** @}*//*** @}*//*** @}*//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/Ask yourself how much research you would need to come up with the above code. Almost nobody knows anything about this. Your chances of writing MSC code by reading the RM is just about zero. You would have to lift code from around the internet. But you can reasonably expect ST code to work, whereas you can't reasonably expect something you found on Github to work - a lot of stuff posted there is just work in progress, terminated when the coder lost interest.Admittedly a lot of it is bloated but if you are looking for some code, this is a good starting point to see what is required. Then you can chop out the bits which don't apply (e.g. SPI code which transmits out of the SPI, checking if CRC is enabled, but you never enabled CRC originally, so this wastes a few clocks on the conditional) and crucially you know where in the RM you need to look to understand the code. The problem with trying to write code just by reading the RM (which a number of super-experienced people on here and the ST forum tell you to do, usually forcefully, occassionally with extreme rudeness which would have them instantly fired from any job) is that it is hard to know where to start, and a lot of peripherals need stuff done in a certain order.There are also plenty of mistakes in ST's code, which is another story. Basically, people who develop this way spend as much time as "RM readers" on googling to see who has been up this road before, to fix stuff which doesn't work properly.So if I was to debate whether MX saves time, yes it saves a lot of time initially. In that sense ST Cube is a great tool. Afterwards, you can write your own bare metal code by reference to the RM, and googling for github code, of which on a good day 50% works

author: Siwastaja
author_rank: Super Contributor
timestamp: September 11, 2022, 07:58:57 am
content: Quote from: artag on September 10, 2022, 11:25:49 pmYou have the terminology totally mixed up.The only confusing thing in ST's HAL is using the generic term for a name, similar to selling chocolate under trade name "Chocolate", now how confusing is that.Other than that, it is exactly what the name suggests, a HAL. It definitely is not an OS. API? The ST's HALhasan API. API is just a generic term for an interface; in a simple C module, the API is the set of function definitions that come in the .h file you #include.Now the GPIO_Init_Struct type bullshit is really not a HAL but just a so-called boilerplate or bloat layer with no use. But HAL_Start_SPI_Transfer type thingisa HAL because it abstracts some details away and thus gains something.But I understand the confusion, some call the autogenerated bullshit code by Cube "HAL", other's just call the ST's HAL library, which have the HAL prefix in function names, the HAL. The latter is an actual HAL. Former is a crappy code generator.

author: peter-h
author_rank: Super Contributor
timestamp: September 11, 2022, 09:23:03 am
content: IMHO "HAL" is a deliberately confusing marketing term.QuoteIt saves one reading quite a lot of the RMBasically you can avoid learning about AF mapping.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 11, 2022, 02:32:52 pm
content: Quote from: peter-h on September 11, 2022, 09:23:03 amWhat are you talking about? The AF bitfields are exposed directly, as is, no abstraction, but no 1:1 memory correspondence either, so just downsides:Code:GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;Sure, there is added peripheral name in that #define name but you wouldn't need any of the struct init function "abstraction" bullshit for that. That's exactly what every MCU vendor since early 1990's have been doing in their header files, say how PORTB is #defined so you don't need to remember the memory address yourself.

author: peter-h
author_rank: Super Contributor
timestamp: September 11, 2022, 06:40:08 pm
content: I was thinking of the HAL functions which set up individual pins to be in, out, and the various types of in and out circuitry. They contain very convoluted code but are easy to get into.

author: tellurium
author_rank: Frequent Contributor
timestamp: September 11, 2022, 10:22:02 pm
content: Quote from: jnz on September 09, 2022, 11:46:55 pmOut of curiosity.. Why CMake? Why not a plain Make? What is the point of learning an obscure Make generator instead of just writing Make yourself - which is quite easy?

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 11, 2022, 10:32:39 pm
content: CMake has become popular for embedded development. It certainly brings some benefits, but I don't like it much myself. So I do stick to just makefiles. Much more flexible IMHO.Also one point that annoys me to no end with CMake is how it tends to promote a very heavily hierarchical file structure. All projects I've seen built with CMake are structured this way. You practically have one source file per folder, with sometimes the header file yet in another subfolder and CMake files everywhere at every level. While I understand that it may make the whole project "tidier" and sligthly easier to reuse components in a given build environment, it's so nested and convoluted that it's a royal pain to set up and navigate. I hate it.

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 12, 2022, 12:07:49 am
content: Quote from: Simon on September 10, 2022, 07:57:10 pmOh sure. Probably workable with some shiny slides, a nice video and a few unmeetable promises.Thing is, there's a world between designing a MCU for your own internal needs and designing one for direct market consumption. If you crowfund one, it would have to be the latter. Then you'd have to write proper documentation, include features and peripherals that you don't care about but that are needed for general-purpose use, and so on, and so forth.And, as I said, access to foundries at the moment is a joke anyway. So, there would be nothing in the end. Maybe it'll get better next year. Or the year after. Or... you get the idea. I dunno.Unfortunately.

author: jnz
author_rank: Frequent Contributor
timestamp: September 12, 2022, 12:47:12 am
content: On topic…That link series I posted is on a site of a guy that likes NXP, but his guides for VS Code have stm32 examples.The Segger EDU is super cheap. The only tool I would buy as a hobbiest.Why CMake vs Make? For one, because I wanted to use Ninja. And Make is showing its age a bit. I wanted to be able to define functions and run other scripts during and after the build process, CMake and Ninja seemed better for this. You don’t have to lay things out in different folders/files, it supports any layout you want. Everything makes sense to me, so I have no real problem with it. Plus, if you don’t already know Make, it makes more sense to skip and go right on to CMake imo.It doesn’t matter.The only thing that PIO got definitely right imo was VSCode. They didn’t outright mess up with SCons but other decisions made that pointless.

author: wek
author_rank: Frequent Contributor
timestamp: September 12, 2022, 05:16:14 am
content: Quote from: SiliconWizard on September 12, 2022, 12:07:49 amCrowdfund also a foundry, then... ;-)JW

author: analityk
author_rank: Regular Contributor
timestamp: September 14, 2022, 07:05:52 pm
content: Everything you wrote is true. This python scripts for easy build your solution works on default (compilable) setting and if you need something more that's fail. Problems is this software pack for stm and python scripts.Some days ago I watch on yt channel where someone explain and show how to install arm toolchain, gdb, make for windows, git etc.I spent many hours but successfuly compiled solution from scratch, for stm32f7xx. Of course with gnu make etc.This is hard way but it it is not dependent for vsc or platformio actualization. And I bet for 19 years compilation will be like today. Another valuable thing is i not need use of stm ide. It look like someone stop developing it in 1999.Visual Studio code is only code editor, good but by default is like piece of shit and is unusable.

author: tellurium
author_rank: Frequent Contributor
timestamp: September 14, 2022, 07:20:11 pm
content: Quote from: analityk on September 14, 2022, 07:05:52 pmI found ARM GCC toolchain and Make very easy to install and use; it is just a matter of minutes, not hours.What is not trivial, if we're speaking about bare metal approach, is 1) linker script and 2) initialization / boot code. The rest is easy peasy.Can you point out, what exactly took hours, and was hard?

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 14, 2022, 07:26:53 pm
content: To get started with the linker script and startup code, just take the ones that are provided by the vendor. They are always there in their SDKs.Then you can always modify them to suit your particular needs, but that's a working starting point.Some people just assume that vendor SDKs/tools just magically make things happen. Nah, they are just tools that are generating or using all the same stuff behind the scenes: startup code, linker scripts, GCC (most of the time) and makefiles. (Those using CMake can go from there too. Either makefiles or Cmake files contain compiler and linker options, so that gives you the right options to use.)You don't need to go through a mountain of docs to get started. Use vendor-provided stuff as they should be used (IMO): as a starting point. All you need is to dig a bit.

author: westfw
author_rank: Super Contributor
timestamp: September 14, 2022, 11:27:25 pm
content: I think I miss having a "Corporate infrastructure" dictating the tools I have to use. On the one hand, I might be forced into using something that I don't particularly like, at least initially. On the other hand, it also implies an environment where there are enough users of those tools that I'll get "support" - people explaining how (and why) to use features that I wouldn't have noticed. How to work around bugs. The corporate "weight" to get the vendor (or a local tools team) to actually fix bugs. Commiseration for those problems that aren't going to be fixed.All I've learned from online fora is that there is no IDE that someone doesn't really hate. IDEs that are too slow. IDEs that are ugly. IDEs that are too simple. IDEs that are too complex. IDEs that are too vendor-specific. IDEs that require too much configuration to use with XXX. Bah humbug!

author: wek
author_rank: Frequent Contributor
timestamp: September 15, 2022, 03:37:00 am
content: Quote from: westfw on September 14, 2022, 11:27:25 pmAlso, there is no IDE that someone doesn't really love.JW

author: Siwastaja
author_rank: Super Contributor
timestamp: September 15, 2022, 06:56:02 am
content: Quote from: tellurium on September 14, 2022, 07:20:11 pmEven this would be nearly easy-peasy if someone went to write a good beginner-level (yet accurate) tutorial with a few good examples.After all, people do program in C, which is orders of magnitude more complex to understand than the usually needed subset of linker script commands. Boot code is also just some memory copying.

author: westfw
author_rank: Super Contributor
timestamp: September 15, 2022, 09:11:41 am
content: Quotehave you seen @atardov's "starter projects"? I'm not sure that I'm completely fond of his "first implement my HAL macros" approach, but I'm not sure I dislike it, either. And he cover a wide range of processors...https://github.com/ataradov/mcu-starter-projects(Hmm. Maybe it's not quite "tutorial" level; just examples. But still pretty useful.)

author: artag
author_rank: Super Contributor
timestamp: September 15, 2022, 12:14:55 pm
content: Quote from: peter-h on September 10, 2022, 02:20:18 pmJIT certainly didn't work out for the car industry right now. It can do well when operating with long schedules and plans, but they tried to turn it off and on like a tap, and it's failed very badly.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 15, 2022, 01:29:37 pm
content: Quote from: westfw on September 15, 2022, 09:11:41 amYes, this is the best set of practical MCU development project templates I have ever seen. It's not far from what I mean, a step-by-step tutorial for Arduino-level people who want to go one step further and need to choose between seemingly "complex" (but actually easy and sustainable!) classical development, or seemingly "easy" (but actually complex, and time wasting (in the long run)!) "trend toolset of the year" development. They almost always choose the latter because of all the tutorials, manuals and advertising and "support" from manufacturers. ataradov's Github repository can't fight against all that.

author: tellurium
author_rank: Frequent Contributor
timestamp: September 16, 2022, 12:44:59 pm
content: I have started such a tutorial athttps://github.com/cpq/bare-metal-programming-guideThose who want to contribute or fix mistakes - your PRs are welcome.

author: westfw
author_rank: Super Contributor
timestamp: September 16, 2022, 10:28:54 pm
content: QuoteQuotePersonally, I think developing your own definitions for peripheral registers is going too far in the "bare metal" direction.People should use the standard definitions and include files provided by the vendor, and should be actively discouraged from creating their own definitions.Alas, this does mean that any tutorial on bare metal programming must spend significant time on "how to get the vendor include files", since they're frequently buried inside an IDE or tool download, arranged in a weird directory structure, or otherwise "difficult to deal with." (sigh.)

author: tellurium
author_rank: Frequent Contributor
timestamp: September 16, 2022, 11:33:33 pm
content: Quote from: westfw on September 16, 2022, 10:28:54 pmThat's why there is (not yet completed) "CMSIS" section in the tutorial.IMO, before introducing the CMSIS headers, it is important to show why, and how, things are organised.The idea is to gradually introduce major concepts, with the corresponding source code directories:- minimal "do nothing" firmware- blinky firmware- blinly with systick interrupt- blinky with systick, using CMSISAfter that, a reader should have enough background to choose any approach suitable

author: Smokey
author_rank: Super Contributor
timestamp: September 17, 2022, 12:14:41 am
content: Quote from: Siwastaja on September 08, 2022, 06:02:29 pmThe most frustrating experience I have had in the recent(ish) past was manually getting the STM32 toolchain set up in plain eclipse before ST bought Atollic Truestudio and turned it into STMCubeIDE. I was even following the "Mastering STM32" instructions and it still was super tedious and I never felt like it was solid. I don't think this reflects as much on ST as it does on how much of a mess it is getting these toolchains all setup and working with everything as a system. I dreaded having to change anything once I got it building.I don't want to be a GNU toolchain expert. I just want my code to build. Learning how to be a toolchain expert is not a good use of my time ultimately.

author: thm_w
author_rank: Super Contributor
timestamp: September 17, 2022, 12:35:24 am
content: Quote from: Smokey on September 17, 2022, 12:14:41 amIts not a good use of our time.For those who spend a large portion of their time coding (presumably Siwastaja) and are very good at what they do, it totally makes sense.I just state what I use, that it works for me, and move on. As OP said, they don't regret trying PIO. Which I agree with, try a few different options, maybe not for a week but I think you can get an overall idea in a day or so if you have past experience.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 17, 2022, 05:38:01 am
content: Quote from: westfw on September 16, 2022, 10:28:54 pmBut as an example, this can be highly educational, because it takes the magic aways, and shows what exactly happens at bit level.And this is exactly the right amount of abstraction, all that needs to happen is to use a manufacturer-supplied file containing this very #define.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 17, 2022, 05:43:59 am
content: Quote from: Smokey on September 17, 2022, 12:14:41 amYou are proving the point! Don't do that.arm-none-eabi "toolchain", AFAIK, is installable as a single package for any platform (to be fair, I have only installed it on linux where it is one apt-get command) and there is zero need to configure or set up anything! Just run gcc, ld and you have your binary. You can usemaketo run gcc for you, but even that is optional if it is too complicated (I recommend writing simple and short makefiles, though, it's a good tool if you don't overcomplicate it.)QuoteSuch bad advice is all around.QuoteI agree, but you can't avoid knowing your tools. It's like saying "I don't want to know how to operate an excavator, I just want to dig trenches". It does not work that way.The key to success is to find tools that are simple to use yet give you control instead of distraction, and that do not change every other year. These are the GNU tools used as backend in every crap solution. These are the common ground. Understand the basic usage and you are fine for decades.And a linker script is as much part of MCU programming as is the .c file itself. You can learn the basics by following an example file in matter of hours. You probably spent years learning C so this shouldn't be a problem.If you want to write C, you need to know how the C "ecosystem" works, concept of object files, symbols, compilers, linkers, sections and whatnot. Not perfectly, but enough to do the job.

author: JPortici
author_rank: Super Contributor
timestamp: September 17, 2022, 06:11:48 am
content: Quote from: thm_w on September 17, 2022, 12:35:24 amhis experience was exactly my experience with STM32 when i first tried them years ago. Only tutorials, not guides. Only "do this" without the why. Everything unstable because a month later component x of the infinite list of components is updated and something breaks and you waste at least half a day googling for someone who has the answer. No "just do" because i'm not "just doing" something i have no idea about, and there is always something else i have to "just do"I will quote verbatim: I don't want to be a GNU toolchain expert. I just want my code to build. Learning how to be a toolchain expert is not a good use of my time ultimately.And i spend a LOT of my time coding, but i want my tools to be one click installers. At least at first. After i have a solid base to write code i can start exploring the rest, how it's set up and everything. The developer tools must not be a hinderance or i will use the manufacturers that satisfy my requirements in dev tools.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 17, 2022, 08:09:48 am
content: I'm asking because I don't know - is installing arm-none-eabi-gcc, -ld, -objdump etc. (the whole package)nota "one click installer" on some platform?I'm asking because I also went through the horror of trying to follow tutorials and installing manufacturer bullshit for STM32 a decade ago. It was not Cube at the time. Totally wasted time. Then I found a tutorial which said "run apt-get install gcc-arm-none-eabi". On linux, it is still this easy.Literally the only problem was the same tutorial site gave an example linker script which was faulty and caused colossal waste of time. But it was so close to being a total success. I bit the bullet and after months of wasted time understood what was wrong in the linker script (wrongly aligned stack pointer). In the end that was good, too, because working with linker scripts became a valuable skill after going for more complex MCUs.But I'm sure ataradov's linker scripts do not have this problem and they just work. All you need is to communicate to people how easy this is. It is non-trivial because of the huge mass of information. How do you tell people "this is the right way"?

author: westfw
author_rank: Super Contributor
timestamp: September 17, 2022, 09:00:37 am
content: QuoteI believe that it WASN'T, in the "recent(ish) past."These days, you can download recent versions of the gcc tools from ARM, which is likely to be a slightly more supported version than what some package manager manager may have put together :-(The most recent versions don't work on oldish versions of MacOSX, though :-( dynamic library incompatibilities or something. (Grr. Why a cli compiler would have "mysterious" OS version dependencies is ... a mystery :-( )(Of course, I do feel a bit like the people complaining that the latest Windows thing doesn't work on their W7 system, but it's still annoying. (I'm running High Sierra (10.13.x), and it looks like "many" things require at least 10.15.))

author: hans
author_rank: Super Contributor
timestamp: September 17, 2022, 09:16:33 am
content: 1-click install:Windows:https://community.chocolatey.org/packages?q=gccLinux: use your package maneger to get arm-none-eabi-gccMac: never used it, probably similar in it's package manager.Version numbers are here or there, as long as it's on the latest of a particular major release. If you use the latest C++ versions then you may care about having the latest major GCC release. But I doubt many will care for regular C code, unless you want to be the first to use the latest features. Recent GCC (10 and beyond) have had some significant changes to the optimizer in where it can make smarter assumptions on the range and domain of variables and statements. However this has introduced some issues, like not being able to compile the latest DMA driver code from STM32U5xx on recent GCCs with optimizer turned on (IIRC there was a bug on some pointer arithmetic to determine base address for DMA operations, GCC segfaulted on it).GCC is not perfect, but it does a pretty good job for being free and working on a ton of architectures with up to date mainstream language specifications. In my experience it's still driven best on some kind of Unix though, but I think that's true in general for almost any kind of programming.QuoteAs a reply-all: do you want to build your code or do you want to build your firmware? You need code and toolchain knowledge to make firmware. If you want to write a bootloader it's unlikely you can do it without modifying startup and linker files. Linker files are specific to each toolchain, so that's already a toolchain choice lock-in and requires knowledge of how to use said toolchain.If I want to design professional PCBs in Altium, but don't want to learn Altium as I just want to draw my PCB art manually without netlist and DRC, then that's a very inefficient way of operating my business. Why do I get Altium in the first place? Sure you can make it work, but without a netlist to show what needs to be connected to what, and without a DRC checking for clearance and trace widths, it will be very hard to get it done right..

author: Siwastaja
author_rank: Super Contributor
timestamp: September 17, 2022, 10:48:37 am
content: In other words, maybe becoming a world-class Altium or GCC expert is not for everyone, but if you design PCBs and write firmware for your MCU projects, you need to know enough of your tools to get the job done. When it comes to PCB EDA, it's obvious there is some learning curve ahead before you can get into the "actual" work. Somehow, people are reluctant to accept learning to use GCC, yet same people are often fine with investing the same amount of time to some volatile crappy framework. This behavior is not rational. Part of the reason are wrong assumptions, for example that understanding how to use GCC, LD and binutils isdifficult, when in reality these are all quite simple tools with long heritage.

author: Smokey
author_rank: Super Contributor
timestamp: September 17, 2022, 05:04:29 pm
content: Quote from: Siwastaja on September 17, 2022, 05:43:59 amYou can take that argument to the extreme on so many levels..."You save your files to a hard drive without knowing all the details of ext3/NTFS and how to hack the filesystem kernel drivers?""You use a voltage reference chip without knowing the quantum physics of how bandgaps work?"To use your example:Sometimes you just want a trench dug. If you don't know how to work an excavator you need to run an opportunity cost analysis and decide if your time is better spent learning that skill because you will use it enough in the future to make it worth your effort or finding someone else that already knows how to do it and just having them dig trench.You would be insane if you wanted to write a bootloader but refused to learn how linkers/loaders/sectors/etc worked. At the same time I've been doing embedded design for quite a while now and I've never had to actually write a bootloader.No matter how much you know, and how much of an expert you are, there is always a level of details one step lower that you don't understand.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 17, 2022, 05:43:46 pm
content: Quote from: Smokey on September 17, 2022, 05:04:29 pmI did not suggest learning the internals of GCC, just enough to USE IT, equivalent to knowing "CTRL+S" or knowing how to read the voltage reference datasheet (pinout, for example). So you are 100% bullshitting here.QuoteCongratulations, you got it! Similarly, if you don't know how to do firmwares and don't want to learn, subcontracting this work to someone who does is an excellent idea. This is what I do for a living.What I suggest is, if you are interested, learn the minimum required to get forward. This includes understanding the C ecosystem, and most basic use of the tools that allow you going from specification, to a finished binary. You have to understand it yourself completely, or subcontract part of it to others,someonehas to do it. And substituting random trend toolchain/framework of the year for understanding is a trap that only wastes your time and does not solve anything, this is truly the experince not only by myself butdecadeworth of reading this forum and others and see how people struggle with the same things over and over again.But I suppose I will not succeed getting this idea through to you, and it doesn't matter.

author: hans
author_rank: Super Contributor
timestamp: September 17, 2022, 09:35:46 pm
content: Take it easy. It's all a matter of choices. Let's not get into extremes: to make decent coffee I don't need to know what boiler temperature and pressure my automated coffee machine runs at. I'm not that much of a barista. But it's still a"small effort large upgrade" step (relatively speaking) from a Senseo or similar machine. And I atleast have full choice of the coffee beans I can use instead of only a handful of brands that make those coffee pads/cups!Perhaps another half-baked example from me. But I hope you get my point. Sure you can roll every part of the toolchain yourself, roll every protocol stack by your own.. but you'll never get anything done. The opposite side: refusing to go (slightly) into depth even if a project necessitates it sounds irrational to me. Driving GCC and linker scripts is only a handful of files, and once you do, you're completely free to setup it like what you want it to be.But I guess choices are made on an individual basis, and opportunity costs are very much that

author: cfbsoftware
author_rank: Regular Contributor
timestamp: September 17, 2022, 11:08:34 pm
content: Quote from: Siwastaja on September 17, 2022, 10:48:37 amhttps://man7.org/linux/man-pages/man1/gcc.1.htmlI would not describe that as simple.

author: westfw
author_rank: Super Contributor
timestamp: September 17, 2022, 11:26:20 pm
content: QuoteI think the complaints were about the somewhat convoluted path needed to BUILD FROM SOURCE a cross-compiling set of binutils/gcc/libc/make/etc for a set of chips. Particularly for windows, where the first step has to be the installation of a native-x86 C compiler and tools.The RPi community has balked at the windows install procedure for the RPi Pico, for example. Even though you can get the ARM gcc/binutils stuff in binary form (from a separate source), some of the "incidental tools" are distributed in source form, and one of the steps is to install 5G+ of "Visual Studio" to get the native C compiler.On MacOS, I've chased "dependency hell" where the library versions for the native gcc on the Mac (XTools) do not match the versions desired by some open-source tool (or at least the auto-configure stuff that checks all of the 'requirements.")It's all doable. There are usually tutorials, and sometimes scripts. But it certainly can be a pain in the neck, and I do think it's beyond what should be expected of the "user" of a development environment.

author: JPortici
author_rank: Super Contributor
timestamp: September 18, 2022, 05:57:22 am
content: Quote from: westfw on September 17, 2022, 09:00:37 amFWI, there is the "minimum supported os version" field in one of the plist files inside the application package, you can change the field, touch the file and the application will not be marked as incompatible anymore. unless it uses features and api changes from later os versions you can use itIn any case, installing GCC in windows, it's easy to mess it up. But I use MinGW with their installer manager as i found it the least painful option, and i have to keep different versions installed because some abandoned tools need them.

author: tooki
author_rank: Super Contributor
timestamp: September 18, 2022, 12:29:37 pm
content: Here’s how I see it, as someone who is still a novice at programming: I have only so much mental energy and time available at a given moment. If my goal is to learn microcontroller programming, then any effort expended on the toolchain is mental energy and time taken away from the actual programming. And it’s not some kind of linear relationship: learning how to set up any part of the toolchain requires learning and understanding significantly more than is needed at the moment. (For example, while typing in the configurations for a given MCU doesn’t take too long, knowing what the options are and why you’d choose one or the other requires understanding the MCU in question, and that in turn requires understanding a lot of the inner workings of MCUs and digital logic.) So while it very well may make sense to learn all those things in the long run, it’s an insurmountable hurdle for a beginner. In the meantime, I can’t learn programming if I can’t even get the toolchain working. I can’t learn programming if the programming environment is throwing an error that is literally meaningless to me, before it’s even gotten to the point of trying to compile code.So what happens? Your teacher or mentor configures it for you and leaves you to do the coding.This is precisely why Arduino has become so extraordinarily successful: it provides a simple way to dip your toes. If MCU programming appeals to you, then you quickly outgrow it and progressively move closer and closer to bare metal. For many, this is where PlatformIO comes in: it’s a big step away from the Fisher-Price environment of the Arduino IDE, giving you a lot more flexibility, tools, and rope to hang yourself from, while still not quite requiring you to delve into the nitty gritty like the first-party IDEs do (let alone very “manual” toolchains like compiling gcc or whatever).I think a lot of the people who think configuring this stuff from scratch is easy, and that it’s how everyone should start, have a) completely forgotten what it was like when they started out, and b) may not recognize that not everyone is as interested or talented in it as they are.

author: westfw
author_rank: Super Contributor
timestamp: September 19, 2022, 08:02:41 am
content: QuoteIt's a command-line program, not an "application package." It doesn't have a plist, and it isn't "marked" as incompatible. It justcrashesover something silly in the libraries:Code:/usr/local/gcc-arm-11.2-arm-none-eabi/bin/arm-none-eabi-gcc /dev/nulldyld: lazy symbol binding failed: Symbol not found: ____chkstk_darwinReferenced from: /usr/local/gcc-arm-11.2-arm-none-eabi/bin/arm-none-eabi-gcc (which was built for Mac OS X 10.15)Expected in: /usr/lib/libSystem.B.dylibdyld: Symbol not found: ____chkstk_darwinReferenced from: /usr/local/gcc-arm-11.2-arm-none-eabi/bin/arm-none-eabi-gcc (which was built for Mac OS X 10.15)Expected in: /usr/lib/libSystem.B.dylibAbort trap: 6(I'm running 10.13.6 "High Sierra.")

author: wek
author_rank: Frequent Contributor
timestamp: September 21, 2022, 01:24:39 pm
content: Quote from: Sal Ammoniac on September 09, 2022, 06:33:40 pmOn STM32 forum, this linkhttps://devblogs.microsoft.com/cppblog/importing-st-projects-into-visual-studio-code/just appeared in one of the threads.It also has one comment.JW

author: westfw
author_rank: Super Contributor
timestamp: September 21, 2022, 11:55:13 pm
content: I am reminded of when TI released the first "LaunchPad" board as an "Arduino Killer."It came with a nice tutorial on how to set it up:Install the TI compiler.Install the MSP430 libraries.Install the drivers for the programming hardware.Install the launchpad examples.:20. Plug your Launchpad into the USB port of your computer.They were ... "not clear on the concept."But that's GOOD, right? "Arduino is too easy and doesn't make you learn important skills."

author: tellurium
author_rank: Frequent Contributor
timestamp: September 22, 2022, 09:47:30 am
content: So what is the right solution for this?Make an arduino-like tool, with bundled toolchain & make for bare metal programming, if current installers/builds are buggy?Create an online editor/compiler with import/export capabilities?Or something else?

author: JPortici
author_rank: Super Contributor
timestamp: September 22, 2022, 10:07:22 am
content: Quote from: westfw on September 21, 2022, 11:55:13 pmmicrochip came up with a really good alternative with the xpress boards:the board presents itself as a composite device, VCP and MSDstdio routed through VCP for printf/scanfcopy hex file to the msd device to initiate programming of the target microcontrolleryou can use the mplab xpress cloud ide to write code and download an hex file, a shitton of examples on the web archive (which i used myself from time to time) and you can contribute. you can use mcc to create the application or write bare metal codeor of course install the toolchain if you don't want to use the cloud version, take the hex file and copy to the board. xpress board was really nice and (at first) priced really aggressively

author: wek
author_rank: Frequent Contributor
timestamp: September 22, 2022, 11:17:14 am
content: Quote from: tellurium on September 22, 2022, 09:47:30 amThere is no one size fits all.JW

author: jnz
author_rank: Frequent Contributor
timestamp: September 22, 2022, 06:29:28 pm
content: You guys are fucking professionals at going topic-adjacent. If as OP I can chime in...If you want to be a toolchain expert, or if you want to make tools to make tools, yea go for it. But the sentiment is correct for most of us, we don't want to be toolchain experts. It's not like CMake/Make is hard. It's really not. A little intimidating if all you've ever done is IDE or nothing.It's taken me a long time to come around it - but GCC + CMake/Make is just a better setup long term- WHEN - coupled with agood environment(notice I didn't say IDE). The lines of IDE are blurred. Is VSCode an IDE? No, but is it an IDE for me as set up? Much Yes.But the overall point here, the reason for making this post to begin with is thatPlatform IOor really any IDE once you stray outside developer intentions, you'll be doing the same effort as the toolchain-direct people but in a system that offers fewer options and less support.Might as well just put your pants on all by yourself like a big boy. Because like it or not, you'll be forced to at some point.

author: JPortici
author_rank: Super Contributor
timestamp: September 22, 2022, 07:00:35 pm
content: Quote from: jnz on September 22, 2022, 06:29:28 pmRule 25. Relation to the original topic decreases with every single post.But not really, it started as why PIO sucks completely and the discussion moved to why some need it, then to why the pro way is actually easy (or not), then to alternatives

author: wek
author_rank: Frequent Contributor
timestamp: September 22, 2022, 08:36:50 pm
content: Quote from: jnz on September 22, 2022, 06:29:28 pmWhat were/are PIO developer intentions? And did they fail to accomplish them, or just they missed your expectations? In any case, how would you know without trying?Thanks again for sharing your experience.JWPS. Make is hard to me. I don't use anything other, so I don't know CMake.

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 22, 2022, 08:41:06 pm
content: I dunno what the original intentions were. But what it is now should be relatively clear:https://platformio.org/

author: wek
author_rank: Frequent Contributor
timestamp: September 22, 2022, 08:58:42 pm
content: Quote from: SiliconWizard on September 22, 2022, 08:41:06 pmTo provide Integrated Debugger, Unit Testing, Static Code Analysis and Remote Development, with Single Source Code on Multiple Platforms? (Just extracted the big letters.)Aren't these commendable goals?JW

author: wek
author_rank: Frequent Contributor
timestamp: September 25, 2022, 09:02:35 am
content: Quote from: tellurium on September 16, 2022, 12:44:59 pmMmm, progress. Nice. I'd strongly recommend introducing the CMSIS-mandated device headers early on, and then stick to their usage, rather than (re)defining your symbols. I know it means reworking substantial portion of the existing tutorial, but I believe it's worth doing it, from methodological point of view.One long-time rant of mine is, that those headers don't contain values for non-single-bit bitfields. I see you use enums (enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF, GPIO_MODE_ANALOG };) rather than defines, that's a nice idea although I'm not entirely sure what are all the positive and negative ramifications of this. I also tend to visually separate the "register/field" portion of these symbols from the "value" portion by double-underscore (as in GPIO_MODE__INPUT), but that's my personal preference.JWPS. Sorry for hijacking the thread again, but I think this *is* somewhat germane to the topic. IDEs suck, but there's no alternative as in decently documented alternatives.

author: voltsandjolts
author_rank: Unknown
timestamp: September 25, 2022, 09:34:23 am
content: Quote from: tellurium on September 16, 2022, 12:44:59 pmI read through it today, I like the content, style and the pace.Background on accessing the device registers is good but most newcomers will just want to get going using the manufacturer supplied header, so perhaps some hints where to get those might be useful. IIUC some folks create their own header files from SVD and being able to easily create a header in a style of your choice is appealing.Looking forward to the reading the Ozone section - I've been considering upgrading my j-link base to get access to Ozone.

author: wek
author_rank: Frequent Contributor
timestamp: September 25, 2022, 10:10:45 am
content: Quote from: voltsandjolts on September 25, 2022, 09:34:23 amTo help tellurium: For STM32,https://github.com/STMicroelectronics/cmsis_device_f4(substitute last two characters for given STM32 family), under Include/. It also contains an example startup code under Source/Templates/.If you already have Cube (which means the "library", automatically downloaded by CubeIDE or any other IDE) for your STM32 family - or you download Cube fromhttps://github.com/STMicroelectronics/STM32CubeF4(again substitute last two characters for family) - then the same is under /Drivers/CMSIS/Device/ST/[STM32 family]/.Quote from: voltsandjoltsI wouldn't recommend nor even mention this in a tutorial.One reason for using symbols from the manufacturer-supplied CMSIS-mandated header is that it provides a common denominator, making community support and collaboration easier (or even possible at all).2 eurocents.JW

author: tellurium
author_rank: Frequent Contributor
timestamp: September 25, 2022, 10:48:18 am
content: Gents, thanks for the suggestions.Yes, I am quite aware of the STM32 CMSIS include files - the appropriate section in a tutorial is coming soon.W.r.t. Ozone - I found it the best debugger for the bare-metal firmwares. Ozone is "stand-alone" - once you have a firmware .elf file, built with debug symbols using any framework you like, you just point Ozone to it and it picks up the source, allows to reflash automatically on .elf refresh, etc. No need for an IDE or anything. It provides a handy peripherals view, akin to what Keil provides, which may be helpful to analyze the state of a given peripheral.I am biased towards printf style of debugging, but when a debugger is required, I prefer Ozone.

author: paulca
author_rank: Super Contributor
timestamp: September 25, 2022, 11:15:11 am
content: Question: I'm about to look into ARM development. I'd like to get fairly low level (after maybe a few Hello Worlds in PlatformIO).What would you suggest?On build systems/environments/cicds...All build platforms suck.I was exposed to Makefiles after a period without seeing one. It wasn't a pleasant revival. I mean, when you are spending your days working with Makefiles you sort of get used to it, but on the surface is a syntax from when bytes were expensive and variables had single or double mnemonics! Operators and expressions are contracted into symbols with implicit and explicity intermixed in a big fragile tree of of usually script generated non-sense, thousands of C files compiled by "configure" which are ALL recusively generated from automake/conf m4, awk et. al 1960s script languages which ALL suffer from compaction to save memory/disk because it cost $100,000 a megabyte back them!It doesn't matter what one you choose it will always have unpleasant side effects.If you are learning, sure, go for a glitzy "black magic" IDE like Arduinno/PlatformIO. However, do also pause a take a trip down manually building it with an open build platform, like gcc. But start with a shell script! I swear when you are learning, by the time that shell script becomes untainable, your first dozen projects will be collecting dust anyway.In day job I use Java + Eclipse + Maven and I get paid to fiddle with by build tools. In fact I'd say 90% of my job is either waiting on build tools or trying to figure out why they aren't working. Especially as those build tools the full CI/CD is shared and locked down with dozens of layers of security. Maven and Java in enterprise produce deployables sometimes in the multiple gigabytes, mostly code depenencies! My own project (last touched) had 450 dependencies and produces a 300Mb tar.gz. The actual application is a single class of about 200 lines and does very simply things. Recently they demanded we remove ALL vulnerable jars from all projects. Fine. But wait. They scanned the build environment manifest, NOT the deployable manifest. So if you had a dep with a vulnerable dep included, you override it and upgrade it. Test it works. Oh, but no... too late.. you accessed it. Your build is marked "Out of compliance" and your name appears beside it on a spreadsheet sent out to name and shame! So even if a build tool like a compiler pulls in an old version of, say, beanutils. It's over, build fails. Took me a WEEK! to fix that across 4 projects. Tedious, unnecessary, dogmatic, bureaucratic BS!At home I've just come out of a session of "bare metal x86 programming". Where yes, I spent time with gcc, ld, make, including managing my memory segments and executable format. I still managed to get a "Hello World", full 64bit long mode, "OS", not much more than a bootloader, but a bit more.... using a shell script. It had like 10 lines in it. clean it up, compile/assemble/link make boot.bin run the qemu.

author: wek
author_rank: Frequent Contributor
timestamp: September 25, 2022, 04:42:20 pm
content: Quote from: paulca on September 25, 2022, 11:15:11 amThen there's no hope, thus no point in seeking the "best one".Quote from: paulcaThat's maybe not a bad idea, and I personally lean towards that too... but then again, it depends on the working environment. Surely a "shell script" in Win whichever version is somewhat different from "shell script" in *nix, and yet even more different on whatever the Apple stuff is called this week. Even *running* "shell scripts" is not without challenges. So, for those who write tutorials it's a nightmare; OTOH those who manage to write "shell scripts" don't really need tutorials...JW

author: westfw
author_rank: Super Contributor
timestamp: September 26, 2022, 12:04:54 am
content: QuoteWell, yeah. The interesting question is whether it is better to spend your time getting better at understanding a particular platform (despite its suckiness), or spend similar amounts of time searching for a better (but sucky in different ways) platform.It's quite the toss-up.This is the crux of "engineering" - trying to produce "good" results even though all the stuff you have to work with sucks.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 26, 2022, 02:12:47 pm
content: You don't need to overthink "build systems" in embedded MCU projects.The core reason for the existence of build systems is to probe the available libraries, compiler etc. tool versions to build working binaries for your operating system(s), and add some compile time modularity for complex and large desktop applications etc.MCU development is nearly free of these needs (except maybe some compile time modularity). I have never seen any real use for cmake, for example. Standard makefile is enough and if it seems complicated, reduce until it fits to 1-2 screens.Going for cmake "so that I don't have to deal with makefiles" is a step in the wrong direction.

author: tellurium
author_rank: Frequent Contributor
timestamp: September 26, 2022, 03:23:46 pm
content: For those who are interested - I have finished the tutorial. Added a section on UART, IO retargeting (printf redirect), debugging with Segger Ozone, and using a vendor-specific CMSIS headers.If you find a mistake or wish to extend it, PRs are welcome.https://github.com/cpq/bare-metal-programming-guideThanks to those who came up with suggestions!

author: wek
author_rank: Frequent Contributor
timestamp: September 26, 2022, 04:07:50 pm
content: Wow.JW

author: paulca
author_rank: Super Contributor
timestamp: September 26, 2022, 04:10:33 pm
content: Quote from: wek on September 25, 2022, 04:42:20 pmYea. Tutorials have to pick their fights and stick to them.I have been frustrated trying to find advanced OS functionality tutorials. I keep finding things like Paging and memory management with x86_64... only to find it's 99% an Intel ASM tutorial and the only actual bit about paging and memory management is a single slide discussion flat VM space.Similarly I have found it refreshing to find tutorial on at least some basics of OS development that completely side stepped the whole build environment, using shell scripts. He also completly side stepped most C++ coding standards and included CPP files etc. A lot of people gave his shit in teh comments. I just thought he had the right attitude. Can you tell I'm not a dogmatic engineer. I mean if you can build it out cardboard and it works once and only needs to work once... why build it out of wood?

author: peter-h
author_rank: Super Contributor
timestamp: September 26, 2022, 08:32:17 pm
content: Gosh, tellurium's writeup is amazingly detailed.It has some really clever bits in it e.g.Code:for (long *src = &_sbss; src < &_ebss; src++) *src = 0;for (long *src = &_sdata, *dst = &_sidata; src < &_edata;) *src++ = *dst++;main(); // Call main()for (;;) (void) 0; // Infinite loop in the case if main() returnsFirst two lines replace a whole load of asm in the traditional startup... .s file. The last one is an imaginative bit of C which completely baffles me but then I just use C in a basic way.I am a bit surprised that CPU works with just thisCode:uart->BRR = FREQ / baud;because the 32F417 uses two registers and you decompose the baud rate into these two, so weird values like 120000 baud are possible with quite a high accuracy, when the clock (16MHz in this case) is not a power of two. I have never seen a UART which could get a usefully accurate 115200 with a 16MHz xtal. There is a thread here on how the dual-divider thing works, but nobody was quite sure. I reckon it was using some form of fractional-N synthesis. But I am probably missing something obvious.I am very happy I don't have to write that base code again

author: tellurium
author_rank: Frequent Contributor
timestamp: September 26, 2022, 09:22:34 pm
content: Quote from: peter-h on September 26, 2022, 08:32:17 pmThat code should be like this:Code:uart->BRR = FREQ / PRE / baud;Where PRE is the APB prescaler. By default, when a system clock is not modified, it is 1. I didn't add that to make things simpler.

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 26, 2022, 09:24:48 pm
content: Nice work I have to say.

author: westfw
author_rank: Super Contributor
timestamp: September 27, 2022, 01:32:44 am
content: QuoteI've complained about the horrible process that ST libraries go to set the baud rate for a long time.2014:https://www.eevblog.com/forum/microcontrollers/one-dollar-one-minute-arm-development/msg516710/#msg516710More recently:https://www.eevblog.com/forum/microcontrollers/is-st-cube-ide-a-piece-of-buggy-crap/msg3900779/#msg3900779

author: tooki
author_rank: Super Contributor
timestamp: September 27, 2022, 05:50:09 am
content: Quote from: jnz on September 07, 2022, 05:16:05 pmIt’s right there on the support page:

author: peter-h
author_rank: Super Contributor
timestamp: September 27, 2022, 06:28:00 am
content: QuoteAs I've said, I don't think it is a simple divider, because you would not get 115200 with enough accuracy if the CPU clock was 16MHz, especially as this is usually divided by two first before getting to the UART baud rate setting. Bear in mind that the RX channel of a UART has to sample the data at some multiple of the baud rate, and "classically" this has been 16x. So you need to get 1843200Hz, with an accuracy of a few % of better. The divider is 8.68 which is a 3.5% error which is probably OK, but the 32F4 silicon is not doing that; they get a much smaller error. One can use a smaller sampling rate and it can work down to 4x, just about.Herehttps://www.eevblog.com/forum/microcontrollers/32f417-any-way-to-get-baud-rates-below-1200/msg3561821/#msg3561821Anyway, this is digressing. The writeup is very good and shows that getting stuff working is much simpler than the "HAL" Cube IDE approach makes one believe. In the last year or so of working on this project I have done all new code directly. OTOH, there is alotof RM reading, forum posting, and forum googling behind that... the learning curves are steep these days.

author: wek
author_rank: Frequent Contributor
timestamp: September 27, 2022, 07:44:29 am
content: Quote from: westfw on September 27, 2022, 01:32:44 amBut why here? Nobody hears you here.And why do you use those "libraries", then?Over at the STM32 forum, Clive (Tesla DeLorean these days) complained multiple times back then, and IIRC some progress was made. I don't follow.But at the end of the day, this is quite relevant to this thread, too: the horrible process, as you've said, is horrible because it tries to cater for the clicking background, i.e. for both variants of oversampling and for the fact that users don't want to be bothered with the nasty details of setting up clocks (yes, APB prescaler, but in many newer STM32 models also a dedicated UART clock mux). Magic comes at a cost.Quote from: peter-hNo, it's not, it's a fractional divider, as described in the RM. So, in your example, for 16MHz UART clock and 115200 desired baudrate you set it to 8+10/16 (you should correctly round it to 8 + 11/16 but let's not split hair that tightly here), that gives you 115942.0 Baud which is +0.6% deviation.The transmitter doesn't need to be bothered, it simply divides by 8*16+10=138 and then spits out the next bit. Only the receiver sampler needs to be oversample 16x to have several samples close the bit middle for noise rejection. The way how receiver's sampler works is, that the divider divides the input clock by 9 ten times in 16 cases, and divides by 8 six times in 16 cases. This results in exactly 138 timer periods within the 16 sampling points, except that the sampling points are not placed regularly, with the worst case shift from ideal being around one clock period, which in all but the highest baudrates is negligible.JW

author: peter-h
author_rank: Super Contributor
timestamp: September 27, 2022, 08:12:42 am
content: QuoteNobody hears you anywhere. On the ST forum, there is (mainly) you posting good replies, and there is "Piranha" who tells you that you are a complete moron, then he might tell you something useful if he fell off the right side of the bed that morning, then he finishes off by telling you that you are a completely illiterate moron and an idiot. Tesla has not been seen much lately; I think he is getting tired.This is the reality of developing with complex chips which the mfg does not support, and 2000 page RMs which nobody can read - well the people who can read them are those who already know most of it.I've gone a long way up the 32F417 learning curve and this will last me for the rest of my life (actuarily speaking another 20 years). I am completely sick of it and will never do this again. Last few weeks sunk into fixing a subtle data loss issue on USB. I will re-use my board for every new product - which makes sense anyway. It's got everything I might want on it, and SPI for any expansion.QuoteRight

author: westfw
author_rank: Super Contributor
timestamp: September 27, 2022, 09:22:45 am
content: QuoteAnd the way the math works out, and the way the bits are arranged in the register, once you put together the integer part and the fractional part, you get exactly the same results as the simple division gives you.I didn't believe it myself when I first saw it - I figured I must have missed something that STPLIB went to all that trouble to calculate, so I wrote some PC-side C code to exhaustively test essentially all the values, using the ST code vs the simple division. Identical. Sigh.QuoteI don't. Actually, since that initial $1 ARM thread, I pretty much haven't used STM32s at all.I've been preferring the Atmel/Microchip parts, mainly because of their popularity in the Arduino world. (although they put the fractional part of the Baudrate divisor in the wrong place, so the math doesn't work out as well.)

author: wek
author_rank: Frequent Contributor
timestamp: September 27, 2022, 09:45:03 am
content: Quote from: peter-h on September 27, 2022, 08:12:42 amIf you're talking about answering questions, then maybe. Many of your questions are very specific ('F42x+RTOS+FreeRTOS in particular+lwip+one particular setting of lwip) and there's just so many people on the planet which possibly have the knowledge, not to mention time and willing, to answer you. The vast majority of questions on that forum is completely out of my range of knowledge, some are honestly too annoying to me to even read them ("I clicked USB in CubeMX and it ain't work").But when it comes to suggestions to improve "libraries" and documentation, the ST crew listens. There, not here. Not in all respects, and some topics are simply no go, but generally they do. here's some "proof":http://www.efton.sk/STM32/STM32F4xx_doc_errors.txtI used to maintain and brag about on that forum; most of that is already incorporated in RM0090QuoteAnd what's the chance of knowing most of it without having it read first?I understand, that printed word with static pictures is not the perfect method to convey information, and I am also aware of the fact that different people perceive different sorts of information better. But I still believe that that's still the best method we currently have, from both the provider and the consumer point of view.For example, the clock setup which was carried over from microXplorer to CubeMX is a widely praised feature; yet I personally find it way more cumbersome to use than to read the few dozens pages of RCC chapter (disclaimer, never actually tried CubeMX). Admittedly, I never used the 'H7 where the RCC complexity shot the roof to the sky, but I'd probably try to read first. Maybe this has something to do with the fact that the STM32 manuals are written mostly by non-english speakers as myself. Maybe this has something to do with the fact that I read unusually lot from early age and I enjoy it much. Maybe it's my aversion to primarily clicky software which deliberately and joyfully breaks the usual control rules. Maybe I'm just simply old. Maybe something else, I don't know.Again, this has much to do with the IDEs vs. barebones discussion, too.JW

author: wek
author_rank: Frequent Contributor
timestamp: September 27, 2022, 09:46:50 am
content: Quote from: westfw on September 27, 2022, 09:22:45 amSo, no perfection at the HW front, either... ;-)In ST's case, it won't work with OVER8 set. The hardware could've been done better, too. That was actually the reason for that weird and ultimately broken calculation.JW

author: peter-h
author_rank: Super Contributor
timestamp: September 27, 2022, 01:08:27 pm
content: There isn't much wrong with the RM. You have to publish the info somehow and that is the best way.Videos are the most annoying way to do anything - especially if the speaker speaks unintelligible English which is the case with the ST ones I watched.Something needs to be done with the steep learning curve though and I think ST did the right thing with the MX forinitialhardware setup. There are just too many ways to screw up and one could spend weeks full-time getting one of these chips to run properly. And one will never know if it is marginal - look at e.g. some wait loops around the PLL setup. It isafterthat, where it becomes debatable whether to go bare-metal. But even then MX is handy to get some code to examine.As I posted in the other "support" thread, ST, a $14BN company, should have forum presence. Not for "obviously stupid" threads, but for the ones where the poster has taken care to frame the question properly.I am probably older than you, and being ex CZ (left in 1969) I also read from an early ageQuoteLotshave the knowledge (how many LWIP installations are there?) but they acquired it in employer time so aren't posting itFor example the "Monday-pm guy" who started the project I am working on has a great and inexplicable reluctance to post on a forum, even though he is not prohibited from doing so, and would gain from it (like I have, considerably).More evidently, people aren't interested in helping somebody with "old stuff" like LWIP which is ~15 years old. Those who integrated it have long moved on. This is really clear from places like the LWIP mailing list, which has been dead for ~10 years.I've been doing micro hardware and software since ~1980 but without the internet, I would never have got 32F4 hardware working, from just the RM.

author: bson
author_rank: Unknown
timestamp: September 27, 2022, 07:49:07 pm
content: Quote from: tellurium on September 26, 2022, 03:23:46 pmYour startup _reset() function doesn't call the constructor list. This may seem unnecessary outside of C++, but you still need to do it for C since that's how static initializers get invoked.Also, gcc has memcpy(), memmove(), memcmp() and memset() as builtins.

author: tellurium
author_rank: Frequent Contributor
timestamp: September 27, 2022, 09:00:26 pm
content: Quote from: bson on September 27, 2022, 07:49:07 pmThank you!I understand about static C++ initialisers - and you're correct, _reset() does not invoke constructors.Can you elaborate a bit more on the "still need to do it in C" - do you mean, to cover the case when a firmware uses C++ code?

author: JPortici
author_rank: Super Contributor
timestamp: September 28, 2022, 06:05:16 am
content: Quote from: peter-h on September 27, 2022, 01:08:27 pmThat's because some KEY informations are missing in the STM reference manual and datasheets (unless i'm wrong that they have been added in the last couple of years)key information such as a minimal connection diagramlooking at the schematic for a devboard is not really an excuse, it's an image and some description of key connection and required values, fits in a page

author: peter-h
author_rank: Super Contributor
timestamp: September 28, 2022, 07:42:22 am
content: QuoteNot long ago I tried to find out what that function does (for C, not C++) and nobody knew. I don't think it does anything for C. I am not calling itCode:/* Call static constructors *//* bl _libc_init_array */Zeroed variables are cleared when BSS is zeroed. Nonzero variables are initialised by code in startup... .s (can be done in C as shown).QuoteIt is what everybody does though and is what I didIt saves amassiveamount of time.This discussion has been moved to a new thread started bywekhttps://www.eevblog.com/forum/microcontrollers/lets-discuss-telluriums-tutorial/

author: wek
author_rank: Frequent Contributor
timestamp: September 28, 2022, 08:12:58 am
content: Quote from: JPortici on September 28, 2022, 06:05:16 amAN4488?JW

author: peter-h
author_rank: Super Contributor
timestamp: September 28, 2022, 08:41:07 am
content: That's a new oneBut this is yet anotherdescriptiveappnote. It doesn't tell you the steps needed and their order.It also has some fairly typical dodgy stuff - 2nd grade engineers throwing in caps and inductors around for good measure - on page 34: L1 and R11?? I actually use a 10R from the 3.3V rail, then a 22uF + 100nF to VREF+ , to form a proper filter with a low Zout to feed Vref. There is a fair bit of muck on the 3.3V rail and that miniscule inductor will do minus nothing

author: paulca
author_rank: Super Contributor
timestamp: September 28, 2022, 08:59:27 am
content: I found it fairly coincidental that I received my first STM32 (F4) dev board yesterday and the first problem is my test setup was caused by:snprintf( buf, 64, "%.2f", temp_c );I got an error because the floating point conversion code was not included in the stdio library. Luckily it even gave me the linker flag.Now I knew the precision of that number and I could fix point it, but I decided to and see how much hassle it would be to change. Turns out none really. The documentation is out of date as the run dialogs have changed recently, but it wasn't that hard to locate where they'd oved the Settings tab to.

author: wek
author_rank: Frequent Contributor
timestamp: September 28, 2022, 09:09:37 am
content: Quote from: peter-h on September 28, 2022, 08:41:07 amOK so we're back at square one - there's no one size which would fit all.Now the question is, what's the IDE of HW design?JW

author: peter-h
author_rank: Super Contributor
timestamp: September 28, 2022, 10:52:20 am
content: One tends to start with the circuit of the dev board.Strip off stuff not needed (the accelerometer, etc) and add stuff neededto the dev board(birdsnest it) and get it all running.Then design the PCB, reading the data sheet page by page (all 300 pages). It is very likely to work 100%, which won't be the case if you just thumb through the data sheet.That appnote is good but really a condensate (and an amplification at times) of the data sheet.

author: JPortici
author_rank: Super Contributor
timestamp: September 28, 2022, 11:27:38 am
content: Quote from: wek on September 28, 2022, 08:12:58 amNice! i didn't know about this one. Is it referenced anywhere in the device datasheet/reference manual? I had a quick look at some STM32F4 product pages. In some there is, in some there isn't

author: peter-h
author_rank: Super Contributor
timestamp: September 28, 2022, 02:35:13 pm
content: Really?This is not actually funny because I read somewhere else that 100nF is too much for the debugger to discharge. So I am using 10nF. There needs to be "something" to prevent spikes getting coupled capacitively into the NRST PCB track, although to be honest if that is happening, it's game over anyway.I am reading through this AN to see if it has something relevant to my board.

author: paulca
author_rank: Super Contributor
timestamp: September 28, 2022, 05:08:34 pm
content: Quote from: peter-h on September 28, 2022, 02:35:13 pmMan, that energy you dump out of the cap with a discharge resistor could probably power the thing in standby for week!When you get people that anal about low power and let them influence the tech writers, it's going to appear.

author: peter-h
author_rank: Super Contributor
timestamp: September 28, 2022, 05:24:06 pm
content: I doubt it, when a0.22 FARADsupercap runs the 32F417 RTC for just a few days (actual data)

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 28, 2022, 05:38:14 pm
content: Ahah, man. Exaggerations.ST makes ultra-low power MCUs (in the STM32Lx lines), so they are definitely sensitive to power consumption and that's a good thing.Now when you use a STM32F4, you rarely are after ultra low power consumption, so obviously this note has less place in this datasheet. I suspect this is the same note in many others of their datasheets, that's all. I do not remember what's the typical power consumption of a F417 in one of its stop modes though. Might be in the µA range so depending on your applications, a few µA could matter.Now what boggles me a bit is that action on the NRST pin should be pretty rare under normal operation, so even for an ultra-low power design, I don't really see how charging and discharging through the NRST pin could affect the average power consumption in any measurable way. (And OTOH when you're using a debugger, you rarely care about power consumption.) So, yeah.As to this cap on NRST, I personally use at least 100nF for reasonable robustness against spurious resets that could be due to external noise (EMI.) Never had any problem pulling it down with a SWD adapter. Entirely depends on the adapter you use of course.

author: uliano
author_rank: Regular Contributor
timestamp: September 29, 2022, 10:28:46 am
content: Quote from: tellurium on September 26, 2022, 03:23:46 pmThat is really wonderful! Thank you so much!I'm really looking forward to try your tutorial. (It will happen very soon as, for some twist of fate, I actually have one Nucleo-F429ZI at home, I just need some free time).I understand that you are suggesting to flash the Nucleo embedded ST-Link debugger with Ozone firmware and that's a great possibility.If I may I'd suggest one more tutorial section explaining how to use the ST-Link debugger as this would be useful for other (non Nucleo or non ST) boards, possibly the very cheap one that can easily be found on amazon or chinese markets.

author: paulca
author_rank: Super Contributor
timestamp: September 29, 2022, 10:52:58 am
content: Quote from: SiliconWizard on September 28, 2022, 05:38:14 pmIs the NRST pin not used to wake the device via the RTC? IIRC ESP and arduino land, deep sleep calls halt on the CPUs, powers the board down, leaving the RTC's alarm pin connected to the RESET pin.In a low power device you would send it to deep sleep for a minute or more, then wake, do something and straight back to sleep. If your wake time is only a few milliseconds it's still more efficient to sleep and wake 100 times a second. Thought that's maybe exagerating a bit.

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 29, 2022, 05:19:51 pm
content: Quote from: paulca on September 29, 2022, 10:52:58 amNo, not at all. Wake-up sources on STM32 MCUs are entirely internal.

author: newbrain
author_rank: Super Contributor
timestamp: September 30, 2022, 07:53:44 am
content: Quote from: SiliconWizard on September 29, 2022, 05:19:51 pmNot really "entirely internal"?Depending on the sleep mode, various external WAKE UP events are available, ranging from EXTI interrupts, UART/I2C address match etc.The deepest sleep mode still allows for the use of a dedicated WKUP pin (available even in 20 pins package for e.g. STM32F042).