Introduction to PX4 and Ardupilot (Chapter 1: Architecture and Startup Process)

Keywords: network shell osd socket

abstract

This section mainly records the comparison documents between the code architecture of px4 and Ardupilot, welcome criticism and correction.

  (1)px4 and apm The Difference and Connection of Firmware
  (2)px4 and apm The role of each folder
  (3)px4 and apm Start-up process of UAV
  • 1
  • 2
  • 3

Section one: px4 and apm Differences and Connections


(1)pixhawk

(2)APM

(3)px4—Firmware

(4)apm—Ardupilot

The second section: px4 and apm The role of each folder

(1)px4 Code Code Architecture
1>Collation catalog

2>The role of each folder

(2)apm Code Code Architecture
1>Collation catalog

2>The role of each folder

The third section: px4 and apm Start-up process of UAV

I'll just talk about it here. Nuttx Boot to ArduCopter The process of multi-rotor entry function, Bootloader reach Nuttx The process will be: Bootloader Startup analysis Explain in Chinese.

1.px4 Firmware startup process

(1)Bootloader After startup, the entry function of MCU is: stm32_start.c

Questions to consider: The start-up process is STM32F427 still STM32F103 The entrance, or both.

//Restored entry function: This is the reset entry point.
void __start(void)
{
  const uint32_t *src;
  uint32_t *dest;

#ifdef CONFIG_ARMV7M_STACKCHECK
  /* Set the stack limit before we attempt to call any functions */

  __asm__ volatile ("sub r10, sp, %0" : : "r" (CONFIG_IDLETHREAD_STACKSIZE - 64) : );
#endif

  /* Configure the UART so that we can get debug output as soon as possible */

  stm32_clockconfig(); //Initialization Clock
  stm32_fpuconfig();   //Configure FPU (Floating Point Operations)
  stm32_lowsetup();    //Basic initialization of the serial port, and then up_lowputc()
  stm32_gpioinit();    //Initialize gpio, just call stm32_gpioremap() to set up remapping
  showprogress('A');   //Output A

  /* 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 = _START_BSS; dest < _END_BSS; )
    {
      *dest++ = 0;
    }

  showprogress('B');

  /* 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 = _DATA_INIT, dest = _START_DATA; dest < _END_DATA; )
    {
      *dest++ = *src++;
    }

  showprogress('C');

#ifdef CONFIG_ARMV7M_ITMSYSLOG
  /* Perform ARMv7-M ITM SYSLOG initialization */

  itm_syslog_initialize();
#endif

  /* Perform early serial initialization */

#ifdef USE_EARLYSERIALINIT
  up_earlyserialinit(); //Initialize the serial port and then use up_putc()
#endif
  showprogress('D');

  /* 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.
   */

#ifdef CONFIG_BUILD_PROTECTED
  stm32_userspace();
  showprogress('E');
#endif

  /* Initialize onboard resources */

  stm32_boardinitialize();  //STM32 hardware board configuration initialization, completion, after which you can start STM32 Nutx operating system
  showprogress('F');

  /* Then start NuttX */

  showprogress('\r');
  showprogress('\n');

#ifdef CONFIG_STACK_COLORATION
  /* Set the IDLE stack to the coloration value and jump into os_start() */

  go_os_start((FAR void *)&_ebss, CONFIG_IDLETHREAD_STACKSIZE);
#else
  /* Call os_start() */

  os_start();  //Start Nuttx Operating System

  /* Shoulnd't get here */

  for (; ; ); //Enter the dead cycle, do you see here is basically the same as the general FreeRTOS, that is to configure hardware clocks, serial ports, IO and so on, can start the Nuttx operating system, and then execute the while dead cycle?
#endif
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

(2) Nutx startup entry function: void os_start(void)

/****************************************************************************
 * Name: os_start
 *
 * Description:
 *   This function is called to initialize the operating system and to spawn
 *   the user initialization thread of execution.  This is the initial entry
 *   point into NuttX
 *
 * Input Parameters:
 *   None
 *
 * Returned value:
 *   Does not return.
 *
 ****************************************************************************/
//This function is called to initialize the operating system and generate an executing user initialization thread. This is NuttX's initial entry point.
void os_start(void)
{
#ifdef CONFIG_SMP
  int cpu;
#else
# define cpu 0
#endif
  int i;

  sinfo("Entry\n");

  /* Boot up is complete */

  g_os_initstate = OSINIT_BOOT;

  /* Initialize RTOS Data ***************************************************/
  /* Initialize all task lists */

  dq_init(&g_readytorun); //Initialize a list of tasks in various states (null)
  dq_init(&g_pendingtasks);
  dq_init(&g_waitingforsemaphore);
#ifndef CONFIG_DISABLE_SIGNALS
  dq_init(&g_waitingforsignal);
#endif
#ifndef CONFIG_DISABLE_MQUEUE
  dq_init(&g_waitingformqnotfull);
  dq_init(&g_waitingformqnotempty);
#endif
#ifdef CONFIG_PAGING
  dq_init(&g_waitingforfill);
#endif
  dq_init(&g_inactivetasks);
#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
     defined(CONFIG_MM_KERNEL_HEAP)
  sq_init(&g_delayed_kfree);
#endif
#ifndef CONFIG_BUILD_KERNEL
  sq_init(&g_delayed_kufree);
#endif

#ifdef CONFIG_SMP
  for (i = 0; i < CONFIG_SMP_NCPUS; i++)
    {
      dq_init(&g_assignedtasks[i]);
    }
#endif

  /* Initialize the logic that determine unique process IDs. */

  g_lastpid = 0;
  for (i = 0; i < CONFIG_MAX_TASKS; i++) //Initialize the only deterministic element -- process ID
    {
      g_pidhash[i].tcb = NULL;
      g_pidhash[i].pid = INVALID_PROCESS_ID;
    }

  /* Initialize the IDLE task TCB *******************************************/
//Initialize idle task TCB
#ifdef CONFIG_SMP
  for (cpu = 0; cpu < CONFIG_SMP_NCPUS; cpu++, g_lastpid++)
#endif
    {
      FAR dq_queue_t *tasklist;
      int hashndx;

      /* Assign the process ID(s) of ZERO to the idle task(s) */

      hashndx                = PIDHASH(g_lastpid);
      g_pidhash[hashndx].tcb = &g_idletcb[cpu].cmn;
      g_pidhash[hashndx].pid = g_lastpid;

      /* Initialize a TCB for this thread of execution.  NOTE:  The default
       * value for most components of the g_idletcb are zero.  The entire
       * structure is set to zero.  Then only the (potentially) non-zero
       * elements are initialized. NOTE:  The idle task is the only task in
       * that has pid == 0 and sched_priority == 0.
       */

      memset((void *)&g_idletcb[cpu], 0, sizeof(struct task_tcb_s));
      g_idletcb[cpu].cmn.pid        = g_lastpid;
      g_idletcb[cpu].cmn.task_state = TSTATE_TASK_RUNNING;

      /* Set the entry point.  This is only for debug purposes.  NOTE: that
       * the start_t entry point is not saved.  That is acceptable, however,
       * becaue it can be used only for restarting a task: The IDLE task
       * cannot be restarted.
       */

#ifdef CONFIG_SMP
      if (cpu > 0)
        {
          g_idletcb[cpu].cmn.start      = os_idle_trampoline;
          g_idletcb[cpu].cmn.entry.main = os_idle_task;
        }
      else
#endif
        {
          g_idletcb[cpu].cmn.start      = (start_t)os_start;
          g_idletcb[cpu].cmn.entry.main = (main_t)os_start;
        }

      /* Set the task flags to indicate that this is a kernel thread and, if
       * configured for SMP, that this task is locked to this CPU.
       */

#ifdef CONFIG_SMP
      g_idletcb[cpu].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_NONCANCELABLE |
                                  TCB_FLAG_CPU_LOCKED);
      g_idletcb[cpu].cmn.cpu   = cpu;
#else
      g_idletcb[cpu].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_NONCANCELABLE);
#endif

#ifdef CONFIG_SMP
      /* Set the affinity mask to allow the thread to run on all CPUs.  No,
       * this IDLE thread can only run on its assigned CPU.  That is
       * enforced by the TCB_FLAG_CPU_LOCKED which overrides the affinity
       * mask.  This is essential because all tasks inherit the affinity
       * mask from their parent and, ultimately, the parent of all tasks is
       * the IDLE task.
       */

      g_idletcb[cpu].cmn.affinity = SCHED_ALL_CPUS;
#endif

#if CONFIG_TASK_NAME_SIZE > 0
      /* Set the IDLE task name */

#  ifdef CONFIG_SMP
      snprintf(g_idletcb[cpu].cmn.name, CONFIG_TASK_NAME_SIZE, "CPU%d IDLE", cpu);
#  else
      strncpy(g_idletcb[cpu].cmn.name, g_idlename, CONFIG_TASK_NAME_SIZE);
      g_idletcb[cpu].cmn.name[CONFIG_TASK_NAME_SIZE] = '\0';
#  endif
#endif

      /* Configure the task name in the argument list.  The IDLE task does
       * not really have an argument list, but this name is still useful
       * for things like the NSH PS command.
       *
       * In the kernel mode build, the arguments are saved on the task's
       * stack and there is no support that yet.
       */

#if CONFIG_TASK_NAME_SIZE > 0
      g_idleargv[cpu][0]  = g_idletcb[cpu].cmn.name;
#else
      g_idleargv[cpu][0]  = (FAR char *)g_idlename;
#endif /* CONFIG_TASK_NAME_SIZE */
      g_idleargv[cpu][1]  = NULL;
      g_idletcb[cpu].argv = &g_idleargv[cpu][0];

      /* Then add the idle task's TCB to the head of the corrent ready to
       * run list.
       */

#ifdef CONFIG_SMP
      tasklist = TLIST_HEAD(TSTATE_TASK_RUNNING, cpu);
#else
      tasklist = TLIST_HEAD(TSTATE_TASK_RUNNING);
#endif
      dq_addfirst((FAR dq_entry_t *)&g_idletcb[cpu], tasklist);

      /* Initialize the processor-specific portion of the TCB */

      up_initial_state(&g_idletcb[cpu].cmn);
    }

  /* Task lists are initialized */

  g_os_initstate = OSINIT_TASKLISTS;

  /* Initialize RTOS facilities *********************************************/
  /* Initialize the semaphore facility.  This has to be done very early
   * because many subsystems depend upon fully functional semaphores.
   */

  sem_initialize();   //Initialization semaphore

