text: /****************************************************************************
   * arch/arm/src/tiva/cc13xx/cc13xx_start.c
   *
   *   Copyright (C) 2018 Gregory Nutt. All rights reserved.
   *   Author: Gregory Nutt <gnutt@nuttx.org>
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 3. Neither the name NuttX nor the names of its contributors may be
   *    used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
   * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGE.
   *
   ****************************************************************************/
  
  /****************************************************************************
   * Included Files
   ****************************************************************************/
  
  #include <nuttx/config.h>
  
  #include <stdint.h>
  #include <assert.h>
  #include <debug.h>
  
  #include <nuttx/init.h>
  #include <arch/irq.h>
  
  #include "nvic.h"
  #include "arm_arch.h"
  #include "arm_internal.h"
  
  #include "tiva_enablepwr.h"
  #include "tiva_enableclks.h"
  #include "tiva_lowputc.h"
  #include "tiva_userspace.h"
  #include "tiva_eeprom.h"
  #include "tiva_start.h"
  
  #include <arch/board/board.h>
  
  /****************************************************************************
   * Pre-processor Definitions
   ****************************************************************************/
  
  /* .data is positioned first in the primary RAM followed immediately by .bss.
   * The IDLE thread stack lies just after .bss and has size give by
   * CONFIG_IDLETHREAD_STACKSIZE;  The heap then begins just after the IDLE.
   * ARM EABI requires 64 bit stack alignment.
   */
  
  #define IDLE_STACKSIZE (CONFIG_IDLETHREAD_STACKSIZE & ~7)
  #define IDLE_STACK     ((uintptr_t)&_ebss + IDLE_STACKSIZE)
  #define HEAP_BASE      ((uintptr_t)&_ebss + IDLE_STACKSIZE)
  
  /****************************************************************************
   * Public Data
   ****************************************************************************/
  
  /* g_idle_topstack: _sbss is the start of the BSS region as defined by the
   * linker script. _ebss lies at the end of the BSS region. The idle task
   * stack starts at the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE.
   * The IDLE thread is the thread that the system boots on and, eventually,
   * becomes the IDLE, do nothing task that runs only when there is nothing
   * else to run.  The heap continues from there until the end of memory.
   * g_idle_topstack is a read-only variable the provides this computed
   * address.
   */
  
  const uintptr_t g_idle_topstack = HEAP_BASE;
  
  /****************************************************************************
   * Public Function Prototypes
   ****************************************************************************/
  
  /* REVISIT: Should be moved to a header file */
  
  void cc13xx_trim_device(void);
  
  /****************************************************************************
   * Private Functions
   ****************************************************************************/
  
  /****************************************************************************
   * Name: showprogress
   *
   * Description:
   *   Print a character on the UART to show boot status.
   *
   ****************************************************************************/
  
  #ifdef CONFIG_DEBUG_FEATURES
  #  define showprogress(c) arm_lowputc(c)
  #else
  #  define showprogress(c)
  #endif
  
  /****************************************************************************
   * Name: tiva_fpuconfig
   *
   * Description:
   *   Configure the FPU.  Relative bit settings:
   *
   *     CPACR:  Enables access to CP10 and CP11
   *     CONTROL.FPCA: Determines whether the FP extension is active in the
   *       current context:
   *     FPCCR.ASPEN:  Enables automatic FP state preservation, then the
   *       processor sets this bit to 1 on successful completion of any FP
   *       instruction.
   *     FPCCR.LSPEN:  Enables lazy context save of FP state. When this is
   *       done, the processor reserves space on the stack for the FP state,
   *       but does not save that state information to the stack.
   *
   *  Software must not change the value of the ASPEN bit or LSPEN bit while
   *  either:
   *   - the CPACR permits access to CP10 and CP11, that give access to the FP
   *     extension, or
   *   - the CONTROL.FPCA bit is set to 1
   *
   ****************************************************************************/
  
  #ifdef CONFIG_ARCH_FPU
  #ifndef CONFIG_ARMV7M_LAZYFPU
  
  static inline void tiva_fpuconfig(void)
  {
    uint32_t regval;
  
    /* Set CONTROL.FPCA so that we always get the extended context frame
     * with the volatile FP registers stacked above the basic context.
     */
  
    regval = getcontrol();
    regval |= (1 << 2);
    setcontrol(regval);
  
    /* Ensure that FPCCR.LSPEN is disabled, so that we don't have to contend
     * with the lazy FP context save behaviour.  Clear FPCCR.ASPEN since we
     * are going to turn on CONTROL.FPCA for all contexts.
     */
  
    regval = getreg32(NVIC_FPCCR);
    regval &= ~((1 << 31) | (1 << 30));
    putreg32(regval, NVIC_FPCCR);
  
    /* Enable full access to CP10 and CP11 */
  
    regval = getreg32(NVIC_CPACR);
    regval |= ((3 << (2 * 10)) | (3 << (2 * 11)));
    putreg32(regval, NVIC_CPACR);
  }
  
  #else
  
  static inline void tiva_fpuconfig(void)
  {
    uint32_t regval;
  
    /* Clear CONTROL.FPCA so that we do not get the extended context frame
     * with the volatile FP registers stacked in the saved context.
     */
  
    regval = getcontrol();
    regval &= ~(1 << 2);
    setcontrol(regval);
  
    /* Ensure that FPCCR.LSPEN is disabled, so that we don't have to contend
     * with the lazy FP context save behavior.  Clear FPCCR.ASPEN since we
     * are going to keep CONTROL.FPCA off for all contexts.
     */
  
    regval = getreg32(NVIC_FPCCR);
    regval &= ~((1 << 31) | (1 << 30));
    putreg32(regval, NVIC_FPCCR);
  
    /* Enable full access to CP10 and CP11 */
  
    regval = getreg32(NVIC_CPACR);
    regval |= ((3 << (2 * 10)) | (3 << (2 * 11)));
    putreg32(regval, NVIC_CPACR);
  }
  
  #endif
  
  #else
  #  define tiva_fpuconfig()
  #endif
  
  /****************************************************************************
   * Public Functions
   ****************************************************************************/
  
  /****************************************************************************
   * Name: _start
   *
   * Description:
   *   This is the reset entry point.
   *
   ****************************************************************************/
  
  void __start(void)
  {
  #ifdef CONFIG_BOOT_RUNFROMFLASH
    const uint32_t *src;
  #endif
    uint32_t *dest;
  
    /* Perform the necessary trim of the device which is not done in boot
     * code.
     */
  
    cc13xx_trim_device();
  
    /* Clear .bss.  We'll do this inline (vs. calling memset) just to be
     * certain that there are no issues with the state of global variables.
     */
  
    for (dest = &_sbss; dest < &_ebss; )
      {
        *dest++ = 0;
      }
  
    /* Enable power and clocking for the GPIO peripheral. */
  
    tiva_gpio_enablepwr();
    tiva_gpio_enableclk();
  
    /* Configure the UART so that we can get debug output as soon as
     * possible
     */
  
    tiva_lowsetup();
    tiva_fpuconfig();
    showprogress('A');
  
  #ifdef CONFIG_BOOT_RUNFROMFLASH
    /* Move the initialized data section from his temporary holding spot in
     * FLASH into the correct place in SRAM.  The correct place in SRAM is
     * give by _sdata and _edata.  The temporary location is in FLASH at the
     * end of all of the other read-only data (.text, .rodata) at _eronly.
     */
  
    for (src = &_eronly, dest = &_sdata; dest < &_edata; )
      {
        *dest++ = *src++;
      }
  
    showprogress('B');
  #endif
  
  #ifdef USE_EARLYSERIALINIT
    /* Perform early serial initialization */
  
    arm_earlyserialinit();
    showprogress('C');
  #endif
  
  #ifdef CONFIG_BUILD_PROTECTED
    /* For the case of the separate user-/kernel-space build, perform whatever
     * platform specific initialization of the user memory is required.
     * Normally this just means initializing the user space .data and .bss
     * segments.
     */
  
    tiva_userspace();
    showprogress('D');
  #endif
  
  #ifdef CONFIG_TIVA_CC26X2_POWERLIB /* REVISIT:  Used with CC13x2 as well. */
    /* Initialize the Power Manager internal state.  This must be called prior
     * to any other Power API.
     */
  
    cc13xx_power_initialize();
    showprogress('E');
  #endif
  
    /* Initialize on-board resources */
  
    tiva_boardinitialize();
    showprogress('F');
  
  #ifdef CONFIG_TIVA_EEPROM
    /* Initialize the EEPROM */
  
    tiva_eeprom_initialize();
    showprogress('G');
  #endif
  
    /* Then start NuttX */
  
    showprogress('\r');
    showprogress('\n');
    nx_start();
  
    /* Shouldn't get here */
  
    for (; ; );
  }
  