[En-Nut-Discussion] Ethernut on TI's Cortex-M3 (Stellaris LM3S...)

Philipp Burch phip at hb9etc.ch
Tue Oct 9 22:31:35 CEST 2012

Hi Uwe, Ole,

On 10/09/2012 02:29 PM, Uwe Bonnes wrote:
>>>>>> "Philipp" == Philipp Burch <phip at hb9etc.ch> writes:
>      Philipp> I've now started to update the directory structure and the
>      Philipp> headers.  Please find attached the Git bundle containing the
>      Philipp> changesets which I've made so far.
> There was nothing attached to the mail on the list. Perhaps send private
> mail

Indeed. I've uploaded the Git bundle and the complete diff from 
Subversion revision r4719 here:


> [...]
> I will try to have a look, but there are millions of "correct ways" and
> zillions of ways with obstacle. One test is that at least your changes dont'
> break any other build, the next step is that your changes build on a foreign
> system.

Good point. I hope that my changes do not interfere with any other 
targets, but this needs to be ensured of course. Are there any 
testsuites for this, or do you usually do this by hand?

> [...]
> Thes number and names are STM32 specific.  Let me explain with a look at the
> LM4F120H5QR, August 29, 2012 page 217 Fig 5-5 and the ST reference manual for
> the STM32F4 familiy RM0090 ( Doc ID 018909 Rev 1,  File download
> DM00031020.pdf) page 83 Figure 9. Both figures show the clock tree.
> The numbers are used to identify the clock sources feeding the CPU. They
> might be
>   - SYSCLK_HSE : High Speed External quartz or external clock feeds the CPU
>   - SYSCLK_HSI : High Speed internal esxillator feeds the CPU
>   - SYSCLK_PLL : PLL feeds the CPI
> The PLL itself can be feed from HSE or HSI.
> For LM4 HSE is "Main OSC", HSI is "  Precision Internal OSC" and there is
> also the PLL. Probably is is good to use the similar names as used in the
> peripheral library heades

Ok, thanks for the explanation. I'll see what could fit for the LM3s.

> [...]
>      Philipp> Again, what do these numbers stand for? This time it can't be
>      Philipp> specific to one single Cortex-M3 architecture, as it is in a
>      Philipp> generic file and the same defines are present for different
>      Philipp> families.
> I don't know if there are users of theses definitions yet. But the thought
> is to have perhaps a generic EMAC driver and then say " turn on
> NUT_HWCLK_EMC" and not have a to say
> # if defined(STM32_F$4)
> turn on RCC_AHB1ENR bit ETHMAC_EN
> #elif defined (LM4)
> turn on LM4 related bits
> #elsif
> ...
> #endif

Yes, that would be nice. But it's not easy to get that working equally 
well on all available targets.

>      Philipp> Generally: How is the clocking handled in Ethernut?
> For the STM32 with a given frequency of the external clock and the macros
> SYSCLK_PLL/PLLCLK_HSE I try to reach the maximum allowed frequency. If wee
> need to conserve energy, we then can sleep in the idle thread at the cost
> possible delay between interrupt handler and interrupt bootom half running
> in the thread context. There was a discussion some weeks ago about that.
> Runntime frequency switching is another case, not yet abstracted...

Yeah, the question might be what the intended purpose of Ethernut (or 
Nut/OS) is. Most of the users (me included) will probably use it because 
of the integrated TCP/IP stack, whereas ethernet does not perform very 
well when it comes to low power...
Of course, the more flexibility the better, as long as it is still usable.

>      Philipp> Is there a document explaining this?
> I don't know of any yet.
>      Philipp> I'd expect something like SetClock()
>      Philipp> to which I'd pass some params to define how the device is
>      Philipp> clocked, but this seems to be handled differently.
> stm32f4_clk.c e.g. has "int SetSysClock(void)". As setting the sysclock
> happens at startup, there is no input device yet to give
> arguments to SetClock(). So SetSysClock(void) is configured with macros
> derived from the board.conf file. Macros also have the advantage of
> resulting in smaller code, as a lot of calculations are done at compile
> time, not at run time.

