Topics

Porting to Cortex-M0+


Euan Mutch <euan.mutch@...>
 

Hi,

I am in the process of porting Zephyr to Cortex-M0+, the problem is that for the M0+ if you use a Supervisor Call (SVC) with interrupts disabled, since there is no interrupt masking either, then the Supervisor Call will generate a hard fault.

Which means that every time _Swap() is called it hard faults.

Currently I have managed to get round this by just commenting out the disabling of interrupts before _Swap() is called. However I don't think this is a viable long term solution!

Do I have to rewrite _Swap() to not use SVC or is there another way to do it that I have missed?

Thanks,
Euan


Boie, Andrew P
 

On Mon, 2016-08-01 at 13:34 +0000, Euan Mutch wrote:
Do I have to rewrite _Swap() to not use SVC or is there another way 
to do it that I have missed?
I am not too deeply familiar with ARM arch code. Ben Walsh would be the
person to talk to. I believe he gets back from sabbatical today
although it may take him some time to get through all his email.

Andrew


Benjamin Walsh <benjamin.walsh@...>
 

Hi Euan,

I am in the process of porting Zephyr to Cortex-M0+, the problem is
that for the M0+ if you use a Supervisor Call (SVC) with interrupts
disabled, since there is no interrupt masking either, then the
Supervisor Call will generate a hard fault.

Which means that every time _Swap() is called it hard faults.

Currently I have managed to get round this by just commenting out the
disabling of interrupts before _Swap() is called. However I don't
think this is a viable long term solution!
Indeed, it is not. :)

Do I have to rewrite _Swap() to not use SVC or is there another way to
do it that I have missed?
You have to take another approach in this case. I _think_ you can simply
pend the PendSV exception instead, and then unlock interrupts.

You have to use PRIMASK instead of BASEPRI as well for the interrupt
locking, since there is no BASEPRI on M0 (IIRC). Some of the ARM arch
code has to be adapted to that as well.

The SVC handler for M3/M4 does not do much more work than that anyway
(apart from the IRQ offload). We might be able to merge the M0 and
M3/M4 implementations as well.

HTH,
Ben


Euan Mutch <euan.mutch@...>
 

Hi Ben,

I created a new board and soc for the M0+ I will be using, then just fixed
all the compiler errors with the M3/M4 assembler.
Then replaced all occurrences of BASEPRI with PRIMASK.

I don't have the M0+ yet so I have been testing on a Arduino Due in the
mean time and after changing all that it still seems to work fine (although
its not an M0+ so we will see)
Will try pending the PendSV exception tomorrow and see if that works!

Thanks,
Euan

On Tue, Aug 2, 2016 at 8:38 PM, Benjamin Walsh <benjamin.walsh(a)windriver.com
wrote:
Hi Euan,

I am in the process of porting Zephyr to Cortex-M0+, the problem is
that for the M0+ if you use a Supervisor Call (SVC) with interrupts
disabled, since there is no interrupt masking either, then the
Supervisor Call will generate a hard fault.

Which means that every time _Swap() is called it hard faults.

Currently I have managed to get round this by just commenting out the
disabling of interrupts before _Swap() is called. However I don't
think this is a viable long term solution!
Indeed, it is not. :)

Do I have to rewrite _Swap() to not use SVC or is there another way to
do it that I have missed?
You have to take another approach in this case. I _think_ you can simply
pend the PendSV exception instead, and then unlock interrupts.

You have to use PRIMASK instead of BASEPRI as well for the interrupt
locking, since there is no BASEPRI on M0 (IIRC). Some of the ARM arch
code has to be adapted to that as well.

The SVC handler for M3/M4 does not do much more work than that anyway
(apart from the IRQ offload). We might be able to merge the M0 and
M3/M4 implementations as well.

HTH,
Ben


Euan Mutch <euan.mutch@...>
 

Hi Ben,

That seems to be working properly now with the interrupts being disabled.

We might be able to merge the M0 and
M3/M4 implementations as well.
I have been trying to make sure that anything I change still works on M3/M4
and will add config options where a common approach would not work.

Thanks,
Euan


On Tue, Aug 2, 2016 at 10:05 PM, Euan Mutch <euan.mutch(a)gmail.com> wrote:

Hi Ben,

