zephyriot / zephyr-issues

0 stars 0 forks source link

Port Zephyr to Altera Max10 (Nios 2 CPU) #185

Closed nashif closed 8 years ago

nashif commented 8 years ago

Reported by Andrew Boie:

We are interested in supporting FPGAs running the Nios II CPU. This will be a ground-up arch port.

(Imported from Jira ZEP-178)

nashif commented 8 years ago

by Andrew Boie:

What is needed to write an arch port:
------

Startup sequence: 

- Bring the system in a state where it can run C code
  - if not always using an elf loader:
    - copy data from ROM if needed
    - clear BSS
  - architecture-specific operations (e.g. setup segment registers on x86)

- Jump to _Cstart(), the early kernel initialization
  - _Cstart() is responsible for context switching out of the fake context
    running at startup into the background/idle task

The microkernel is completely written in C, and is almost entirely
arch-agnostic, and runs on top of the nanokernel. The arch port is thus
mostly constrained to the nanokernel.

- exception handling
- interrupt handling
  - the ISR signature is void (*isr)(void *arg), so if the arch cannot support
    it, implement the sw_isr_table like ARM and ARC
  - for that implementation, there is only one main ISR installed in the vector
    table, a demux from a table that contains the device ISR and arg
- timer driver for system clock, for both nano and micro.
  - nanokernel timers/timeouts handled in timer ISR
  - microkernel timers handling deferred to k_server fiber as a kernel event
  - tickless idle support optional, but strongly suggested
- interrupt controller driver
- serial port driver for console
- context switch
  - _Swap() is the cooperative context switch, which is called by task and
    fiber nanokernel objects when they have to yield the CPU
    - when the context switch is called, you _know_ there is the need for a
      context switch, i.e. _Swap() finds out _what_ to switch in, not _if_
      something has to be switched in
    - the context switch might be called when exiting any interrupt
    - the decision to invoke the context switch is extrememly simple
      - if the interrupted thread is a fiber, do not invoke it
      - else, if there is a fiber ready, invoke it
      - else, do not invoke it
  - When calling _Swap(), since it is cooperative, the caller-saved registers
    from the ABI are already saved on the stack, so there is no need to save
    the in the TCB
- _new_thread() that constructs the context for starting a fiber/task
  - sets up the stack frame that _Swap() is able to use to context switch to
    the new thread
- if needed by the arch: fiber and/or task abort routine
  - e.g. ARM Cortex-M needs to exit handler mode if taking an exception, but
    not if the thread exits gracefully
- atomic operators: if instructions don't exist for the arch, create a generic
  version that wraps irq_lock/unlock around non-atomic operations (trivial, but
  does not currently exist)
- find-first/last-set functions
- linker script (most sections can be derived from other arches + arch-specific
  ones if needed)
- CPU idling
  - at least the APIs are needed, even if they are NOPs
  - nanoCpuAtomicIdle() must be able to put the CPU in idle _and_ reenable the
    interrupts atomically
- fatal error handler
  - _NanoFatalErrorHandler(), called by software for unrecoverable errors
  - _SysFatalErrorHandler(), which takes the decision on how to handle the
    thread where the error is generated, most likely by terminating it
- arch-specific definitions in toolchain/gcc.h

Nice to have:
- fault handling on unwanted exceptions
- spurious interrupt handler
- tickless idle support
- real CPU idling
nashif commented 8 years ago

by Andrew Boie:

I believe the work involved has been scoped. I had intended to start work on it and have already made a little progress on some preliminaries. I have a call shortly with Altera to discuss how they can help out, they are interested in contributing. In summary:

Preliminaries: Get a working toolchain in the SDK (in progress with Juro) Determine command-line/scriptable process for flashing an image (can do this now with Linux image, Altera people should be able to help optimize) BKM for GDB debugging via JTAG interface Finalize Nios II config. Going to discuss with Altera folks, but I think what we want is Nios II/e (economy) with timer IP block, no MMU/MPU, no caches, simple non-vectored internal interrupt controller.

Signs of life: Get a linker script going which sets up memory the way we want. Write ASM code that runs before Cstart(). Zero BSS, copy R/W stuff to RAM, do any arch-specific initialization, jump into Cstart() to get the nanokernel going. Core interrupt/exception handling code. Nios II/e is fortunately very simple in this area. Can port much of the ARC/ARM sw_isr_table stuff. Core arch-specific scheduling stuff: Write _Swap() for this arch, _new_thread(), fiber/task abort routines, idle routines (can be no-ops for now) Bring in C-based ffs, atomic ops A few necessary drivers: timer driver, console UART

After this point, I believe that this will then be very parallelizable to write more drivers for interesting IP blocks, do real ASM implementations of atomic ops or ffs functions etc, tickless idle, real CPU idling, etc. I could probably get Altera started on some of these (like the ASM implementations) while I get the signs of life going.

Bonus: Altera SW stack has a HAL library with BSD-licensed example drivers for their IP blocks, which I think can be a very useful reference.

Let me know if you have any additional questions. I'm tracking the work in GH-1746.

Andrew

-----Original Message----- From: Nashif, Anas Sent: Wednesday, April 13, 2016 10:19 AM To: Boie, Andrew P andrew.p.boie@intel.com Cc: Rhoads, Rob rob.rhoads@intel.com Subject: Re: MSR Andrew Boie April 2016

Andrew, The work on NIOS-2 you are doing, is it scoping work or are you already beyond this phase and intending to do the actual port?

Anas

nashif commented 8 years ago

by Andrew Boie:

This has been broken up into an Epic and a bunch of User Stories, see GH-280