#if defined(MM_KERNEL_USRHEAP_INIT) || defined(CONFIG_MM_KERNEL_HEAP) || \
    defined(CONFIG_MM_PGALLOC)
  /* Initialize the memory manager */

  {
    FAR void *heap_start;
    size_t heap_size;

#ifdef MM_KERNEL_USRHEAP_INIT
    /* Get the user-mode heap from the platform specific code and configure
     * the user-mode memory allocator.
     */

    up_allocate_heap(&heap_start, &heap_size); //Assign user-mode heaps (set the starting point and size of the heap)
    kumm_initialize(heap_start, heap_size); //Initialize user-mode heap
#endif

#ifdef CONFIG_MM_KERNEL_HEAP
    /* Get the kernel-mode heap from the platform specific code and configure
     * the kernel-mode memory allocator.
     */

    up_allocate_kheap(&heap_start, &heap_size);
    kmm_initialize(heap_start, heap_size);
#endif

#ifdef CONFIG_MM_PGALLOC
    /* If there is a page allocator in the configuration, then get the page
     * heap information from the platform-specific code and configure the
     * page allocator.
     */
    //If you configure the page allocator, then let the page heap information from platform-specific code and configure the page allocator.
    up_allocate_pgheap(&heap_start, &heap_size); //Assign user-mode heaps (set the starting point and size of the heap)
    mm_pginitialize(heap_start, heap_size);      //Initialize the heap in kernel mode
#endif
  }
#endif

  /* The memory manager is available */

  g_os_initstate = OSINIT_MEMORY;

#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
  /* Initialize tasking data structures */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (task_initialize != NULL)
#endif
    {
      task_initialize(); //Initialize Task Data Structure
    }
#endif

  /* Initialize the interrupt handling subsystem (if included) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (irq_initialize != NULL)
#endif
    {
      irq_initialize(); //Initialize the interrupt processing subsystem (if included)
    }

  /* Initialize the watchdog facility (if included in the link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (wd_initialize != NULL)
#endif
    {
      wd_initialize(); //Initialize the watchdog facility (if included in the link)
    }

  /* Initialize the POSIX timer facility (if included in the link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (clock_initialize != NULL)
#endif
    {
      clock_initialize(); //Initialize the POSIX timer tool (if included in the link)
    }

#ifndef CONFIG_DISABLE_POSIX_TIMERS
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (timer_initialize != NULL)
#endif
    {
      timer_initialize(); //Configuration of POSIX Timer
    }
#endif

#ifndef CONFIG_DISABLE_SIGNALS
  /* Initialize the signal facility (if in link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (sig_initialize != NULL)
#endif
    {
      sig_initialize();//Initialize the signal facility (if in the link)
    }
#endif

#ifndef CONFIG_DISABLE_MQUEUE
  /* Initialize the named message queue facility (if in link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (mq_initialize != NULL)
#endif
    {
      mq_initialize(); //Initialize the named message queue facility (if in a link)
    } 
#endif

#ifndef CONFIG_DISABLE_PTHREAD
  /* Initialize the thread-specific data facility (if in link) */

#ifdef CONFIG_HAVE_WEAKFUNCTIONS
  if (pthread_initialize != NULL)
#endif
    {
      pthread_initialize(); //Initialize thread-specific data, empty functions
    }
#endif

#if CONFIG_NFILE_DESCRIPTORS > 0
  /* Initialize the file system (needed to support device drivers) */

  fs_initialize(); //Initialize file system 
#endif

#ifdef CONFIG_NET
  /* Initialize the networking system.  Network initialization is
   * performed in two steps:  (1) net_setup() initializes static
   * configuration of the network support.  This must be done prior
   * to registering network drivers by up_initialize().  This step
   * cannot require upon any hardware-depending features such as
   * timers or interrupts.
   */

  net_setup(); //Initialize the network
#endif

  /* The processor specific details of running the operating system
   * will be handled here.  Such things as setting up interrupt
   * service routines and starting the clock are some of the things
   * that are different for each  processor and hardware platform.
   */

  up_initialize(); //Processor-specific initialization

  /* Hardware resources are available */

  g_os_initstate = OSINIT_HARDWARE;

#ifdef CONFIG_NET
  /* Complete initialization the networking system now that interrupts
   * and timers have been configured by up_initialize().
   */

  net_initialize();
#endif

#ifdef CONFIG_MM_SHM
  /* Initialize shared memory support */

  shm_initialize();
#endif

  /* Initialize the C libraries.  This is done last because the libraries
   * may depend on the above.
   */

  lib_initialize();

  /* IDLE Group Initialization **********************************************/
  /* Announce that the CPU0 IDLE task has started */

  sched_note_start(&g_idletcb[0].cmn);

#ifdef CONFIG_SMP
  /* Initialize the IDLE group for the IDLE task of each CPU */

  for (cpu = 0; cpu < CONFIG_SMP_NCPUS; cpu++)
#endif
    {
#ifdef HAVE_TASK_GROUP
      /* Allocate the IDLE group */

      DEBUGVERIFY(group_allocate(&g_idletcb[cpu], g_idletcb[cpu].cmn.flags));
#endif

#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
#ifdef CONFIG_SMP
      if (cpu > 0)
        {
          /* Clone stdout, stderr, stdin from the CPU0 IDLE task. */

          DEBUGVERIFY(group_setuptaskfiles(&g_idletcb[cpu]));
        }
      else
#endif
        {
          /* Create stdout, stderr, stdin on the CPU0 IDLE task.  These
           * will be inherited by all of the threads created by the CPU0
           * IDLE task.
           */

          DEBUGVERIFY(group_setupidlefiles(&g_idletcb[cpu]));
        }
#endif

#ifdef HAVE_TASK_GROUP
      /* Complete initialization of the IDLE group.  Suppress retention
       * of child status in the IDLE group.
       */

      DEBUGVERIFY(group_initialize(&g_idletcb[cpu]));
      g_idletcb[cpu].cmn.group->tg_flags = GROUP_FLAG_NOCLDWAIT;
#endif
    }

  /* Start SYSLOG ***********************************************************/
  /* Late initialization of the system logging device.  Some SYSLOG channel
   * must be initialized late in the initialization sequence because it may
   * depend on having IDLE task file structures setup.
   */

  syslog_initialize(SYSLOG_INIT_LATE);

#ifdef CONFIG_SMP
  /* Start all CPUs *********************************************************/

  /* A few basic sanity checks */

  DEBUGASSERT(this_cpu() == 0 && CONFIG_MAX_TASKS > CONFIG_SMP_NCPUS);

  /* Take the memory manager semaphore on this CPU so that it will not be
   * available on the other CPUs until we have finished initialization.
   */

  DEBUGVERIFY(kmm_trysemaphore());

  /* Then start the other CPUs */

  DEBUGVERIFY(os_smp_start());//Then start the other cpus

#endif /* CONFIG_SMP */

  /* Bring Up the System ****************************************************/
  /* The OS is fully initialized and we are beginning multi-tasking */

  g_os_initstate = OSINIT_OSREADY;

  /* Create initial tasks and bring-up the system */

  DEBUGVERIFY(os_bringup()); //Create initial threads and propose systems

#ifdef CONFIG_SMP
  /* Let other threads have access to the memory manager */

  kmm_givesemaphore(); //Allow other threads to access the memory manager