I created a new board and soc for the M0+ I will be using, then just fixed
all the compiler errors with the M3/M4 assembler.
Then replaced all occurrences of BASEPRI with PRIMASK.

I don't have the M0+ yet so I have been testing on a Arduino Due in the
mean time and after changing all that it still seems to work fine (although
its not an M0+ so we will see)
Will try pending the PendSV exception tomorrow and see if that works!

Thanks,
Euan

On Tue, Aug 2, 2016 at 8:38 PM, Benjamin Walsh <
benjamin.walsh(a)windriver.com> wrote:

Hi Euan,

I am in the process of porting Zephyr to Cortex-M0+, the problem is
that for the M0+ if you use a Supervisor Call (SVC) with interrupts
disabled, since there is no interrupt masking either, then the
Supervisor Call will generate a hard fault.

Which means that every time _Swap() is called it hard faults.

Currently I have managed to get round this by just commenting out the
disabling of interrupts before _Swap() is called. However I don't
think this is a viable long term solution!
Indeed, it is not. :)

Do I have to rewrite _Swap() to not use SVC or is there another way to
do it that I have missed?
You have to take another approach in this case. I _think_ you can simply
pend the PendSV exception instead, and then unlock interrupts.

You have to use PRIMASK instead of BASEPRI as well for the interrupt
locking, since there is no BASEPRI on M0 (IIRC). Some of the ARM arch
code has to be adapted to that as well.

The SVC handler for M3/M4 does not do much more work than that anyway
(apart from the IRQ offload). We might be able to merge the M0 and
M3/M4 implementations as well.

HTH,
Ben


Jon Medhurst (Tixy) <tixy@...>
 

Top posting made this conversation difficult to follow and quote, so
I'll heavily edit and paraphrase...

Euan said:
Got some problems with _Swap() when porting to Cortex M0+

Ben said:
You have to use PRIMASK instead of BASEPRI as well for the
interrupt locking, since there is no BASEPRI on M0 (IIRC)
We might be able to merge the M0 and M3/M4 implementations as well.

Euan said:
I created a new board and soc for the M0+ I will be using... then
replaced all occurrences of BASEPRI with PRIMASK.

I have been trying to make sure that anything I change still works
on M3/M4 and will add config options where a common approach would
not work.
One thing that may be relevant here is that with the advent of ARMv8-M,
differences like presence of BASEPRI etc are predicated on whether the
CPU implements the 'Main Extension'. The ARM ARM [1] also refers to
Mainline and Baseline implementation.

So, I just wanted to suggest that if any work is going on to support M0+
then if the temptation is to have something like

#ifndef CONFIG_CORTEX_M0PLUS
use BASEPRI
#else
do something different
#endif

Probably best to instead have the test above check
CONFIG_CORTEXM_HAVE_BASEPRI and get Cortex M3 etc to select that.
(Or have a negative config DONT_HAVE_BASEPRI and/or or have some clever
kconfig defaults, whatever seems best). If we do that the we can more
easily add support for v8-M devices.

I hit the lack of BASEPRI issue booting Zephyr on a v8-M emulator [2]
which defaulted to Baseline implementation. Fortunately it had a
commandline option to select Mainline so I could ignore the problem for
the time being :-)

[1] https://silver.arm.com/download/download.tm?pv=3394548&;p=1610307
(Free registration required)

[2] https://developer.arm.com/products/system-design/fixed-virtual-platforms#AllFVPS
(Licence required to run emulators).

--
Tixy


Ricardo Salveti <ricardo.salveti@...>
 

Hi Euan,

On Thu, Aug 4, 2016 at 6:00 AM, Euan Mutch <euan.mutch(a)gmail.com> wrote:
Hi Ben,

That seems to be working properly now with the interrupts being disabled.

We might be able to merge the M0 and
M3/M4 implementations as well.
I have been trying to make sure that anything I change still works on M3/M4
and will add config options where a common approach would not work.
I was looking at what would take to get Zephyr to support Cortex-M0
today (wanted to port Zephyr to nRF51), and found your thread :-)

Are you expecting to open source/upstream your Cortex M0+ based port?
Wanted to avoid duplicating this effort, as the M0 port would be quite
similar with M0+. Happy to test/review your implementation as well.

Thanks,
--
Ricardo Salveti


