Hi,
Let me volunteer suggestions to at some of your questions.
Also (unrelated to the patch), somethings that I think should be discussed/addressed soon are:
- How we will handle the boards in nuttx (including variants like
US/EU version of the same phone)
Nuttx is designed to support a hiearchical configuration: processor family, chips in the family, boards that host the chips, and board software configurations.
NuttX is configured with .config file. In that file you specify the family (ARM), the chip (Calypso), and the board (also Calypso now?). The family corresponds to a directory under arch/ (arch/arm) and the chip corresponds to sub-directories under arch/arm/src and arch/arm/include (arch/arm/src/calypso and arch/arm/include/calypso). * arch/arm/include holds general ARM header files
* arch/arm/include/calypso holds calypso specific header files
* arch/arm/src/calypso holds calypso specific source files
Boards are represented by directories under configs/. Right now, I think there is only a configs/compal_e99.
* configs/compal_e99/include holds Compal E99 specific header files
* configs/compal_e99/src holds Compal E99 specific header files
Other directories under configs/compal_e99 can hold different software configurations for the same board. For example, configs/compal_e99/ostest holds the make logic for the OS test; configs/compal_e99/nsh would hold the NuttShell (NSH) make configuration files, etc. The .config file, for example, is on of the software configuration files in those directories (it is call defconfig before it is copied to the top-level directory as .config).
You can see these settings in the .config/defconfig file: CONFIG_ARCH=arm
CONFIG_ARCH_ARM=y CONFIG_ARCH_ARM7TDMI=y CONFIG_ARCH_CHIP=calypso CONFIG_ARCH_CHIP_CALYPSO=y CONFIG_ARCH_BOARD=compal_e99 CONFIG_ARCH_BOARD_COMPALE99=y
When the OS is configured, the top-level Makefile uses these definitions to create symbolic links:
* arch/arm/src/chip will refer to arch/arm/src/calypso
* arch/arm/include/chip will refer to arch/arm/include/calypso
* arch/arm/include/board will refer to configs/compal_e99/include
* arch/arm/src/board will refer to configs/compal_e99/src.
And
* include/arch will refer to to arch/arm/include
So you can include ARM general header, calypso-specific, and board-specific header files like:
#include <arch/arch.h> // architecture (ARM) specific header files
#include <arch/chip/chip.h> // Chip (calypso) specific header files #include <arch/board/board.h> // Board specific header files
So, if you want to support the same processor (calypso) on a different board, say boardX, you could create a directory:
configs/boardX And put boardX specific header files and source files in:
configs/boardX/include
configs/boardX/src
And put boardX software configurations under
config/boardX/configY
- How we will handle our different ram config (boot from ram / flash),
can we use the loader to load part of the SDRAM if we don't fit in SRAM completely ?
I would think that these would correspond to different software build configuration directories under configs/BoardX.
You also ask several memory related questions that I can't really answer. I think there may be some additional memory management requirements here:
- How we will handle the memory zones (SRAM / SDRAM / Flash / XIP from
flash (or just .rodata ?))
- Memory allocator (handling zones ...). I think that'd be something
very useful. Currently we can only allocate msgb and that's a little limiting.
Right now, the memory allocator can handle multiple, discontinuous regions of memory. There is an interface called mm_addregion() that can always add a new block of memory to the memory pool.
But there is mechanism now to select which region memory will be allocated from. malloc() is the only allocator for user programs. It will allocate memory only from the best fitting free memory chunk, but does not take into account any properties of the memory.
Greg
Gregory,
thanks a lot for your detailed response.
On Mon, May 23, 2011 at 02:14:52PM -0700, Gregory Nutt wrote:
Nuttx is designed to support a hiearchical configuration: processor family, chips in the family, boards that host the chips, and board software configurations. [..]
I think there is no obvious missing part from our requirements point of view.
config/boardX/configY
- How we will handle our different ram config (boot from ram / flash),
can we use the loader to load part of the SDRAM if we don't fit in SRAM completely ?
I would think that these would correspond to different software build configuration directories under configs/BoardX.
btw: there is no SDRAM. IT's SRAM, but there is external SRAM (slow) and internal SRAM (fast), as well eas external NOR flash. The normal procedure is to use section attributes in the code to determine which parts of the code get put into what part of memory. I think Nuttx doesn't care much about this, except that we will have custom linker scripts that will produce output for the different memory regions.
I think the division will be roughly: * internal SRAM * super time critical code like FIQ handler for GSM TDMA * IRQ and FIQ stack * normal process stack? * external SRAM * external NOR flash * bootloader * .text segment of Nuttx, XIP * filesystem
this is at least the configuration that would make most sense for the final version. During development (so far) we have been using no code in flash, and always loaded our code into RAM on every boot. This is definitely also a configuration that would make sense to have with Nuttx. But here it would probably make even more sense to have the Nuttx kernel in NOR flash and only load our application into external+internal SRAM.
You also ask several memory related questions that I can't really answer. I think there may be some additional memory management requirements here:
- How we will handle the memory zones (SRAM / SDRAM / Flash / XIP from
flash (or just .rodata ?))
XIP from flash should be a no-brainer, if the code is linked to the right address. I guess we simply divide the flash in one .text+.rodata part, and one filesystem partition.
SRAM/SDRAM division as indicated above. Linker script will take care of correct linking. The only part I see is that our bootloader will have to load the different segments to different addresses correctly before jumping into Nuttx.
- Memory allocator (handling zones ...). I think that'd be something
very useful. Currently we can only allocate msgb and that's a little limiting.
Right now, the memory allocator can handle multiple, discontinuous regions of memory. There is an interface called mm_addregion() that can always add a new block of memory to the memory pool.
I think what our use case really wants is something that can efficiently create (and allocate from) pools of same-sized objects (like our 'struct msgb'). We'll probably have to code something custom for it,
One real Nuttx related question that I have in mind though: Do you see an easy way how we can keep our 'application' code (that is all the GSM related stuff) in a separete source repository? I would like to come up with a situation where we have two repositories:
1) Nuttx (contains calypso uart/spi/i2c/lcd/... drivers and demo apps) 2) OsmocomBB (contains GSM layer1 and our application code)
The reason for this is simple: The GSM code is still under a lot of flux, and we have many branches of it for different types of experiments. None of it will be useful to the general Nuttx user, as it is very specific to our project.
Would it be as simple as to put a symlink pointing to the OsmocomBB repository somewhere in the Nuttx source tree?
Regards, Harald
Hi, Harald,
.. The normal procedure is to use section attributes in the code to determine which parts of the code get put into what part of memory. I think Nuttx doesn't care much about this, except that we will have custom linker scripts that will produce output for the different memory regions.
The NuttX startup logic may have to care in that it may have to initialize data sections. Running in RAM, the start-up code may have to initialized .bss. But running out of FLASH, it will need to copy .data from into RAM. If you want executable code in internal SRAM, then that code would have to be copied into IRAM in either case.
... During development (so far) we have been using no code in flash, and always loaded our code into RAM on every boot. This is definitely also a configuration that would make sense to have with Nuttx.
This worked fine that last time I used that configuration. There is a configuration option CONFIG_BOOT_RUNFROMFLASH that would have to be deselected so that it would not try to initialize .data (and a different linker script would have to be used so that initialization data is not saved in FLASH)
... But here it would probably make even more sense to have the Nuttx kernel in NOR flash and only load our application into external+internal SRAM.
Are you talking about a separately linked, monolithic kernel (like a tiny Linux) and a separately built application image? The application image would then have to communicate to the monolithic kernel either through a call table or through system calls (or it would have to be linked with the kernel image at build time).
Is that what you are thinking? I have implemented that configuration for the Cortex M3 (with supervisor/user mode and system calls). There there hooks are in place for ARM7 as well but more integration work is needed.
XIP from flash should be a no-brainer, if the code is linked to the right address. I guess we simply divide the flash in one .text+.rodata part, and one filesystem partition.
XIP from FLASH can mean a lot of things. Running a NuttX image from flash truly is a no brainer. Running separate programs from FLASH is complex because dynamic linking is needed. NuttX supports a file format called NXFLAT that will let you run a program from an XIP file system (like ROMFS) but it needs a symbol table and NXFLAT loader (the moral equivalent of ld.so).
SRAM/SDRAM division as indicated above. Linker script will take care of correct linking. The only part I see is that our bootloader will have to load the different segments to different addresses correctly before jumping into Nuttx.
Or if NuttX is in FLASH, it can copy memory as it does now to initialize .data.
I think what our use case really wants is something that can efficiently create (and allocate from) pools of same-sized objects (like our 'struct msgb'). We'll probably have to code something custom for it,
That seems appropriate.
One real Nuttx related question that I have in mind though: Do you see an easy way how we can keep our 'application' code (that is all the GSM related stuff) in a separete source repository? I would like to come up with a situation where we have two repositories:
- Nuttx (contains calypso uart/spi/i2c/lcd/... drivers and demo apps)
- OsmocomBB (contains GSM layer1 and our application code)
The reason for this is simple: The GSM code is still under a lot of flux, and we have many branches of it for different types of experiments. None of it will be useful to the general Nuttx user, as it is very specific to our project.
Yes, I am sure you have noticed that NuttX is provided as two tarballs: One called nuttx-a.b.tar.gz that hold the core OS functionality in the nuttx/ directory and one called apps-a.b.tar.gz that holds sample application code in the apps/. That apps/ directory is meant to be a "break-away." You would discard the current apps/ directory (taking whatever is useful to you), and create your own application directory.
When NuttX builds is needs to know the location of the apps directory. In the .config configuration file, you will see:
# # General OS setup # # CONFIG_APPS_DIR - Identifies the relative path to the directory # that builds the application to link with NuttX. Default: ../apps ... #CONFIG_APPS_DIR=
Note that CONFIG_APPS_DIR is not defined. And at the very bottom of the configuration file you will see:
# Application configuration
CONFIG_APPS_DIR="../apps"
The version of CONFIG_APPS_DIR at the bottom of the .config file was not in the original defconfig file. It was appended by the configuration script. The configuration script noted that there was no application directory and looked around in some well known locations and picked one.
However, if you were to have defined CONFIG_APPS_DIR=../calypso, then that is the application directory that would have been used. Your low-level drivers and ARM7 code code could be released inside of the common nuttx repository. But your application-specific code would reside in your custom application directory.
Would you like to retain the Calypso code in the NuttX SVN repository? There are some long range advantages to that in that the Calypso code will maintained and will always be in sync with the latest NuttX. Licensing is the only issue. NuttX is BSD and Calypso is GPL. So the possibilities are: (1) You carry the NuttX code in your repository, (2) You release the Calypso OS (only) logic under BSD, or (3) I carry the Calypso code as GPL add-on.
The base NuttX is BSD, but I have started putting together GPL add-on support. I would keep the GPL separate and there would be an INSTALL script. In the install script would require that the user agree to the GPL license. And if so, it would copy the GPL code into the NuttX source tree and replace the COPYING files, making the combined code GPL. This is kind of awkward, but if you would like to have a GPL version of NuttX for Calypso, then I think this could be the way to go.
Greg
Yes, I am sure you have noticed that NuttX is provided as two tarballs: One called nuttx-a.b.tar.gz that hold the core OS functionality in the nuttx/ directory and one called apps-a.b.tar.gz that holds sample application code in the apps/. That apps/ directory is meant to be a "break-away." You would discard the current apps/ directory (taking whatever is useful to you), and create your own application directory.
Note that our "App" is more than a userspace "app"
It's also a FIQ interrupt handler and some 'drivers' (for the GSM specific stuff like DSP / TPU and the RF / external chips). I'm also leaning toward having the board definition separate (at least part of them) since they'll including things like RFFE stuff that will only be useful for the GSM stuff.
Cheers,
Sylvain
On 24.05.2011 16:46, Sylvain Munaut wrote:
Note that our "App" is more than a userspace "app"
Since we don't have a MMU, it's not much of a difference and there is no real userspace. We can still register IRQs etc. I would suggest that the GSM specific calls in board_init are moved to the "userspace" user_start function. For the MT6235, we need a cleaner API once it runs Linux. But for now on Nuttx, the current things are fine.
It's also a FIQ interrupt handler and some 'drivers' (for the GSM specific stuff like DSP / TPU and the RF / external chips).
I'll add FIQs and extend the interface to support them soon.
I'm also leaning toward having the board definition separate (at least part of them) since they'll including things like RFFE stuff that will only be useful for the GSM stuff.
Well, the configs directory holds board specific stuff. However, it's probably not the appropriate place since it doesn't belong to the OS bit is GSM related.
Cheers,
Sylvain
Hi Gregory,
On Tue, May 24, 2011 at 06:38:10AM -0700, Gregory Nutt wrote:
... But here it would probably make even more sense to have the Nuttx kernel in NOR flash and only load our application into external+internal SRAM.
Are you talking about a separately linked, monolithic kernel (like a tiny Linux) and a separately built application image? The application image would then have to communicate to the monolithic kernel either through a call table or through system calls (or it would have to be linked with the kernel image at build time).
Well, the call table or syscall approach may be nice to have in the future, but even linking it at build time (so it knows the addresses of the various kernel functions it wants to call) would be fine for me right now.
Is that what you are thinking? I have implemented that configuration for the Cortex M3 (with supervisor/user mode and system calls). There there hooks are in place for ARM7 as well but more integration work is needed.
I've tried to compile the syscall code for ARM7TDMI and figured it is not complete yet. As indicated above, I don't think it's a big deal. We shouldn't try to put too much effort into changing/extending Nuttx and rather use what's there and focus on our GSM related work.
XIP from flash should be a no-brainer, if the code is linked to the right address. I guess we simply divide the flash in one .text+.rodata part, and one filesystem partition.
XIP from FLASH can mean a lot of things. Running a NuttX image from flash truly is a no brainer.
that's what I was primarily thinking of.
Running separate programs from FLASH is complex because dynamic linking is needed. NuttX supports a file format called NXFLAT that will let you run a program from an XIP file system (like ROMFS) but it needs a symbol table and NXFLAT loader (the moral equivalent of ld.so).
if those things exist and work for ARM7TDMI: great, let's use them. If not, we can live with that, too. The idea of separate kernel and application images is simple: We normally download our code via a 115,200 bps serial line, and to speed up development it would be great to not re-download "all of" nuttx again, but only the GSM related applicaitons.
One real Nuttx related question that I have in mind though: Do you see an easy way how we can keep our 'application' code (that is all the GSM related stuff) in a separete source repository? I would like to come up with a situation where we have two repositories:
- Nuttx (contains calypso uart/spi/i2c/lcd/... drivers and demo apps)
- OsmocomBB (contains GSM layer1 and our application code)
The reason for this is simple: The GSM code is still under a lot of flux, and we have many branches of it for different types of experiments. None of it will be useful to the general Nuttx user, as it is very specific to our project.
Yes, I am sure you have noticed that NuttX is provided as two tarballs:
Actually I haven't noticed since I rarely use any release tarballs of FOSS projects but simply the contents of the revision control system. But I've noticed the nuttx/ and apps/ directories ;)
When NuttX builds is needs to know the location of the apps directory. In the .config configuration file, you will see: # # General OS setup # # CONFIG_APPS_DIR - Identifies the relative path to the directory # that builds the application to link with NuttX. Default: ../apps ... #CONFIG_APPS_DIR=
great, we will simply use that feature then.
Would you like to retain the Calypso code in the NuttX SVN repository? There are some long range advantages to that in that the Calypso code will maintained and will always be in sync with the latest NuttX.
yes, this is what I had in mind.
Licensing is the only issue. NuttX is BSD and Calypso is GPL. So the possibilities are: (1) You carry the NuttX code in your repository, (2) You release the Calypso OS (only) logic under BSD, or (3) I carry the Calypso code as GPL add-on.
We've already briefly discussed this either here or on IRC, and I have no problems with the 'standard' non-gsm port+drivers to be under a BSD license. We would have to see if all developers agree, but I don't see big problems here.
BTW, since we're in this discussion anyway: The synchronous part of the GSM Layer1 right runs in FIQ context, to ensure the tight timing of the TDMA nature of GSM. All non-GSM related interrupts are normal IRQs, so they can be pre-empted by the GSM FIQ.
Do you see any problems with this? Is there something in the Nuttx ARM7TDMI related code that disables FIQs or otherwise interferes with them?
Thanks once again for all your support, Harald
Hi all,
after that bunch of patches, some more thoughts:
On 24.05.2011 17:04, Harald Welte wrote:
Hi Gregory,
On Tue, May 24, 2011 at 06:38:10AM -0700, Gregory Nutt wrote:
Running separate programs from FLASH is complex because dynamic linking is needed. NuttX supports a file format called NXFLAT that will let you run a program from an XIP file system (like ROMFS) but it needs a symbol table and NXFLAT loader (the moral equivalent of ld.so).
if those things exist and work for ARM7TDMI: great, let's use them. If not, we can live with that, too. The idea of separate kernel and application images is simple: We normally download our code via a 115,200 bps serial line, and to speed up development it would be great to not re-download "all of" nuttx again, but only the GSM related applicaitons.
My plan is to bring up NuttShell, add NXFLAT support and put that into flash. We can then load a ramfs image by whatever means and execute the app.
The problem is that the UART driver is still a hack. I'm reusing the Osmocom code (with IRQ stuff modified) and wrapped it into a Nuttx device structure. However, this is one-way phone to host for the time being. The current UART driver is closely tied to sercomm and the console, respectively. A cleaner seperation might help ports to other devices, new protocols, etc.
Before I spend more work on the current code: Is the sercomm protocol successful and will stay? What interface to userspace do you suggest? Should be something that works on Linux if our stuff ends up on more powerful devices. My proposal: A char device /dev/sercomm Each time you open it, it starts a new channel. With ioctl, you can change the channel. Each write is send as a message. Nuttx has buffers for stdio and hence will take care that there are not too many messages (I hope :P ) The receive part: a blocking read?
When NuttX builds is needs to know the location of the apps directory. In the .config configuration file, you will see: # # General OS setup # # CONFIG_APPS_DIR - Identifies the relative path to the directory # that builds the application to link with NuttX. Default: ../apps ... #CONFIG_APPS_DIR=
great, we will simply use that feature then.
If you don't see any problems, I would like to go one step further and move some of the hardware initialization like dsp, dma,... into user_main. Advantage: I won't go into the binary if you don't need it (hello_world, charger debugging, whatever)
BTW, since we're in this discussion anyway: The synchronous part of the GSM Layer1 right runs in FIQ context, to ensure the tight timing of the TDMA nature of GSM. All non-GSM related interrupts are normal IRQs, so they can be pre-empted by the GSM FIQ.
Do you see any problems with this? Is there something in the Nuttx ARM7TDMI related code that disables FIQs or otherwise interferes with them?
I thought local_fiq_disable() in secomm_cons messes around with FIQs. Why is that save or what does it actually do?
Thanks once again for all your support, Harald
Regards, Stefan
Before I spend more work on the current code: Is the sercomm protocol successful and will stay? What interface to userspace do you suggest?
I think that yes sercomm is useful and should stay but be 'separate'.
So my vision is to have a real 'normal' uart driver. Then 'above' that, we have a 'sercomm' layer that allows multiple protocol to be 'registred' over it and one of those would be a 'virtual' uart driver that would have for nuttx the same interface as any other driver). Then the gsm ass would just register another DLCI handler for the L1CTL link. And you just configure the 'secomm' layer to use any nuttx uart (in our case the ) as physical link.
|Ser com UART | Sercom L1CTL | Sercomm xxx | ------------------------------------------- Sercomm layer ------------------------------------------- Phys UART
My proposal: A char device /dev/sercomm Each time you open it, it starts a new channel. With ioctl, you can change the channel. Each write is send as a message. Nuttx has buffers for stdio and hence will take care that there are not too many messages (I hope :P ) The receive part: a blocking read?
On linux, yes that sounds good, but I would also have an internal API (for the kernel) so that you can create a real /dev/ttyXXX driver that talks over sercomm as well.
If you don't see any problems, I would like to go one step further and move some of the hardware initialization like dsp, dma,... into user_main. Advantage: I won't go into the binary if you don't need it (hello_world, charger debugging, whatever)
DSP is really GSM specific and should not be there IMHO because it's one of those things that can change (especially all the API zone init and the patches loading). It's also completely useless for anything but GSM.
I thought local_fiq_disable() in secomm_cons messes around with FIQs. Why is that save or what does it actually do?
it's to protect the state of the various queues and some shared state.
Hi Stefan,
On Wed, May 25, 2011 at 12:13:31AM +0200, l--putt wrote:
Before I spend more work on the current code: Is the sercomm protocol successful and will stay?
yes.
What interface to userspace do you suggest?
each DLC should be a separate device e.g. /dev/ttyHDLC0.., so a userspace process can simply open one DLC and read/write to it using stadard read/write calls.
Should be something that works on Linux if our stuff ends up on more powerful devices. My proposal: A char device /dev/sercomm Each time you open it, it starts a new channel.
No, please make it explicit and have one device for each DLC Automatically assigning a channel is not a useful feature.
With ioctl, you can change the channel.
then you would have to do that ioctl() every time. I like the idea of one device per DLC better.
Each write is send as a message. Nuttx has buffers for stdio and hence will take care that there are not too many messages (I hope :P )
The receive part: a blocking read?
either blocking read, or the user can set O_NONBLOCK and do select/poll (not sure if nuttx supports that, but at least on Linux it would work)
In terms of Linux there may already be a more generic serial multiplexer protocol that we can re-use. Not sure if it finally has a TS07.10 multiplexer, e.g. If yes, the we may consider switching to TS07.10 instead of our homebrew HDLC.
In any case, on Linux the multiplex driver would be bound as a line discipline to the real serial port, and offers N virtual serial ports for the N DLCs.
Do you see any problems with this? Is there something in the Nuttx ARM7TDMI related code that disables FIQs or otherwise interferes with them?
I thought local_fiq_disable() in secomm_cons messes around with FIQs. Why is that save or what does it actually do?
it is neccessary as we also want to log messages from the L1. Right now the L1 (from FIQ) submits a log message, and the normal code in the UART driver fetches those messages and writes them to the UART. You need some kind of locking/mutex for a very short time to protect the queue of messages here.
baseband-devel@lists.osmocom.org