#endif /* CONFIG_SMP */

  /* The IDLE Loop **********************************************************/
  /* When control is return to this point, the system is idle. */

  sinfo("CPU0: Beginning Idle Loop\n");
  for (; ; )
    {
      /* Perform garbage collection (if it is not being done by the worker
       * thread).  This cleans-up memory de-allocations that were queued
       * because they could not be freed in that execution context (for
       * example, if the memory was freed from an interrupt handler).
       */

#ifndef CONFIG_SCHED_WORKQUEUE
      /* We must have exclusive access to the memory manager to do this
       * BUT the idle task cannot wait on a semaphore.  So we only do
       * the cleanup now if we can get the semaphore -- this should be
       * possible because if the IDLE thread is running, no other task is!
       *
       * WARNING: This logic could have undesirable side-effects if priority
       * inheritance is enabled.  Imaginee the possible issues if the
       * priority of the IDLE thread were to get boosted!  Moral: If you
       * use priority inheritance, then you should also enable the work
       * queue so that is done in a safer context.
       */

      if (sched_have_garbage() && kmm_trysemaphore() == 0)
        {
          sched_garbage_collection();
          kmm_givesemaphore();
        }
#endif

      /* Perform any processor-specific idle state operations */

      up_idle(); //Perform any processor-specific idle state operation
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495

(3) Create the initial thread task: os_bringup()

int os_bringup(void)
{
  /* Setup up the initial environment for the idle task.  At present, this
   * may consist of only the initial PATH variable.  The PATH variable is
   * (probably) not used by the IDLE task.  However, the environment
   * containing the PATH variable will be inherited by all of the threads
   * created by the IDLE task.
   */

//Set up the initial environment for idle tasks. At present, this may only be the initial path variable. Path variables (possibly) are not used by idle tasks. However, it contains path variables, creating threaded inheritance environments for all idle tasks.
#if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_PATH_INITIAL)
  (void)setenv("PATH", CONFIG_PATH_INITIAL, 1);
#endif

  /* Start the page fill worker kernel thread that will resolve page faults.
   * This should always be the first thread started because it may have to
   * resolve page faults in other threads
   */
//Starting a page filler worker kernel thread that will resolve page errors. This should always be the first thread to start, because it may need to resolve page errors in other threads.
  os_pgworker();

  /* Start the worker thread that will serve as the device driver "bottom-
   * half" and will perform misc garbage clean-up.
   */
 //Start the worker thread that will act as the "bottom half" of the device driver and perform MISC garbage cleaning
  os_workqueues();

  /* Once the operating system has been initialized, the system must be
   * started by spawning the user initialization thread of execution.  This
   * will be the first user-mode thread.
   */
//Once the operating system is initialized, the system must be started by generating an executing user initialization thread. This will be the first user mode thread.
  os_start_application(); //Here's the more important function.

  /* We an save a few bytes by discarding the IDLE thread's environment. */

#if !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_PATH_INITIAL)
  (void)clearenv();
#endif

  return OK;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

(4) Create the initial thread task: os_start_application()

static inline void os_start_application(void)
{
#ifdef CONFIG_BOARD_INITTHREAD
  int pid;

  /* Do the board/application initialization on a separate thread of
   * execution.
   */
  //Execute board/application initialization on a separate thread of execution.
  //Task Creation: Name, Priority, Stack Size, Task Function Entry
  pid = kernel_thread("AppBringUp", CONFIG_BOARD_INITTHREAD_PRIORITY,  //Kernel thread functions,
                      CONFIG_BOARD_INITTHREAD_STACKSIZE,
                      (main_t)os_start_task, (FAR char * const *)NULL);
  ASSERT(pid > 0);

#else
  /* Do the board/application initialization on this thread of execution. */

  os_do_appstart();//Execution board/application initialization on this thread of execution

#endif
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

// Analyse this function: kernel_thread()

int kernel_thread(FAR const char *name, int priority,
                  int stack_size, main_t entry, FAR char *const argv[])
{
  return thread_create(name, TCB_FLAG_TTYPE_KERNEL, priority, stack_size,
                       entry, argv);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
static int thread_create(FAR const char *name, uint8_t ttype, int priority,
                         int stack_size, main_t entry,
                         FAR char * const argv[])
{
  FAR struct task_tcb_s *tcb;
  pid_t pid;
  int errcode;
  int ret;

  /* Allocate a TCB for the new task. */

  tcb = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s));
  if (!tcb)
    {
      serr("ERROR: Failed to allocate TCB\n");
      errcode = ENOMEM;
      goto errout;
    }

  /* Allocate a new task group with privileges appropriate for the parent
   * thread type.
   */

#ifdef HAVE_TASK_GROUP
  ret = group_allocate(tcb, ttype);
  if (ret < 0)
    {
      errcode = -ret;
      goto errout_with_tcb;
    }
#endif

#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
#if 0 /* No... there are side effects */
  /* Associate file descriptors with the new task.  Exclude kernel threads;
   * kernel threads do not have file or socket descriptors.  They must use
   * SYSLOG for output and the low-level psock interfaces for network I/O.
   */

  if (ttype != TCB_FLAG_TTYPE_KERNEL)
#endif
    {
      ret = group_setuptaskfiles(tcb);
      if (ret < OK)
        {
          errcode = -ret;
          goto errout_with_tcb;
        }
    }
#endif

  /* Allocate the stack for the TCB */

  ret = up_create_stack((FAR struct tcb_s *)tcb, stack_size, ttype);
  if (ret < OK)
    {
      errcode = -ret;
      goto errout_with_tcb;
    }

  /* Initialize the task control block */

  ret = task_schedsetup(tcb, priority, task_start, entry, ttype);
  if (ret < OK)
    {
      errcode = -ret;
      goto errout_with_tcb;
    }

  /* Setup to pass parameters to the new task */

  (void)task_argsetup(tcb, name, argv);

  /* Now we have enough in place that we can join the group */

#ifdef HAVE_TASK_GROUP
  ret = group_initialize(tcb);
  if (ret < 0)
    {
      errcode = -ret;
      goto errout_with_tcb;
    }
#endif

  /* Get the assigned pid before we start the task */

  pid = (int)tcb->cmn.pid;

  /* Activate the task */

  ret = task_activate((FAR struct tcb_s *)tcb);
  if (ret < OK)
    {
      errcode = get_errno();

      /* The TCB was added to the active task list by task_schedsetup() */

      dq_rem((FAR dq_entry_t *)tcb, (FAR dq_queue_t *)&g_inactivetasks);
      goto errout_with_tcb;
    }

  return pid;

errout_with_tcb:
  sched_releasetcb((FAR struct tcb_s *)tcb, ttype);

errout:
  set_errno(errcode);
  return ERROR;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

(5) Create the initial thread task: os_start_task()

#ifdef CONFIG_BOARD_INITTHREAD
static int os_start_task(int argc, FAR char **argv)
{
  /* Do the board/application initialization and exit */

  os_do_appstart(); //Core task, which will call APP function entry of FMU and IO
  return OK;
}
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
#if defined(CONFIG_INIT_ENTRYPOINT)
static inline void os_do_appstart(void)
{
  int pid;

#ifdef CONFIG_BOARD_INITIALIZE
  /* Perform any last-minute, board-specific initialization, if so
   * configured.
   */

  board_initialize();
#endif

  /* Start the application initialization task.  In a flat build, this is
   * entrypoint is given by the definitions, CONFIG_USER_ENTRYPOINT.  In
   * the protected build, however, we must get the address of the
   * entrypoint from the header at the beginning of the user-space blob.
   */

  sinfo("Starting init thread\n");

#ifdef CONFIG_BUILD_PROTECTED
  DEBUGASSERT(USERSPACE->us_entrypoint != NULL);
  pid = task_create("init", SCHED_PRIORITY_DEFAULT,
                    CONFIG_USERMAIN_STACKSIZE, USERSPACE->us_entrypoint,
                    (FAR char * const *)NULL);
#else
  pid = task_create("init", SCHED_PRIORITY_DEFAULT,  //priority
                    CONFIG_USERMAIN_STACKSIZE,      //Stack size
                    (main_t)CONFIG_USER_ENTRYPOINT, //Function entry
                    (FAR char * const *)NULL);
#endif
  ASSERT(pid > 0);
}
#elif defined(CONFIG_INIT_FILEPATH)
static inline void os_do_appstart(void)
{
  int ret;

#ifdef CONFIG_BOARD_INITIALIZE
  /* Perform any last-minute, board-specific initialization, if so
   * configured.
   */

  board_initialize();
#endif

  /* Start the application initialization program from a program in a
   * mounted file system.  Presumably the file system was mounted as part
   * of the board_initialize() operation.
   */

  sinfo("Starting init task: %s\n", CONFIG_USER_INITPATH);

  ret = exec(CONFIG_USER_INITPATH, NULL, CONFIG_INIT_SYMTAB,
             CONFIG_INIT_NEXPORTS);
  ASSERT(ret >= 0);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

(6) Core interface CONFIG_USER_ENTRYPOINT

CONFIG_USER_ENTRYPOINT="nsh_main"
  • 1

// Directory

CONFIG_USER_ENTRYPOINT="user_start"
  • 1

// Directory

There are two ways to study it. One is the nsh_main() function of STM32F427 and the other is user_start().

(7) Core interface nsh_main() function

int nsh_main(int argc, char *argv[])
#endif
{
  int exitval = 0;
  int ret;

  /* Call all C++ static constructors */

#if defined(CONFIG_EXAMPLES_NSH_CXXINITIALIZE)
  up_cxxinitialize(); //Calling C++ static constructor
#endif

  /* Make sure that we are using our symbol table */

#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
  exec_setsymtab(CONFIG_EXECFUNCS_SYMTAB, 0); //Lack of definitions for external functions
#endif

  /* Register the BINFS file system */

#if defined(CONFIG_FS_BINFS) && (CONFIG_BUILTIN)
  ret = builtin_initialize();
  if (ret < 0)
    {
     fprintf(stderr, "ERROR: builtin_initialize failed: %d\n", ret);
     exitval = 1;
   }
#endif

  /* Initialize the NSH library */

  nsh_initialize(); //Initialize NSH Library

  /* If the Telnet console is selected as a front-end, then start the
   * Telnet daemon UNLESS network initialization is deferred via
   * CONFIG_NSH_NETLOCAL.  In that case, the telnet daemon must be
   * started manually with the telnetd command after the network has
   * been initialized
   */

#if defined(CONFIG_NSH_TELNET) && !defined(CONFIG_NSH_NETLOCAL)
  ret = nsh_telnetstart(ADDR_FAMILY);
  if (ret < 0)
    {
     /* The daemon is NOT running.  Report the error then fail...
      * either with the serial console up or just exiting.
      */

     fprintf(stderr, "ERROR: Failed to start TELNET daemon: %d\n", ret);
     exitval = 1;
   }
#endif

  /* If the serial console front end is selected, then run it on this thread */

#ifdef CONFIG_NSH_CONSOLE
  ret = nsh_consolemain(0, NULL); //Important functions

  /* nsh_consolemain() should not return.  So if we get here, something
   * is wrong.
   */

#if CONFIG_NFILE_DESCRIPTORS > 0
  fprintf(stderr, "ERROR: nsh_consolemain() returned: %d\n", ret);
#else
  printf("ERROR: nsh_consolemain() returned: %d\n", ret);
#endif

  exitval = 1;
#endif

  return exitval;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

(1)int nsh_consolemain(int argc, char *argv[])

int nsh_consolemain(int argc, char *argv[])
{
  FAR struct console_stdio_s *pstate = nsh_newconsole();
  int ret;

  DEBUGASSERT(pstate != NULL);

#ifdef CONFIG_NSH_ROMFSETC
  /* Execute the start-up script */

  (void)nsh_initscript(&pstate->cn_vtbl); //Execute script initialization

#ifndef CONFIG_NSH_DISABLESCRIPT
  /* Reset the option flags */

  pstate->cn_vtbl.np.np_flags = NSH_NP_SET_OPTIONS_INIT;
#endif
#endif

#ifdef CONFIG_NSH_USBDEV_TRACE
  /* Initialize any USB tracing options that were requested */

  usbtrace_enable(TRACE_BITSET);
#endif

  /* Execute the session */

  ret = nsh_session(pstate); //Terminal commands that interact with users, we use serial commands that interact with flight control when connecting to flight control in that crisis

  /* Exit upon return */

  nsh_exit(&pstate->cn_vtbl, ret);
  return ret;
}

#endif /* !HAVE_USB_CONSOLE && !HAVE_USB_KEYBOARD */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

This is the key point of PX4. Many people want to know how Px4 or apm create tasks and how the whole program works, so they have to analyze it carefully.

(2) (void)nsh_initscript(&pstate->cn_vtbl);

int nsh_initscript(FAR struct nsh_vtbl_s *vtbl)
{
  static bool initialized;
  bool already;
  int ret = OK;

  /* Atomic test and set of the initialized flag */

  sched_lock();  //Task Scheduling Lock
  already     = initialized;
  initialized = true;
  sched_unlock(); //Task Scheduling Unlocking

  /* If we have not already executed the init script, then do so now */
//If we haven't executed the init script yet, execute it now.
  if (!already)
    {
      ret = nsh_script(vtbl, "init", NSH_INITPATH); //Parsing scripts, which is important here, is how px4 works.
    }

  return ret;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

(3) ret = nsh_script(vtbl,'init', NSH_INITPATH); // parse script

Here we need to analyze the directory "init.d/rcS", which is the rcS file. See the following document is rcS.

#!nsh     #Default start format for shell scripts
# Un comment and use set +e to ignore and set -e to enable 'exit on error control'
set +e    #Here's an error, an error, but go ahead and execute the following script
# Un comment the line below to help debug scripts by printing a trace of the script commands
#set -x #Display the redundant output that the script is running. Every command executed after the set command and any parameters on the loading command line will be displayed. Each line will be marked with a plus sign (+), indicating that it is the identifier of the tracking output.
# PX4FMU startup script.
#
# NOTE: environment variable references:
#    If the dollar sign ('$') is followed by a left bracket ('{') then the
#    variable name is terminated with the right bracket character ('}').
#    Otherwise, the variable name goes to the end of the argument.
#
#
# NOTE: COMMENT LINES ARE REMOVED BEFORE STORED IN ROMFS.
#
# Serial port mapping FMUv2/3/4:
# UART mapping on FMUv2/3/4:
#
# UART1         /dev/ttyS0      IO debug
# USART2        /dev/ttyS1      TELEM1 (flow control)
# USART3        /dev/ttyS2      TELEM2 (flow control)
# UART4
# UART7                         CONSOLE
# UART8                         SERIAL4
#
#
# UART mapping on FMUv5: This is the serial port of FMUV5
#
# UART1         /dev/ttyS0      GPS
# USART2        /dev/ttyS1      TELEM1 (flow control)
# USART3        /dev/ttyS2      TELEM2 (flow control)
# UART4         /dev/ttyS3      ?
# USART6        /dev/ttyS4      TELEM3 (flow control)
# UART7         /dev/ttyS5      ?
# UART8         /dev/ttyS6      CONSOLE

#
# Mount the procfs. Mount the PROCFS (process file system, containing a pseudo file system (dynamically generated file system at startup) for accessing process information through the kernel.)
#
mount -t procfs /proc  #Mount file system

#
# Start CDC/ACM serial driver  # Start usb / serial driver (sercon)
#
sercon

# print full system version print system version
ver all

#
# Default to auto-start mode. UAV mode defaults to automatic mode
#
set MODE autostart  #Setting default mode

set TUNE_ERR ML<<CP4CP4CP4CP4CP4
set LOG_FILE /fs/microsd/bootlog.txt  #Setting up LOG files

#
# Try to mount the microSD card. Try mounting the SD card
#
# REBOOTWORK This need to start after the flight control loop which needs to start after the flight control loop.
if mount -t vfat /dev/mmcsd0 /fs/microsd
then
    echo "[i] microSD mounted: /fs/microsd"
    if hardfault_log check
    then
        tone_alarm error #Alarm Sound Application
        if hardfault_log commit
        then
            hardfault_log reset
            tone_alarm stop
        fi
    else
        # Start playing the startup tune to start playing the startup tune
        tone_alarm start
    fi
else
    tone_alarm MBAGP
    if mkfatfs /dev/mmcsd0
    then
        if mount -t vfat /dev/mmcsd0 /fs/microsd
        then
            echo "INFO  [init] MicroSD card formatted"
        else
            echo "ERROR [init] Format failed"
            tone_alarm MNBG
            set LOG_FILE /dev/null
        fi
    else
        set LOG_FILE /dev/null
    fi
fi

#
# Look for an init script on the microSD card. Find init script on the MICROSD card
# Disable autostart if the script found. If a script is found, disable autostart.
#
set FRC /fs/microsd/etc/rc.txt
if [ -f $FRC ]
then
    echo "INFO  [init] Executing script: ${FRC}"
    sh $FRC
    set MODE custom
fi
unset FRC

if [ $MODE == autostart ]
then

    #
    # Start the ORB (first app to start) uorb message bus startup (first application to start)
    #
    uorb start#Start uorb

    #
    # Load parameters loading parameters
    #
    # Application of mtd connection board e2rom
    set PARAM_FILE /fs/microsd/params
    if mtd start
    then
        set PARAM_FILE /fs/mtd_params
    fi

    param select $PARAM_FILE
    if param load
    then
    else
        if param reset
        then
        fi
    fi

    #
    # Start system state indicator
    ## Start System Status Indicator
    if rgbled start
    then
    else
        if blinkm start
        then
            blinkm systemstate
        fi
    fi

    # FMUv5 may have both PWM I2C RGB LED support
    # FMUv5 supports PWM, I2C, RGB LED at the same time
    rgbled_pwm start

    #
    # Set AUTOCNF flag to use it in AUTOSTART scripts
    # Setting AUTOCNF parameters for AUTOSTART scripts
    if param compare SYS_AUTOCONFIG 1
    then
        # Wipe out params except RC* and total flight time
        param reset_nostart RC* LND_FLIGHT_T_*
        set AUTOCNF yes
    else
        set AUTOCNF no

        #
        # Release 1.4.0 transitional support:
        # set to old default if unconfigured.
        # this preserves the previous behaviour
        #
        if param compare BAT_N_CELLS 0
        then
            param set BAT_N_CELLS 3
        fi
    fi

    #
    # Set default values
    #Setting default parameters
    set VEHICLE_TYPE none
    set MIXER none
    set MIXER_AUX none
    set OUTPUT_MODE none
    set PWM_OUT none
    set PWM_RATE p:PWM_RATE
    set PWM_DISARMED p:PWM_DISARMED
    set PWM_MIN p:PWM_MIN
    set PWM_MAX p:PWM_MAX
    set PWM_AUX_OUT none
    set PWM_AUX_RATE none
    set PWM_ACHDIS none
    set PWM_AUX_DISARMED p:PWM_AUX_DISARMED
    set PWM_AUX_MIN p:PWM_AUX_MIN
    set PWM_AUX_MAX p:PWM_AUX_MAX
    set FAILSAFE_AUX none
    set MK_MODE none
    set FMU_MODE pwm
    set AUX_MODE pwm
    set FMU_ARGS ""
    set MAVLINK_F default
    set MAVLINK_COMPANION_DEVICE /dev/ttyS2
    set MAV_TYPE none
    set FAILSAFE none
    set USE_IO no
    set LOGGER_BUF 16

    if ver hwcmp PX4FMU_V4
    then
        param set SYS_FMU_TASK 1
    fi

    if ver hwcmp PX4FMU_V4PRO
    then
        param set SYS_FMU_TASK 1
    fi

    if ver hwcmp PX4FMU_V5
    then
        param set SYS_FMU_TASK 1
        set MAVLINK_COMPANION_DEVICE /dev/ttyS3

        set LOGGER_BUF 64
        param set SDLOG_MODE 2
    fi

    if ver hwcmp CRAZYFLIE
    then
        if param compare SYS_AUTOSTART 0
        then
            param set SYS_AUTOSTART 4900
            set AUTOCNF yes
        fi
    fi

    if ver hwcmp AEROFC_V1
    then
        if param compare SYS_AUTOSTART 0
        then
            set AUTOCNF yes
        fi

        # We don't allow changing AUTOSTART as it doesn't work in
        # other configurations
        param set SYS_AUTOSTART 4070
    fi

    if ver hwcmp NXPHLITE_V3
    then
        param set SYS_FMU_TASK 1
        set MAVLINK_COMPANION_DEVICE /dev/ttyS4
    fi

    #
    # Set USE_IO flag
    #
    if param compare SYS_USE_IO 1
    then
        set USE_IO yes
    fi

    if param compare SYS_FMU_TASK 1
    then
        set FMU_ARGS "-t"
    fi

    #
    # Set parameters and env variables for selected AUTOSTART
    #
    if param compare SYS_AUTOSTART 0
    then
    else
        sh /etc/init.d/rc.autostart
    fi
    unset MODE

    #
    # If mount (gimbal) control is enabled and output mode is AUX, set the aux
    # mixer to mount (override the airframe-specific MIXER_AUX setting)
    #
    if param compare MNT_MODE_IN -1
    then
    else
        if param compare MNT_MODE_OUT 0
        then
            set MIXER_AUX mount
        fi
    fi

    #
    # Override parameters from user configuration file
    #
    set FCONFIG /fs/microsd/etc/config.txt
    if [ -f $FCONFIG ]
    then
        echo "Custom: ${FCONFIG}"
        sh $FCONFIG
    fi
    unset FCONFIG

    #
    # If autoconfig parameter was set, reset it and save parameters
    #
    if [ $AUTOCNF == yes ]
    then
        # Disable safety switch by default on Pixracer
        if ver hwcmp PX4FMU_V4
        then
            param set CBRK_IO_SAFETY 22027
        fi
        param set SYS_AUTOCONFIG 0
    fi
    unset AUTOCNF

    set IO_PRESENT no

    if [ $USE_IO == yes ]
    then
        #
        # Check if PX4IO present and update firmware if needed
        # Check whether PX4IO firmware needs to be updated
        if [ -f /etc/extras/px4io-v2.bin ]
        then
            set IO_FILE /etc/extras/px4io-v2.bin

            if px4io checkcrc ${IO_FILE}
            then
                echo "[init] PX4IO CRC OK" >> $LOG_FILE

                set IO_PRESENT yes
            else
                tone_alarm MLL32CP8MB

                if px4io start
                then
                    # try to safe px4 io so motor outputs dont go crazy
                    if px4io safety_on
                    then
                        # success! no-op
                    else
                        # px4io did not respond to the safety command
                        px4io stop
                    fi
                fi

                if px4io forceupdate 14662 ${IO_FILE}
                then
                    usleep 10000
                    if px4io checkcrc ${IO_FILE}
                    then
                        echo "PX4IO CRC OK after updating" >> $LOG_FILE
                        tone_alarm MLL8CDE

                        set IO_PRESENT yes
                    else
                        echo "PX4IO update failed" >> $LOG_FILE
                        tone_alarm ${TUNE_ERR}
                    fi
                else
                    echo "PX4IO update failed" >> $LOG_FILE
                    tone_alarm ${TUNE_ERR}
                fi
            fi
        fi
        unset IO_FILE

        if [ $IO_PRESENT == no ]
        then
            echo "PX4IO not found" >> $LOG_FILE
            tone_alarm ${TUNE_ERR}
        fi
    fi

    #
    # Set default output if not set
    #
    if [ $OUTPUT_MODE == none ]
    then
        if [ $USE_IO == yes ]
        then
            set OUTPUT_MODE io
        else
            set OUTPUT_MODE fmu
        fi
    fi

    if [ $OUTPUT_MODE == io -a $IO_PRESENT != yes ]
    then
        # Need IO for output but it not present, disable output
        set OUTPUT_MODE none
    fi

    if [ $OUTPUT_MODE == tap_esc ]
    then
        set FMU_MODE rcin
    fi
#Track Point Management of dataman Map
    set DATAMAN_OPT ""
    if ver hwcmp AEROFC_V1
    then
        set DATAMAN_OPT -i
    fi
    if ver hwcmp AEROCORE2
    then
        set DATAMAN_OPT "-f /fs/mtd_dataman"
    fi
    # waypoint storage
    # REBOOTWORK this needs to start in parallel
    if dataman start $DATAMAN_OPT
    then
    fi
    unset DATAMAN_OPT

    #
    # Sensors System (start before Commander so Preflight checks are properly run)
    # commander Needs to be this early for in-air-restarts
    #Sensor system (start before commander starts to ensure that the detection is running properly)
    if param compare SYS_HITL 1
    then
        set OUTPUT_MODE hil
        sensors start -h
        commander start --hil
    else
        if ver hwcmp PX4_SAME70XPLAINED_V1
        then
            gps start -d /dev/ttyS2
        else
            gps start
        fi
        sh /etc/init.d/rc.sensors# Start rc.sensors
        commander start #Central Control Procedure
    fi

    send_event start
    load_mon start

    #
    # Check if UAVCAN is enabled, default to it for ESCs
    #Check whether UAVCAN is enabled, default is ESC
    if param greater UAVCAN_ENABLE 2
    then
        set OUTPUT_MODE uavcan_esc
    fi

    # Sensors on the PWM interface bank
    if param compare SENS_EN_LL40LS 1
    then
        # clear pins 5 and 6
        set FMU_MODE pwm4
        set AUX_MODE pwm4
    fi
    if param greater TRIG_MODE 0
    then
        # We ONLY support trigger on pins 5 and 6 when simultanously using AUX for actuator output
        if param compare TRIG_PINS 56
        then
            # clear pins 5 and 6
            set FMU_MODE pwm4
            set AUX_MODE pwm4
        else
            set FMU_MODE none
            set AUX_MODE none
        fi
        camera_trigger start

        param set CAM_FBACK_MODE 1
        camera_feedback start
    fi

    # If OUTPUT_MODE == none then something is wrong with setup and we shouldn't try to enable output
    if [ $OUTPUT_MODE != none ]
    then
        if [ $OUTPUT_MODE == uavcan_esc ]
        then
            if param compare UAVCAN_ENABLE 0
            then
                echo "OVERRIDING UAVCAN_ENABLE = 3" >> $LOG_FILE
                param set UAVCAN_ENABLE 3
            fi
        fi

        if [ $OUTPUT_MODE == io -o $OUTPUT_MODE == uavcan_esc ]
        then
            if px4io start
            then
                sh /etc/init.d/rc.io    #rc.io boot
            else
                echo "PX4IO start failed" >> $LOG_FILE
                tone_alarm $TUNE_ERR
            fi
        fi

        if [ $OUTPUT_MODE == fmu ]
        then
            if fmu mode_$FMU_MODE $FMU_ARGS
            then
            else
                echo "FMU start failed" >> $LOG_FILE
                tone_alarm $TUNE_ERR
            fi
        fi

        if [ $OUTPUT_MODE == mkblctrl ]
        then
            set MKBLCTRL_ARG ""
            if [ $MKBLCTRL_MODE == x ]
            then
                set MKBLCTRL_ARG "-mkmode x"
            fi
            if [ $MKBLCTRL_MODE == + ]
            then
                set MKBLCTRL_ARG "-mkmode +"
            fi

            if mkblctrl $MKBLCTRL_ARG
            then
            else
                echo "MK start failed" >> $LOG_FILE
                tone_alarm $TUNE_ERR
            fi
            unset MKBLCTRL_ARG
        fi
        unset MK_MODE

        if [ $OUTPUT_MODE == hil ]
        then
            if pwm_out_sim mode_pwm16
            then
            else
                tone_alarm $TUNE_ERR
            fi
        fi

        #
        # Start IO or FMU for RC PPM input if needed Open IO or FMU for RCPPM input needs
        #
        if [ $IO_PRESENT == yes ]
        then
            if [ $OUTPUT_MODE != io ]
            then
                if px4io start #Open px4io
                then
                    sh /etc/init.d/rc.io
                else
                    echo "PX4IO start failed" >> $LOG_FILE
                    tone_alarm $TUNE_ERR
                fi
            fi
        else
            if [ $OUTPUT_MODE != fmu ]
            then
                if fmu mode_${FMU_MODE} $FMU_ARGS
                then
                else
                    echo "FMU mode_${FMU_MODE} start failed" >> $LOG_FILE
                    tone_alarm $TUNE_ERR
                fi
            fi
        fi
    fi

    if [ $MAVLINK_F == default ]
    then
        # Normal mode, use baudrate 57600 (default) and data rate 1000 bytes/s
        set MAVLINK_F "-r 1200 -f"

        # Avoid using ttyS1 for MAVLink on FMUv4
        if ver hwcmp PX4FMU_V4
        then
            set MAVLINK_F "-r 1200 -d /dev/ttyS1"
            # Start MAVLink on Wifi (ESP8266 port)
            mavlink start -r 20000 -b 921600 -d /dev/ttyS0
        fi

        if ver hwcmp AEROFC_V1
        then
            set MAVLINK_F "-r 1200 -d /dev/ttyS3"
        fi

        if ver hwcmp CRAZYFLIE
        then
            # Avoid using either of the two available serials
            set MAVLINK_F none
        fi
    fi

    if [ "x$MAVLINK_F" == xnone ]
    then
    else
        mavlink start ${MAVLINK_F}
    fi
    unset MAVLINK_F

    #
    # MAVLink onboard / TELEM2
    #
    # XXX We need a better way for runtime eval of shell variables,
    # but this works for now
    if param compare SYS_COMPANION 10
    then
        frsky_telemetry start -d ${MAVLINK_COMPANION_DEVICE}
    fi
    if param compare SYS_COMPANION 20
    then
        syslink start
        mavlink start -d /dev/bridge0 -b 57600 -m osd -r 40000
    fi
    if param compare SYS_COMPANION 921600
    then
        if ver hwcmp AEROFC_V1
        then
            if protocol_splitter start ${MAVLINK_COMPANION_DEVICE}
            then
                mavlink start -d /dev/mavlink -b 921600 -m onboard -r 5000 -x
                micrortps_client start -d /dev/rtps -b 921600 -l -1 -s 2000
            else
                 mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 921600 -m onboard -r 80000 -x -f
            fi
        else
            mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 921600 -m onboard -r 80000 -x -f
        fi
    fi
    if param compare SYS_COMPANION 57600
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 57600 -m onboard -r 5000 -x -f
    fi
    if param compare SYS_COMPANION 460800
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 460800 -m onboard -r 5000 -x -f
    fi
    if param compare SYS_COMPANION 157600
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 57600 -m osd -r 1000
    fi
    if param compare SYS_COMPANION 257600
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 57600 -m magic -r 5000 -x -f
    fi
    if param compare SYS_COMPANION 319200
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 19200 -r 1000 -f
    fi
    if param compare SYS_COMPANION 338400
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 38400 -r 1000 -f
    fi
    if param compare SYS_COMPANION 357600
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 57600 -r 1000 -f
    fi
    if param compare SYS_COMPANION 3115200
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 115200 -r 1000 -f
    fi
    if param compare SYS_COMPANION 419200
    then
        iridiumsbd start -d /dev/ttyS2
        mavlink start -d /dev/iridium -b 19200 -m iridium -r 10
    fi
    if param compare SYS_COMPANION 1921600
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 921600 -r 20000
    fi
    if param compare SYS_COMPANION 1500000
    then
        mavlink start -d ${MAVLINK_COMPANION_DEVICE} -b 1500000 -m onboard -r 10000 -x -f
    fi

    unset MAVLINK_COMPANION_DEVICE

    #
    # Starting stuff according to UAVCAN_ENABLE value
    #
    if param greater UAVCAN_ENABLE 0
    then
        if uavcan start
        then
            set LOGGER_BUF 6
            uavcan start fw
        else
            tone_alarm ${TUNE_ERR}
        fi
    fi

    if ver hwcmp PX4FMU_V4
    then
        frsky_telemetry start -d /dev/ttyS6
    fi

    if ver hwcmp MINDPX_V2
    then
        frsky_telemetry start -d /dev/ttyS6
    fi

    if ver hwcmp PX4FMU_V2
    then
        # Check for flow sensor - as it is a background task, launch it last
        px4flow start &
    fi

    if ver hwcmp PX4FMU_V4
    then
        # Check for flow sensor - as it is a background task, launch it last
        px4flow start &
    fi

    if ver hwcmp PX4FMU_V4PRO
    then
        # Check for flow sensor - as it is a background task, launch it last
        px4flow start &
    fi

    if ver hwcmp MINDPX_V2
    then
        px4flow start &
    fi

    if ver hwcmp AEROFC_V1
    then
        # don't start mavlink ttyACM0 on aerofc_v1
    else
        # Start MAVLink
        mavlink start -r 800000 -d /dev/ttyACM0 -m config -x
    fi

    #
    # Logging
    #
    if param compare SYS_LOGGER 0
    then
        sdlog2 start -r 100 -a -b 9 -t
    else
        set LOGGER_ARGS ""

        if param compare SDLOG_MODE 1
        then
            set LOGGER_ARGS "-e"
        fi

        if param compare SDLOG_MODE 2
        then
            set LOGGER_ARGS "-f"
        fi

        if ver hwcmp AEROFC_V1
        then
            set LOGGER_ARGS "-m mavlink"
        fi

        logger start -b ${LOGGER_BUF} -t ${LOGGER_ARGS}

        unset LOGGER_BUF
        unset LOGGER_ARGS
    fi

    #
    # Fixed wing setup
    #
    if [ $VEHICLE_TYPE == fw ]
    then
        if [ $MIXER == none ]
        then
            # Set default mixer for fixed wing if not defined
            set MIXER AERT
        fi

        if [ $MAV_TYPE == none ]
        then
            # Use MAV_TYPE = 1 (fixed wing) if not defined
            set MAV_TYPE 1
        fi

        param set MAV_TYPE ${MAV_TYPE}

        # Load mixer and configure outputs
        sh /etc/init.d/rc.interface

        # Start standard fixedwing apps
        sh /etc/init.d/rc.fw_apps
    fi

    #
    # Multicopters setup
    #
    if [ $VEHICLE_TYPE == mc ]
    then
        if [ $MIXER == none ]
        then
            echo "Mixer undefined"
        fi

        if [ $MAV_TYPE == none ]
        then
            # Use mixer to detect vehicle type
            if [ $MIXER == quad_x -o $MIXER == quad_+ ]
            then
                set MAV_TYPE 2
            fi
            if [ $MIXER == quad_w -o $MIXER == quad_dc ]
            then
                set MAV_TYPE 2
            fi
            if [ $MIXER == quad_h ]
            then
                set MAV_TYPE 2
            fi
            if [ $MIXER == tri_y_yaw- -o $MIXER == tri_y_yaw+ ]
            then
                set MAV_TYPE 15
            fi
            if [ $MIXER == hexa_x -o $MIXER == hexa_+ ]
            then
                set MAV_TYPE 13
            fi
            if [ $MIXER == hexa_cox ]
            then
                set MAV_TYPE 13
            fi
            if [ $MIXER == octo_x -o $MIXER == octo_+ ]
            then
                set MAV_TYPE 14
            fi
            if [ $MIXER == octo_cox -o $MIXER == octo_cox_w ]
            then
                set MAV_TYPE 14
            fi
            if [ $MIXER == coax ]
            then
                set MAV_TYPE 3
            fi
        fi

        # Still no MAV_TYPE found
        if [ $MAV_TYPE == none ]
        then
            echo "Unknown MAV_TYPE"
            param set MAV_TYPE 2
        else
            param set MAV_TYPE ${MAV_TYPE}
        fi

        # Load mixer and configure outputs
        sh /etc/init.d/rc.interface

        # Start standard multicopter apps
        sh /etc/init.d/rc.mc_apps
    fi

    #
    # VTOL setup
    #
    if [ $VEHICLE_TYPE == vtol ]
    then
        if [ $MIXER == none ]
        then
            echo "VTOL mixer undefined"
        fi

        if [ $MAV_TYPE == none ]
        then
            # Use mixer to detect vehicle type
            if [ $MIXER == caipirinha_vtol ]
            then
                set MAV_TYPE 19
            fi
            if [ $MIXER == firefly6 ]
            then
                set MAV_TYPE 21
            fi
            if [ $MIXER == quad_x_pusher_vtol ]
            then
                set MAV_TYPE 22
            fi
        fi

        # Still no MAV_TYPE found
        if [ $MAV_TYPE == none ]
        then
            echo "Unknown MAV_TYPE"
            param set MAV_TYPE 19
        else
            param set MAV_TYPE ${MAV_TYPE}
        fi

        # Load mixer and configure outputs
        sh /etc/init.d/rc.interface

        # Start standard vtol apps
        sh /etc/init.d/rc.vtol_apps
    fi

    #
    # UGV setup
    #
    if [ $VEHICLE_TYPE == ugv ]
    then
        if [ $MIXER == none ]
        then
            # Set default mixer for UGV if not defined
            set MIXER ugv_generic
        fi

        if [ $MAV_TYPE == none ]
        then
            # Use MAV_TYPE = 10 (UGV) if not defined
            set MAV_TYPE 10
        fi

        param set MAV_TYPE ${MAV_TYPE}

        # Load mixer and configure outputs
        sh /etc/init.d/rc.interface

        # Start standard UGV apps
        sh /etc/init.d/rc.ugv_apps
    fi

    #
    # For snapdragon, we need a passthrough mode
    # Do not run any mavlink instances since we need the serial port for
    # communication with Snapdragon.
    #
    if [ $VEHICLE_TYPE == passthrough ]
    then
        mavlink stop-all
        commander stop

        # Stop multicopter attitude controller if it is running, the controls come
        # from Snapdragon.
        if mc_att_control stop
        then
        fi

        # Start snapdragon interface on serial port.
        if ver hwcmp PX4FMU_V2
        then
            # On Pixfalcon use the standard telemetry port (Telem 1).
            snapdragon_rc_pwm start -d /dev/ttyS1
            px4io start
        fi

        if ver hwcmp PX4FMU_V4
        then
            # On Pixracer use Telem 2 port (TL2).
            snapdragon_rc_pwm start -d /dev/ttyS2
            fmu mode_pwm4 $FMU_ARGS
        fi

        pwm failsafe -c 1234 -p 900
        pwm disarmed -c 1234 -p 900

        # Arm straightaway.
        pwm arm
        # Use 400 Hz PWM on all channels.
        pwm rate -a -r 400
    fi

    unset MIXER
    unset MAV_TYPE
    unset OUTPUT_MODE

    #
    # Start the navigator
    #
    navigator start

    #
    # Generic setup (autostart ID not found)
    #
    if [ $VEHICLE_TYPE == none ]
    then
        echo "No autostart ID found"
        ekf2 start
    fi

    # Start any custom addons
    set FEXTRAS /fs/microsd/etc/extras.txt
    if [ -f $FEXTRAS ]
    then
        echo "Addons script: ${FEXTRAS}"
        sh $FEXTRAS
    fi
    unset FEXTRAS

    if ver hwcmp CRAZYFLIE
    then
        # CF2 shouldn't have an sd card
    else

        if ver hwcmp AEROCORE2
        then
            # AEROCORE2 shouldn't have an sd card
        else

            # Run no SD alarm
            if [ $LOG_FILE == /dev/null ]
            then
                # Play SOS
                tone_alarm error
            fi

        fi

    fi

    #
    # Check if we should start a thermal calibration
    # TODO move further up and don't start unnecessary services if we are calibrating
    #
    set TEMP_CALIB_ARGS ""
    if param compare SYS_CAL_GYRO 1
    then
        set TEMP_CALIB_ARGS "${TEMP_CALIB_ARGS} -g"
        param set SYS_CAL_GYRO 0
    fi
    if param compare SYS_CAL_ACCEL 1
    then
        set TEMP_CALIB_ARGS "${TEMP_CALIB_ARGS} -a"
        param set SYS_CAL_ACCEL 0
    fi
    if param compare SYS_CAL_BARO 1
    then
        set TEMP_CALIB_ARGS "${TEMP_CALIB_ARGS} -b"
        param set SYS_CAL_BARO 0
    fi
    if [ "x$TEMP_CALIB_ARGS" != "x" ]
    then
        send_event temperature_calibration ${TEMP_CALIB_ARGS}
    fi
    unset TEMP_CALIB_ARGS

    # vmount to control mounts such as gimbals, disabled by default.
    if param compare MNT_MODE_IN -1
    then
    else
        if vmount start
        then
        fi
    fi

# End of autostart
fi

# There is no further script processing, so we can free some RAM
# XXX potentially unset all script variables.
unset TUNE_ERR

# Boot is complete, inform MAVLink app(s) that the system is now fully up and running
mavlink boot_complete
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
  • 593
  • 594
  • 595
  • 596
  • 597
  • 598
  • 599
  • 600
  • 601
  • 602
  • 603
  • 604
  • 605
  • 606
  • 607
  • 608
  • 609
  • 610
  • 611
  • 612
  • 613
  • 614
  • 615
  • 616
  • 617
  • 618
  • 619
  • 620
  • 621
  • 622
  • 623
  • 624
  • 625
  • 626
  • 627
  • 628
  • 629
  • 630
  • 631
  • 632
  • 633
  • 634
  • 635
  • 636
  • 637
  • 638
  • 639
  • 640
  • 641
  • 642
  • 643
  • 644
  • 645
  • 646
  • 647
  • 648
  • 649
  • 650
  • 651
  • 652
  • 653
  • 654
  • 655
  • 656
  • 657
  • 658
  • 659
  • 660
  • 661
  • 662
  • 663
  • 664
  • 665
  • 666
  • 667
  • 668
  • 669
  • 670
  • 671
  • 672
  • 673
  • 674
  • 675
  • 676
  • 677
  • 678
  • 679
  • 680
  • 681
  • 682
  • 683
  • 684
  • 685
  • 686
  • 687
  • 688
  • 689
  • 690
  • 691
  • 692
  • 693
  • 694
  • 695
  • 696
  • 697
  • 698
  • 699
  • 700
  • 701
  • 702
  • 703
  • 704
  • 705
  • 706
  • 707
  • 708
  • 709
  • 710
  • 711
  • 712
  • 713
  • 714
  • 715
  • 716
  • 717
  • 718
  • 719
  • 720
  • 721
  • 722
  • 723
  • 724
  • 725
  • 726
  • 727
  • 728
  • 729
  • 730
  • 731
  • 732
  • 733
  • 734
  • 735
  • 736
  • 737
  • 738
  • 739
  • 740
  • 741
  • 742
  • 743
  • 744
  • 745
  • 746
  • 747
  • 748
  • 749
  • 750
  • 751
  • 752
  • 753
  • 754
  • 755
  • 756
  • 757
  • 758
  • 759
  • 760
  • 761
  • 762
  • 763
  • 764
  • 765
  • 766
  • 767
  • 768
  • 769
  • 770
  • 771
  • 772
  • 773
  • 774
  • 775
  • 776
  • 777
  • 778
  • 779
  • 780
  • 781
  • 782
  • 783
  • 784
  • 785
  • 786
  • 787
  • 788
  • 789
  • 790
  • 791
  • 792
  • 793
  • 794
  • 795
  • 796
  • 797
  • 798
  • 799
  • 800
  • 801
  • 802
  • 803
  • 804
  • 805
  • 806
  • 807
  • 808
  • 809
  • 810
  • 811
  • 812
  • 813
  • 814
  • 815
  • 816
  • 817
  • 818
  • 819
  • 820
  • 821
  • 822
  • 823
  • 824
  • 825
  • 826
  • 827
  • 828
  • 829
  • 830
  • 831
  • 832
  • 833
  • 834
  • 835
  • 836
  • 837
  • 838
  • 839
  • 840
  • 841
  • 842
  • 843
  • 844
  • 845
  • 846
  • 847
  • 848
  • 849
  • 850
  • 851
  • 852
  • 853
  • 854
  • 855
  • 856
  • 857
  • 858
  • 859
  • 860
  • 861
  • 862
  • 863
  • 864
  • 865
  • 866
  • 867
  • 868
  • 869
  • 870
  • 871
  • 872
  • 873
  • 874
  • 875
  • 876
  • 877
  • 878
  • 879
  • 880
  • 881
  • 882
  • 883
  • 884
  • 885
  • 886
  • 887
  • 888
  • 889
  • 890
  • 891
  • 892
  • 893
  • 894
  • 895
  • 896
  • 897
  • 898
  • 899
  • 900
  • 901
  • 902
  • 903
  • 904
  • 905
  • 906
  • 907
  • 908
  • 909
  • 910
  • 911
  • 912
  • 913
  • 914
  • 915
  • 916
  • 917
  • 918
  • 919
  • 920
  • 921
  • 922
  • 923
  • 924
  • 925
  • 926
  • 927
  • 928
  • 929
  • 930
  • 931
  • 932
  • 933
  • 934
  • 935
  • 936
  • 937
  • 938
  • 939
  • 940
  • 941
  • 942
  • 943
  • 944
  • 945
  • 946
  • 947
  • 948
  • 949
  • 950
  • 951
  • 952
  • 953
  • 954
  • 955
  • 956
  • 957
  • 958
  • 959
  • 960
  • 961
  • 962
  • 963
  • 964
  • 965
  • 966
  • 967
  • 968
  • 969
  • 970
  • 971
  • 972
  • 973
  • 974
  • 975
  • 976
  • 977
  • 978
  • 979
  • 980
  • 981
  • 982
  • 983
  • 984
  • 985
  • 986
  • 987
  • 988
  • 989
  • 990
  • 991
  • 992
  • 993
  • 994
  • 995
  • 996
  • 997
  • 998
  • 999
  • 1000
  • 1001
  • 1002
  • 1003
  • 1004
  • 1005
  • 1006
  • 1007
  • 1008
  • 1009
  • 1010
  • 1011
  • 1012
  • 1013
  • 1014
  • 1015
  • 1016
  • 1017
  • 1018
  • 1019
  • 1020
  • 1021
  • 1022
  • 1023
  • 1024
  • 1025
  • 1026
  • 1027
  • 1028
  • 1029
  • 1030
  • 1031
  • 1032
  • 1033
  • 1034
  • 1035
  • 1036
  • 1037
  • 1038
  • 1039
  • 1040
  • 1041
  • 1042
  • 1043
  • 1044

int nsh_script(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
               FAR const char *path)
{
  FAR char *fullpath;
  FAR FILE *savestream;
  FAR char *buffer;
  FAR char *pret;
  int ret = ERROR;

  /* The path to the script may be relative to the current working directory */

  fullpath = nsh_getfullpath(vtbl, path);
  if (!fullpath)
    {
      return ERROR;
    }

  /* Get a reference to the common input buffer */

  buffer = nsh_linebuffer(vtbl);
  if (buffer)
    {
      /* Save the parent stream in case of nested script processing */

      savestream = vtbl->np.np_stream;

      /* Open the file containing the script */

      vtbl->np.np_stream = fopen(fullpath, "r");
      if (!vtbl->np.np_stream)
        {
          nsh_output(vtbl, g_fmtcmdfailed, cmd, "fopen", NSH_ERRNO);

          /* Free the allocated path */

          nsh_freefullpath(fullpath);

          /* Restore the parent script stream */

          vtbl->np.np_stream = savestream;
          return ERROR;
        }

      /* Loop, processing each command line in the script file (or
       * until an error occurs)
       */

      do
        {
          /* Flush any output generated by the previous line */

          fflush(stdout);

#ifndef CONFIG_NSH_DISABLE_LOOPS
          /* Get the current file position.  This is used to control
           * looping.  If a loop begins in the next line, then this file
           * offset will be needed to locate the top of the loop in the
           * script file.  Note that ftell will return -1 on failure.
           */

          vtbl->np.np_foffs = ftell(vtbl->np.np_stream);
          vtbl->np.np_loffs = 0;

          if (vtbl->np.np_foffs < 0)
            {
              nsh_output(vtbl, g_fmtcmdfailed, "loop", "ftell", NSH_ERRNO);
            }
#endif

          /* Now read the next line from the script file */

          pret = fgets(buffer, CONFIG_NSH_LINELEN, vtbl->np.np_stream);
          if (pret)
            {
              /* Parse process the command.  NOTE:  this is recursive...
               * we got to cmd_sh via a call to nsh_parse.  So some
               * considerable amount of stack may be used.
               */

              if ((vtbl->np.np_flags & NSH_PFLAG_SILENT) == 0)
                {
                  nsh_output(vtbl,"%s", buffer);
                }

              ret = nsh_parse(vtbl, buffer);
            }
        }
      while (pret && (ret == OK || (vtbl->np.np_flags & NSH_PFLAG_IGNORE)));

      /* Close the script file */

      fclose(vtbl->np.np_stream);

      /* Restore the parent script stream */

      vtbl->np.np_stream = savestream;
    }

  /* Free the allocated path */

  nsh_freefullpath(fullpath);
  return ret;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

(8) Core interface user_start() function

// Directory

It can be seen that IO is only a core module of FMU. So how FMU and IO start the process is what we need to focus on.



int user_start(int argc, char *argv[])
{
    /* configure the first 8 PWM outputs (i.e. all of them) */
    up_pwm_servo_init(0xff); //Configure 8-way PWM output

#if defined(CONFIG_HAVE_CXX) && defined(CONFIG_HAVE_CXXINITIALIZE)

    /* run C++ ctors before we go any further */

    up_cxxinitialize(); //Run C++ Library

#   if defined(CONFIG_EXAMPLES_NSH_CXXINITIALIZE)
#       error CONFIG_EXAMPLES_NSH_CXXINITIALIZE Must not be defined! Use CONFIG_HAVE_CXX and CONFIG_HAVE_CXXINITIALIZE.
#   endif

#else
#  error platform is dependent on c++ both CONFIG_HAVE_CXX and CONFIG_HAVE_CXXINITIALIZE must be defined.
#endif

    /* reset all to zero */
    memset(&system_state, 0, sizeof(system_state));//Reset System Storage

    /* configure the high-resolution time/callout interface */
    hrt_init(); //Configuration of High Speed Clocks

    /* calculate our fw CRC so FMU can decide if we need to update */
    calculate_fw_crc(); //Calculate the crc clock I used to determine if the fmu is updated

    /*
     * Poll at 1ms intervals for received bytes that have not triggered
     * a DMA event.Polling at 1ms intervals for untouched received bytes
     */
#ifdef CONFIG_ARCH_DMA
    hrt_call_every(&serial_dma_call, 1000, 1000, (hrt_callout)stm32_serial_dma_poll, NULL);
#endif

    /* print some startup info */
    syslog(LOG_INFO, "\nPX4IO: starting\n");

    /* default all the LEDs to off while we start */
    LED_AMBER(false); //Turn off all lights
    LED_BLUE(false);
    LED_SAFETY(false);
#ifdef GPIO_LED4
    LED_RING(false);
#endif

    /* turn on servo power (if supported) */
#ifdef POWER_SERVO
    POWER_SERVO(true); //Turn on servo power
#endif

    /* turn off S.Bus out (if supported) */
#ifdef ENABLE_SBUS_OUT
    ENABLE_SBUS_OUT(false); //Close SBUS
#endif

    /* start the safety switch handler */
    safety_init(); //Start the Safety Switch Processor

    /* initialise the control inputs */
    controls_init(); //Initialization control input

    /* set up the ADC */
    adc_init(); //Initialize ADC

    /* start the FMU interface */
    interface_init();//Serial port initialization

    /* add a performance counter for mixing */
    perf_counter_t mixer_perf = perf_alloc(PC_ELAPSED, "mix"); //Add performance counters for mixing

    /* add a performance counter for controls */
    perf_counter_t controls_perf = perf_alloc(PC_ELAPSED, "controls");//Adding performance counters to controls

    /* and one for measuring the loop rate */
    perf_counter_t loop_perf = perf_alloc(PC_INTERVAL, "loop"); //A Method for Measuring Loop Rate

    struct mallinfo minfo = mallinfo();
    r_page_status[PX4IO_P_STATUS_FREEMEM] = minfo.mxordblk;
    syslog(LOG_INFO, "MEM: free %u, largest %u\n", minfo.mxordblk, minfo.fordblks);

    /* initialize PWM limit lib */
    pwm_limit_init(&pwm_limit); //Initialization of PWM restrictions

    /*
     *    P O L I C E    L I G H T S
     *
     * Not enough memory, lock down.
     *
     * We might need to allocate mixers later, and this will
     * ensure that a developer doing a change will notice
     * that he just burned the remaining RAM with static
     * allocations. We don't want him to be able to
     * get past that point. This needs to be clearly
     * documented in the dev guide.
     *
     */
    if (minfo.mxordblk < 600) 
    {

        syslog(LOG_ERR, "ERR: not enough MEM");
        bool phase = false;

        while (true) 
        {

            if (phase) 
            {
                LED_AMBER(true);
                LED_BLUE(false);

            } else 
            {
                LED_AMBER(false);
                LED_BLUE(true);
            }

            up_udelay(250000);

            phase = !phase;
        }
    }

    /* Start the failsafe led init */
    failsafe_led_init();//Start Failure Safety LED Initialization

    /*
     * Run everything in a tight loop.Make a mess of everything.
     */

    uint64_t last_debug_time = 0;
    uint64_t last_heartbeat_time = 0;
    uint64_t last_loop_time = 0;

    for (;;) 
    {
        dt = (hrt_absolute_time() - last_loop_time) / 1000000.0f;
        last_loop_time = hrt_absolute_time();

        if (dt < 0.0001f) 
        {
            dt = 0.0001f;

        } else if (dt > 0.02f) 
        {
            dt = 0.02f;
        }

        /* track the rate at which the loop is running */
        perf_count(loop_perf);//Calculate cycle run time

        /* kick the mixer */
        perf_begin(mixer_perf);
        mixer_tick();
        perf_end(mixer_perf);

        /* kick the control inputs */
        perf_begin(controls_perf);
        controls_tick();
        perf_end(controls_perf);

        /* some boards such as Pixhawk 2.1 made
           the unfortunate choice to combine the blue led channel with
           the IMU heater. We need a software hack to fix the hardware hack
           by allowing to disable the LED / heater.
         */
        if (r_page_setup[PX4IO_P_SETUP_THERMAL] == PX4IO_THERMAL_IGNORE) {
            /*
              blink blue LED at 4Hz in normal operation. When in
              override blink 4x faster so the user can clearly see
              that override is happening. This helps when
              pre-flight testing the override system
             */
            uint32_t heartbeat_period_us = 250 * 1000UL;

            if (r_status_flags & PX4IO_P_STATUS_FLAGS_OVERRIDE) {
                heartbeat_period_us /= 4;
            }

            if ((hrt_absolute_time() - last_heartbeat_time) > heartbeat_period_us) {
                last_heartbeat_time = hrt_absolute_time();
                heartbeat_blink();
            }

        } else if (r_page_setup[PX4IO_P_SETUP_THERMAL] < PX4IO_THERMAL_FULL) {
            /* switch resistive heater off */
            LED_BLUE(false);

        } else {
            /* switch resistive heater hard on */
            LED_BLUE(true);
        }

        update_mem_usage();

        ring_blink();

        check_reboot();

        /* check for debug activity (default: none) */
        show_debug_messages();

        /* post debug state at ~1Hz - this is via an auxiliary serial port
         * DEFAULTS TO OFF!
         */
        if (hrt_absolute_time() - last_debug_time > (1000 * 1000)) {

            isr_debug(1, "d:%u s=0x%x a=0x%x f=0x%x m=%u",
                  (unsigned)r_page_setup[PX4IO_P_SETUP_SET_DEBUG],
                  (unsigned)r_status_flags,
                  (unsigned)r_setup_arming,
                  (unsigned)r_setup_features,
                  (unsigned)mallinfo().mxordblk);
            last_debug_time = hrt_absolute_time();
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222

It can be seen that all tasks in px4 are executed as task functions in that rcs, but not in apm
This is where the PX4 runs first, and then we will continue to study the role of each function. Here is just a brief overview of the process. Comparisons with APM Formation

2.APM firmware startup process

(1)void __start(void)

void __start(void)
{
  const uint32_t *src;
  uint32_t *dest;

#ifdef CONFIG_ARMV7M_STACKCHECK
  /* Set the stack limit before we attempt to call any functions */

  __asm__ volatile ("sub r10, sp, %0" : : "r" (CONFIG_IDLETHREAD_STACKSIZE - 64) : );
#endif

  /* Configure the uart so that we can get debug output as soon as possible */

  stm32_clockconfig();//Initialization Clock
  stm32_fpuconfig();  //Configure FMU
  stm32_lowsetup();   //Initialization of Basic Serial Port
  stm32_gpioinit();   //Configure IO
  showprogress('A');

  /* 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;
    }

  showprogress('B');

  /* Move the intialized 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++ = *s

Posted by p0pb0b on Fri, 17 May 2019 06:32:53 -0700