Euan Mutch <euan.mutch@...>
 

TIxy,
I am thinking either, CPU_HAS_BASEPRI or ARCH_HAS_BASEPRI.

I also want to add an ARCH_ARMV6, V7 etc to handle architecture specific code. We still need the more specific CPU_CORTEX_M0PLUS, 3, 4, etc because each cpu has different features.

Ricardo,
I am hoping to push the finished port back to the community. Although it might not be finished for a litle while yet!

I now have my M0+ board (SAMD20 Xplained Pro) and have managed to program it with zephyr using Atmel Studio. So far it gets to main and can run C code, but not much else.


Jon Medhurst (Tixy) <tixy@...>
 

On Wed, 2016-08-17 at 09:40 +0000, Euan Mutch wrote:
I am thinking either, CPU_HAS_BASEPRI or ARCH_HAS_BASEPRI.

I also want to add an ARCH_ARMV6, V7 etc to handle architecture
specific code. We still need the more specific CPU_CORTEX_M0PLUS, 3,
4, etc because each cpu has different features.
Sounds reasonable to me. (I'm new around here though, so don't count
that as anything other than a random opinion ;-)

My main thought was that boards/SoCs select a CPU type which then
selects the individual feature that CPU supports. That way, core kernel
changes are decoupled better from people's board/SoC definitions which
don't have to break when kernel changes are made.

--
Tixy


Benjamin Walsh <benjamin.walsh@...>
 

On Wed, Aug 17, 2016 at 02:36:07PM +0100, Jon Medhurst (Tixy) wrote:
On Wed, 2016-08-17 at 09:40 +0000, Euan Mutch wrote:
I am thinking either, CPU_HAS_BASEPRI or ARCH_HAS_BASEPRI.
No objection from me.

I also want to add an ARCH_ARMV6, V7 etc to handle architecture
specific code. We still need the more specific CPU_CORTEX_M0PLUS, 3,
4, etc because each cpu has different features.
Sounds reasonable to me. (I'm new around here though, so don't count
that as anything other than a random opinion ;-)
Sounds reasonable to me as well. I'd like to hear from the ARM
maintainers to get their opinion too.

My main thought was that boards/SoCs select a CPU type which then
selects the individual feature that CPU supports. That way, core kernel
changes are decoupled better from people's board/SoC definitions which
don't have to break when kernel changes are made.
Cheers,
Ben


Jon Medhurst (Tixy) <tixy@...>
 

On Wed, 2016-08-17 at 14:13 -0400, Benjamin Walsh wrote:
I also want to add an ARCH_ARMV6, V7 etc to handle architecture
specific code. We still need the more specific CPU_CORTEX_M0PLUS,
3,
4, etc because each cpu has different features.
Sounds reasonable to me. (I'm new around here though, so don't count
that as anything other than a random opinion ;-)
Sounds reasonable to me as well. I'd like to hear from the ARM
maintainers to get their opinion too.
Which reminds me to ask... who _are_ the ARM maintainers and how do we
find out such things given that the MAINTAINERS file in the source tree
is somewhat deficient in coverage?

--
Tixy


Nashif, Anas
 

See https://gerrit.zephyrproject.org/r/4160 for the maintainers.

Anas

On 18/08/2016, 11:00, "Jon Medhurst (Tixy)" <tixy(a)linaro.org> wrote:

On Wed, 2016-08-17 at 14:13 -0400, Benjamin Walsh wrote:
> > > I also want to add an ARCH_ARMV6, V7 etc to handle architecture
> > > specific code. We still need the more specific CPU_CORTEX_M0PLUS,
> 3,
> > > 4, etc because each cpu has different features.
>
> > Sounds reasonable to me. (I'm new around here though, so don't count
> > that as anything other than a random opinion ;-)
>
> Sounds reasonable to me as well. I'd like to hear from the ARM
> maintainers to get their opinion too.

Which reminds me to ask... who _are_ the ARM maintainers and how do we
find out such things given that the MAINTAINERS file in the source tree
is somewhat deficient in coverage?

--
Tixy


Euan Mutch <euan.mutch@...>
 

I have started writing the drivers for peripherals on the M0+ now, but I am getting the feeling that I should probably just add Atmel ASF to the \ext\hal\ folder rather than basically rewriting them. I am just wondering why this was not done already for the Arduino Due which also has an Atmel SOC?


