You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@nuttx.apache.org by Petro Karashchenko <pe...@gmail.com> on 2022/03/27 20:21:25 UTC

FAR usage education

Hi,

I want to improve my knowledge about FAR usage in NuttX code. I've already
read some initial information related to "Far memory" and "3-byte pointers
to access extended memory spaces", but still lacking a practical experience
with a real compiler and device use case. My main question is about FAR
usage notation, because currently it seems to me very confusing. I assume
that notation is very similar to "const", but do not have a way to prove
it, so I'm asking for help from people that have more practical experience.
So I will go with few examples:

1. FAR char *p; -- that is fully understood. Generate code to use a 3-bytes
pointer to char.
2. FAR char **p; -- here where my understanding ends. Is this a 3-byte
pointer to an array of traditional 2-byte pointers or traditional 2-byte
pointer to an array of 3-byte pointers? Or even a 3-byte pointer to an
array of 3-byte pointers?
3. The answer to this will come from answer on 2, but still: is "FAR char *
FAR *p;" valid?

I'm asking this because sometimes I modify common code that is equipped
with "FAR" and want to be sure that my changes will not break things.

Best regards,
Petro

Re: FAR usage education

Posted by Petro Karashchenko <pe...@gmail.com>.
Thank you Gregory for your reply. I will definitely examine all the links
that you provided.
I'm familiar with ARM address access limitations and also with more exotic
ARC architecture where I first met .sdata and .sbss sections usage for data
that are located near GP. But as you already pointed out that is usually
handled by the compiler or by inserting a proper inline assembly code.

With FAR and NEAR I have more practical questions because those we are
handling manually in NuttX code. I will give you one example: In
libs/libc/dirent/lib_scandir.c there is "scandir" function that performs
next calls:
//-----start code---------------------------------------------
  FAR struct dirent *dnew;
  FAR struct dirent **list = NULL;
...
      /* Grow the directory entry list, if required. */

      if (cnt == listsize)
        {
          struct dirent **newlist;
...
          newlist = lib_realloc(list, listsize * sizeof(*list));
...
          list = newlist;
        }
...
      dnew = lib_malloc(dsize);
...
      list[cnt] = dnew;
//-----end code---------------------------------------------

So when I review code like this I start asking myself "Is everything right
here?", because:
1. it seems to me that "lib_malloc" / "lib_realloc" return pointer to "FAR"
memory.
2. "newlist" is declared as "NEAR" pointer.
3. "list" -- seems to be a "NEAR" pointer to "FAR" data.

So either my assumption that "lib_realloc" / "lib_malloc" return "FAR"
pointers is wrong or we are missing "FAR struct dirent * FAR *list = NULL;"
and "struct dirent * FAR *newlist;".

I'm feeling like my example might look like a trivial case for a person who
is strongly familiar with the "FAR" / "NEAR" concept, so I will go and read
some papers before continuing this discussion :) I just want to describe
you were my intention comes from.

Best regards,
Petro

нд, 27 бер. 2022 р. о 22:42 Gregory Nutt <sp...@gmail.com> пише:

> These are pretty standard C compiler concepts, although people used to
> > working with pure 32-/64-bit CPUs may not have experience with them.
> They
> > used to be very standard like in x86 real mode.
> >
> >
> ARM does not have near and far qualifier, but it does have some similar
> memory-related issues.  The range of a subroutine call via a BL or  branch,
> B,  is only +/- 32Mb.  That is usually large enough if you are executing
> out of a single, contiguous FLASH memory space.  But if, for example, you
> are running an ELF module in RAM at, say, 0x20000000 and calling into the
> OS in FLASH, at 0x00000000, it is not enough range.  There are no FAR
> pointers, but there is a long call compiler option(-mlong-calls) that is
> necessary to get the full 32-bit range of function calls and branches.
>

Re: FAR usage education

Posted by Gregory Nutt <sp...@gmail.com>.
These are pretty standard C compiler concepts, although people used to
> working with pure 32-/64-bit CPUs may not have experience with them.  They
> used to be very standard like in x86 real mode.
>
>
ARM does not have near and far qualifier, but it does have some similar
memory-related issues.  The range of a subroutine call via a BL or  branch,
B,  is only +/- 32Mb.  That is usually large enough if you are executing
out of a single, contiguous FLASH memory space.  But if, for example, you
are running an ELF module in RAM at, say, 0x20000000 and calling into the
OS in FLASH, at 0x00000000, it is not enough range.  There are no FAR
pointers, but there is a long call compiler option(-mlong-calls) that is
necessary to get the full 32-bit range of function calls and branches.

Re: FAR usage education

Posted by Gregory Nutt <sp...@gmail.com>.
These are pretty standard C compiler concepts, although people used to
working with pure 32-/64-bit CPUs may not have experience with them.  They
used to be very standard like in x86 real mode.

Since they are standard concepts, you can probably get the more
authoritative information by Googling, like
https://www.google.com/search?q=far+near+C+qualifers .  That brings up
dozens of technical articles on near and far pointers.

The first hit gives a pretty concise definition:
https://public.support.unisys.com/aseries/docs/ClearPath-MCP-20.0/86002268-209/section-000066613.html

The second hit, I think, answers all of you questions in the context of
some Renesas CPU:
http://tool-support.renesas.com/autoupdate/support/onlinehelp/csp/V4.01.00/CS+.chm/Compiler-CCRL.chm/Output/cd_EXP_LANG8.html

There is a lot more info out there.




On Sun, Mar 27, 2022 at 2:21 PM Petro Karashchenko <
petro.karashchenko@gmail.com> wrote:

> Hi,
>
> I want to improve my knowledge about FAR usage in NuttX code. I've already
> read some initial information related to "Far memory" and "3-byte pointers
> to access extended memory spaces", but still lacking a practical experience
> with a real compiler and device use case. My main question is about FAR
> usage notation, because currently it seems to me very confusing. I assume
> that notation is very similar to "const", but do not have a way to prove
> it, so I'm asking for help from people that have more practical experience.
> So I will go with few examples:
>
> 1. FAR char *p; -- that is fully understood. Generate code to use a 3-bytes
> pointer to char.
> 2. FAR char **p; -- here where my understanding ends. Is this a 3-byte
> pointer to an array of traditional 2-byte pointers or traditional 2-byte
> pointer to an array of 3-byte pointers? Or even a 3-byte pointer to an
> array of 3-byte pointers?
> 3. The answer to this will come from answer on 2, but still: is "FAR char *
> FAR *p;" valid?
>
> I'm asking this because sometimes I modify common code that is equipped
> with "FAR" and want to be sure that my changes will not break things.
>
> Best regards,
> Petro
>