/*
 *  TOPPERS/ASP Kernel
 *      Toyohashi Open Platform for Embedded Real-Time Systems/
 *      Advanced Standard Profile Kernel
 * 
 *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
 *                              Toyohashi Univ. of Technology, JAPAN
 *  Copyright (C) 2005-2007 by Embedded and Real-Time Systems Laboratory
 *              Graduate School of Information Science, Nagoya Univ., JAPAN
 *  Copyright (C) 2010 by TOPPERS/ASP for LPC project
 *              http://sourceforge.jp/projects/toppersasp4lpc/
 * 
 *  上記著作権者は，以下の(1)〜(4)の条件を満たす場合に限り，本ソフトウェ
 *  ア（本ソフトウェアを改変したものを含む．以下同じ）を使用・複製・改
 *  変・再配布（以下，利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *      と．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *        報告すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 *      また，本ソフトウェアのユーザまたはエンドユーザからのいかなる理
 *      由に基づく請求からも，上記著作権者およびTOPPERSプロジェクトを
 *      免責すること．
 * 
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，特定の使用目的
 *  に対する適合性も含めて，いかなる保証も行わない．また，本ソフトウェ
 *  アの利用により直接的または間接的に生じたいかなる損害に関しても，そ
 *  の責任を負わない．
 * 
 */
/**
 * \addtogroup TOPPERS_TARGET
 * \{
 */

/**
 * \file target_config.c
 * \brief カーネル実装のターゲット依存モジュール（NXP LPC1768用）
 * \details
 * カーネル構築に必要でターゲットに依存する定義をこのファイルで行う。
 */
#include "kernel_impl.h"
#include <sil.h>
#include "lpcxpresso1768.h"
#include "target_serial.h"
#include "target_syssvc.h"

#define POWER_ON_UART0()    (LPC_SC->PCONP |= (1 <<  3))
#define POWER_ON_UART1()    (LPC_SC->PCONP |= (1 <<  4))
#define POWER_ON_UART2()    (LPC_SC->PCONP |= (1 << 24))
#define POWER_ON_UART3()    (LPC_SC->PCONP |= (1 << 25))

#define USE_TXD3_ON_P0_0()  (LPC_PINCON->PINSEL0 |= (0x2 <<  0))
#define USE_RXD3_ON_P0_1()  (LPC_PINCON->PINSEL0 |= (0x2 <<  2))
#define USE_TXD0_ON_P0_2()  (LPC_PINCON->PINSEL0 |= (0x1 <<  4))
#define USE_RXD0_ON_P0_3()  (LPC_PINCON->PINSEL0 |= (0x1 <<  6))
#define USE_TXD2_ON_P0_10() (LPC_PINCON->PINSEL0 |= (0x1 << 20))
#define USE_RXD2_ON_P0_11() (LPC_PINCON->PINSEL0 |= (0x1 << 22))
#define USE_TXD1_ON_P0_15() (LPC_PINCON->PINSEL0 |= (0x1 << 30))
#define USE_RXD1_ON_P0_16() (LPC_PINCON->PINSEL1 |= (0x1 <<  0))
#define USE_TXD3_ON_P0_25() (LPC_PINCON->PINSEL1 |= (0x3 << 18))
#define USE_RXD3_ON_P0_26() (LPC_PINCON->PINSEL1 |= (0x3 << 20))
#define USE_TXD1_ON_P2_0()  (LPC_PINCON->PINSEL4 |= (0x2 <<  0))
#define USE_RXD1_ON_P2_1()  (LPC_PINCON->PINSEL4 |= (0x2 <<  2))
#define USE_TXD2_ON_P2_8()  (LPC_PINCON->PINSEL4 |= (0x2 << 16))
#define USE_RXD2_ON_P2_9()  (LPC_PINCON->PINSEL4 |= (0x2 << 18))
#define USE_TXD3_ON_P4_28() (LPC_PINCON->PINSEL9 |= (0x3 << 24))
#define USE_RXD3_ON_P4_29() (LPC_PINCON->PINSEL9 |= (0x3 << 26))

/**
 * \brief ターゲット依存部　初期化処理
 * \details
 * sta_ker() の中から呼び出されてターゲットのハードウェアの初期化を行う。この関数の中では
 * PLLの初期化やペリフェラル・ピンの初期化などを行う。
 */
void target_initialize(void)
{
    int siocnt = 0;

    /*
     *  チップ依存部の初期化。この呼び出しは削除してはいけない。
     */
    chip_initialize();

    /* Flash Accelerator を初期化。100MHz動作に対応 */
    LPC_SC->FLASHCFG = 0x403a;

    /*
     *  プロセッサクロックの初期化
     */
    // PLLの設定 (2 * 50 * 4MHz)/1/4 = 100MHz
    initPLL0(
            eIrc,   // pllClockSource_type clkSrc,
            0,      // unsigned int isMainOsc20MHzMore,
            1,      // unsigned int N,
            50,     // unsigned int M,
            4       // unsigned int cpuClkDiv
            );

    /*
     *  SIOポートの初期化
     *
     *  SIO_PORTIDの値に応じて自動的にピン・コンフィギュレーションを行うが、
     *  これはLPC1768の一部機能に過ぎない。
     *  LPC1768は、UART1や2の割り当て先を複数種類持っている。
     *  以下のコードはそれらのうちの一つに対応しているにすぎない。
     *  必要に応じてアプリケーション・プログラマが書き換えて使うこと。
     */

#if defined (SIO_BAUD_RATE_PORT1)
    POWER_ON_UART0();
    USE_TXD0_ON_P0_2();
    USE_RXD0_ON_P0_3();
    target_uart_init(SIO1_PORTID);
    siocnt++;
#endif

#if defined (SIO_BAUD_RATE_PORT2)
    POWER_ON_UART1();
    USE_TXD1_ON_P2_0();
    USE_RXD1_ON_P2_1();
    target_uart_init(SIO2_PORTID);
    siocnt++;
#endif

#if defined (SIO_BAUD_RATE_PORT3)
    POWER_ON_UART2();
    USE_TXD2_ON_P0_10();
    USE_RXD2_ON_P0_11();
    target_uart_init(SIO3_PORTID);
    siocnt++;
#endif

#if defined (SIO_BAUD_RATE_PORT4)
    POWER_ON_UART3();
    USE_TXD3_ON_P0_0();
    USE_RXD3_ON_P0_1();
    target_uart_init(SIO4_PORTID);
    siocnt++;
#endif

    /*
     * 不正な設定を見つけた。
     */
    if (siocnt != TNUM_SIOP_UART) {
        syslog(LOG_NOTICE, "Invalid TNUM_SIOP configuration found.");
        target_exit();
    }
}

/**
 * \brief ターゲット依存部　終了処理
 * \details
 * システム終了時にカーネルから呼ばれる。この関数は呼び出し元に戻らない。
 */
void target_exit(void)
{
    /* チップ依存部の終了処理 */
    chip_exit();

    while(1) {
    }
}

/**
 * \brief システムログの低レベル出力のための文字出力
 * \param c 出力キャラクタ
 * \details
 * コンソールに１文字出力する。チップ依存部が供給する出力関数をそのまま利用する。
 */
void target_fput_log(char_t c)
{
    chip_fput_log(c);
}

/**
 * \}
 */