Vinicius Costa Gomes
 

Hi,

Euan Mutch <euan.mutch(a)gmail.com> writes:

I have started writing the drivers for peripherals on the M0+ now, but
I am getting the feeling that I should probably just add Atmel ASF to
the \ext\hal\ folder rather than basically rewriting them. I am just
wondering why this was not done already for the Arduino Due which also
has an Atmel SOC?
Licensing issues perhaps[1]?

"Disclaimer and Credits

...

4. This software may only be redistributed and used in connection with
an Atmel microcontroller product."


[1] http://www.atmel.com/Images/asf-releasenotes-3.32.0.pdf page 34


Cheers,
--
Vinicius


Nashif, Anas
 

On 23 Aug 2016, at 10:39, Vinicius Costa Gomes <vinicius.gomes(a)intel.com> wrote:

Hi,

Euan Mutch <euan.mutch(a)gmail.com> writes:

I have started writing the drivers for peripherals on the M0+ now, but
I am getting the feeling that I should probably just add Atmel ASF to
the \ext\hal\ folder rather than basically rewriting them. I am just
wondering why this was not done already for the Arduino Due which also
has an Atmel SOC?
Licensing issues perhaps[1]?
Actually more because nobody did it until now, so you are welcome to do this.



"Disclaimer and Credits

...

4. This software may only be redistributed and used in connection with
an Atmel microcontroller product."

I do not think this will conflict with the intent of how to use it in Zephyr. After all the code will be used with Atmel MCUs only…

Anas


[1] http://www.atmel.com/Images/asf-releasenotes-3.32.0.pdf page 34


Cheers,


Piotr Mienkowski <Piotr.Mienkowski@...>
 

Hi,

I have the same problem. I would like to add support for Atmel SAM E70 chip (Cortex-M7) and was thinking that using the header files provided by Atmel as part of their ASF would make the job much, much easier.

Euan, did you already add files to ext/hal/ folder? Have you talked to Maureen Helm, the ARM architecture maintainer? Should we agree on folder structure so support for future Atmel chips can be easily added?

My thoughts:
I think we should only add header files that define register access and do not add any device drivers. While header files are valuable the Atmel implementation of device drivers looks low quality, at least the SAM E70 package. The way API is written is not directly useful for any serious development, neither it follows CMSIS standard. While some drivers look good, some are incomplete and some are buggy. We would need to fix them and cooperate with Atmel to push changes upstream. I reckon using third party source code which is not maintained in open source model is not a viable long term solution. Not mentioning the fact that device drivers will have to be tightly integrated with Zephyr kernel. I believe it's easier to write our own drivers from scratch. Anyway, that's only my opinion.

The text of SAM Software Package License included in the source code (and header files) looks actually very permissive but IANAL, also the ext/hal/ folder has already a selection of proprietary code with similar licenses. In any case we should probably get an official green light from someone.

Cheers,
Piotr


Maureen Helm
 

-----Original Message-----
From: Piotr Mienkowski [mailto:Piotr.Mienkowski(a)schmid-telecom.ch]
Sent: Thursday, August 25, 2016 4:22 AM
To: devel(a)lists.zephyrproject.org
Subject: [devel] Re: Re: Re: Re: Porting to Cortex-M0+

Hi,

I have the same problem. I would like to add support for Atmel SAM E70 chip
(Cortex-M7) and was thinking that using the header files provided by Atmel as
part of their ASF would make the job much, much easier.

Euan, did you already add files to ext/hal/ folder? Have you talked to Maureen
Helm, the ARM architecture maintainer? Should we agree on folder structure
so support for future Atmel chips can be easily added?
I agree it would make sense to add the device header files from Atmel to ext/hal. We already have the CMSIS Core header files from ARM in ext/hal/cmsis, which are being used by the NXP ksdk and Nordic mdk. As far as folder structure goes, I think anything under ext/hal/asf (or whatever we end up calling it) has some freedom to do what makes sense. For ext/hal/cmsis and ext/hal/ksdk, I tried to preserve the structure from the original source as much as possible. The folder structure under arch/arm/soc is intended to be more standardized, though you may have noticed that some SoCs have a family/series hierarchy (nxp_kinetis) and some don't (atmel_sam3). To add SAM E70, we'll need to first convert the existing atmel_sam3 to the family/series hierarchy. Something like this:

