示例#1
0
int aos_task_new(const char *name, void (*fn)(void *), void *arg,
                 int stack_size)
{
    xTaskHandle xHandle;
    AosStaticTask_t *task = malloc(sizeof(AosStaticTask_t));
    struct targ *targ = malloc(sizeof(*targ));
    void *stack = malloc(stack_size);

    bzero(stack, stack_size);
    bzero(task, sizeof(*task));
    task->key_bitmap = 0xfffffff0;
    task->stack = stack;
    strncpy(task->name, name, sizeof(task->name)-1);
    task->magic = AOS_MAGIC;

    targ->task = task;
    targ->fn = fn;
    targ->arg = arg;

    stack_size /= sizeof(StackType_t);
    xHandle = xTaskCreateStatic(dfl_entry, name, stack_size, targ,
                                10, stack, &task->fTask);
    if (xHandle == NULL) {
        free(task);
        free(stack);
        free(targ);
    }
    return xHandle ? 0 : -1;
}
示例#2
0
STATIC void mptask_pre_init (void) {
    // this one only makes sense after a poweron reset
    pyb_rtc_pre_init();

    // Create the simple link spawn task
    ASSERT (OSI_OK == VStartSimpleLinkSpawnTask(SIMPLELINK_SPAWN_TASK_PRIORITY));

    // Allocate memory for the flash file system
    ASSERT ((sflash_vfs_fat = mem_Malloc(sizeof(*sflash_vfs_fat))) != NULL);

    // this one allocates memory for the nvic vault
    pyb_sleep_pre_init();

    // this one allocates memory for the WLAN semaphore
    wlan_pre_init();

    // this one allocates memory for the updater semaphore
    updater_pre_init();

    // this one allocates memory for the socket semaphore
    modusocket_pre_init();

    //CRYPTOHASH_Init();

#ifndef DEBUG
    OsiTaskHandle svTaskHandle;
#endif
    svTaskHandle = xTaskCreateStatic(TASK_Servers, "Servers",
        SERVERS_STACK_LEN, NULL, SERVERS_PRIORITY, svTaskStack, &svTaskTCB);
    ASSERT(svTaskHandle != NULL);
}
示例#3
0
	TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer )
	{
	TaskHandle_t xReturn;
	BaseType_t xRunningPrivileged = xPortRaisePrivilege();

		xReturn = xTaskCreateStatic( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer );
		vPortResetPrivilege( xRunningPrivileged );
		return xReturn;
	}
示例#4
0
void main_blinky( void )
{
	/* See http://www.FreeRTOS.org/TI_MSP432_Free_RTOS_Demo.html for 
	instructions and notes regarding the difference in power saving that can be 
	achieved between using the generic tickless RTOS implementation (as used by 
	the blinky demo) and a tickless RTOS implementation that is tailored 
	specifically to the MSP432. */

	/* The full demo configures the clocks for maximum frequency, wheras this
	blinky demo uses a slower clock as it also uses low power features. */
	prvConfigureClocks();
	CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);

	/* Create the queue. */
	xQueue = xQueueCreateStatic( mainQUEUE_LENGTH, sizeof(TransportMessages), xRxQueueBuf, &xRxQueueDef);

	if( xQueue != NULL )
	{
		/* Start the two tasks as described in the comments at the top of this
		file. */
		xTaskCreateStatic( prvQueueReceiveTask,					/* The function that implements the task. */
					"Rx", 									/* The text name assigned to the task - for debug only as it is not used by the kernel. */
					configMINIMAL_STACK_SIZE, 				/* The size of the stack to allocate to the task. */
					( void * ) mainQUEUE_RECEIVE_PARAMETER, /* The parameter passed to the task - just to check the functionality. */
					mainQUEUE_RECEIVE_TASK_PRIORITY, 		/* The priority assigned to the task. */
					NULL,									/* The task handle is not required, so NULL is passed. */
					xRxStack,
					&xRxTaskBuffer);

		xTaskCreateStatic( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, ( void * ) mainQUEUE_SEND_PARAMETER, mainQUEUE_SEND_TASK_PRIORITY, NULL,
						   xTxStack, &xTxTaskBuffer);

		/* Start the tasks and timer running. */
		vTaskStartScheduler();
	}

	/* If all is well, the scheduler will now be running, and the following
	line will never be reached.  If the following line does execute, then
	there was insufficient FreeRTOS heap memory available for the idle and/or
	timer tasks	to be created.  See the memory management section on the
	FreeRTOS web site for more details. */
	for( ;; );
}
示例#5
0
/*******************************************************************************
 * vTraceEnable
 *
 * Function that enables the tracing and creates the control task. It will halt
 * execution until a Start command has been received if haltUntilStart is true.
 *
 ******************************************************************************/
