//----------------------------------------------------------------------------------
// <copyright file="base.c" company="LiquidRobotics">
//	Copyright (c) Liquid Robotics Corporation.  All rights reserved.
// </copyright>
//
// <summary>
// 	Standard implementation of main() and the startup administration task
//  (admin_task)
// </summary>
//
// <owner>Mike Cookson</owner>
//---------------------------------------------------------------------------------

#include "includes.h"
#include "user_app_init.h"
#include <avr/wdt.h>
#include <stdlib.h>
#include "timer.h"
#include "uart.h"
#include "pib.h"
#include "base.h"

/*PAGE*/
/*
 *******************************************************************************
 *                            PROGRAM ENTRY POINT
 *
 * Description :	This is the program entry point, which performs the following
 *					tasks:
 *
 *					1) Call AppInit(), which is meant to be implemented by the
 *					   client application
 *
 *					2) Call OSInit() to initialize MicroC/OS
 *
 *					3) Create admin_task as the highest-priority task; admin_task
 *					   must perform some actions to complete initialization
 *
 *					4) Call OSStart(), which causes the the highest-priority task
 *					   to start running.
 *
 * Arguments : 		n/a
 *
 * Returns:			
 *					OS_ERR_UART_ID_INVALID if the port ID is out of range
 *					OS_ERR_UART_DUPLICATE_INIT if the UART was already initialized
 *
 * Notes:			
 *******************************************************************************
 */
int main(void)
{
static OS_STK admin_stack[ADMIN_TASK_STACK_SIZE];
	INT8U oserr;

	AppInit();
	OSInit();

	OSTaskCreateExt(admin_task, (void*) 0, &admin_stack[ADMIN_TASK_STACK_SIZE-1],
		ADMIN_TASK_PRIO, ADMIN_TASK_ID, admin_stack, ADMIN_TASK_STACK_SIZE,
		(void*) 0, OS_TASK_OPT_STK_CHK);
	OSTaskNameSet(ADMIN_TASK_PRIO, (INT8U*) ADMIN_TASK_NAME, &oserr);

	OSStart();
}

/*PAGE*/
/*
 *******************************************************************************
 *                          ADMIN TASK ENTRY POINT
 *
 * Description :	This is the entry point for the admin task, which receives
 *					control from main() after the OS is started.  It is
 *					responsible for:
 *
 *					1) Completing any initialization required, such as starting
 *					   task switching from the timer tick.  This responsibility
 *					   is delegated to AppStartTasks(), which can be implemented
 *					   by the client app.
 *
 *					2) Starting any client app tasks, which is delegated to
 *					   AppStartTasks()
 *
 *					3) Optionally making use of this task slot by jumping to
 *					   a client-app-designated function, which is returned
 *					   from AppStartTasks()  If the pointer is null, this task
 *					   is suspended.
 *
 * Arguments : 		n/a
 *
 * Returns:			n/a
 *
 * Notes:			
 *******************************************************************************
 */
void admin_task(void* pdata)
{
	AppStartContinuationTask_t continuationTask = AppStartTasks();

	if (continuationTask)
		continuationTask((void*) 0L);

	OSTaskSuspend(OS_PRIO_SELF);
}

/*PAGE*/
/*
 *******************************************************************************
 *               CONFIGURES EXTERNAL MEMORY DURING INITIALIZATION
 *
 * Description :	This function runs ** prior to main() ** to set up external
 *					memory in section .init1
 *
 * Arguments : 		n/a
 *
 * Returns:			n/a
 *
 * Notes:			1) Note that this is not a real "function": it is executed
 *					   inline and contains no return since it never called.
 *******************************************************************************
 */
void xmem_init(void)
{
	asm(" clr r1\n");
    DDRH = _BV(7) | _BV(6);
    XMCRA = 0x80;
    XMCRB = 0x00;
}

/*PAGE*/
/*
 *******************************************************************************
 *               CONFIGURES EXTERNAL MEMORY DURING INITIALIZATION
 *
 * Description :	This function runs ** prior to main() ** to disable the
 *					watchdog timer in section .init3  It does this because
 *					sometimes the system is reset by setting a very short
 *					watchdog timeout; in this case, if the watchdog is not
 *					disabled soon after start up, it may reset the board again,
 *					causing an infinite reset loop.
 *
 * Arguments : 		n/a
 *
 * Returns:			n/a
 *
 * Notes:			1) Note that this is not a real "function": it is executed
 *					   inline and contains no return since it never called.
 *******************************************************************************
 */
void wdt_init(void)
{
	wdt_disable();
}
