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—ArdupilotThe second section: px4 and apm The role of each folder
(1)px4 Code Code Architecture
1>Collation catalog2>The role of each folder
(2)apm Code Code Architecture
1>Collation catalog2>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