diff --git a/configuration.c b/configuration.c new file mode 100644 index 0000000..363e8bf --- /dev/null +++ b/configuration.c @@ -0,0 +1,114 @@ +/* + * configuration.c + * Scooter final project's configuration file for timer, gpio, uart, etc. + * Authors: Ryan ZumBrunnen, Guanxiong Fu and Arash Yousefdezah + * Created on: October 26, 2017 + * + */ + +#include "msp.h" +#include "configuration.h" +#include "interrupt_handlers.h" +#include "conversion.h" +#include +#include "Crystalfontz128x128_ST7735.h" + +extern Graphics_Context g_sContext; + +void display_configure(void) +{ + /* Initializes display */ + Crystalfontz128x128_Init(); + + /* Set default screen orientation */ + Crystalfontz128x128_SetOrientation(LCD_ORIENTATION_UP); + + /* Initializes graphics context */ + Graphics_initContext(&g_sContext, &g_sCrystalfontz128x128); + Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_RED); + Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_WHITE); + GrContextFontSet(&g_sContext, &g_sFontFixed6x8); + Graphics_clearDisplay(&g_sContext); + Graphics_drawStringCentered(&g_sContext, "Velocity:", AUTO_STRING_LENGTH, 64, 30, OPAQUE_TEXT); + Graphics_drawStringCentered(&g_sContext, "Distance:", AUTO_STRING_LENGTH, 64, 60, OPAQUE_TEXT); + Graphics_drawStringCentered(&g_sContext, "Stopped", AUTO_STRING_LENGTH, 64, 90, OPAQUE_TEXT); +} + +// configuration for GPIO ports +void GPIO_configure(void) +{ + /* Left button configure */ + P1->SEL0 &= ~(BIT1); + P1->SEL1 &= ~(BIT1); + P1->DIR &= ~(BIT1); + P1->OUT |= BIT1; + P1->REN |= BIT1; + P1->IFG &= ~(BIT1); + P1->IES |= BIT1; + P1->IE |= BIT1; + + /* Right button configure */ + P1->SEL0 &= ~(BIT4); + P1->SEL1 &= ~(BIT4); + P1->DIR &= ~(BIT4); + P1->OUT |= BIT4; + P1->REN |= BIT4; + P1->IFG &= ~(BIT4); + P1->IES |= BIT4; + P1->IE |= BIT4; + + //Configure pin for input interrupt + P1->DIR &= ~(BIT6); + P1->SEL0 &= ~(BIT6); + P1->SEL1 &= ~(BIT6); + P1->IE |= BIT6; + P1->REN |= BIT6; + P1->IFG &= ~(BIT6); + + /* P1.0 LED Output */ + P1->DIR |= BIT0; + P1->SEL0 &= ~(BIT0); + P1->SEL1 &= ~(BIT0); + P1->OUT &= ~(BIT0); + + /* RGB LED Output */ + P2->DIR |= BIT0 | BIT1 | BIT2; + P2->SEL0 &= ~(BIT0 | BIT1 | BIT2); + P2->SEL1 &= ~(BIT0 | BIT1 | BIT2); + P2->OUT = BIT0; //Start with red on + + P6->SEL0 |= BIT0; + P6->SEL1 |= BIT0; + + NVIC_EnableIRQ(PORT1_IRQn); +} + +// configuration for Timer32 +void timer_configure(void){ + //enable prescaling, interrupt flag, and set to be periodically repeating + TIMER32_1->CONTROL |= TIMER32_CONTROL_PRESCALE_1 | TIMER32_CONTROL_IE | TIMER32_CONTROL_SIZE | TIMER32_CONTROL_MODE | TIMER32_CONTROL_ENABLE; + TIMER32_1->LOAD = 93749; //time to get 0.5sec + NVIC_EnableIRQ(T32_INT1_IRQn); +} + + +// configuration for ADC14 +void ADC_configure(void){ + // Initialize the shared reference module + // By default, REFMSTR=1 => REFCTL is used to configure the internal reference + while(REF_A->CTL0 & REF_A_CTL0_GENBUSY); // If ref generator busy, WAIT + REF_A->CTL0 = REF_A_CTL0_VSEL_0 | REF_A_CTL0_ON; // Enable internal 1.2V ref + REF_A->CTL0 &= ~REF_A_CTL0_TCOFF; // Turn on Temperature Sensor + + ADC14->CTL0 |= ADC14_CTL0_SHT0_5 | ADC14_CTL0_ON | ADC14_CTL0_SHP | ADC14_CTL0_CONSEQ_1; //multiple sampling (repeating sequence of channel) + ADC14->CTL1 |= ADC14_CTL1_TCMAP | BIT(16) | ADC14_CTL1_RES__14BIT ; // Conf internal temp sensor channel, ADC conversion start address from 1, set resolution to 14 bit + ADC14->MCTL[0]= ADC14_MCTLN_INCH_22 | ADC14_MCTLN_VRSEL_0; // Map Temp Analog channel to MEM0/MCTL0, set 3.3v ref + ADC14->MCTL[1]= ADC14_MCTLN_INCH_14 | ADC14_MCTLN_VRSEL_0; // Map Analog channel for Accelerometer x direction to MEM1/MCTL1, set 3.3v ref Accelerometer X Direction + ADC14->MCTL[2]= ADC14_MCTLN_INCH_13 | ADC14_MCTLN_VRSEL_0; // Y Direction to MEM2/MCTL2 + ADC14->MCTL[3]= ADC14_MCTLN_INCH_11 | ADC14_MCTLN_VRSEL_0 | ADC14_MCTLN_EOS; //Z direction to MEM3/MCTL3 + ADC14->IER0 = ADC14_IER0_IE0 | ADC14_IER0_IE1 | ADC14_IER0_IE2 | ADC14_IER0_IE3; // Enable MCTL1/MEM0 , MCTL1/MEM1 , MCTL2/MEM2 , MCTL3|MEM3 Interrupts + + while(!(REF_A->CTL0 & REF_A_CTL0_GENRDY)); // Wait for ref generator to settle + ADC14->CTL0 |= ADC14_CTL0_ENC; // Enable Conversions + NVIC_EnableIRQ(ADC14_IRQn); // Enable ADC int in NVIC module +} diff --git a/configuration.h b/configuration.h new file mode 100644 index 0000000..3397396 --- /dev/null +++ b/configuration.h @@ -0,0 +1,20 @@ +/* + * configuration.c + * Scooter final project's header file for configuration + * Authors: Ryan ZumBrunnen, Guanxiong Fu and Arash Yousefdezah + * Created on: October 26, 2017 + * + */ + +#ifndef CONFIGURATION_H_ +#define CONFIGURATION_H_ + +void display_configure(void); + +void GPIO_configure(void); + +void timer_configure(void); + +void ADC_configure(void); + +#endif /* CONFIGURATION_H_ */ diff --git a/conversion.c b/conversion.c new file mode 100644 index 0000000..eafdabc --- /dev/null +++ b/conversion.c @@ -0,0 +1,80 @@ +/* + * conversion.c + * Scooter final project's implementation file for conversion functions + * Authors: Ryan ZumBrunnen, Guanxiong Fu and Arash Yousefdezah + * Created on: October 26, 2017 + * + */ + +#include "msp.h" +#include "configuration.h" +#include "interrupt_handlers.h" +#include "conversion.h" +#include "send_terminal.h" + +void reverse(char s[], int slength) +{ + int i, j; + char c; + + for (i = 0, j = slength-1; i 0); /* delete it */ + if (sign < 0) + s[i++] = '-'; + s[i] = '\0'; + reverse(s, i); //MIGHT BE MESSING WITH NULL CHARACTER + return i; +} + +//ftoa taken from http://www.geeksforgeeks.org/convert-floating-point-number-string/ +//and modified to fit our needs better +void ftoa(float n, char s[], int afterpoint){ + // Extract integer part + int ipart = (int)n; + + // Extract floating part + float fpart = n - (float)ipart; + + // convert integer part to string + int position = itoa(ipart, s); + + // check for display option after point + if (afterpoint != 0) + { + s[position] = '.'; + // Get the value of fraction part upto given no. + // of points after dot. The third parameter is needed + // to handle cases like 233.007 + int tempnum = 1; + int i=0; + for (i = 0; i < afterpoint; i++) + tempnum *= 10; //to get 10^afterpoint + fpart = fpart * tempnum; //should make this a number without dec + if (fpart<0) + fpart=abs(fpart); + tempnum/=10; + while (fpart + +void reverse(char s[], int slength); + +int itoa(uint32_t n, char s[]); + +void ftoa(float n, char s[], int afterpoint); + +#endif /* CONVERSION_H_ */ diff --git a/interrupt_handlers.c b/interrupt_handlers.c new file mode 100644 index 0000000..02e2a53 --- /dev/null +++ b/interrupt_handlers.c @@ -0,0 +1,73 @@ + +/* + * interrupt_handlers.c + * Scooter final project's implementation file for interrupt handlers + * Authors: Ryan ZumBrunnen, Guanxiong Fu and Arash Yousefdezah + * Created on: October 26, 2017 + * + */ + +#include "msp.h" +#include "configuration.h" +#include "interrupt_handlers.h" +#include "conversion.h" +#include "send_terminal.h" + +extern volatile uint8_t flag_dist; +extern volatile uint8_t flag_vel; + +extern volatile uint32_t count_pin; +extern volatile float distance; + +extern volatile float distance_prev; +extern volatile float velocity; +extern volatile float velocity_prev; + +extern volatile float Nadc; +extern volatile float Nadcx; +extern volatile float Nadcy; +extern volatile float Nadcz; + +void PORT1_IRQHandler(void){ + if (P1->IFG & BIT1){ // Left button press + flag_dist = 1; + P1->IFG &= ~BIT1; // clear interrupt flag for Left button + // NVIC_DisableIRQ(T32_INT1_IRQn); + } + if (P1->IFG & BIT4){ // Right button press + ADC14->CTL0 |= ADC14_CTL0_SC; // start sampling and conversion + P1->IFG &= ~BIT4; + } + if (P1->IFG & BIT6) { // input interrupt + count_pin++; // count the number of time the interrupt is triggered + P1->IFG &= ~(BIT6); // clear interrupt flag + } +} + + +void T32_INT1_IRQHandler(void){ + distance = count_pin * 0.022; + velocity_prev = velocity; + velocity = distance - distance_prev; + distance_prev = distance; + + flag_vel = 1; // goes to main because function calls inside ISRs is bad practice + + ADC14->CTL0 |= ADC14_CTL0_SC; // start sampling and conversion + + TIMER32_1->INTCLR = 0; +} + + +void ADC14_IRQHandler(void){ + if (ADC14->IFGR0 & ADC14_IFGR0_IFG0){ + Nadc = ADC14->MEM[0]; //Nadc value for temperature + // don't need to clear flag because it automatically clears when data is read + } + if (ADC14->IFGR0 & (ADC14_IFGR0_IFG1 | ADC14_IFGR0_IFG2 | ADC14_IFGR0_IFG3)){ + Nadcx = ADC14->MEM[1]; // Nadc value for accelerometer in x direction + Nadcy = ADC14->MEM[2]; // y direction + Nadcz = ADC14->MEM[3]; // z direction + } +} + diff --git a/interrupt_handlers.h b/interrupt_handlers.h new file mode 100644 index 0000000..ebe3f8a --- /dev/null +++ b/interrupt_handlers.h @@ -0,0 +1,19 @@ +/* + * interrupt_handlers.h + * Scooter final project's header file for interrupt handlers + * Authors: Ryan ZumBrunnen, Guanxiong Fu and Arash Yousefdezah + * Created on: October 26, 2017 + * + */ + + +#ifndef INTERRUPT_HANDLERS_H_ +#define INTERRUPT_HANDLERS_H_ + +void PORT1_IRQHandler(void); + +void T32_INT1_IRQHandler(void); + +void ADC14_IRQHandler(void); + +#endif /* INTERRUPT_HANDLERS_H_ */ diff --git a/main.c b/main.c new file mode 100644 index 0000000..cab6227 --- /dev/null +++ b/main.c @@ -0,0 +1,75 @@ +/* + * main.c + * Scooter final project's main source file + * Authors: Ryan ZumBrunnen, Guanxiong Fu and Arash Yousefdezah + * Created on: October 26, 2017 + * + */ + +#include "msp.h" +#include "configuration.h" +#include "interrupt_handlers.h" +#include "conversion.h" +#include "send_terminal.h" +#include +#include +#include "Crystalfontz128x128_ST7735.h" + +/* Graphic library context */ +Graphics_Context g_sContext; + +volatile uint8_t flag_dist =1; +volatile uint8_t flag_vel; +volatile uint8_t startflag; +volatile uint8_t delay = 0; + +volatile uint32_t count_pin = 0; +volatile float distance; +volatile float velocity; +volatile float velocitydiff = 0; + +volatile float distance_prev = 0; +volatile float velocity_prev = 0; + +volatile float Nadc; +volatile float Nadcx; +volatile float Nadcy; +volatile float Nadcz; + +void main(void) +{ + WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // stop watchdog timer + ADC_configure(); + GPIO_configure(); + timer_configure(); + display_configure(); + + while(1){ + if (flag_dist == 1){ // button press occurred + print_distance(); + flag_dist = 0; + } + if (flag_vel == 1){ + if (delay==1) //delay since 0.5 sec printing is too fast + delay=0; + if (delay==0){ + print_velocity(); + delay=1; + } + flag_vel = 0; + } + velocitydiff = velocity - velocity_prev; + if (velocity < 1 && startflag==0 && velocitydiff > 0.1){ //less than .5 meter/sec == 1 mph and some positive accel + Graphics_drawStringCentered(&g_sContext, "Moving", AUTO_STRING_LENGTH, 64, 90, OPAQUE_TEXT); + print_direction(); //changes the P2.0 LED to either green or blue based on direction + startflag=1; + } + if (velocity < 0.1 && startflag==1 && velocitydiff < 0){ //small velocity and some buffer for negative accel + Graphics_drawStringCentered(&g_sContext, "Stopped", AUTO_STRING_LENGTH, 64, 90, OPAQUE_TEXT); + P2->OUT = BIT0; //red LED for stopped + startflag=0; + } + } +} + + diff --git a/send_terminal.c b/send_terminal.c new file mode 100644 index 0000000..5291ea4 --- /dev/null +++ b/send_terminal.c @@ -0,0 +1,46 @@ +/* + * send_terminal.c + * Scooter final project's implementation file for functions for sending things terminal + * Authors: Ryan ZumBrunnen ,Guanxiong Fu and Arash Yousefdezah + * Created on: October 26, 2017 + * + */ +#include "msp.h" +#include "configuration.h" +#include "interrupt_handlers.h" +#include "conversion.h" +#include "send_terminal.h" +#include +#include "Crystalfontz128x128_ST7735.h" + +extern Graphics_Context g_sContext; + +extern volatile uint32_t count_pin; +extern volatile float distance; +extern volatile float velocity; +extern volatile float velocity_prev; + +extern volatile float Nadcz; + +void print_distance(void){ + distance = count_pin * 0.022; // use count_pin to find the distance of scooter + char string[6]={}; + ftoa(distance, string, 2); + Graphics_drawStringCentered(&g_sContext, (int8_t *)string, 8, 64, 70, OPAQUE_TEXT); +} + +void print_velocity(void){ + char string[6]={}; + ftoa(velocity, string, 2); + Graphics_drawStringCentered(&g_sContext, (int8_t *)string, 8, 64, 70, OPAQUE_TEXT); +} + +void print_direction(void){ + float zaccel = (0.00020142*Nadcz)/0.66-2.5; //voltage divided by mV per g and subtracting 2.5 to get equilibrium + if (zaccel > 0.25) //forward + P2->OUT = BIT1; //Green + else if (zaccel < 0.25) //backward + P2->OUT = BIT2; //Blue +} + + diff --git a/send_terminal.h b/send_terminal.h new file mode 100644 index 0000000..22a8c9b --- /dev/null +++ b/send_terminal.h @@ -0,0 +1,18 @@ +/* + * send_terminal.h + * Scooter final project's header file for functions for sending things terminal + * Authors: Ryan ZumBrunnen ,Guanxiong Fu and Arash Yousefdezah + * Created on: October 26, 2017 + * + */ + +#ifndef SEND_TERMINAL_H_ +#define SEND_TERMINAL_H_ + +void print_distance(void); + +void print_velocity(void); + +void print_direction(void); + +#endif /* SEND_TERMINAL_H_ */ diff --git a/startup_msp432p401r_ccs.c b/startup_msp432p401r_ccs.c new file mode 100644 index 0000000..d403cca --- /dev/null +++ b/startup_msp432p401r_ccs.c @@ -0,0 +1,206 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 2017 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* MSP432P401R Interrupt Vector Table +* +*****************************************************************************/ + +#include + +/* Linker variable that marks the top of the stack. */ +extern unsigned long __STACK_END; + +/* External declaration for the reset handler that is to be called when the */ +/* processor is started */ +extern void _c_int00(void); + +/* External declaration for system initialization function */ +extern void SystemInit(void); + +/* Forward declaration of the default fault handlers. */ +void Default_Handler (void) __attribute__((weak)); +extern void Reset_Handler (void) __attribute__((weak)); + +/* Cortex-M4 Processor Exceptions */ +extern void NMI_Handler (void) __attribute__((weak, alias("Default_Handler"))); +extern void HardFault_Handler (void) __attribute__((weak, alias("Default_Handler"))); +extern void MemManage_Handler (void) __attribute__((weak, alias("Default_Handler"))); +extern void BusFault_Handler (void) __attribute__((weak, alias("Default_Handler"))); +extern void UsageFault_Handler (void) __attribute__((weak, alias("Default_Handler"))); +extern void SVC_Handler (void) __attribute__((weak, alias("Default_Handler"))); +extern void DebugMon_Handler (void) __attribute__((weak, alias("Default_Handler"))); +extern void PendSV_Handler (void) __attribute__((weak, alias("Default_Handler"))); + +/* device specific interrupt handler */ +extern void SysTick_Handler (void) __attribute__((weak,alias("Default_Handler"))); +extern void PSS_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void CS_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void PCM_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void WDT_A_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void FPU_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void FLCTL_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void COMP_E0_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void COMP_E1_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void TA0_0_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void TA0_N_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void TA1_0_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void TA1_N_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void TA2_0_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void TA2_N_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void TA3_0_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void TA3_N_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void EUSCIA0_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void EUSCIA1_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void EUSCIA2_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void EUSCIA3_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void EUSCIB0_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void EUSCIB1_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void EUSCIB2_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void EUSCIB3_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void ADC14_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void T32_INT1_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void T32_INT2_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void T32_INTC_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void AES256_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void RTC_C_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void DMA_ERR_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void DMA_INT3_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void DMA_INT2_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void DMA_INT1_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void DMA_INT0_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void PORT1_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void PORT2_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void PORT3_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void PORT4_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void PORT5_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); +extern void PORT6_IRQHandler (void) __attribute__((weak,alias("Default_Handler"))); + +/* Interrupt vector table. Note that the proper constructs must be placed on this to */ +/* ensure that it ends up at physical address 0x0000.0000 or at the start of */ +/* the program if located at a start address other than 0. */ +#pragma RETAIN(interruptVectors) +#pragma DATA_SECTION(interruptVectors, ".intvecs") +void (* const interruptVectors[])(void) = +{ + (void (*)(void))((uint32_t)&__STACK_END), + /* The initial stack pointer */ + Reset_Handler, /* The reset handler */ + NMI_Handler, /* The NMI handler */ + HardFault_Handler, /* The hard fault handler */ + MemManage_Handler, /* The MPU fault handler */ + BusFault_Handler, /* The bus fault handler */ + UsageFault_Handler, /* The usage fault handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* SVCall handler */ + DebugMon_Handler, /* Debug monitor handler */ + 0, /* Reserved */ + PendSV_Handler, /* The PendSV handler */ + SysTick_Handler, /* The SysTick handler */ + PSS_IRQHandler, /* PSS Interrupt */ + CS_IRQHandler, /* CS Interrupt */ + PCM_IRQHandler, /* PCM Interrupt */ + WDT_A_IRQHandler, /* WDT_A Interrupt */ + FPU_IRQHandler, /* FPU Interrupt */ + FLCTL_IRQHandler, /* Flash Controller Interrupt*/ + COMP_E0_IRQHandler, /* COMP_E0 Interrupt */ + COMP_E1_IRQHandler, /* COMP_E1 Interrupt */ + TA0_0_IRQHandler, /* TA0_0 Interrupt */ + TA0_N_IRQHandler, /* TA0_N Interrupt */ + TA1_0_IRQHandler, /* TA1_0 Interrupt */ + TA1_N_IRQHandler, /* TA1_N Interrupt */ + TA2_0_IRQHandler, /* TA2_0 Interrupt */ + TA2_N_IRQHandler, /* TA2_N Interrupt */ + TA3_0_IRQHandler, /* TA3_0 Interrupt */ + TA3_N_IRQHandler, /* TA3_N Interrupt */ + EUSCIA0_IRQHandler, /* EUSCIA0 Interrupt */ + EUSCIA1_IRQHandler, /* EUSCIA1 Interrupt */ + EUSCIA2_IRQHandler, /* EUSCIA2 Interrupt */ + EUSCIA3_IRQHandler, /* EUSCIA3 Interrupt */ + EUSCIB0_IRQHandler, /* EUSCIB0 Interrupt */ + EUSCIB1_IRQHandler, /* EUSCIB1 Interrupt */ + EUSCIB2_IRQHandler, /* EUSCIB2 Interrupt */ + EUSCIB3_IRQHandler, /* EUSCIB3 Interrupt */ + ADC14_IRQHandler, /* ADC14 Interrupt */ + T32_INT1_IRQHandler, /* T32_INT1 Interrupt */ + T32_INT2_IRQHandler, /* T32_INT2 Interrupt */ + T32_INTC_IRQHandler, /* T32_INTC Interrupt */ + AES256_IRQHandler, /* AES256 Interrupt */ + RTC_C_IRQHandler, /* RTC_C Interrupt */ + DMA_ERR_IRQHandler, /* DMA_ERR Interrupt */ + DMA_INT3_IRQHandler, /* DMA_INT3 Interrupt */ + DMA_INT2_IRQHandler, /* DMA_INT2 Interrupt */ + DMA_INT1_IRQHandler, /* DMA_INT1 Interrupt */ + DMA_INT0_IRQHandler, /* DMA_INT0 Interrupt */ + PORT1_IRQHandler, /* Port1 Interrupt */ + PORT2_IRQHandler, /* Port2 Interrupt */ + PORT3_IRQHandler, /* Port3 Interrupt */ + PORT4_IRQHandler, /* Port4 Interrupt */ + PORT5_IRQHandler, /* Port5 Interrupt */ + PORT6_IRQHandler /* Port6 Interrupt */ +}; + +/* Forward declaration of the default fault handlers. */ +/* This is the code that gets called when the processor first starts execution */ +/* following a reset event. Only the absolutely necessary set is performed, */ +/* after which the application supplied entry() routine is called. Any fancy */ +/* actions (such as making decisions based on the reset cause register, and */ +/* resetting the bits in that register) are left solely in the hands of the */ +/* application. */ +void Reset_Handler(void) +{ + SystemInit(); + + /* Jump to the CCS C Initialization Routine. */ + __asm(" .global _c_int00\n" + " b.w _c_int00"); +} + + +/* This is the code that gets called when the processor receives an unexpected */ +/* interrupt. This simply enters an infinite loop, preserving the system state */ +/* for examination by a debugger. */ +void Default_Handler(void) +{ + /* Fault trap exempt from ULP advisor */ + #pragma diag_push + #pragma CHECK_ULP("-2.1") + + /* Enter an infinite loop. */ + while(1) + { + } + + #pragma diag_pop +} diff --git a/system_msp432p401r.c b/system_msp432p401r.c new file mode 100644 index 0000000..b47526d --- /dev/null +++ b/system_msp432p401r.c @@ -0,0 +1,405 @@ +/****************************************************************************** +* @file system_msp432p401r.c +* @brief CMSIS Cortex-M4F Device Peripheral Access Layer Source File for +* MSP432P401R +* @version 3.202 +* @date 08/03/17 +* +* @note View configuration instructions embedded in comments +* +******************************************************************************/ +//***************************************************************************** +// +// Copyright (C) 2015 - 2017 Texas Instruments Incorporated - http://www.ti.com/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the +// distribution. +// +// Neither the name of Texas Instruments Incorporated nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#include +#include "msp.h" + +/*--------------------- Configuration Instructions ---------------------------- + 1. If you prefer to halt the Watchdog Timer, set __HALT_WDT to 1: + #define __HALT_WDT 1 + 2. Insert your desired CPU frequency in Hz at: + #define __SYSTEM_CLOCK 12000000 + 3. If you prefer the DC-DC power regulator (more efficient at higher + frequencies), set the __REGULATOR to 1: + #define __REGULATOR 1 + *---------------------------------------------------------------------------*/ + +/*--------------------- Watchdog Timer Configuration ------------------------*/ +// Halt the Watchdog Timer +// <0> Do not halt the WDT +// <1> Halt the WDT +#define __HALT_WDT 1 + +/*--------------------- CPU Frequency Configuration -------------------------*/ +// CPU Frequency +// <1500000> 1.5 MHz +// <3000000> 3 MHz +// <12000000> 12 MHz +// <24000000> 24 MHz +// <48000000> 48 MHz +#define __SYSTEM_CLOCK 3000000 + +/*--------------------- Power Regulator Configuration -----------------------*/ +// Power Regulator Mode +// <0> LDO +// <1> DC-DC +#define __REGULATOR 0 + +/*---------------------------------------------------------------------------- + Define clocks, used for SystemCoreClockUpdate() + *---------------------------------------------------------------------------*/ +#define __VLOCLK 10000 +#define __MODCLK 24000000 +#define __LFXT 32768 +#define __HFXT 48000000 + +/*---------------------------------------------------------------------------- + Clock Variable definitions + *---------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = __SYSTEM_CLOCK; /*!< System Clock Frequency (Core Clock)*/ + +/** + * Update SystemCoreClock variable + * + * @param none + * @return none + * + * @brief Updates the SystemCoreClock with current core Clock + * retrieved from cpu registers. + */ +void SystemCoreClockUpdate(void) +{ + uint32_t source, divider; + uint8_t dividerValue; + + float dcoConst; + int32_t calVal; + uint32_t centeredFreq; + int16_t dcoTune; + + divider = (CS->CTL1 & CS_CTL1_DIVM_MASK) >> CS_CTL1_DIVM_OFS; + dividerValue = 1 << divider; + source = CS->CTL1 & CS_CTL1_SELM_MASK; + + switch(source) + { + case CS_CTL1_SELM__LFXTCLK: + if(BITBAND_PERI(CS->IFG, CS_IFG_LFXTIFG_OFS)) + { + // Clear interrupt flag + CS->KEY = CS_KEY_VAL; + CS->CLRIFG |= CS_CLRIFG_CLR_LFXTIFG; + CS->KEY = 1; + + if(BITBAND_PERI(CS->IFG, CS_IFG_LFXTIFG_OFS)) + { + if(BITBAND_PERI(CS->CLKEN, CS_CLKEN_REFOFSEL_OFS)) + { + SystemCoreClock = (128000 / dividerValue); + } + else + { + SystemCoreClock = (32000 / dividerValue); + } + } + else + { + SystemCoreClock = __LFXT / dividerValue; + } + } + else + { + SystemCoreClock = __LFXT / dividerValue; + } + break; + case CS_CTL1_SELM__VLOCLK: + SystemCoreClock = __VLOCLK / dividerValue; + break; + case CS_CTL1_SELM__REFOCLK: + if (BITBAND_PERI(CS->CLKEN, CS_CLKEN_REFOFSEL_OFS)) + { + SystemCoreClock = (128000 / dividerValue); + } + else + { + SystemCoreClock = (32000 / dividerValue); + } + break; + case CS_CTL1_SELM__DCOCLK: + dcoTune = (CS->CTL0 & CS_CTL0_DCOTUNE_MASK) >> CS_CTL0_DCOTUNE_OFS; + + switch(CS->CTL0 & CS_CTL0_DCORSEL_MASK) + { + case CS_CTL0_DCORSEL_0: + centeredFreq = 1500000; + break; + case CS_CTL0_DCORSEL_1: + centeredFreq = 3000000; + break; + case CS_CTL0_DCORSEL_2: + centeredFreq = 6000000; + break; + case CS_CTL0_DCORSEL_3: + centeredFreq = 12000000; + break; + case CS_CTL0_DCORSEL_4: + centeredFreq = 24000000; + break; + case CS_CTL0_DCORSEL_5: + centeredFreq = 48000000; + break; + } + + if(dcoTune == 0) + { + SystemCoreClock = centeredFreq; + } + else + { + + if(dcoTune & 0x1000) + { + dcoTune = dcoTune | 0xF000; + } + + if (BITBAND_PERI(CS->CTL0, CS_CTL0_DCORES_OFS)) + { + dcoConst = *((float *) &TLV->DCOER_CONSTK_RSEL04); + calVal = TLV->DCOER_FCAL_RSEL04; + } + /* Internal Resistor */ + else + { + dcoConst = *((float *) &TLV->DCOIR_CONSTK_RSEL04); + calVal = TLV->DCOIR_FCAL_RSEL04; + } + + SystemCoreClock = (uint32_t) ((centeredFreq) + / (1 + - ((dcoConst * dcoTune) + / (8 * (1 + dcoConst * (768 - calVal)))))); + } + break; + case CS_CTL1_SELM__MODOSC: + SystemCoreClock = __MODCLK / dividerValue; + break; + case CS_CTL1_SELM__HFXTCLK: + if(BITBAND_PERI(CS->IFG, CS_IFG_HFXTIFG_OFS)) + { + // Clear interrupt flag + CS->KEY = CS_KEY_VAL; + CS->CLRIFG |= CS_CLRIFG_CLR_HFXTIFG; + CS->KEY = 1; + + if(BITBAND_PERI(CS->IFG, CS_IFG_HFXTIFG_OFS)) + { + if(BITBAND_PERI(CS->CLKEN, CS_CLKEN_REFOFSEL_OFS)) + { + SystemCoreClock = (128000 / dividerValue); + } + else + { + SystemCoreClock = (32000 / dividerValue); + } + } + else + { + SystemCoreClock = __HFXT / dividerValue; + } + } + else + { + SystemCoreClock = __HFXT / dividerValue; + } + break; + } +} + +/** + * Initialize the system + * + * @param none + * @return none + * + * @brief Setup the microcontroller system. + * + * Performs the following initialization steps: + * 1. Enables the FPU + * 2. Halts the WDT if requested + * 3. Enables all SRAM banks + * 4. Sets up power regulator and VCORE + * 5. Enable Flash wait states if needed + * 6. Change MCLK to desired frequency + * 7. Enable Flash read buffering + */ +void SystemInit(void) +{ + // Enable FPU if used + #if (__FPU_USED == 1) // __FPU_USED is defined in core_cm4.h + SCB->CPACR |= ((3UL << 10 * 2) | // Set CP10 Full Access + (3UL << 11 * 2)); // Set CP11 Full Access + #endif + + #if (__HALT_WDT == 1) + WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // Halt the WDT + #endif + + SYSCTL->SRAM_BANKEN = SYSCTL_SRAM_BANKEN_BNK7_EN; // Enable all SRAM banks + + #if (__SYSTEM_CLOCK == 1500000) // 1.5 MHz + // Default VCORE is LDO VCORE0 so no change necessary + + // Switches LDO VCORE0 to DCDC VCORE0 if requested + #if __REGULATOR + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR_4; + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + #endif + + // No flash wait states necessary + + // DCO = 1.5 MHz; MCLK = source + CS->KEY = CS_KEY_VAL; // Unlock CS module for register access + CS->CTL0 = CS_CTL0_DCORSEL_0; // Set DCO to 1.5MHz + CS->CTL1 = (CS->CTL1 & ~(CS_CTL1_SELM_MASK | CS_CTL1_DIVM_MASK)) | CS_CTL1_SELM__DCOCLK; + // Select MCLK as DCO source + CS->KEY = 0; + + // Set Flash Bank read buffering + FLCTL->BANK0_RDCTL = FLCTL->BANK0_RDCTL & ~(FLCTL_BANK0_RDCTL_BUFD | FLCTL_BANK0_RDCTL_BUFI); + FLCTL->BANK1_RDCTL = FLCTL->BANK1_RDCTL & ~(FLCTL_BANK1_RDCTL_BUFD | FLCTL_BANK1_RDCTL_BUFI); + + #elif (__SYSTEM_CLOCK == 3000000) // 3 MHz + // Default VCORE is LDO VCORE0 so no change necessary + + // Switches LDO VCORE0 to DCDC VCORE0 if requested + #if __REGULATOR + while(PCM->CTL1 & PCM_CTL1_PMR_BUSY); + PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR_4; + while(PCM->CTL1 & PCM_CTL1_PMR_BUSY); + #endif + + // No flash wait states necessary + + // DCO = 3 MHz; MCLK = source + CS->KEY = CS_KEY_VAL; // Unlock CS module for register access + CS->CTL0 = CS_CTL0_DCORSEL_1; // Set DCO to 1.5MHz + CS->CTL1 = (CS->CTL1 & ~(CS_CTL1_SELM_MASK | CS_CTL1_DIVM_MASK)) | CS_CTL1_SELM__DCOCLK; + // Select MCLK as DCO source + CS->KEY = 0; + + // Set Flash Bank read buffering + FLCTL->BANK0_RDCTL = FLCTL->BANK0_RDCTL & ~(FLCTL_BANK0_RDCTL_BUFD | FLCTL_BANK0_RDCTL_BUFI); + FLCTL->BANK1_RDCTL = FLCTL->BANK1_RDCTL & ~(FLCTL_BANK1_RDCTL_BUFD | FLCTL_BANK1_RDCTL_BUFI); + + #elif (__SYSTEM_CLOCK == 12000000) // 12 MHz + // Default VCORE is LDO VCORE0 so no change necessary + + // Switches LDO VCORE0 to DCDC VCORE0 if requested + #if __REGULATOR + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR_4; + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + #endif + + // No flash wait states necessary + + // DCO = 12 MHz; MCLK = source + CS->KEY = CS_KEY_VAL; // Unlock CS module for register access + CS->CTL0 = CS_CTL0_DCORSEL_3; // Set DCO to 12MHz + CS->CTL1 = (CS->CTL1 & ~(CS_CTL1_SELM_MASK | CS_CTL1_DIVM_MASK)) | CS_CTL1_SELM__DCOCLK; + // Select MCLK as DCO source + CS->KEY = 0; + + // Set Flash Bank read buffering + FLCTL->BANK0_RDCTL = FLCTL->BANK0_RDCTL & ~(FLCTL_BANK0_RDCTL_BUFD | FLCTL_BANK0_RDCTL_BUFI); + FLCTL->BANK1_RDCTL = FLCTL->BANK1_RDCTL & ~(FLCTL_BANK1_RDCTL_BUFD | FLCTL_BANK1_RDCTL_BUFI); + + #elif (__SYSTEM_CLOCK == 24000000) // 24 MHz + // Default VCORE is LDO VCORE0 so no change necessary + + // Switches LDO VCORE0 to DCDC VCORE0 if requested + #if __REGULATOR + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR_4; + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + #endif + + // 1 flash wait state (BANK0 VCORE0 max is 12 MHz) + FLCTL->BANK0_RDCTL = (FLCTL->BANK0_RDCTL & ~FLCTL_BANK0_RDCTL_WAIT_MASK) | FLCTL_BANK0_RDCTL_WAIT_1; + FLCTL->BANK1_RDCTL = (FLCTL->BANK1_RDCTL & ~FLCTL_BANK1_RDCTL_WAIT_MASK) | FLCTL_BANK1_RDCTL_WAIT_1; + + // DCO = 24 MHz; MCLK = source + CS->KEY = CS_KEY_VAL; // Unlock CS module for register access + CS->CTL0 = CS_CTL0_DCORSEL_4; // Set DCO to 24MHz + CS->CTL1 = (CS->CTL1 & ~(CS_CTL1_SELM_MASK | CS_CTL1_DIVM_MASK)) | CS_CTL1_SELM__DCOCLK; + // Select MCLK as DCO source + CS->KEY = 0; + + // Set Flash Bank read buffering + FLCTL->BANK0_RDCTL = FLCTL->BANK0_RDCTL | (FLCTL_BANK0_RDCTL_BUFD | FLCTL_BANK0_RDCTL_BUFI); + FLCTL->BANK1_RDCTL = FLCTL->BANK1_RDCTL & ~(FLCTL_BANK1_RDCTL_BUFD | FLCTL_BANK1_RDCTL_BUFI); + + #elif (__SYSTEM_CLOCK == 48000000) // 48 MHz + // Switches LDO VCORE0 to LDO VCORE1; mandatory for 48 MHz setting + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR_1; + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + + // Switches LDO VCORE1 to DCDC VCORE1 if requested + #if __REGULATOR + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR_5; + while((PCM->CTL1 & PCM_CTL1_PMR_BUSY)); + #endif + + // 1 flash wait states (BANK0 VCORE1 max is 16 MHz, BANK1 VCORE1 max is 32 MHz) + FLCTL->BANK0_RDCTL = (FLCTL->BANK0_RDCTL & ~FLCTL_BANK0_RDCTL_WAIT_MASK) | FLCTL_BANK0_RDCTL_WAIT_1; + FLCTL->BANK1_RDCTL = (FLCTL->BANK1_RDCTL & ~FLCTL_BANK1_RDCTL_WAIT_MASK) | FLCTL_BANK1_RDCTL_WAIT_1; + + // DCO = 48 MHz; MCLK = source + CS->KEY = CS_KEY_VAL; // Unlock CS module for register access + CS->CTL0 = CS_CTL0_DCORSEL_5; // Set DCO to 48MHz + CS->CTL1 = (CS->CTL1 & ~(CS_CTL1_SELM_MASK | CS_CTL1_DIVM_MASK)) | CS_CTL1_SELM__DCOCLK; + // Select MCLK as DCO source + CS->KEY = 0; + + // Set Flash Bank read buffering + FLCTL->BANK0_RDCTL = FLCTL->BANK0_RDCTL | (FLCTL_BANK0_RDCTL_BUFD | FLCTL_BANK0_RDCTL_BUFI); + FLCTL->BANK1_RDCTL = FLCTL->BANK1_RDCTL | (FLCTL_BANK1_RDCTL_BUFD | FLCTL_BANK1_RDCTL_BUFI); + #endif + +} + +