Ok, so I'll start with a fixed clock frequency and add some macros for 
it later.

> On 10/09/2012 12:00 PM, Ole Reinhardt wrote:> Hi Philipp,
>>> [...]
>> Sorry, but the attachment is cut off by mailman... could you please send
>> me a private mail?

See above, http://hb9etc.ch/ethernut/

>> [...]
>>> And them something specifically @Ole:
>>> Most parts of the headers are fairly self-explaining, but two locations
>>> confused me so far. Both are related to the clocking. The first one is
>>> the _clk.h (e.g. stm32_clk.h in nut/include/arch/cm3/stm):
>>> /* STM32F Clock source selectors */
>>> #define SYSCLK_HSI  0
>>> #define SYSCLK_PLL  1
>>> #define SYSCLK_HSE  2
>>> #define PLLCLK_HSI  3
>>> #define PLLCLK_HSE  4
>>> What are these numbers for? Are they something STM32-related, or
>>> should these be present on all Cortex-M3?
>> These are special to STM and are used to select the clock source used as
>> system clock. The way, system clocks are initialised, depends on your
>> hardware. For example the LPC17xx can be clocked directly from the
>> crystal, from a PLL etc.
>> You should start implementing the standard way, wich is used on the
>> devkit as well (most propably PLL generated clock from a crystal input)
>> and later add the configuration options for different clock settings.

Great, thanks.

>>> [...]
>>> Again, what do these numbers stand for? This time it can't be specific
>>> to one single Cortex-M3 architecture, as it is in a generic file and the
>>> same defines are present for different families.
>> Indeed these settings define the CPU internal clocking domains (output
>> of the PLLs). But not all CM3 architectures implement all of these
>> clocking domains.
>> You should keep the existing and (if needed) add further clocking domain
>> defines here. These defines are used to query a clock using
>> NutClockGet()            // nut/os/timer.c
>> which calls
>> NutArchClockGet()        // nur/arch/cm3/cmsis/ostimer_cortex.c
>> /*!
>>   * \brief Return the specified clock frequency.
>>   *
>>   * If only 1 hardware clock is defined, then this function is mapped
>>   * to NutGetCpuClock().
>>   *
>>   * The number of available hardware clocks depends on the target harware
>>   * and is specified by NUT_HWCLK_MAX + 1.
>>   *
>>   * \param idx Index of the hardware clock. Can be any of the following:
>>   *            - NUT_HWCLK_CPU
>>   *            - NUT_HWCLK_PERIPHERAL
>>   *
>>   * \return CPU clock frequency in Hertz.
>>   */

Ah, great, thanks for that!

>>> Generally: How is the clocking handled in Ethernut? Is there a document
>>> explaining this? I'd expect something like SetClock() to which I'd pass
>>> some params to define how the device is clocked, but this seems to be
>>> handled differently.
>> Unfortunately not that I know.
>> Clock set up is very different on each architecture. It is done during
>> startup either in in the crtxxx.S file (avr and arm) or in <CPU>_clk.c
>> called from SetSysclock() in nut/arch/cm3/os/nutinit.c for the Cortex
>> architecture.
>> So in general we are missing a common clocking concept right now.
>> Normally clock settings are defined using the Nut/OS configurator.

Well, I don't think that this is a bad way. The configurator is a great 
tool, so why not use it's capabilities for this?

>> Again: For the moment start with creating some fixed clock settings and
>> later make them configurable.

I'll do that.

>> Do you have any sample sources (CMSIS examples) which came with your
>> devkit? You could easily take over the settings (and code) provided in
>> your system.c file (most probably it will be called system.c)

Yes, the distribution comes with a whole bunch of examples. As 
mentioned, the actual implementation of the drivers should not cause too 
much trouble, but I had to know how to interface with Ethernut before.


More information about the En-Nut-Discussion mailing list