# Introduction
NCC is a bare-metal toolchain for NOEL-V. It can be used for developing
single-threaded C and C++ applications.

Use cases
* RTL simulation
* Build benchmarks for HW and sim. execution
* Try out new features and reproduce HW bugs
* Environment for single-threaded applications
* A set of tools useful when developing a custom run-time or boot loader.

## Getting started

Extract the binary distribution and add bin to PATH. For example
  cd /opt
  tar xf ncc-1.0.0-gcc.tar.bz2
  PATH="$PATH:/opt/ncc-1.0.0-gcc/bin"

The following examples is expected to "just work" on a 64-bit NOEL-V
system.

riscv-gaisler-elf-gcc hello.c -o hello.elf

It creates a program with the following characteristics:

* RV64IM instruction set
* linked to address 0
* UART, TIMER, PLIC is probed using Plug&Play.
* Plug&Play ioarea located at 0xFFF00000.


## Multilibs
The default multilib when (no march or mabi) is used corresponds to
-march=rv64im -mabi=lp64.

  $ riscv-gaisler-elf-gcc -print-multi-lib
  .;
  rv32i/ilp32;@march=rv32i@mabi=ilp32
  rv32ic/ilp32;@march=rv32ic@mabi=ilp32
  rv32im/ilp32;@march=rv32im@mabi=ilp32
  rv32imc/ilp32;@march=rv32imc@mabi=ilp32
  rv32ima/ilp32;@march=rv32ima@mabi=ilp32
  rv32imac/ilp32;@march=rv32imac@mabi=ilp32
  rv32imafd/ilp32d;@march=rv32imafd@mabi=ilp32d
  rv32imafdc/ilp32d;@march=rv32imafdc@mabi=ilp32d
  rv64ima/lp64;@march=rv64ima@mabi=lp64
  rv64imac/lp64;@march=rv64imac@mabi=lp64
  rv64imafd/lp64d;@march=rv64imafd@mabi=lp64d
  rv64imafdc/lp64d;@march=rv64imafdc@mabi=lp64d

Note that the above list may change in the future.

# libbcc
The library consists of:
- Run-time statup code.
- Functions for programming NOEL-V.
- Implementation of newlib C standard library portability layer.

The library is available in the target library file
libbcc.a. There are multiple versions of libbcc.a, customized
for specific BSPs and compiler options (GCC multilibs). The
exact versions of the library is selected based on compiler
command line parameters. This also reflects that different
low-level drivers are implemented for different hardware.


## Usage
Functions described in the summary below have prototypes in
the header file bcc/bcc.h. The functions are implemented in
libbcc.a and are available per default when linking with the
GCC front-end. The same user API is available independent of
target NOEL-V hardware.

API summary follows. For API details, see bcc/bcc.h.


## Interrupt based timer service
Use bcc_timer_tick_init_period() to allow for the timer services
to not wrap around after 2^32 microseconds.


## Exception API
Execution aborts with ebreak by default for non-interrupt
exceptions.

This behavior can be overridden in the user application
by implementing a function named __bcc_handle_exception().
The prototype is in <bcc/bcc_param.h>. See also the example
named "exception.c".


## Interrupt disable and enable
All maskable interrupts are disabled with bcc_int_disable()
and enabled again with bcc_int_enable(). A nesting mechanism
allows multiple disable operations to be performed in sequence
without the corresponding enable operation inbetween.

Interrupts are in the enabled state when main() is called.


## Interrupt source masking
An interrupt source can be masked (disabled) with bcc_int_mask()
and unmasked (enabled) with bcc_int_unmask().


## Interrupt service routines
Functions are provided for the user to install custom interrupt
service routines.  It is possible to install multiple interrupt
handlers for the same interrupt: this is referred to as
interrupt sharing.

bcc_isr_register() and bcc_isr_unregister() can be used
to install an interrupt handler. These functions manage
memory allocation automatically by using malloc() and free()
internally.


## Processor API
libbcc is a single-threaded single-processor run-time. A limited
set of functionlity is provided to start secondary processors.

The number of processors in the system can be retrieved with
the function bcc_get_cpu_count() and the ID of the current
processor is bcc_get_cpuid().

A secondary processor (any CPU which is not CPU0) in a
multiprocessor NOEL-V system can be started by calling
bcc_start_processor().

The entry point and stack pointer is picked up from the
following data structure by the secondary processor:

        struct bcc_startinfo {
                void (*pc)(int mhartid);
                uintptr_t sp;
        };
        extern struct bcc_startinfo __bcc_startinfo[16];

An example named cpustart.c is available which demonstrates
how this can be done.


# Board support packages
A BSP is selected with the GCC option -qbsp=bspname, where
bspname specifies any of the BSPs described in this chapter. The
option is typically combined with -march=cpuname.

It is important that the -qbsp=, -march= and -mabi= options
are given to GCC both at the compile and link steps.

If option -qbsp= is not given explicitly, then -qbsp=2020q4
is implied.


## 2020q4
- 32-bit and 64-bit systems
- Uses AMBA Plug & Play to scan for devices.
- ioarea at 0xFFF00000
- RAM at    0x00000000



## Remapping ioarea
You can override the Plug&Play ioarea assumed by the run-time by defining the
global variable uintptr_t __bcc_ioarea. For example by adding the following in
global scope of a C file:

  uintptr_t __bcc_ioarea 0xffe00000;


# newlib
Low-level functionality required by newlib C standard library
is implemented in the NOEL-V specific layer (libbcc).


## File I/O
The target newlib supports file I/O on the standard
input, standard output and standard error files
(stdin/stdout/stderr). These files are always open and are
typically associated with an APBUART.

There is no support in libbcc for operating on disk files. There
is no file system support.


## Time functions
GPTIMER timer is used to generate the system time. The C
standard library functions time() and clock() return the time
elapsed in seconds and microseconds respectively. times()
and gettimeofday(), defined by POSIX, are also available.


## Dynamic memory allocation
Dynamic memory can be allocated/deallocated using for example
malloc(), calloc() and free(). For information on customizing
the memory heap,


# FAQ
Q: Which NOEL-V specific functions are available?

For the NOEL-V API functions available to applications, see the file
  libbcc/shared/include/bcc/bcc.h


Q: How do I install an exception handler?

Override the function __bcc_handle_exception(). there is a function prototype in
  libbcc/shared/include/bcc/bcc_param.h.

See also the the example in examples/exception/exception.c.


Q: How do I install an interrupt handler?

Use bcc_isr_register() and bcc_isr_unregister()
(libbcc/shared/include/bcc/bcc.h).


Q: How can I start the other processors?
See the example examples/cpustart/cpustart.c.


Q: Does the runtime support SMP?

The provided C standard library and libbcc supports a single-threaded
single-processor run-time.

Functionality is available to start secondary processors. See the "cpustart"
example.


Q: Is the C standard library available?

Yes newlib is available. malloc(), snprintf(), printf, etc can be used.
File I/O is limited to the files stdin, stdout and stderr.

