I'm making yet another attempt to port a complex project to the MCUX SDK and once again I'm baffled by the (lack of) documentation. Am I missing something? Is the documentation still being worked on? It's completely inadequate in many areas.
I'm using the MK22FN1M0AVLH12 specifically, with SDK version 2.3.1. To give an example of what I'm talking about, let's consider the simplest of the drivers: GPIO. I just want to set and clear some pins.
The GPIO section in the API reference manual (MK22F51212 Rev. 0) has a blank overview section - no description at all. Ok, I know what GPIO is and I've got a good idea of what should be here, that's not a big deal.
There's an FGPIO driver section that says a few MCUs support it. It doesn't say which ones. Seems like if we're going to have different API reference documents generated for every MCU, optional features like this ought to be excluded if they're not present. If all of the documents are the same, why the elaborate SDK builder system?
Moving on to the GPIO driver. This section at least has a one-line description that defines what GPIO stands for. That's a start. No use case or examples, though - it just says to check out the driver examples. If there are multiple boards, this means we've got to dig around and see which ones actually have useful examples. In this case I've got only one board to check, and the GPIO example demonstrates exactly two of the functions - GPIO_PinInit and GPIO_PortToggle.
There's a list of output operations and GPIO_PinWrite includes the brilliant description "Sets the output level of the multiple GPIO pins to the logic 1 or 0." Pretty clear that it works on multiple pins. The description says parameter "pin" is "GPIO pin number", though - number, not mask. There's no further description of the function, so now we've got contradictory hints and no certainty as to what it's expecting. And recall that there is no example given anywhere for GPIO_PinWrite, so we can't even deduce it from that.
How do we resolve this ambiguity? We've got to read the source for GPIO_PinWrite(), where we can see that it's setting PCOR or PSOR and shifting 1 by the pin number - and if you're not already familiar with the hardware registers, you've got to look them up in the reference manual to see that that means.
So it's not a multiple pin write - it does take a single pin number. The one-sentence explanation given for this function is wrong. The API has failed to save the developer one iota of development time, and in fact this discovery process has more steps than just starting with the reference manual and writing one's own code.
Then there's the GPIO_PortSet() function. I've got to jump back to the overview to get a description, which is "Sets the output level of the multiple GPIO pins to the logic 1". The second parameter is named 'mask' and it's defined as "GPIO pin number macro". Ok, where is the pin number macro defined? There's nothing about macros anywhere in this section. But checking the source code reveals that it's not a macro of any sort, it's a mask, and it just sets base->PSOR.
What if I want to read all of the pins for a port at once? There's not an API function for that. Is the expectation that we'll access GPIOn->PDIR directly? Why does PSOR get an API wrapper but PDOR doesn't? Should I be able to use the API and the API documentation alone to interact with the hardware? If not, what's the expected starting point for a developer reading up on how to access registers directly in a way that conforms to the SDK's conventions? Like where would I find the base pointer names for this part?
The language used is also often ambiguous or not quite parsable as English. Take "0: corresponding pin output low-logic level." I challenge you to diagram that sentence/fragment. Is 'pin output' the subject? Is 'output' a verb? Why is "low-logic" hyphenated?
What about metadata for this documentation? How do I tell what version of the SDK it applies to? When was it last revised? For that matter, where are any dates other than the 2016 copyright? It conveniently does provide a link for "the latest version of this and other MCUXpresso SDK documents" (https://mcuxpresso.nxp.com/apidoc/) - and the link is dead.
This isn't documentation - this is what you get when you tell a first-year computer science student they have to document their code for an assignment and they install Doxygen and hand in whatever it automatically generated. For the GPIO section at least, I'd consider that a 'C' grade at best if the information was accurate. Given the errors in the mask and pin number definitions, it's a solid 'F' to me - worse than no documentation.
Yes, a competent programmer can figure all of this out with the combination of the SDK docs, the MCU reference manual, and the SDK source code. It doesn't really save any time, though.
NXP as an organization is not incapable of writing good docs - the sensor fusion user's guide is really quite good. Good luck finding it, though. As far as I can tell the current revision is 2.2 but I can't come up with any Google search or search terms on NXP's site that will actually take you to that document. You have to know to build a custom SDK package for one of the two boards that supports ISSDK, and add the ISSDK option. That's assuming you already knew Sensor Fusion is now part of ISSDK.
That's why I'm asking here. Is there some newer version of the SDK API reference manual that I'm not finding? Or is this really as good as it gets?
For what it's worth: I've used SiLabs and TI ARM devices, I've looked at Atmel (now Microchip) ARMs, and the documentation provided by those vendors is far superior to the garbage NXP publishes. I'm looking at using the LPC5528 in a new design, as the hardware features really fit the bill -- and I like the whole idea of FLEXCOMMs vs different U(S)ARTs and I2C and the like -- but holy molybdenum the SDK and the examples and the documentation are disasters.
Why don't the examples use the Configurator tool? I import a USB example and then open the Pin Tool or the Clock Tool to see what's going on, and those tools know nothing of what's hardcoded by the examples. So then I'm faced with trying to figure out whether using the Configurator to add other stuff (UARTs, SPI, whatever) will break the USB stuff.
Pick any example. Open the Configurator and look at the Clocks or the Peripherals tab. Under "Clock Outputs," all of the peripherals show their clocks as "inactive." Under "Peripherals," none of the peripherals used in the design are enabled and there's a warning that the peripheral is not initialized.
So why don't the examples have a .mex file included?
Back to USB: the official advice for implementing a Vendor-Defined USB device class, or even one of the standard Classes NXP hasn't implemented, is basically, "copy an example that's close to what you want, modify all of these inscrutable files full of unexplained macros, and make sure you add all of these files to your project even if you don't need them ..." and oh by the way what the heck is an LPCIP3511 anyway?
The whole wizard idea for creating examples falls flat when the engineer's designs deviate from the canned stuff.
Greetings from 2021 and SDK 2.9. Somebody has heard you and corrected the description of GPIO_PinWrite() to reflect that it applies to a single pin. However, the lack of clarity regarding "GPIO pin number macro" is still there. Therefore I wholeheartedly concur with you.
Recently, I needed to employ SCTimer.
First, I consulted the SDK API for my cpu.
I was overwhelmed by the many SCTimer functions available and the little explanation that came with them. For example SCTIMER_SetupOutputSetAction() is described with "This output will be set when the event number that is passed in by the user is triggered." and the obvious parameter related to output has type uint32_t. There's no further explanation how the output is encoded. There's, however, an sctimer_out_t enum which is used by other functions - but not by this function's signature. So maybe the output is encoded differently. We don't know by reading the SDK documentation only. We have to read the source of this function to solve that riddle.
Then, I also imported SDK examples, e.g., on multi state pwm.
This example uses SCTIMER_SetupNextStateActionwithLdMethod(). The function has the following description: " Change the load method of transition, it will be triggered by the event number that is passed in by the user.". The function includes the parameter fgLoad which is explained as "true: Load the STATEV value to STATE when the event occurs to be the next state.". Neither the example code nor the documentation explains why that is important and how STATEV is set. Once again one has to read the source and the cpu manual to understand what STATEV is used for and that STATEV is set by this very function using the parameter nextState. I'm puzzled why the SDK documentation is terse when the topic is quite complex.
So instead of learning SCTimer API I resorted to an older application note called "SCTimer/PWM Cookbook - AN11538". There, the use of SCTimer is not explained using the SDK API but accessing hardware registers directly. That's fine and in combination with the cpu manual worked for me.
Still I think that the SDK doxygen based documentation can be a very powerful tool. It just needs more detailed explanations and a more consistent use and description of enum types.
Thank you very much for your sincere feedback, I reported this to the SDK doc team.
Your comments are very important for us to improve the document quality.
Thanks for the reply. Can you tell me if I'm looking in the right place for the latest documentation? Will the generated docs downloaded with an SDK package always be the latest?
Both the PDF and the HTML version have links to the 'latest version' that don't work right:
That link is dead. The HTML version links to that URL with https and it works, but it says "Kinetis SDK 2.0 API Reference Manual". Which in turn links you back to the MCUXpresso SDK builder login.
When I'm viewing a document like https://mcuxpresso.nxp.com/api_doc/dev/466/, how do I tell what devices it's for, or when it was revised, or what SDK version it applies to?
The PDF version says Mar 2018, which is a start. Still no mention of applicable devices. It has document number MCUXSDKK21FAPIRM.
Is there a secret decoder ring for the part numbers? Why does the MK22FN1M0AVLH12 fall under 'K21F'? Other places you'll see, for example, MK22F51212 (like mk22f51212_usb.h) and MK22FA12 as shorthand for the family. The SDK for the MK22FN1M0AVLH12 contains under 'devices' both MK21FA12 and MK22FA12. I'm assuming that's because the SDK uses the TWRK21F120M board for its examples, however there's also a TWRK22F120M board that you would think would be the one for the MK22FN1M0 parts but it's not.
I would suggest you download the SDK documentation archive, docs in the archive are targeted to the specific MCU , and are the latest.
For the online document issue, I will report it to the doc team. Thanks for your feedback.
One internal doc said that for K22FN1M0A parts, the silicon revision is 1N41K, same as K21fn1m0a, the evaluation board is TWR-K21F120MA board.
For K22fn128 parts, the silicon revision is 0N74k, the evaluation board is FRDM-K22F and TWR-K22F120M.
For K22 parts, there are a comprehensive set of software and develop tools offering optimized performance and power efficiency with low dynamic power consumption.
Please also read the engineering bulletin for K22F 120 Mhz mask sets and revision numbers. I hope it helps.
I'll just keep adding notes here in case anyone cares. I'm still working on migrating bits of old code that used the PEx drivers (long since converted to static code) and the ADC driver provides another good example of what's wrong with the SDK.
The clock source setting takes an enum of type adc16_clock_source_t. The possible sources are kADC16_ClockSourceAlt0 through Alt3. No useful descriptions are given. I understand that the reason for that is that they're chip-specific, but it'd be nice to say as much and give a pointer to the right place to find them. Or if you're going to force the user to build and download chip-specific SDKs you could, you know, add some chip-specific information to them.
If you switch back to the MCU reference manual, all it says about clocks in the chip-specific section on the ADC is "For this device, the alternate clock is connected to OSCERCLK." That doesn't tell us which one of Alt0-Alt3 is the 'alternate clock'. The 'Alt' naming kind of suggests they're all alternatives.
The correct answer is that the setting is going directly into ADCx_CFG1:ADICLK. There's no mention of that parameter in the SDK docs; if there was, it'd be a lot easier to jump to the right place in the reference manual. It'd still be a bit inconvenient to have to skip back and forth, but at least that way you wouldn't have to read through the driver code.
Once again, there's no way to write this code based only on the docs and examples without having to work forward and backward from the docs and the driver code. It really eats up any gains from having ostensibly tested and proven initialization code when you have to reverse engineer it to figure out how to use it.