[En-Nut-Discussion] Nut/OS port for H8/300H.

Jan Dubiec jdx at slackware.pl
Tue Mar 16 23:51:53 CET 2004


On Tue, 16 Mar 2004 19:55:23 +0100, Harald Kipp <harald.kipp at egnite.de> wrote:
> Hi again,
> 
> OK, rebuilding under Windows CMD shell is gone. It may work
> on a Cygwin shell, but I'd prefer the native system without
> too many tools required to get it build.
> 
> Anyway, the port is clean and you really invested a lot of
> effort, so I decided to add it to the CVS head.
Well, I had spent about a week few months ago when I ported Nut/OS
first time. And recently 48 hours non stop. :-) It could take less time
but of course I missed out some things (eg. TCP checksum calculation)
and spent few hour thinking why ICMP works but TCP does not. Although I
like such games. ;-)

> I added missing or changed a few existing copyrights and ran
> indent -kr -nut -l 132
> on all sources. This will produce more diff lines against
> your patch. But it will avoid them in the future, not all
> contributors are as disciplined as you are.
I had remembered about copyrights and doxygen stuff but I was too lazy
to change it. So I am not so disciplined. :-)

[.....]
> >- arch subdirectory has been added in the Nut/OS main directory - currently it
> >   contains startup code, header file and generic linker scripts for H8/3068F,
> 
> I still don't think it would have been required to
> use the arch subdir. Actually I have no preference.
IMO this is a good place for linker scripts and startup code (copying
aproporiate sections into RAM, setting MCU registers, etc). IMO we
shouldn't mix this code with kernel code (os directory) or device
drivers.

BTW. I know that AVR port rely on avr-libc startup code and linker
scripts but IMO you should consider using custom scripts and startup
code. It may be a bit difficult on the beginning but it gives you much
more flexibility thus you don't have to use strange hacks as mentioned
on the top of nutinit.c. ;-) Just a suggestion.

> >- __HARVARD_ARCH__ has been added which which allows to turn off building
> >    of functions with _P suffix on non Harvard based micros,
> 
> That might become a problem. Most commercial projects I
> know of make extensive use of string constants in program
> space. At least something like
> #define printf_P printf
> would be required to maintain portability of existing
> applications.
At least H8 gcc puts string constats (and other data declared as
const) into .rodata sections and it is up to linker script whether to
put this section into ROM or RAM. The "problem" with AVR (and
eg. MCS51) is that they are based on Harvard architecture where
program memory (usually some kind of ROM) and data memory (usually
some kind of RAM) are located in different address spaces. This
implies that different instructions must be used when accesing data
located in these memories, eg. on MCS51 MOVC is used to load data from
program memory and MOVX to load/store data from/in data memory. And
that's why _P functions must be provided for Harvard based micros -
string constants are stored in ROM which is usually located in the
program address space. There is no such distinction on von Neumann
(aka Princeton) architectures (eg. H8 and ARM) - data and program
memories are located in the same address space. Hence, for example,
you can run code from RAM - very nice feature when you are debugging
an application.

So, when __HARVARD_ARCH__ is defined (which should be defined for
AVRs!), _P functions are built. On von Neumann MCUs only few aliases
must be provided:
#define strlen_P(x)             strlen(x)
#define strcpy_P(x,y)           strcpy(x,y)
#define strcmp_P(x, y)          strcmp(x, y)
#define memcpy_P(x, y, z)       memcpy(x, y, z)
#define fputs_P(x, y)           fputs(x, y)
#define fprintf_P               fprintf

> I noticed a few lines, where you replaced program memory
> strings by standard literals in NUTDEBUG sequences. Some
> application may now fail to link with NUTDEBUG, because
> they simply run out of RAM.
Indeed, it seems that for some reason (???) I have done a few mistakes
(e.g. in osdebug.c). I have declared some format strings as static
char while they should be static prog_char. I hope you will fix it. :-)

[.....]
> > - macro NutJumpOutCritical() has been added in atom.h; on H8 and ARM
> > interrupts
> 
> >   may have different priorities so it would be good to save current value of
> >   condition register (or whatever is it called) before entering
> > critical section
> 
> >   so smarter Nut{Enter,Exit}Critical() have been defined (for H8 at
> > the moment);
> 
> >   the nice side effect of such definitions is that a programmer must
> > always close
> 
> >   a critical section (a compiler will remind him about it ;-) ); not so nice
> >   is the fact that special function/macro must be provided in order
> > to exit from
> 
> >   critical section dur to an exception, eg.:
> >   [.....]
> >   NutEnterCritical();
> >   [.....]
> >   if (an_exception_occured)
> >      NutJumpOutCritical();
> >   [.....]
> >   NutExitCritical();
> >   [.....]
> 
> Frankly, I need some time to fully understand this.
OK, first look at definition of these macros for H8 MCUs and take into
consideration brackets in Nut{Enter,Exit}Critical():

#define NutEnterCritical()                     \
    {                                          \
        u_char __ccr__;                        \
        asm volatile(                          \
            "stc.b ccr, %0l"            "\n\t" \
            "orc.b #0xc0, ccr":"=r"(__ccr__):  \
        );

#define NutExitCritical()                      \
       asm volatile(                           \
        "ldc.b %0l, ccr"::"r"(__ccr__)         \
       );                                      \
    }

#define NutJumpOutCritical()                   \
       asm volatile(                           \
        "ldc.b %0l, ccr"::"r"(__ccr__)         \
       );

Brackets create a new program block and then automatic variable
__ccr__ is defined which is used to store CCR value. This variable
allows to restore CCR at the end of critical section. This is
important when there are interrupts with different priorities and
different values (bits in CCR) are used to enable/disable these
interrupts.

Having such definitions you cannot use folowing code:

void foo(void)
{
        NutEnterCritical();

        do_something();

        if (a_flag_is_set())
                NutExitCritical();

        do_something_else();

        NutExitCritical();
}

If you try to compile it, compiler will complain due to unmatched
brackets. Therefore macro NutJumpOutCritical() has been defined. It
has the same body as NutExitCritical() but there is no closing bracket.

[.....]
> >- AVR interrupt functions/variables definitions should be put into one file.
> 
> No, because they consume a lot of space.
> 
> In general I'd recommend to split even more files. The
> linker will always add a complete module, even if the
> application needs a single routine only.
OK, although I am not sure. Is there really difference between passing to
the linker an object with functions and passing two separate object files?
I will check that when I find some time.

> >Harald, I hope also that my patch will help you to make port for ARM beacause
> >a lot of stuff is "ARM ready" - H8/300H and H8S in advanced mode have 32 bit
> >internal architecture (with 16 bit data bus).
> 
> I already made some of these changes, but your port is
> much more complete and I'll take it over.
You are welcome. ;-)

If there is such need, I can provide in April schematic of simple H8
board - just a H8/3068F (384k Flash and 16k RAM inside), RTL8019 and
1 or 2 MAX232A chips. Currently I am running Nut/OS on very similar
hardware. PCB has credit card size.

Regards,
/J.D.
-- 
Jan Dubiec, jdx at slackware.pl, mobile: +48 602 101787

Głęboka wiara wymaga płytkiego rozumu i nikłej wiedzy.



More information about the En-Nut-Discussion mailing list