void vTraceEnable(int startOption)
{
	int bytes = 0;
	extern uint32_t RecorderEnabled;
	TracealyzerCommandType msg;
	TRC_STREAM_PORT_INIT();
	
	if (startOption == TRC_START_AWAIT_HOST)
	{
		/* We keep trying to read commands until the recorder has been started */
		do
		{
			bytes = 0;
			TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), &bytes);

			if (bytes == sizeof(TracealyzerCommandType))
			{
				if (prvIsValidCommand(&msg))
				{
					if (msg.cmdCode == CMD_SET_ACTIVE && msg.param1 == 1)
					{
						/* On start, init and reset the timestamping */
						TRC_PORT_SPECIFIC_INIT();
					}
					
					prvProcessCommand(&msg);
				}
			}
		}
		while (RecorderEnabled == 0);
	}
	else if (startOption == TRC_START)
	{
		/* We start streaming directly - this assumes that the interface is ready! */
		msg.cmdCode = CMD_SET_ACTIVE;
		msg.param1 = 1;
		prvProcessCommand(&msg);
	}
	else
	{
		/* Start commands will be processed by the TzCtrl task. */
		TRC_PORT_SPECIFIC_INIT();
	}

	trcWarningChannel = xTraceRegisterString("Warnings from Recorder");

  	/* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
#if (configSUPPORT_STATIC_ALLOCATION == 1)
	HandleTzCtrl = xTaskCreateStatic(TzCtrl, "TzCtrl", TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
	(void)HandleTzCtrl;
#else 
	xTaskCreate( TzCtrl, "TzCtrl", TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );
#endif
}
void vStartStaticallyAllocatedTasks( void  )
{
	/* Create a single task, which then repeatedly creates and deletes the other
	RTOS objects using both statically and dynamically allocated RAM. */
	xTaskCreateStatic( prvStaticallyAllocatedCreator,		/* The function that implements the task being created. */
					   "StatCreate",						/* Text name for the task - not used by the RTOS, its just to assist debugging. */
					   staticCREATOR_TASK_STACK_SIZE,		/* Size of the buffer passed in as the stack - in words, not bytes! */
					   NULL,								/* Parameter passed into the task - not used in this case. */
					   staticTASK_PRIORITY,					/* Priority of the task. */
					   &( uxCreatorTaskStackBuffer[ 0 ] ),  /* The buffer to use as the task's stack. */
					   &xCreatorTaskTCBBuffer );			/* The variable that will hold the task's TCB. */
}
示例#7
0
void SHELL_Init(void) {
#if configSUPPORT_STATIC_ALLOCATION
  if (xTaskCreateStatic(ShellTask, "Shell", SHELL_TASK_SIZE, NULL, tskIDLE_PRIORITY+1, &xStack[0], &xTaskTCBBuffer)==NULL) {
    for(;;){} /* task creation failed */
  }
#elif configSUPPORT_DYNAMIC_ALLOCATION
  if (xTaskCreate(ShellTask, "Shell", configMINIMAL_STACK_SIZE+300, NULL, tskIDLE_PRIORITY+1, NULL) != pdPASS) {
    for(;;){} /* error, maybe out of heap memory */
  }
#else
  #error "Either configSUPPORT_STATIC_ALLOCATION or configSUPPORT_DYNAMIC_ALLOCATION has to be enabled"
#endif
}
示例#8
0
BaseType_t xTimerCreateTimerTask( void )
{
BaseType_t xReturn = pdFAIL;

	/* This function is called when the scheduler is started if
	configUSE_TIMERS is set to 1.  Check that the infrastructure used by the
	timer service task has been created/initialised.  If timers have already
	been created then the initialisation will already have been performed. */
	prvCheckForValidListAndQueue();

	if( xTimerQueue != NULL )
	{
		#if( configSUPPORT_STATIC_ALLOCATION == 1 )
		{
			StaticTask_t *pxTimerTaskTCBBuffer = NULL;
			StackType_t *pxTimerTaskStackBuffer = NULL;
			uint32_t ulTimerTaskStackSize;

			vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );
			xTimerTaskHandle = xTaskCreateStatic(	prvTimerTask,
													configTIMER_SERVICE_TASK_NAME,
													ulTimerTaskStackSize,
													NULL,
													( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
													pxTimerTaskStackBuffer,
													pxTimerTaskTCBBuffer );

			if( xTimerTaskHandle != NULL )
			{
				xReturn = pdPASS;
			}
		}
		#else
		{
			xReturn = xTaskCreate(	prvTimerTask,
									configTIMER_SERVICE_TASK_NAME,
									configTIMER_TASK_STACK_DEPTH,
									NULL,
									( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
									&xTimerTaskHandle );
		}
		#endif /* configSUPPORT_STATIC_ALLOCATION */
	}
	else
	{
		mtCOVERAGE_TEST_MARKER();
	}

	configASSERT( xReturn );
	return xReturn;
}
示例#9
0
文件: main.c 项目: Eclo/FreeRTOS
static void prvStartCheckTask( void )
{
/* Allocate the data structure that will hold the task's TCB.  NOTE:  This is
declared static so it still exists after this function has returned. */
static StaticTask_t xCheckTask;

/* Allocate the stack that will be used by the task.  NOTE:  This is declared
static so it still exists after this function has returned. */
static StackType_t ucTaskStack[ configMINIMAL_STACK_SIZE * sizeof( StackType_t ) ];

	/* Create the task, which will use the RAM allocated by the linker to the
	variables declared in this function. */
	xTaskCreateStatic( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, ucTaskStack, &xCheckTask );
}
// starts RTOS scheduler
void run_rtos()
{
	configASSERT(NUM_MUTEXES == sizeof(all_mutexes_ordered) / sizeof(SemaphoreHandle_t*));
	
	// create first init task to start RTOS and other tasks
	xTaskCreateStatic(startup_task,
		"initializer task",
		TASK_INIT_STACK_SIZE,
		NULL,
		TASK_INIT_PRIORITY,
		init_task_stack,
		&init_task_buffer);

	/* Start the tasks and timer running. */
	vTaskStartScheduler();
}
示例#11
0
void vStartStaticallyAllocatedTasks( void  )
{
	/* Create a single task, which then repeatedly creates and deletes the
	task implemented by prvStaticallyAllocatedTask() at various different
	priorities, and both with and without statically allocated TCB and stack. */
	xTaskCreateStatic( prvStaticallyAllocatedCreator,		/* The function that implements the task being created. */
					   "StatCreate",						/* Text name for the task - not used by the RTOS, its just to assist debugging. */
					   staticCREATOR_TASK_STACK_SIZE,		/* Size of the buffer passed in as the stack - in words, not bytes! */
					   NULL,								/* Parameter passed into the task - not used in this case. */
					   staticTASK_PRIORITY,					/* Priority of the task. */
					   NULL,								/* Handle of the task being created, not used in this case. */
					   &( uxCreatorTaskStackBuffer[ 0 ] ),  /* The buffer to use as the task's stack. */
					   &xCreatorTaskTCBBuffer );			/* The variable that will hold the task's TCB. */

	/* Pseudo seed the random number generator. */
	ulNextRand = ( uint32_t ) prvRand;
}
示例#12
0
int main() {
  // Reset of all peripherals, Initializes the Flash interface and the Systick.
  HAL_Init();

  // Configure the system clock
  SystemClock_Config();

  // Setup main task
  xTaskCreateStatic( main_task, "main", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, ucMainStack, &xMainTask );

  // Start the FreeRTOS scheduler
  vTaskStartScheduler();

  // Should never reach there
  while(1);

  return 0;
}
示例#13
0
void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
    // store thread entry function into a global variable so we can access it
    ext_thread_entry = entry;

    if (*stack_size == 0) {
        *stack_size = 4096; // default stack size
    } else if (*stack_size < 2048) {
        *stack_size = 2048; // minimum stack size
    }

    // allocate TCB, stack and linked-list node (must be outside thread_mutex lock)
    StaticTask_t *tcb = m_new(StaticTask_t, 1);
    StackType_t *stack = m_new(StackType_t, *stack_size / sizeof(StackType_t));
    thread_t *th = m_new_obj(thread_t);

    mp_thread_mutex_lock(&thread_mutex, 1);

    // create thread
    TaskHandle_t id = xTaskCreateStatic(freertos_entry, "Thread", *stack_size / sizeof(void*), arg, 2, stack, tcb);
    if (id == NULL) {
        mp_thread_mutex_unlock(&thread_mutex);
        mp_raise_msg(&mp_type_OSError, "can't create thread");
    }

    // add thread to linked list of all threads
    th->id = id;
    th->ready = 0;
    th->arg = arg;
    th->stack = stack;
    th->stack_len = *stack_size / sizeof(StackType_t);
    th->next = thread;
    thread = th;

    mp_thread_mutex_unlock(&thread_mutex);

    // adjust stack_size to provide room to recover from hitting the limit
    *stack_size -= 512;
}
示例#14
0
int main (void) {

    // Initialize the clocks and the interrupt system
    HAL_SystemInit();

#if MICROPY_HW_ANTENNA_DIVERSITY
    // configure the antenna selection pins
    antenna_init0();
#endif

    // Init the watchdog
    pybwdt_init0();

#ifndef DEBUG
    OsiTaskHandle mpTaskHandle;
#endif
    mpTaskHandle = xTaskCreateStatic(TASK_Micropython, "MicroPy",
        MICROPY_TASK_STACK_LEN, NULL, MICROPY_TASK_PRIORITY, mpTaskStack, &mpTaskTCB);
    ASSERT(mpTaskHandle != NULL);

    osi_start();

    for ( ; ; );
}
示例#15
0
static void prvCreateAndDeleteStaticallyAllocatedTasks( void )
{
TaskHandle_t xCreatedTask;

/* The variable that will hold the TCB of tasks created by this function.  See
the comments above the declaration of the xCreatorTaskTCBBuffer variable for
more information. */
StaticTask_t xTCBBuffer;

/* This buffer that will be used as the stack of tasks created by this function.
See the comments above the declaration of the uxCreatorTaskStackBuffer[] array
above for more information. */
static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];

	/* Create the task.  xTaskCreateStatic() has two more parameters than
	the usual xTaskCreate() function.  The first new parameter is a pointer to
	the pre-allocated stack.  The second new parameter is a pointer to the
	StaticTask_t structure that will hold the task's TCB.  If both pointers are
	passed as NULL then the respective object will be allocated dynamically as
	if xTaskCreate() had been called. */
	xCreatedTask = xTaskCreateStatic(
						prvStaticallyAllocatedTask, 	/* Function that implements the task. */
						"Static",						/* Human readable name for the task. */
						configMINIMAL_STACK_SIZE,		/* Task's stack size, in words (not bytes!). */
						NULL,							/* Parameter to pass into the task. */
						uxTaskPriorityGet( NULL ) + 1,	/* The priority of the task. */
						&( uxStackBuffer[ 0 ] ),		/* The buffer to use as the task's stack. */
						&xTCBBuffer );					/* The variable that will hold that task's TCB. */

	/* Check the task was created correctly, then delete the task. */
	if( xCreatedTask == NULL )
	{
		xErrorOccurred = pdTRUE;
	}
	else if( eTaskGetState( xCreatedTask ) != eSuspended )
	{
		/* The created task had a higher priority so should have executed and
		suspended itself by now. */
		xErrorOccurred = pdTRUE;
	}
	else
	{
		vTaskDelete( xCreatedTask );
	}

	/* Now do the same using a dynamically allocated task to ensure the delete
	function is working correctly in both the static and dynamic allocation
	cases. */
	#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
	{
	BaseType_t xReturned;

		xReturned = xTaskCreate(
									prvStaticallyAllocatedTask,		/* Function that implements the task - the same function is used but is actually dynamically allocated this time. */
									"Static",						/* Human readable name for the task. */
									configMINIMAL_STACK_SIZE,		/* Task's stack size, in words (not bytes!). */
									NULL,							/* Parameter to pass into the task. */
									uxTaskPriorityGet( NULL ) + 1,	/* The priority of the task. */
									&xCreatedTask );				/* Handle of the task being created. */

		if( eTaskGetState( xCreatedTask ) != eSuspended )
		{
			xErrorOccurred = pdTRUE;
		}

		configASSERT( xReturned == pdPASS );
		if( xReturned != pdPASS )
		{
			xErrorOccurred = pdTRUE;
		}
		vTaskDelete( xCreatedTask );
	}
	#endif
}
示例#16
0
static void prvCreateAndDeleteStaticallyAllocatedTasks( void )
{
TaskHandle_t xCreatedTask;
BaseType_t xReturned;

/* The variable that will hold the TCB of tasks created by this function.  See
the comments above the declaration of the xCreatorTaskTCBBuffer variable for
more information. */
StaticTask_t xTCBBuffer;

/* This buffer that will be used as the stack of tasks created by this function.
See the comments above the declaration of the uxCreatorTaskStackBuffer[] array
above for more information. */
static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];

	/* Create the task.  xTaskCreateStatic() has two more parameters than
	the usual xTaskCreate() function.  The first new parameter is a pointer to
	the pre-allocated stack.  The second new parameter is a pointer to the
	StaticTask_t structure that will hold the task's TCB.  If either pointer is
	passed as NULL then the respective object will be allocated dynamically as
	if xTaskCreate() had been called. */
	xReturned = xTaskCreateStatic(
						prvStaticallyAllocatedTask, /* Function that implements the task. */
						"Static",					/* Human readable name for the task. */
						configMINIMAL_STACK_SIZE,	/* Task's stack size, in words (not bytes!). */
						NULL,						/* Parameter to pass into the task. */
						tskIDLE_PRIORITY,			/* The priority of the task. */
						&xCreatedTask,				/* Handle of the task being created. */
						&( uxStackBuffer[ 0 ] ),	/* The buffer to use as the task's stack. */
						&xTCBBuffer );				/* The variable that will hold that task's TCB. */

	/* Check the task was created correctly, then delete the task. */
	configASSERT( xReturned == pdPASS );
	if( xReturned != pdPASS )
	{
		xErrorOccurred = pdTRUE;
	}
	vTaskDelete( xCreatedTask );

	/* Ensure lower priority tasks get CPU time. */
	vTaskDelay( prvGetNextDelayTime() );

	/* Create and delete the task a few times again - testing both static and
	dynamic allocation for the stack and TCB. */
	xReturned = xTaskCreateStatic(
						prvStaticallyAllocatedTask, /* Function that implements the task. */
						"Static",					/* Human readable name for the task. */
						configMINIMAL_STACK_SIZE,	/* Task's stack size, in words (not bytes!). */
						NULL,						/* Parameter to pass into the task. */
						staticTASK_PRIORITY + 1,	/* The priority of the task. */
						&xCreatedTask,				/* Handle of the task being created. */
						NULL,						/* This time, dynamically allocate the stack. */
						&xTCBBuffer );				/* The variable that will hold that task's TCB. */

	configASSERT( xReturned == pdPASS );
	if( xReturned != pdPASS )
	{
		xErrorOccurred = pdTRUE;
	}
	vTaskDelete( xCreatedTask );

	/* Just to show the check task that this task is still executing. */
	uxCycleCounter++;

	/* Ensure lower priority tasks get CPU time. */
	vTaskDelay( prvGetNextDelayTime() );

	xReturned = xTaskCreateStatic(
						prvStaticallyAllocatedTask, /* Function that implements the task. */
						"Static",					/* Human readable name for the task. */
						configMINIMAL_STACK_SIZE,	/* Task's stack size, in words (not bytes!). */
						NULL,						/* Parameter to pass into the task. */
						staticTASK_PRIORITY - 1,	/* The priority of the task. */
						&xCreatedTask,				/* Handle of the task being created. */
						&( uxStackBuffer[ 0 ] ),	/* The buffer to use as the task's stack. */
						NULL );						/* This time dynamically allocate the TCB. */

	configASSERT( xReturned == pdPASS );
	if( xReturned != pdPASS )
	{
		xErrorOccurred = pdTRUE;
	}
	vTaskDelete( xCreatedTask );

	/* Ensure lower priority tasks get CPU time. */
	vTaskDelay( prvGetNextDelayTime() );

	xReturned = xTaskCreateStatic(
						prvStaticallyAllocatedTask, /* Function that implements the task. */
						"Static",					/* Human readable name for the task. */
						configMINIMAL_STACK_SIZE,	/* Task's stack size, in words (not bytes!). */
						NULL,						/* Parameter to pass into the task. */
						staticTASK_PRIORITY,		/* The priority of the task. */
						&xCreatedTask,				/* Handle of the task being created. */
						NULL,						/* This time dynamically allocate the stack and TCB. */
						NULL );						/* This time dynamically allocate the stack and TCB. */

	configASSERT( xReturned == pdPASS );
	if( xReturned != pdPASS )
	{
		xErrorOccurred = pdTRUE;
	}
	vTaskDelete( xCreatedTask );

	/* Ensure lower priority tasks get CPU time. */
	vTaskDelay( prvGetNextDelayTime() );

	/* Just to show the check task that this task is still executing. */
	uxCycleCounter++;
}
/**
 * Only task configured to start at boot; starts the rest of RTOS.
 * We use this task to do most of the startup because it allows
 * use of various RTOS functionality (which can cause issues when used
 * before the scheduler is running).
 * WARNING: The vApplicationDaemonTaskStartupHook did not work for us.
 */
