Quantum Leaps 7fc376f5e5 4.5.03
2012-12-10 16:00:27 -05:00

279 lines
11 KiB
C

/*****************************************************************************
* BSP for Explorer 16 board with dsPIC33FJ256GP710, Vanilla kernel
* Last Updated for Version: 4.5.02
* Date of the Last Update: Oct 26, 2012
*
* Q u a n t u m L e a P s
* ---------------------------
* innovating embedded systems
*
* Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved.
*
* This program is open source software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Alternatively, this program may be distributed and modified under the
* terms of Quantum Leaps commercial licenses, which expressly supersede
* the GNU General Public License and are specifically designed for
* licensees interested in retaining the proprietary status of their code.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Contact information:
* Quantum Leaps Web sites: http://www.quantum-leaps.com
* http://www.state-machine.com
* e-mail: info@quantum-leaps.com
*****************************************************************************/
#include "qp_port.h"
#include "bsp.h"
#include "dpp.h"
Q_DEFINE_THIS_FILE
_FOSCSEL(FNOSC_FRC); /* set flash configuration for the device */
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE);
_FWDT(FWDTEN_OFF);
/* frequency of the FRC oscillator for dsPICFJ */
#define FOSC_HZ 7370000.0
/* instruction cycle clock frequency */
#define FCY_HZ (FOSC_HZ / 2.0)
/* system clock tick period in CPU clocks / TMR2 prescaler */
#define BSP_TMR2_PERIOD ((uint16_t)(FCY_HZ / BSP_TICKS_PER_SEC))
static uint8_t const l_led[] = {
(1 << 0), /* LED D3 on the Explorer 16 board */
(1 << 1), /* LED D4 on the Explorer 16 board */
(1 << 2), /* LED D5 on the Explorer 16 board */
(1 << 3), /* LED D6 on the Explorer 16 board */
(1 << 4), /* LED D7 on the Explorer 16 board */
(1 << 5), /* LED D8 on the Explorer 16 board */
(1 << 6), /* LED D9 on the Explorer 16 board */
(1 << 7), /* LED D10 on the Explorer 16 board */
0 /* non-existent LED */
};
#define LED_ON(n_) (PORTA |= l_led[n_])
#define LED_OFF(n_) (PORTA &= ~l_led[n_])
#define IDLE_LED 7
#ifdef Q_SPY
static uint32_t l_tickTime; /* timestamp at tick */
static uint8_t const l_T2Interrupt = 0;
enum AppRecords { /* application-specific trace records */
PHILO_STAT = QS_USER
};
#endif
/* ISRs --------------------------------------------------------------------*/
#define TIMER2_ISR_PRIO 4
void __attribute__((__interrupt__, auto_psv)) _T2Interrupt(void) {
_T2IF = 0; /* clear Timer 2 interrupt flag */
#ifdef Q_SPY
l_tickTime += BSP_TMR2_PERIOD; /* account for TMR2 overflow */
#endif
QF_TICK(&l_T2Interrupt); /* handle all armed time events in QF */
}
/*--------------------------------------------------------------------------*/
void BSP_init(void) {
RCONbits.SWDTEN = 0; /* disable Watchdog */
LATA = 0xFF00; /* set LEDs (D3-D10/RA0-RA7) drive state low */
TRISA = 0xFF00; /* set LED pins (D3-D10/RA0-RA7) as outputs */
if (QS_INIT((void *)0) == 0) { /* initialize the QS software tracing */
Q_ERROR();
}
QS_OBJ_DICTIONARY(&l_T2Interrupt);
}
/*..........................................................................*/
void QF_onStartup(void) { /* entered with interrupts locked */
T2CON = 0x0000U; /* Use Internal Osc (Fcy), 16 bit mode, prescaler = 1 */
TMR2 = 0x0000U; /* Start counting from 0 and clear the prescaler count */
PR2 = (uint16_t)(BSP_TMR2_PERIOD - 1U); /* Timer2 period */
_T2IP = TIMER2_ISR_PRIO; /* set Timer 2 interrupt priority */
_T2IF = 0; /* clear the interrupt for Timer 2 */
_T2IE = 1; /* enable interrupt for Timer 2 */
T2CONbits.TON = 1; /* start Timer 2 */
}
/*..........................................................................*/
void QF_onCleanup(void) {
}
/*..........................................................................*/
void QF_onIdle(void) { /* entered with interrupts disabled, NOTE01 */
LED_ON (IDLE_LED); /* blink the IDLE LED, see NOTE02 */
LED_OFF(IDLE_LED);
#ifdef Q_SPY
QF_INT_ENABLE(); /* enable interrupts, see NOTE01 */
while (U2STAbits.UTXBF == 0U) { /* TX Buffer not full? */
uint16_t b;
QF_INT_DISABLE();
b = QS_getByte();
QF_INT_ENABLE();
if (b == QS_EOD) { /* End-Of-Data reached? */
break; /* break out of the loop */
}
U2TXREG = (uint8_t)b; /* stick the byte to TXREG for transmission */
}
#elif defined NDEBUG
__asm__ volatile("disi #0x0001");
Idle(); /* transition to Idle mode, see NOTE03 */
#else
QF_INT_ENABLE(); /* enable interrupts, see NOTE01 */
#endif
}
/*..........................................................................*/
void BSP_displyPhilStat(uint8_t n, char const Q_ROM *stat) {
if (stat[0] == (char const)'e') { /* is this Philosopher eating? */
LED_ON(n);
}
else { /* this Philosopher is not eating */
LED_OFF(n);
}
QS_BEGIN(PHILO_STAT, AO_Philo[n]) /* application-specific record begin */
QS_U8(1, n); /* Philosopher number */
QS_STR(stat); /* Philosopher status */
QS_END()
}
/*..........................................................................*/
void Q_onAssert(char const Q_ROM * const Q_ROM_VAR file, int line) {
(void)file; /* avoid compiler warning */
(void)line; /* avoid compiler warning */
QF_INT_DISABLE(); /* make sure that interrupts are disabled */
for (;;) {
}
}
/*--------------------------------------------------------------------------*/
#ifdef Q_SPY
#define QS_BUF_SIZE 1024U
#define QS_BAUD_RATE 38400.0
uint8_t QS_onStartup(void const *arg) {
static uint8_t qsBuf[QS_BUF_SIZE]; /* buffer for Quantum Spy */
QS_initBuf(qsBuf, sizeof(qsBuf)); /* initialize the QS trace buffer */
/* initialize the UART2 for transmitting the QS trace data */
TRISFbits.TRISF5 = 0; /* set UART2 TX pin as output */
U2MODE = 0x0000U; /* enable low baud rate */
U2STA = 0x0000U; /* use default settings of 8N1 */
U2BRG = (uint16_t)((FCY_HZ / (4.0 * QS_BAUD_RATE)) - 1.0 + 0.5);
U2MODEbits.UARTEN = 1;
U2STAbits.UTXEN = 1;
/* setup the QS filters... */
QS_FILTER_ON(QS_ALL_RECORDS);
// QS_FILTER_OFF(QS_QEP_STATE_EMPTY);
// QS_FILTER_OFF(QS_QEP_STATE_ENTRY);
// QS_FILTER_OFF(QS_QEP_STATE_EXIT);
// QS_FILTER_OFF(QS_QEP_STATE_INIT);
// QS_FILTER_OFF(QS_QEP_INIT_TRAN);
// QS_FILTER_OFF(QS_QEP_INTERN_TRAN);
// QS_FILTER_OFF(QS_QEP_TRAN);
// QS_FILTER_OFF(QS_QEP_dummyD);
QS_FILTER_OFF(QS_QF_ACTIVE_ADD);
QS_FILTER_OFF(QS_QF_ACTIVE_REMOVE);
QS_FILTER_OFF(QS_QF_ACTIVE_SUBSCRIBE);
QS_FILTER_OFF(QS_QF_ACTIVE_UNSUBSCRIBE);
QS_FILTER_OFF(QS_QF_ACTIVE_POST_FIFO);
QS_FILTER_OFF(QS_QF_ACTIVE_POST_LIFO);
QS_FILTER_OFF(QS_QF_ACTIVE_GET);
QS_FILTER_OFF(QS_QF_ACTIVE_GET_LAST);
QS_FILTER_OFF(QS_QF_EQUEUE_INIT);
QS_FILTER_OFF(QS_QF_EQUEUE_POST_FIFO);
QS_FILTER_OFF(QS_QF_EQUEUE_POST_LIFO);
QS_FILTER_OFF(QS_QF_EQUEUE_GET);
QS_FILTER_OFF(QS_QF_EQUEUE_GET_LAST);
QS_FILTER_OFF(QS_QF_MPOOL_INIT);
QS_FILTER_OFF(QS_QF_MPOOL_GET);
QS_FILTER_OFF(QS_QF_MPOOL_PUT);
QS_FILTER_OFF(QS_QF_PUBLISH);
QS_FILTER_OFF(QS_QF_NEW);
QS_FILTER_OFF(QS_QF_GC_ATTEMPT);
QS_FILTER_OFF(QS_QF_GC);
// QS_FILTER_OFF(QS_QF_TICK);
QS_FILTER_OFF(QS_QF_TIMEEVT_ARM);
QS_FILTER_OFF(QS_QF_TIMEEVT_AUTO_DISARM);
QS_FILTER_OFF(QS_QF_TIMEEVT_DISARM_ATTEMPT);
QS_FILTER_OFF(QS_QF_TIMEEVT_DISARM);
QS_FILTER_OFF(QS_QF_TIMEEVT_REARM);
QS_FILTER_OFF(QS_QF_TIMEEVT_POST);
QS_FILTER_OFF(QS_QF_CRIT_ENTRY);
QS_FILTER_OFF(QS_QF_CRIT_EXIT);
QS_FILTER_OFF(QS_QF_ISR_ENTRY);
QS_FILTER_OFF(QS_QF_ISR_EXIT);
return (uint8_t)1; /* indicate successfull QS initialization */
}
/*..........................................................................*/
void QS_onCleanup(void) {
}
/*..........................................................................*/
void QS_onFlush(void) {
uint16_t b;
while ((b = QS_getByte()) != QS_EOD) { /* next QS trace byte available? */
while (U2STAbits.UTXBF != 0U) { /* TX Buffer full? */
}
U2TXREG = (uint8_t)b; /* stick the byte to TXREG for transmission */
}
}
/*..........................................................................*/
/* NOTE: invoked within a critical section (inetrrupts disabled) */
QSTimeCtr QS_onGetTime(void) {
if (_T2IF == 0) {
return l_tickTime + (uint32_t)TMR2;
}
else {
return l_tickTime + BSP_TMR2_PERIOD + (uint32_t)TMR2;
}
}
#endif /* Q_SPY */
/*--------------------------------------------------------------------------*/
/*****************************************************************************
* NOTE01:
* The callback function QF_onIdle() is called with interrupts locked, because
* the idle condition can be invalidated by any enabled interrupt that would
* post events. The QF_onIdle() function *must* unlock interrupts internally
*
* NOTE02:
* The LED 7 (D10 on the Explorer 16 board) is used to visualize the idle loop
* activity. The brightness of the LED is proportional to the frequency of
* invcations of the idle loop. Please note that the LED is toggled with
* interrupts locked, so no interrupt execution time contributes to the
* brightness of the User LED.
*
* NOTE03:
* To be on the safe side, the DISICNT counter is set to just 1 cycle just
* before entering the Idle mode (or Sleep mode, if you choose). This way,
* interrupts (with priorities 1-6) get enabled at the same time as the
* transition to the low-power mode.
*/