Okay, let's start the next talk.
My name is Marigwasheur, and today is going to be slightly different, kind of hot, hot on a
sec.
Better.
It will be slightly different kind of talk, because I'll be talking about not you
good, but I'm SAP firmware-porting this time, and just out of curiosity how many of you
do know what the SAP firmware is all about, very few people, excellent.
So I have a motivational slide to give you some sort of a context what this is even all
about before I plant into the porting part.
Hey, so contemporary embedded SOCs, they do no longer have only an A-core, which is running
Linux, but they also have M cores.
The M cores are running some sort of an RTOS, and the issue is, all these cores share resources,
clock, pin controller, and traditionally there was no arbitration, or there was some sort
of an arbitration in hardware, which was done using hardware spin logs, this kind of stuff,
but the original idea was that everyone is well behaved, the articles is well behaved, the Linux
is well behaved, and they cooperate not to mess up the system state.
Nowadays with push towards security and isolation and so on, we can no longer depend on
that, so we need some sort of an proper arbitration.
So the policies of which govern whether one of the cores or the other core should be able
to do some action with the system, they are increasingly more complex, so there has to be
some more capable arbitrar.
And this more capable arbitrar is called an SAP on newer SOCs, and it's nothing really
special, it's yet another core, which is usually called the XAM, or Cortex R, it's running
some sort of althinbar, and it exposes interfaces.
Today, a cores, today, M cores, or whatever other CPU cores you have on your system.
The arbitric core, the SAP is responsible for managing those cook, the pin moops, potentially
regulators, whatever it has access to this hardware, and all the other cores, the A cores
running Linux, the M cores running RTO, as they talk to this SAP, Arbitric core, and ask
requests via some sort of a protocol.
The other cores, they technically can manipulate with the hardware as well, but it's usually
blocked by trust zone for security reasons, so they can't mess up the system state.
And they have to go through the, this Arbitric.
So the Arbitric core, SAP exposes some sort of interface to what all the cores, there is
usually some bidirectional communication channel, based on mailbox and shared memory, although
it can be something else, it's traditionally that.
It works in such a way that the A cores of the M cores and commands to the Arbitric, and the
Arbitric response, with some sort of a response, or the Arbitric, which is the SAP, can
send notifications to the A cores to the M cores that something happened, and the A cores
and M cores, acknowledge it.
The commands are used for things like, okay, I'm an A core, I want the Arbitric to enable
some cook, or I want the Arbitric to turn on the regulator or whatever.
The Arbitric in response says, yeah, okay, action happened, or no action didn't happen
denied because you cannot do this.
The notifications go the other way from the SAP to the A cores M cores, and this is used
for example, for shutdown notifications.
So when the system is shutting down, for some reason, maybe it overheated, it sends a notification
to all the cores, which says, hey, I'm going down, shutdown is happening, do your thing.
On the Linux site, for example, this is handled internally, then it triggers some sort of
stuff in user space, system de-us, it's own shutdown thing, and then the kernel says, okay,
it's shutdown.
That's why the notifications are there for them.
Now, the protocol that's running on top of this, be directional channel between the
SAP and the A cores and M cores is usually STMI, system control, and management interface,
it's defined in arms specification, if you download the slides, you can get the latest version
of the specification as of today, and it's actually not a single protocol, the SCMI,
it's a collection of protocols.
And it's always going to be one protocol in the SCMI, which is the base protocol, and
the base protocol then allows the Linux on the A cores or the RT was on the M cores to discover
what actually is supported by the SCP.
The base protocol reports things like version of the SCP provider, sorry, SCMI provider,
it reports the vendor of the SCMI provider, which can be used, for example, to apply
for X, Linux uses this to apply for X, in case the implementation of the SCMI protocol provider
is broken in some width way, but it also gives you the information which other protocols
are supported by the SCMI implementation.
The other protocols which can be supported by the SCMI implementation are clock protocol,
regulators, sensors, power domains, all kinds of these things, there is like 15 of them.
You can find the complete list in the specification.
The communication with every one of these protocols is command based, so there is a bunch
of commands and every one of these protocols, and this is something which every client
that means Linux on the A core, RT on the M cores can invoke.
All right, let's talk about the other side of it, that is the SCMI protocol provider,
which is an SCP firmware that's running on the SCP control processor.
Sorry, now the SCP firmware unfortunately on most of the SCC will find nowadays is
not going to be open, it's some sort of a closed source stuff which is written by the vendors.
Some vendors did open it, but it's their own handwritten custom code, but increasingly
there is a push to make it properly open, and there is actually already an existing project
from ARM, which is called ARM SCP firmware, and this is BSD3 calls, and we'll talk about
this one because we do not care about the non-free and close source implementations.
Keep in mind that if something is non-free and it's close source it will usually be very
buggy, so just you don't want that.
I guess I don't have to spell it out to this audience.
So let's talk about ARM SCP firmware, what is this?
It's a project which is actually hosted by ARM, it's BSD3, recalls license, it's very
much self-contained, all you need to compile it is valid, cross compiler, toolchain, it only
depends on new lip nano, lip gcc and STD lip, which means if you have some valid ARM
on the heavy toolchain, you can just compile this and get a valid executable out of it.
The ARM SCP firmware can actually run on more than just Cortex M, it can also run
on R64, but in general, the Cortex M is the prime target for this.
The base code is super simple, it's effectively two functions which call itself until
the rich as main loop, so it's really easy to understand what's going on in there, everything
else in the ARM SCP firmware is then extended by adding modules, so pretty much everything
in the SCP firmware is some sort of a self-contained module, which you can include in the
build or not include in the build, there's a lot of modules which are part of the SCP firmware
code base, which is convenient because a lot of them are generic, some of them implement
the SCMI protocol base, some of them implement the additional SCMI protocols which follow
the standard, so you don't have to implement this yourself and you don't have to reinvent
the real, which is convenient, and there are actually two ways how to port the SCP, I'll
choose the easier way, one of the ways is that you can have the SCP actually do the full
platform initialization, that means it acts as a bootloader as a BL2, this is the more complex
way, the SCP will then compile two binaries, one of them which is really the full bootloader
which thus the platform initialization, pin moves initialization, drum initialization, all
the stuff, and then the second stage will actually run S, the SCP and handle the request on
the SCMI protocol and response is and so on, but since bootloader is generally
do better job at bootloader ink, we can skip the first part and only focus on the second
part that means only port the SCP and let bootloader actually initialize the platform
and start the SCP on the SCP core, this is additional benefit because by the time we start
the SCP firmware, we will have UART initialized so if we need to start doing some printkader
bugging which is or print of the bugging which is awesome, which is can because we can start
writing into the UART FIFO and we will start getting characters right out of out of the UART
so yeah I'll opt for the for the simpler option which is only port the SCP and before we go into
that I still want to go through some terminology, if you start porting a SCP, basically the documentation
the documentation is very short, very concise, it's a very good idea to read at least that
because it gives you the overall concept how this whole codebase structure and how it looks
and it gives you about these five keywords which are being used in this documentation which
define the core keywords in the SCP codebase, the important ones are framework which is essentially
the whole codebase then that is module, a module is a self contained piece of code which does
something it can be a driver, it can be some sort of a service provider like an SCMI protocol,
a SCMI cloud protocol implementation and element is an instance of module that means if you have
say a UART driver which is a module the element would be an instance of this module which has some sort
of an instance specific data attached to it say it's the UART driver which is attached to your
specific UART IP at address blah blah blah that's what the element is it has it's like in terms
of Linux kernel module would be the driver the element would be the driver instance that's what it is
internally the SCP does message passing so there are events and notifications events are messages
which can be exchanged between two elements notifications are the same thing by the broadcast
and that's pretty much all you need to know to grow what's going on in the SCP internally
now porting the SCP firmware itself is also actually super easy because all you have to do is
comb the sources look into the product directory there is a bunch of example products already
find one which is similar to what you have in your SCE what core you have in there
duplicated rename it make a comment then once you have this compile the result and verify that you
can actually get a binary out of it if you have a binary at this point then you effectively have
some sort of an executable which you can't still run on your hardware but you know that you
at least manage to fork a platform and you can compile something you get a valid result
the next step is to actually figure out whether this binary could even potentially run on your hardware
at all that means grab the binary run into object dumb disassembled the binary and have a look
at the entry point address then look into your documentation and do your data sheet
and figure out whether your cortex m which you will use as an SCP has this matching entry point
address if it doesn't then look into the forked product directory there is a bunch of headers
which allow you to refine the entry point address change it, recompile it and verify again
at this point you will have a binary which is most likely going to be executable on your hardware
because it has the right memory map now once you have that you need to figure out how to start
it on your platform this unfortunately is for specific or sox specific so this is something you
need to figure out based on your sox documentation if you have k-tech access that's excellent
you can load it into memory and start going to core directly whatever came out of the build
if you don't have k-tech access you'll probably have to write this binary somewhere into storage into
flash and then somehow start it on the SCP core this is yeah sox specific so this you need to figure out
but once you figure this out then the next step is to validate that there are any signs of life
and to get this information whether your code is actually executing you need to know where to put
some sort of a marker to get these signs of life and for that you should look into the init code
or init process for the SCP the init process for the SCP is in fact super simple because
what it does is it enters yeah it enters main function in the arc main.c right after
serant time has been configured the main function runs through it's super short function it calls
advocate advocate in it that one runs through and then ultimately it calls advocate on main loop
and this is the main loop which is then the runtime of the SCP it's literally these two functions
which you need to analyze and figure out where you are running code in that or not
the best thing you can do is put some sort of a marker at the very beginning of the main function
and what kind of marker would that be well the easiest you can do is make use of the fact that
a bootloader has now initialized your system including a UR so you should be able to write
characters into UR before the simplest marker to denote some sort of a signs of life from the
SCP is basically to write a character into the UR before and wait for it to appear on your serial
console and if you can do whatever plain and simple memory write somewhere at the beginning of the
main function just like that of course if you have a j tag access then that's much easier because
with j tag access you can stop the core and figure out where it's like so you think if you don't have
j tag access then this is the next best thing now once you have this printing primitive you can
add more of these simple outputs throughout the main function throughout the arc unit function
until you reach the main loop and you're going to effectively debug the whole unit process using
simple print markers since the unit process is not complex it's doable now once you actually
reach the main loop we probably need to formalize somehow the UR driver and this is done by
wrapping in into a module of type driver so a module is defined in the following way there is a
structure which is called FWK under SCOR module which is a bunch of callbacks it has to be type driver
it has two callbacks at the very beginning which are relevant to us one of them is in it one of the
other one is element in it the difference is that when the system is going through the unit process
it initializes the module itself using the unit callback and then every module instances initialized
using the element unit callback now the module has an iO adapter which is optional for the
UR we will make use of it and we will fill in the iO functions into the iO adapter so that
when any sort of printing happens within the SCP it goes into the iO adapter and then out of your
UR the functions are very simplistic open putc close you will be interested in the putc function
where this where you will get a character from the intern also the SCP which are supposed to
put on the UR so this is where you will do exactly the same right has happened before in the
simple debugging function but now you will do it in a more formal way within the module
in the putc function now this is not all of it because at this point you have a module but
you need to instantiate it the middle and element this is done by including the module in the
build and yeah this is done by including the module in the build by patching a bunch of
CMake files but this is still not all of it because in the product directory you have to
refine the element private data this stuff the element private data they are used to parameterize
the module instances that means the elements in case of UR it could be for example the UR
base address about rate of the of this UR instance that you now once you have these things in place
it's important to test the UR module and the instance of it now the SCP has a print buffer
internally that means whenever you some sort of a printing within the SCP and this may be surprising
it goes actually into a print buffer internally and after the main loop does one sort of a
round that only then the print buffer gets printed out which is not very practical when testing
UR driver because you'll do some sort of printing and suddenly it's not going anywhere it's
not appearing on the UR at all so you can actually circumvent it by calling the FWKIO putc which will
go directly into the UR output it will skip the print buffer for that all you have to do
is prepare some sort of a local string which you then feed into the UR print buffer now we've that
finished what are the next steps let's summarize this what we did now is we effectively
did a port of the SCP which is running on the SCP core it has some sort of printing facility and
it's running in the main loop so you have module you have element which is instance of the module
and it's running on the SCP core the next steps are to add in a similar way a mailbox module
which will allow you to communicate with the other course through the mailbox and schmem and then
on top of that it's all generic then the SCMI module then on top of that SCMI clock protocol module
with the clock protocol module reset modules there is one other detail which you need to be aware of
because if you are adding SCMI clock protocol module this is generic but you need a matching module
which is a clock driver specific for your platform and this has to expose an API to which the
SCMI clock protocol module binds in the documentation you will find how this API binding is described
but there is also a bunch of examples within the SCP code base itself board of caution when you
are adding clock protocol and for bindings keep in mind that what you are defining is an
API which is facing your users it's an API that's facing Linux it's a BI facing your RTO SS
and this API has to be immutable you cannot change it so when you are defining this be
very careful how you are defining this very good way to do this is to add it incrementally that
means when you define some sort of an SCMI clock define only the minimum subset and verify that
Linux can use them successfully verify that RTO SS are happy with them and only then add them
into your SCP and expose them to users do not expose everything at once because you will make
mistakes and they will be hard to correct so add things gradually as you test them
right with that but summarized this it is possible to have an open SCP implementation
the code which is currently available is PSD 3 calls so it's open and yeah
the port can be implemented incrementally and when you do so be very mindful of the API which you
are exposing to the Linux kernel and your RTO SS and so on with that thank you for your attention
and you have any questions thank you do you have TFA doing like SCMI processing or to
speak SCMI directly to the co-processor that's actually a good good question so the question was
whether I'm talking to TFA and then TFA talks to SCB or whether I directly talk to SCB from all
the clients right so on the platform that I'm working on which is the upcoming SLC from
Renesas this is all the clients directly talk to SCB that means TFA talks to SCB you would talk
to SCB Linux talks to SCB the RTO SS talk to SCB and the SCB is the manager of the overall platform
policy thank you