void startup_task(void* pvParameters) {
	print("EQUiSatOS starting... ");
	
	#ifdef WRITE_DEFAULT_MRAM_VALS
		// utility function to write initial state to MRAM (ONCE before launch)
		write_custom_state();
	#endif
	
	/************************************************************************/
	/* DATA INITIALIZATION                                                  */
	/************************************************************************/	

	// Initialize misc. state mutexes
	hardware_state_mutex = xSemaphoreCreateMutexStatic(&_hardware_state_mutex_d);
	critical_action_mutex = xSemaphoreCreateMutexStatic(&_critical_action_mutex_d);

	// Initialize EQUiStack mutexes
	_idle_equistack_mutex = xSemaphoreCreateMutexStatic(&_idle_equistack_mutex_d);
	_attitude_equistack_mutex = xSemaphoreCreateMutexStatic(&_attitude_equistack_mutex_d);
	_flash_equistack_mutex = xSemaphoreCreateMutexStatic(&_flash_equistack_mutex_d);
	_flash_cmp_equistack_mutex = xSemaphoreCreateMutexStatic(&_flash_cmp_equistack_mutex_d);
	_low_power_equistack_mutex = xSemaphoreCreateMutexStatic(&_low_power_equistack_mutex_d);

	// Initialize EQUiStacks
	equistack_Init(&idle_readings_equistack, &_idle_equistack_arr,
		sizeof(idle_data_t), IDLE_STACK_MAX, _idle_equistack_mutex);
	equistack_Init(&attitude_readings_equistack, &_attitude_equistack_arr,
		sizeof(attitude_data_t), ATTITUDE_STACK_MAX, _attitude_equistack_mutex);
	equistack_Init(&flash_readings_equistack, &_flash_equistack_arr,
		sizeof(flash_data_t), FLASH_STACK_MAX, _flash_equistack_mutex);
 	equistack_Init(&flash_cmp_readings_equistack, &_flash_cmp_equistack_arr,
		sizeof(flash_cmp_data_t), FLASH_CMP_STACK_MAX, _flash_cmp_equistack_mutex);
 	equistack_Init(&low_power_readings_equistack, &_low_power_equistack_arr,
		sizeof(low_power_data_t), LOW_POWER_STACK_MAX, _low_power_equistack_mutex);
		
	/************************************************************************/
	/* ESSENTIAL INITIALIZATION                                             */
	/************************************************************************/
	// read state from MRAM for first time
	// this initializes the error equistacks, so make sure no errors
	// are logged before this (they shouldn't be before RTOS is started...)
	configure_state_from_reboot();

	// function in global to init things that use RTOS 
	// (MUST be done after config state from reboot)
	global_init_post_rtos();

	// populate task_handles array and setup constants
	pre_init_rtos_tasks();
	
	#if configUSE_TRACE_FACILITY == 1
		// name mutexes
		vTraceSetMutexName(critical_action_mutex, "CA");
		vTraceSetMutexName(i2c_irpow_mutex, "I2C");
		vTraceSetMutexName(irpow_semaphore, "IRPOW");
		vTraceSetMutexName(processor_adc_mutex, "ADC");
		vTraceSetMutexName(hardware_state_mutex, "HWST");
		vTraceSetMutexName(watchdog_mutex, "WD");
		vTraceSetMutexName(mram_spi_cache_mutex, "SPI");
		
		vTraceSetMutexName(_idle_equistack_mutex, "eqIDLE");
		vTraceSetMutexName(_attitude_equistack_mutex, "eqATT");
		vTraceSetMutexName(_flash_equistack_mutex , "eqF_BST");
		vTraceSetMutexName(_flash_cmp_equistack_mutex, "eqF_CMP");
		vTraceSetMutexName(_low_power_equistack_mutex, "eqLP");
		vTraceSetMutexName(_error_equistack_mutex, "eqERR");
	#endif
	
	// note RTOS is ready for watchdog callback, and log error if it already tripped
	rtos_ready = true;
	if (got_early_warning_callback_in_boot) {
		log_error(ELOC_WATCHDOG, ECODE_WATCHDOG_EARLY_WARNING, true);
	}

	/************************************************************************/
	/* TASK CREATION                                                        */
	/************************************************************************/

	// NOTE: We can't actually set task state before they are started below,
	// and tasks start as active (resumed), so we have the tasks themselves
	// call the function below which will either suspend them or leave them
	// running as defined by the configuration of initial state.

	// suspend the scheduler while adding tasks so their task handles
	// are non-null when they start executing (i.e. they can be controlled)
	pet_watchdog(); // in case this takes a bit and we're close
	vTaskSuspendAll();
	
	/************************************************************************/
	/* TESTING/MISC                                                         */
	/************************************************************************/
	create_testing_tasks();
	/************************************************************************/
	/* END TESTING                                                          */
	/************************************************************************/
	
	#ifndef ONLY_RUN_TESTING_TASKS
	battery_charging_task_handle = xTaskCreateStatic(battery_charging_task,
		"battery charging action task",
		TASK_BATTERY_CHARGING_STACK_SIZE,
		NULL,
		TASK_BATTERY_CHARGING_PRIORITY,
		battery_charging_task_stack,
		&battery_charging_task_buffer);

	antenna_deploy_task_handle = xTaskCreateStatic(antenna_deploy_task,
		"antenna deploy action task",
		TASK_ANTENNA_DEPLOY_STACK_SIZE,
		NULL,
		TASK_ANTENNA_DEPLOY_PRIORITY,
		antenna_deploy_task_stack,
		&antenna_deploy_task_buffer);

	state_handling_task_handle = xTaskCreateStatic(state_handling_task,
		"state handling action task",
		TASK_STATE_HANDLING_STACK_SIZE,
		NULL,
		TASK_STATE_HANDLING_PRIORITY,
		state_handling_task_stack,
		&state_handling_task_buffer);

	watchdog_task_handle = xTaskCreateStatic(watchdog_task,
		"watchdog task",
		TASK_WATCHDOG_STACK_SIZE,
		NULL,
		TASK_WATCHDOG_PRIORITY,
		watchdog_task_stack,
		&watchdog_task_buffer);

	persistent_data_backup_task_handle = xTaskCreateStatic(persistent_data_backup_task,
		"persistent data backup task",
		TASK_PERSISTENT_DATA_BACKUP_STACK_SIZE,
		NULL,
		TASK_PERSISTENT_DATA_BACKUP_PRIORITY,
		persistent_data_backup_task_stack,
		&persistent_data_backup_task_buffer);

	flash_activate_task_handle = xTaskCreateStatic(flash_activate_task,
		"flash action task",
		TASK_FLASH_ACTIVATE_STACK_SIZE,
		NULL,
		TASK_FLASH_ACTIVATE_PRIORITY,
		flash_activate_task_stack,
		&flash_activate_task_buffer);

	transmit_task_handle = xTaskCreateStatic(transmit_task,
		"transmit action task",
		TASK_TRANSMIT_STACK_SIZE,
		NULL,
		TASK_TRANSMIT_PRIORITY,
		transmit_task_stack,
		&transmit_task_buffer);

	/* Data tasks */

	idle_data_task_handle = xTaskCreateStatic(idle_data_task,
		"idle data reader task",
		TASK_IDLE_DATA_RD_STACK_SIZE,
		NULL,
		TASK_IDLE_DATA_RD_PRIORITY,
		idle_data_task_stack,
		&idle_data_task_buffer);

	attitude_data_task_handle = xTaskCreateStatic(attitude_data_task,
		"attitude data reader task",
		TASK_ATTITUDE_DATA_RD_STACK_SIZE,
		NULL,
		TASK_ATTITUDE_DATA_DATA_RD_PRIORITY,
		attitude_data_task_stack,
		&attitude_data_task_buffer);

	low_power_data_task_handle = xTaskCreateStatic(low_power_data_task,
		"low power data reader task",
		TASK_LOW_POWER_DATA_RD_STACK_SIZE,
		NULL,
		TASK_LOW_POWER_DATA_RD_PRIORITY,
		low_power_data_task_stack,
		&low_power_data_task_buffer);
	#endif

	xTaskResumeAll();

	setTXEnable(false);
	usart_send_string((uint8_t*) "EQUiSatOS started");
	setTXEnable(true);
	
	print("initialization complete.\n");
	
	// delete this task after it's done booting
	vTaskDelete(NULL);
}
/*******************************************************************************
 * vTraceEnable
 *
 * Function that enables the tracing and creates the control task. It will halt
 * execution until a Start command has been received if haltUntilStart is true.
 *
 ******************************************************************************/