arch/arm/soc/atmel_smart/sam3
arch/arm/soc/atmel_smart/same7x


My thoughts:
I think we should only add header files that define register access and do not
add any device drivers. While header files are valuable the Atmel
implementation of device drivers looks low quality, at least the SAM E70
package. The way API is written is not directly useful for any serious
development, neither it follows CMSIS standard. While some drivers look good,
some are incomplete and some are buggy. We would need to fix them and
cooperate with Atmel to push changes upstream. I reckon using third party
source code which is not maintained in open source model is not a viable long
term solution. Not mentioning the fact that device drivers will have to be tightly
integrated with Zephyr kernel. I believe it's easier to write our own drivers
from scratch. Anyway, that's only my opinion.
I can't comment on the state of the Atmel drivers, but at least for NXP we do a lot of testing on the ksdk drivers and they are actively maintained. Intel is doing a similar thing with their qmsi drivers.


The text of SAM Software Package License included in the source code (and
header files) looks actually very permissive but IANAL, also the ext/hal/ folder
has already a selection of proprietary code with similar licenses. In any case we
should probably get an official green light from someone.
IANAL either, but will check with someone at LF on this.


Cheers,
Piotr


Euan Mutch <euan.mutch@...>
 

So the best way forward is to add the device headers to /hal/asf and change sam3 to the family/series hierarchy?

There are some really weird things going on with the Atmel drivers, especially some of the really horrible macros they use. Took me a full day just to decipher the clock init code.

Quick (newbie) question:
I have currently added just the M0+ specific bits of asf, but I can't get it to link properly and so get "undefined reference to 'system_init'" when I try to use it. It is really hard to figure out how to do certain things in zephyr such as adding external stuff... Although that could just be because I have never worked on something like this before.
I don't understand how the other HALs work since they also have drivers in them, I have exactly the same setup as those. Which seems to just be including the files and never building anything?


Iván Briano <ivan.briano at intel.com...>
 

On Mon, 29 Aug 2016 10:56:06 +0000, Euan Mutch wrote:
So the best way forward is to add the device headers to /hal/asf and change sam3 to the family/series hierarchy?

There are some really weird things going on with the Atmel drivers, especially some of the really horrible macros they use. Took me a full day just to decipher the clock init code.

Quick (newbie) question:
I have currently added just the M0+ specific bits of asf, but I can't get it to link properly and so get "undefined reference to 'system_init'" when I try to use it. It is really hard to figure out how to do certain things in zephyr such as adding external stuff... Although that could just be because I have never worked on something like this before.
I don't understand how the other HALs work since they also have drivers in them, I have exactly the same setup as those. Which seems to just be including the files and never building anything?
If the HAL is only a bunch of headers, then you don't need to build
anything. But if you look at the QMSI one, you'll see it's building a
lot of stuff, so it may serve as an example.


Maureen Helm
 

Hi Euan,

-----Original Message-----
From: Euan Mutch [mailto:euan.mutch(a)gmail.com]
Sent: Monday, August 29, 2016 5:56 AM
To: devel(a)lists.zephyrproject.org
Subject: [devel] Re: Re: Re: Re: Re: Re: Porting to Cortex-M0+

So the best way forward is to add the device headers to /hal/asf and change
sam3 to the family/series hierarchy?
Yes. I checked with the LF, and they recommended that the Zephyr TSC asks the governing board to approve the ASF license.

There are some really weird things going on with the Atmel drivers, especially
some of the really horrible macros they use. Took me a full day just to decipher
the clock init code.

Quick (newbie) question:
I have currently added just the M0+ specific bits of asf, but I can't get it to link
properly and so get "undefined reference to 'system_init'" when I try to use it.
It is really hard to figure out how to do certain things in zephyr such as adding
external stuff... Although that could just be because I have never worked on
something like this before.
I don't understand how the other HALs work since they also have drivers in
them, I have exactly the same setup as those. Which seems to just be including
the files and never building anything?
Don't forget to look at the Kbuild files, such as ext/hal/qmsi/Kbuild. I've also go this patch in the works for Kinetis SDK:
https://gerrit.zephyrproject.org/r/#/c/4192/3