-
Notifications
You must be signed in to change notification settings - Fork 23
Implement basic platform support for NXP Kinetis KE02 MCUs (Cortex M0+) #230
Comments
Working branch for this issue : https://github.com/forGGe/theCore/tree/g230_kinetis_ke02_exp_support |
Hi there, I'm interested to work on this issue. So what is the current state of KE02 support ? |
Hi @iia , Currently we have the g230_kinetis_ke02_exp_support branch that pretty outdated and should be refreshed. If you would like to contribute to this issue, I can guide you with steps required to bring KE02 alive and assist in development. If you want me to implement KE02 support, I can rearrange priorities and complete the task. Let me know what you think. |
Hi @forGGe , I'm interested in contributing to this issue. So it would be great if you can provide with some assistance. To be more precise an overview of the project, the main parts and how they relate and connect among themselves. And of course what is involved to add support for new platforms. |
Hi @iia, I really appreciate your interest in contributing! Below is an overview you requested. OverviewtheCore tries to provide a framework that consistent enough to make portable applications for different kinds of microcontrollers. "Portable" means that you just write your application code once and then compile it for every compatible device. For example, an application code for reading humidity sensor and writing samples to the MicroSD card will be the same, no matter where you attached MicroSD card and humidity sensor - to STM32F4 or to TI TM4C microcontroller. In a some way, theCore looks like HAL-on-steroids. (Besides just providing consistent APIs, theCore aims to be a full-featured framework, see Roadmap for more information) Project main partsTo achieve that goal theCore provides different kinds of modules:
Project configurationBesides just providing classes to access different devices or MCU peripheries, often it is required to additionally specify how those modules interacts with each other (say, you have attached LCD to MCU) or you need to configure specific module parameters (baud rate of UART console). theCore gives you an option to specify that details in a JSON configuration file, rather than write C/C++ code that initializes each module in question in a required way (writing C/C++ code can be tedious and error-prone). Part of theCore, responsible for such configuration is basically called the configurator. Good example is TI TM4C configuration for LED demo. Path to that configuration file then passed to theCore in main project file Essentially, theCore configurator is just a code-generation tool, which takes a JSON file and produces corresponding C/C++ definitions that you can use inside your application code See the filesystem module example that shows how incoming JSON converted into the C/C++ code. Configurator is written using Python Cog utility. The aforementioned file system, Cog-based configurator can be found here. Configuration based on JSON is somewhat described in the respective documentation page. Generated code is available if to include BuildsystemNot much to say here, CMake is used everywhere. Where it cannot handle things like code generation, Python is used. Module interaction
All other modules sit aside and wait until they will be used by the configurator tool. You will get more insights about specific modules while hacking KE02 platform. |
I will take an action of refreshing the Let me know what you think about it. |
Hi @forGGe , Thanks for the detailed overview. I'm ordering a KE02 dev board. Let me know after you have refreshed the branch. |
Just for reference: See also: https://www.eevblog.com/forum/microcontrollers/freescale-opensda-linux/ Right now, I'm debugging my fresh, new KE02 dev board by just uploading binaries via the virtual mass-storage that appears after I connect the board. So, I will try to upload correct J-Link compatible MCU firmware, found at these pages: And I hope my board will stay functional :) |
Hi @forGGe, From where you ordered your board? |
Aliexpress, but I can't find it there anymore. I'll try to check other suppliers. |
@iia, branch Here is instructions of how to run simple demo on your KE02 dev board:
|
Also, check https://octopart.com/frdm-ke02z-nxp+semiconductors-70303061?r=sp&s=oR9dcxYPTvqj5TI7Sgx1Ug for list of available suppliers |
Thanks for all the info. I got the board today and everything worked and I could execute ke02_hello.bin. Since now I have a working setup I can take a better look on the whole system. |
Hi @iia,
Great!
Yes, I also uploaded it to https://github.com/forGGe/kexx_driverlib By default, thirdparty git tree is located You can control where to download the KEXX driver library. See https://forgge.github.io/theCore/guides/thirdparty-cache.html . (I see that text there is broken, will fix ASAP) High level architectureNow, let me give you some ideas about the platform you going to implement. I recommend you to start with the UART driver and all the infrastructure required to configure it. Here is the case: theCore platform must take the JSON file, defined in the application: and then convert it to, say,
Pay attention: the The (_Sidenote: if you feel that naming is not consistent, I feel it, too. You can rename all The See examples below. Example implementation: TM4C platformThe UART driver ( The template file for the UART configuration ( The template file for the IRQ handlers (one of which is UART) is also present in Note: IRQ dispatching for TM4C happens in compile time. I.e. based on configuration given, we can be sure where to deliver an interrupt. I encourage you to use the compile-time dispatching for the KE02 as well. If you want the runtime dispatching - let me know, I will guide you how to use old, runtime IRQ manager in theCore The template file for the pin configuration is also placed there. All TM4C template files are then handled in Check that entire file to get more insights. Bypass UART driverThere is a little trickery for the UART driver used as a console output. The UART driver must be able to perform a low-latency output right in the platform periphery. Such shortcut is made in case we need to print something from IRQ context on in case of failed assertion. It is called "bypass console" in terms of theCore. You can check the TM4C platform files to see how it works: |
Yet, I didn't say to you where to put the UART baud rate, stop bits, etc. Let's stick with 115200/8/1 default configuration and after the UART driver will be ready, I will guide you how to handle that configuration. |
Thanks again for the detailed explanation. Before I start with the UART driver I would like to explain my mental model of the overall system to verify if my concepts are correct. I will try to represent my mental model of the system with a little ASCII art. ............................ Is this correct? BTW what does "ecl" stand for? |
@iia , Your mental model is correct enough. To be more precise, let me add there one item:
I though it is important to place external device block there, since without that part, user application can't do much (except blinking LED) If you find that extended model confusing, please let me know. I will try to explain it in more detail. Also, I'm using here (and across theCore) following convention for naming entities:
JSON file laying in the root of example project is a specification of a target. That is, it specifies what MCU is placed on the board (and how it should be configured) and what hardware is connected to the MCU (and how it should be configured). |
ECL stands for "Embedded Core Library" It is not so meaningful, but it has three required properties:
But I'm open for suggestions in that field :) |
Hi, Platform and target clarification was useful. Thanks. |
Hi @forGGe, Can you explain the bus architecture in device module? What I understand so far about it is that it is to provide an uniform interface to theCore applications to use peripherals that operate on a bus architecture e.g, SPI, I2C etc. It also seems that the platform serial driver must register to the bus so that UART becomes transparent to theCore applications. Is my understanding correct? Can you provide a bit more detail of the bus mechanism e.g, how platform drivers register to the bus mechanism and how the bus mechanism is used? |
Hi @forGGe, Can you explain a bit more about compile time interrupt dispatching as you mentioned about TM4C platform ? |
Hi @iia,
Let me reach my PC, I will answer your questions.
Regards,
Max
…On Sun, Apr 15, 2018, 3:05 PM Ishraq Ibne Ashraf ***@***.***> wrote:
Hi @forGGe <https://github.com/forGGe>,
Can you explain a bit more about compile time interrupt dispatching as you
mentioned about TM4C platform ?
|
You are totally correct. In current state of things, all platform drivers that are capable of doing data transfers are compatible with Not only the bus module presents platform drivers in a common way, it is also extracts common functionality (to avoid duplication in every platform driver, obviously). Most notable is the thread-safety support.
Act of registering to the bus system is a simple composition between Abstract exampleSuppose we have platform UART driver, like that: enum class uart_channel
{
ch0,
ch1,
// ...
};
template<uart_channel Ch>
class uart
{
// UART implementation ...
};
and template<typename PlatformBus>
class generic_bus
{
// Generic bus implementation ...
};
Then theCore can combine (based on configuration JSON) them in following way: using uart1_driver = uart<uart_channel::ch1>;
using uart1_bus = generic_bus<uart1_driver>; Now, the Note that there are no run-time registering of the UART driver. theCore is aware which platform driver is used for which purpose, so it can directly aggregate common interface class and specific platform driver using C++ templates. Real-world TM4C implementation exampleHere is the TM4C UART class: Here is the TM4C UART generator (cog template in fact) (pay attention for #365 bug): Here is the example JSON (related to the UART only) provided by user: {
"platform": {
"name": "tm4c",
"console": "UART0",
"uart": [
{
"id": "UART0",
"alias": "test_uart",
"comment": "UART-over-USB console output"
},
{
"id": "UART1",
"alias": "another_uart",
"comment": "Example UART"
}
]
}
} Here is what TM4C UART generator will generate in response to user JSON: namespace ecl
{
// UART configuration ---------------------------------------------------------
/* UART-over-USB console output */
static constexpr uart_channel UART0_channel = uart_channel::ch0;
using UART0_driver = uart<UART0_channel>;
using platform_console = UART0_driver;
using test_uart = UART0_driver;
/* Example UART */
static constexpr uart_channel UART1_channel = uart_channel::ch1;
using UART1_driver = uart<UART1_channel>;
using another_uart = UART1_driver;
} // namespace ecl And there is how theCore uses Check also UART documentation for TM4C (again,pay attention for #365 bug): https://forgge.github.io/theCore/platform/ti-tivac-tm4c123g.html#uart Few more thoughtsThere is a less heavy abstraction that better suites for UART-based communications (and overall it is better for communication drivers that are not buses and shouldn't be shared in different modules) - https://github.com/forGGe/theCore/blob/develop/dev/bus/export/dev/serial.hpp#L25 So I want to rebase console driver from
use:
But that's not related to your particular activity in KE02 platform implementation, it is just thoughts I"m sharing with you Hope this shed some light on driver compositions in theCore. |
Considering our discussion above about driver composition and a purpose of the user config (in JSON form), we can state that theCore is fully aware about all drivers used in the application. Or, in other words, user must list all drivers that he want to use in that JSON. It means that theCore knows where to deliver a specific platform interrupt. It also means that the platform driver don't need to register for interrupts in runtime. theCore can generate IRQ handler for the specific interrupt that will call corresponding platform driver routine. Here is how it looks in TM4C. IRQ table: IRQ handler generator: That if UART0 is listed in JSON will generate code similar to this: /* 21 UART0 */
extern "C"
void UART0_Handler()
{
ecl::uart_irq_proxy<ecl::uart_channel::ch0>::deliver_irq();
}
/* 22 UART1 */
extern "C"
void UART1_Handler()
{
ecl::abort();
} Ideally is to have similar thing made for KE02 platform. Let me know your feedback about it! |
Hi @forGGe, Thanks again for the excellent explanations. I added the UART driver for KE02 which registers to the bus system and used by iostream but can't test it as the compilation fails with the following linking error,
As far as I can guess it seems like something about the std::chrono library. Here is the patch. |
Hi @iia, Sorry for a late response. Thanks for submitting a patch and for your feedback! I suggest you to open pull-request with [WIP] pefix in its name, so we can comment there and put backlinks in this issue. About You can find some info here: https://stackoverflow.com/questions/5745880/simulating-ldrex-strex-load-store-exclusive-in-cortex-m0 So you need to implement that As far as I can google it, it should have following signature (see https://developer.arm.com/docs/100073/0609/the-arm-c-and-c-libraries/iso-c-library-implementation-definition/standard-c-library-implementation-definition):
It is a specific version of the regular As for
For that, I guess you need to check datasheet and examples of PLL configuration. I propose to stick with internal oscillator for now. Also, support for external oscillator should be added in some point in time (and clock speed for that external oscillator must be provided via user's JSON), but you can postpone it for now. |
Or you can do a shortcut - if you know for sure clock configuration from a very start of the MCU, you can just set |
Hi, In this case the system clock is meant to be the RTC of the MCU which is required for measuring time duration. Right? |
Hi @iia , Sorry, was busy with my work, thus answered so late. I'm actually talking about main processor clock. If you check Figure 5-1 of the KE02 Reference Manual, you will see this picture: The Core Clock can be supplied by the ICS (Internal Clock Source) module. The ICS description is located in the same datasheet, page 263. It has different modes of operation, one of which is FEI: FLL engaged internal, is what we are looking for. According to the reference manual:
So idea is to remove current ICS code from This frequency then must be assigned to the Now, you are probably think how you going to test your assumptions about clock speed? There is a function: that you can use to measure delays. If your clock value is correct, then this function must do a delay with a right amount of milliseconds. Note that Let me know your thoughts about it. |
Hi @forGGe, Thanks for the info on clock. But I couldn't manage to resolve the atomic exchange issue. I tried implementing the routing __atomic_exchange_1 with provided signature but with no luck. Ideas ? |
Hi @iia, It is quite strange. Let me apply your patch and try implementing it, so I can play around with it. I'll be back to you with results. Regards, |
Hi again, @iia , I'm sorry for late follow-up again, I'm busy these days due to my work schedule. So, I was able to resolve link error, by using following signature: extern "C"
uint8_t __atomic_exchange_1(volatile void *dest, uint8_t val, int model)
{
// ...
} placed in I suppose, implementation should be something like this (pseudocode!): extern "C"
uint8_t __atomic_exchange_1(volatile void *dest, uint8_t val, int model)
{
(void)model;
disable_irq();
uint8_t *u8_dest = (uint8_t*)dest;
uint8_t old_val = *u8_dest;
*u8_dest = val;
enable_irq();
return old_val;
} Note that I didn't test that implementation. Hope to hear your results! |
Hi @forGGe, No worries about late replies. I couldn't try the solution yet but will later today. I can already see the signature of the function is different from what I tried with according to the ARM documentation page. How did you figure out this working function signature? Cheers. |
Hi @iia, Actually when I put into extern "C" uint8_t __atomic_exchange_1(uint8_t*, uint8_t, int) { /* ... */ } I got:
So I just used that error as a guidance :) Regards, |
Hi @forGGe, Just if I read the error messages a bit further! Thanks BTW. |
@iia , looks awesome! Thanks! Do you want me to conduct a full code-review or just some particular part? |
By the way, examples (along with main repo) should be moved under theCore-embedded organizatoin. Relevant task for KE02 example is #379 . For now, one example is almost moved: https://github.com/theCore-embedded/example_cs43l22_audio and similar instructions I expect for KE02 examples as well. Note that there is no hurry in 379, I suggest to merge/complete KE02 first, and then proceed with moving examples. Nevertheless, there is a challenge of automating the binary flashing into the KE02 FRDM board. I.e. ideally, the user should be able to do following:
And he will get the hello-world displayed in the minicom terminal (of course, it assumes that you have desire to mess with python a bit :) let me know what you think about it) |
Hi @forGGe, A full code review would be nice. Eventually moving the examples to "theCore-embedded" seems to be a good idea as it seem to unify the process even more. But I agree for KE02 this can be done eventually. What would be the the next task for the KE02 port in your opinion? Cheers. |
Hi @iia, I think what we left with (in this task) is to:
As for (1) - review is in process, As for further work on KE02, I suggest following roadmap:
|
Let me know if you have suggestions for the roadmap. |
Task is to integrate theCore with KE02 MCUs
Refs:
Must include
The text was updated successfully, but these errors were encountered: