/** * Initializes a UART controller. * It is enabled for transmission (Tx) only, receive must be enabled separately. * By default all IRQ sources are disabled (masked out). * * Nothing is done if 'nr' is invalid (equal or greater than 3). * * @param nr - number of the UART (between 0 and 2) */ void uart_init(uint8_t nr) { /* Sanity check */ if ( nr >= BSP_NR_UARTS ) { return; } /* * Registers' reserved bits should not be modified. * For that reason, the registers are set in two steps: * - the appropriate bit masks of 1-bits are bitwise or'ed to the register * - zero complements of the appropriate bit masks of 0-bits are bitwise and'ed to the register */ /* * Whatever the current state, as suggested on page 3-16 of the DDI0183, the UART * should be disabled first: */ HWREG_CLEAR_BITS( pReg[nr]->UARTCR, CTL_UARTEN ); /* Set Control Register's TXE to 1: */ HWREG_SET_BITS( pReg[nr]->UARTCR, CTL_TXE ); /* * Set all other bits (except UARTEN) of the Control Register to 0: * - SIREN * - SIRLP * - LBE * - RXE * - DTR * - RTS * - Out1 * - Out2 * - RTSEn * - CTSEn */ HWREG_CLEAR_BITS( pReg[nr]->UARTCR, (CTL_SIREN | CTL_SIRLP | CTL_LBE | CTL_RXE | CTL_DTR) ); HWREG_CLEAR_BITS( pReg[nr]->UARTCR, ( CTL_RTS | CTL_OUT1 | CTL_OUT2 | CTL_RTSEn | CTL_CTSEn ) ); /* By default, all interrupts are masked out (i.e. cleared to 0): */ HWREG_CLEAR_BITS( pReg[nr]->UARTIMSC, ( INT_RIMIM | INT_CTSMIM | INT_DCDMIM | INT_DSRMIM | INT_RXIM | INT_TXIM ) ); HWREG_CLEAR_BITS( pReg[nr]->UARTIMSC, ( INT_RTIM | INT_FEIM | INT_PEIM | INT_BEIM | INT_OEIM ) ); /* TODO: line control... */ /* Finally enable the UART: */ HWREG_SET_BITS( pReg[nr]->UARTCR, CTL_UARTEN ); /* reserved bits remained unmodified */ }
/* * Assigns the selected register a 32-bit reload value. * * Nothing is done if 'wd' is greater than 1. * * @param wd - watchdog timer to be loaded (between 0 and 1) * @param ex - exception type */ static void __wd_setLoadValue(uint8_t wd, uint32_t value) { /* * See page 779 of the Data Sheet for more details. */ if ( wd < BSP_NR_WATCHDOGS ) { /* store the value for reusing it by wd_reload() */ __wdSettings[wd].loadVal = value; /* * There is a hardware bug in both watchdog timers. * If the STALL bit of the WDTTEST register is set, * the WTDLOAD register cannot be changed. * See page 68 of the Silicon Errata for more details. * * For that reason the STALL bit will be cleared first * and set again later. */ HWREG_CLEAR_BITS( pReg[wd]->WD_TEST, TST_STALL ); __waitWd1(wd); pReg[wd]->WD_LOAD = value; __waitWd1(wd); /* Set the STALL bit again. */ HWREG_SET_BITS( pReg[wd]->WD_TEST, TST_STALL ); __waitWd1(wd); } }
/* * Configures an exception that is triggered when the watchdog's * counter reaches 0. * * Nothing is done if 'wd' is greater than 1 or * 'ex' is invalid. * * @param wd - watchdog timer to be configured (between 0 and 1) * @param ex - exception type (any valid value of WatchdogException) */ static void __wd_setExceptionType(uint8_t wd, WatchdogException ex) { /* * Exception type is configured via relevant bits * of the WDTCTL register. * See the Data Sheet, pp. 781 - 782, for more details. */ if ( wd >= BSP_NR_WATCHDOGS ) { return; } __wdSettings[wd].exType = ex; /* Clear the RESEN flag. It will be reenabled if necessary */ HWREG_CLEAR_BITS( pReg[wd]->WD_CTL, CTL_RESEN ); __waitWd1(wd); switch (ex) { case WDEX_NMI: HWREG_SET_BITS( pReg[wd]->WD_CTL, CTL_INTTYPE ); break; case WDEX_IRQ: HWREG_CLEAR_BITS( pReg[wd]->WD_CTL, CTL_INTTYPE ); break; case WDEX_NMI_RESET: HWREG_SET_BITS( pReg[wd]->WD_CTL, CTL_INTTYPE ); __waitWd1(wd); HWREG_SET_BITS( pReg[wd]->WD_CTL, CTL_RESEN ); break; case WDEX_IRQ_RESET: HWREG_CLEAR_BITS( pReg[wd]->WD_CTL, CTL_INTTYPE ); __waitWd1(wd); HWREG_SET_BITS( pReg[wd]->WD_CTL, CTL_RESEN ); break; } __waitWd1(wd); }
/** * Enables the specified UART controller. * * Nothing is done if 'nr' is invalid (equal or greater than 3). * * @param nr - number of the UART (between 0 and 2) */ void uart_enableUart(uint8_t nr) { /* Sanity check */ if ( nr >= BSP_NR_UARTS ) { return; } HWREG_SET_BITS( pReg[nr]->UARTCR, CTL_UARTEN ); }
/** * Enables the interrupt triggering by the specified UART when a character is received. * * Nothing is done if 'nr' is invalid (equal or greater than 3). * * @param nr - number of the UART (between 0 and 2) */ void uart_enableRxInterrupt(uint8_t nr) { /* Sanity check */ if ( nr >= BSP_NR_UARTS ) { return; } /* Set bit 4 of the IMSC register: */ HWREG_SET_BITS( pReg[nr]->UARTIMSC, INT_RXIM ); }
/** * Sets the SysTick's source clock. * The SysTick runs either on the system clock or on the * precision internal oscillator (PIOSC), whose frequency * is divided by 4. * * @param systemClock - 'true' for the system clock; 'false' for PIOSC/4 */ void systick_setSource(bool systemClock) { if ( true == systemClock) { HWREG_SET_BITS( pReg->SYSTICK_STCTRL, CLKSRC_MASK ); } else { HWREG_CLEAR_BITS( pReg->SYSTICK_STCTRL, CLKSRC_MASK ); } }
/** * Enables the timer's interrupt triggering (when the counter reaches 0). * * Nothing is done if either 'timerNr' or 'counterNr' is invalid. * * @param timerNr - timer number (between 0 and 1) * @param counterNr - counter number of the selected timer (between 0 and 1) */ void timer_enableInterrupt(uint8_t timerNr, uint8_t counterNr) { /* sanity check: */ if ( timerNr >= BSP_NR_TIMERS || counterNr >= NR_COUNTERS ) { return; } /* Set bit 5 of the Control Register to 1, do not modify other bits */ HWREG_SET_BITS( pReg[timerNr]->CNTR[counterNr].CONTROL, CTL_INTR ); }
/* * Sets or clears a bit of the Control Register. This function is short and * used by other functions, this is why it is implemented as an inline function. * * Nothing is done if 'nr' is invalid (equal or greater than 3). * * @param nr - number of the UART (between 0 and 2) * @param set - true: bitmask's bit(s) are set to 1; false: bits are cleared to 0 * @param bitmask - bitmask of 1-bits that will be set or cleared */ static inline void __setCrBit(uint8_t nr, bool set, uint32_t bitmask) { uint32_t enabled; /* Sanity check */ if ( nr >= BSP_NR_UARTS ) { return; } /* Store UART's enable status (UARTEN) */ enabled = HWREG_READ_BITS( pReg[nr]->UARTCR, CTL_UARTEN ); /* * As suggested on page 3-16 of the DDI0183, the UART should be disabled * prior to any modification of the Control Register */ HWREG_CLEAR_BITS( pReg[nr]->UARTCR, CTL_UARTEN ); /* Depending on 'set'... */ if (set) { /* Set bitmask's bits to 1 using bitwise OR */ HWREG_SET_BITS( pReg[nr]->UARTCR, bitmask ); } else { /* Clear bitmask's bits to 0 using bitwise AND */ HWREG_CLEAR_BITS( pReg[nr]->UARTCR, bitmask ); } /* Reenable the UART if it was been enabled before */ if (enabled) { HWREG_SET_BITS( pReg[nr]->UARTCR, CTL_UARTEN ); } }
/** * Starts the selected watchdog timer and enables * triggering of interrupts. * * @note Once the watchdog has been start it is * only possible to stop it by reseting it, either * via wd_reset() or by a hardware reset. * See page 782 of the Data Sheet for more details. * * Nothing is done if 'wd' is greater than 1. * * @param wd - watchdog timer (between 0 and 1) */ void wd_start(uint8_t wd) { /* * A watchdog is enabled by the INTEN bit * of the WDTCTL register. * See the Data Sheet, page 782 for more details. */ if ( wd < BSP_NR_WATCHDOGS ) { HWREG_SET_BITS( pReg[wd]->WD_CTL, CTL_INTEN ); __waitWd1(wd); /* and leave registers unlocked: */ pReg[wd]->WD_LOCK = UNLOCK_VAL; __waitWd1(wd); } }
/** * Initializes the specified timer's counter controller. * The following parameters are set: * - periodic mode (when the counter reaches 0, it is wrapped to the value of the Load Register) * - 32-bit counter length * - prescale = 1 * * This function does not enable interrupt triggering and does not start the counter! * * Nothing is done if either 'timerNr' or 'counterNr' is invalid. * * @param timerNr - timer number (between 0 and 1) * @param counterNr - counter number of the selected timer (between 0 and 1) */ void timer_init(uint8_t timerNr, uint8_t counterNr) { /* sanity check: */ if ( timerNr >= BSP_NR_TIMERS || counterNr >= NR_COUNTERS ) { return; } /* * DDI0271 does not recommend modifying reserved bits of the Control Register (see page 3-5). * For that reason, the register is set in two steps: * - the appropriate bit masks of 1-bits are bitwise or'ed to the CTL * - zero complements of the appropriate bit masks of 0-bits are bitwise and'ed to the CTL */ /* * The following bits will be set to 1: * - timer mode (periodic) * - counter length (32-bit) */ HWREG_SET_BITS( pReg[timerNr]->CNTR[counterNr].CONTROL, ( CTL_MODE | CTL_CTRLEN ) ); /* * The following bits are will be to 0: * - enable bit (disabled, i.e. timer not running) * - interrupt bit (disabled) * - both prescale bits (00 = 1) * - oneshot bit (wrapping mode) */ HWREG_CLEAR_BITS( pReg[timerNr]->CNTR[counterNr].CONTROL, ( CTL_ENABLE | CTL_INTR | CTL_PRESCALE_1 | CTL_PRESCALE_2 | CTL_ONESHOT ) ); /* reserved bits remained unmodified */ }
/** * Reloads the selected watchdog's counter to the * load value, specified by wd_config(). * * Nothing is done if 'wd' is greater than 1. * * @param wd - watchdog timer (between 0 and 1) */ void wd_reload(uint8_t wd) { /* * For more details about the WDTLOAD register, * see page 779 of the Data Sheet */ if ( wd >= BSP_NR_WATCHDOGS ) { return; } if ( 1==wd && (6==sysctl_mcu_revision || 7==sysctl_mcu_revision) ) { /* * According to page 64 of the Silicon Errata, * reloading the WDTLOAD of the watchdog 1 will not * restart the counter. As a workaround it is * suggested to reset, reconfigure and restart * the watchdog. */ wd_reset(wd); wd_config(wd, __wdSettings[wd].loadVal, __wdSettings[wd].exType); /* Set the STALL bit if necessary */ HWREG_SET_BITS( pReg[wd]->WD_TEST, TST_STALL ); __waitWd1(wd); wd_start(wd); } else { /* * At other watchdogs, no workaround is necessary. * Reloading the WDTLOAD register will also * restart the counter. * Note: __waitWd1() is still preserved in the code. */ /* * There is a hardware bug in both watchdog timers. * If the STALL bit of the WDTTEST register is set, * the WTDLOAD register cannot be changed. * See page 68 of the Silicon Errata for more details. * * For that reason the STALL bit will be cleared first * and set again later. */ HWREG_CLEAR_BITS( pReg[wd]->WD_TEST, TST_STALL ); __waitWd1(wd); pReg[wd]->WD_LOAD = __wdSettings[wd].loadVal; __waitWd1(wd); /* Set the STALL bit again. */ HWREG_SET_BITS( pReg[wd]->WD_TEST, TST_STALL ); __waitWd1(wd); } }
/** * Starts the SysTick timer. */ void systick_enable(void) { HWREG_SET_BITS( pReg->SYSTICK_STCTRL, ENABLE_MASK ); }
/** * Enables triggering an interrupt each time the counter reaches 0. */ void systick_enableInterrupt(void) { HWREG_SET_BITS( pReg->SYSTICK_STCTRL, INTR_MASK ); }
/** * Resets (clears) the counter state to the reload value. */ void systick_clear(void) { /* writing any value to dedicated bits of the STCURRENT will clear the register and count. */ HWREG_SET_BITS( pReg->SYSTICK_STCURRENT, B24BIT_MASK ); }