void vTraceEnable(int startOption)
{
	int32_t bytes = 0;
	int32_t status;
	extern uint32_t RecorderEnabled;
	TracealyzerCommandType msg;

	/* Only do this first time...*/
	if (HandleTzCtrl == NULL)
	{
		TRC_STREAM_PORT_INIT();
		
		/* Note: Requires that TRC_CFG_INCLUDE_USER_EVENTS is 1. */
		trcWarningChannel = xTraceRegisterString("Warnings from Recorder");

		/* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
		#if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
		HandleTzCtrl = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
		#else
		xTaskCreate( TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, NULL, TRC_CFG_CTRL_TASK_PRIORITY, &HandleTzCtrl );
		#endif

		if (HandleTzCtrl == NULL)
		{
			prvTraceError(PSF_ERROR_TZCTRLTASK_NOT_CREATED);
		}
	}

	if (startOption == TRC_START_AWAIT_HOST)
	{
		/* We keep trying to read commands until the recorder has been started */
		do
		{
			bytes = 0;
			
			status = TRC_STREAM_PORT_READ_DATA(&msg, sizeof(TracealyzerCommandType), (int32_t*)&bytes);
			
			if (status != 0)
			{
				prvTraceWarning(PSF_WARNING_STREAM_PORT_READ);
			}

			if ((status == 0) && (bytes == sizeof(TracealyzerCommandType)))
			{
				if (prvIsValidCommand(&msg))
				{
					if (msg.cmdCode == CMD_SET_ACTIVE && msg.param1 == 1)
					{
						/* On start, init and reset the timestamping */
						TRC_PORT_SPECIFIC_INIT();
					}
					
					prvProcessCommand(&msg);
				}
			}
		}
		while (RecorderEnabled == 0);
	}
	else if (startOption == TRC_START)
	{
		/* We start streaming directly - this assumes that the interface is ready! */
		TRC_PORT_SPECIFIC_INIT();
		
		msg.cmdCode = CMD_SET_ACTIVE;
		msg.param1 = 1;
		prvProcessCommand(&msg);
	}
	else
	{
		/* On TRC_INIT */
		TRC_PORT_SPECIFIC_INIT();
	}
}