commit 9c2fdbf8edb67b0023852004e4501194c091f47c98d2fe9749f073a76967b935 Author: yenru0 Date: Mon Dec 1 19:51:51 2025 +0900 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d00ed28 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +res \ No newline at end of file diff --git a/ccs/.ccsproject b/ccs/.ccsproject new file mode 100644 index 0000000..eb6842a --- /dev/null +++ b/ccs/.ccsproject @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/ccs/.cproject b/ccs/.cproject new file mode 100644 index 0000000..a02cbee --- /dev/null +++ b/ccs/.cproject @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ccs/.project b/ccs/.project new file mode 100644 index 0000000..d9fcc85 --- /dev/null +++ b/ccs/.project @@ -0,0 +1,27 @@ + + + lab_w4 + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + com.ti.ccstudio.core.ccsNature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/ccs/.vscode/c_cpp_properties.json b/ccs/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..de1110d --- /dev/null +++ b/ccs/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/opt/ti/ccs/tools/compiler/ti-cgt-armllvm_3.2.2.LTS/include/**", + "/opt/ti/ccs/ccs_base/arm/include/**", + ], + "defines": ["__MSP432P401R__"], + "compilerPath": "/opt/ti/ccs/tools/compiler/ti-cgt-armllvm_3.2.2.LTS/bin/tiarmclang", + "cStandard": "c11", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-clang-arm" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/ccs/.vscode/settings.json b/ccs/.vscode/settings.json new file mode 100644 index 0000000..e5d34c0 --- /dev/null +++ b/ccs/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "msp.h": "c" + } +} \ No newline at end of file diff --git a/ccs/Clock.c b/ccs/Clock.c new file mode 100644 index 0000000..bc86821 --- /dev/null +++ b/ccs/Clock.c @@ -0,0 +1,169 @@ +// Clock.c +// Runs on the MSP432 +// Daniel and Jonathan Valvano +// February 23, 2017 + +/* This example accompanies the book + "Embedded Systems: Introduction to Robotics, + Jonathan W. Valvano, ISBN: 9781074544300, copyright (c) 2019 + For more information about my classes, my research, and my books, see + http://users.ece.utexas.edu/~valvano/ + +Simplified BSD License (FreeBSD License) +Copyright (c) 2019, Jonathan Valvano, All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. 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. + +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. + +The views and conclusions contained in the software and documentation are +those of the authors and should not be interpreted as representing official +policies, either expressed or implied, of the FreeBSD Project. +*/ + +#include +#include "msp.h" + +uint32_t ClockFrequency = 3000000; // cycles/second +//static uint32_t SubsystemFrequency = 3000000; // cycles/second + +// ------------Clock_InitFastest------------ +// Configure the system clock to run at the fastest +// and most accurate settings. For example, if the +// LaunchPad has a crystal, it should be used here. +// Call BSP_Clock_GetFreq() to get the current system +// clock frequency for the LaunchPad. +// Input: none +// Output: none +uint32_t Prewait = 0; // loops between BSP_Clock_InitFastest() called and PCM idle (expect 0) +uint32_t CPMwait = 0; // loops between Power Active Mode Request and Current Power Mode matching requested mode (expect small) +uint32_t Postwait = 0; // loops between Current Power Mode matching requested mode and PCM module idle (expect about 0) +uint32_t IFlags = 0; // non-zero if transition is invalid +uint32_t Crystalstable = 0; // loops before the crystal stabilizes (expect small) +void Clock_Init48MHz(void){ + // wait for the PCMCTL0 and Clock System to be write-able by waiting for Power Control Manager to be idle + while(PCM->CTL1&0x00000100){ +// while(PCMCTL1&0x00000100){ + Prewait = Prewait + 1; + if(Prewait >= 100000){ + return; // time out error + } + } + // request power active mode LDO VCORE1 to support the 48 MHz frequency + PCM->CTL0 = (PCM->CTL0&~0xFFFF000F) | // clear PCMKEY bit field and AMR bit field +// PCMCTL0 = (PCMCTL0&~0xFFFF000F) | // clear PCMKEY bit field and AMR bit field + 0x695A0000 | // write the proper PCM key to unlock write access + 0x00000001; // request power active mode LDO VCORE1 + // check if the transition is invalid (see Figure 7-3 on p344 of datasheet) + if(PCM->IFG&0x00000004){ + IFlags = PCM->IFG; // bit 2 set on active mode transition invalid; bits 1-0 are for LPM-related errors; bit 6 is for DC-DC-related error + PCM->CLRIFG = 0x00000004; // clear the transition invalid flag + // to do: look at CPM bit field in PCMCTL0, figure out what mode you're in, and step through the chart to transition to the mode you want + // or be lazy and do nothing; this should work out of reset at least, but it WILL NOT work if Clock_Int32kHz() or Clock_InitLowPower() has been called + return; + } + // wait for the CPM (Current Power Mode) bit field to reflect a change to active mode LDO VCORE1 + while((PCM->CTL0&0x00003F00) != 0x00000100){ + CPMwait = CPMwait + 1; + if(CPMwait >= 500000){ + return; // time out error + } + } + // wait for the PCMCTL0 and Clock System to be write-able by waiting for Power Control Manager to be idle + while(PCM->CTL1&0x00000100){ + Postwait = Postwait + 1; + if(Postwait >= 100000){ + return; // time out error + } + } + // initialize PJ.3 and PJ.2 and make them HFXT (PJ.3 built-in 48 MHz crystal out; PJ.2 built-in 48 MHz crystal in) + PJ->SEL0 |= 0x0C; + PJ->SEL1 &= ~0x0C; // configure built-in 48 MHz crystal for HFXT operation +// PJDIR |= 0x08; // make PJ.3 HFXTOUT (unnecessary) +// PJDIR &= ~0x04; // make PJ.2 HFXTIN (unnecessary) + CS->KEY = 0x695A; // unlock CS module for register access + CS->CTL2 = (CS->CTL2&~0x00700000) | // clear HFXTFREQ bit field + 0x00600000 | // configure for 48 MHz external crystal + 0x00010000 | // HFXT oscillator drive selection for crystals >4 MHz + 0x01000000; // enable HFXT + CS->CTL2 &= ~0x02000000; // disable high-frequency crystal bypass + // wait for the HFXT clock to stabilize + while(CS->IFG&0x00000002){ + CS->CLRIFG = 0x00000002; // clear the HFXT oscillator interrupt flag + Crystalstable = Crystalstable + 1; + if(Crystalstable > 100000){ + return; // time out error + } + } + // configure for 2 wait states (minimum for 48 MHz operation) for flash Bank 0 + FLCTL->BANK0_RDCTL = (FLCTL->BANK0_RDCTL&~0x0000F000)|FLCTL_BANK0_RDCTL_WAIT_2; + // configure for 2 wait states (minimum for 48 MHz operation) for flash Bank 1 + FLCTL->BANK1_RDCTL = (FLCTL->BANK1_RDCTL&~0x0000F000)|FLCTL_BANK1_RDCTL_WAIT_2; + CS->CTL1 = 0x20000000 | // configure for SMCLK divider /4 + 0x00100000 | // configure for HSMCLK divider /2 + 0x00000200 | // configure for ACLK sourced from REFOCLK + 0x00000050 | // configure for SMCLK and HSMCLK sourced from HFXTCLK + 0x00000005; // configure for MCLK sourced from HFXTCLK + CS->KEY = 0; // lock CS module from unintended access + ClockFrequency = 48000000; +// SubsystemFrequency = 12000000; +} + +// ------------Clock_GetFreq------------ +// Return the current system clock frequency for the +// LaunchPad. +// Input: none +// Output: system clock frequency in cycles/second +uint32_t Clock_GetFreq(void){ + return ClockFrequency; +} + + +// delay function +// which delays about 6*ulCount cycles +// ulCount=8000 => 1ms = (8000 loops)*(6 cycles/loop)*(20.83 ns/cycle) + //Code Composer Studio Code +void delay(unsigned long ulCount){ + __asm ( "pdloop: subs r0, #1\n" + " bne pdloop\n"); +} + +// ------------Clock_Delay1us------------ +// Simple delay function which delays about n microseconds. +// Inputs: n, number of us to wait +// Outputs: none +void Clock_Delay1us(uint32_t n){ + n = (382*n)/100;; // 1 us, tuned at 48 MHz + while(n){ + n--; + } +} + +// ------------Clock_Delay1ms------------ +// Simple delay function which delays about n milliseconds. +// Inputs: n, number of msec to wait +// Outputs: none +void Clock_Delay1ms(uint32_t n){ + while(n){ + delay(ClockFrequency/9162); // 1 msec, tuned at 48 MHz + n--; + } +} + + diff --git a/ccs/Clock.h b/ccs/Clock.h new file mode 100644 index 0000000..36ec284 --- /dev/null +++ b/ccs/Clock.h @@ -0,0 +1,99 @@ +/** + * @file Clock.h + * @brief Provide functions that initialize the MSP432 clock module + * @details Reconfigure MSP432 to run at 48 MHz + * @version TI-RSLK MAX v1.1 + * @author Daniel Valvano and Jonathan Valvano + * @copyright Copyright 2019 by Jonathan W. Valvano, valvano@mail.utexas.edu, + * @warning AS-IS + * @note For more information see http://users.ece.utexas.edu/~valvano/ + * @date June 28, 2019 + + ******************************************************************************/ + +/* This example accompanies the book + "Embedded Systems: Introduction to Robotics, + Jonathan W. Valvano, ISBN: 9781074544300, copyright (c) 2019 + For more information about my classes, my research, and my books, see + http://users.ece.utexas.edu/~valvano/ + +Simplified BSD License (FreeBSD License) +Copyright (c) 2017, Jonathan Valvano, All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. 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. + +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. + +The views and conclusions contained in the software and documentation are +those of the authors and should not be interpreted as representing official +policies, either expressed or implied, of the FreeBSD Project. +*/ +#include +/** + * Configure the MSP432 clock to run at 48 MHz + * @param none + * @return none + * @note Since the crystal is used, the bus clock will be very accurate + * @see Clock_GetFreq() + * @brief Initialize clock to 48 MHz + */ +void Clock_Init48MHz(void); + + +/** + * Return the current bus clock frequency + * @param none + * @return frequency of the system clock in Hz + * @note In this module, the return result will be 3000000 or 48000000 + * @see Clock_Init48MHz() + * @brief Returns current clock bus frequency in Hz + */ +uint32_t Clock_GetFreq(void); + + +/** + * Simple delay function which delays about n milliseconds. + * It is implemented with a nested for-loop and is very approximate. + * @param n is the number of msec to wait + * @return none + * @note This function assumes a 48 MHz clock. + * This implementation is not very accurate. + * To improve accuracy, you could tune this function + * by adjusting the constant within the implementation + * found in the Clock.c file. + * For a more accurate time delay, you could use the SysTick module. + * @brief Software implementation of a busy-wait delay + */ +void Clock_Delay1ms(uint32_t n); + +/** + * Simple delay function which delays about n microseconds. + * It is implemented with a nested for-loop and is very approximate. + * @param n is the number of usec to wait + * @return none + * @note This function assumes a 48 MHz clock. + * This implementation is not very accurate. + * To improve accuracy, you could tune this function + * by adjusting the constant within the implementation + * found in the Clock.c file. + * For a more accurate time delay, you could use the SysTick module. + * @brief Software implementation of a busy-wait delay + */ +void Clock_Delay1us(uint32_t n); + diff --git a/ccs/ir.c b/ccs/ir.c new file mode 100644 index 0000000..922821a --- /dev/null +++ b/ccs/ir.c @@ -0,0 +1,39 @@ +#include "ir.h" + +#include "Clock.h" + +void ir_init(void) { + P5->SEL0 &= ~0x08; + P5->SEL1 &= ~0x08; + P5->DIR |= 0x08; + P5->OUT &= ~0x08; + P9->SEL0 &= ~0x04; + P9->SEL1 &= ~0x04; + P9->DIR |= 0x04; + P9->OUT &= ~0x04; + P7->SEL0 &= ~0xff; + P7->SEL1 &= ~0xff; + P7->DIR &= ~0xff; +} + +void ir_read_ready() { + P5->OUT |= 0x08; + P9->OUT |= 0x04; + P7->DIR = 0xff; + Clock_Delay1us(10); + P7->DIR = 0x00; + Clock_Delay1us(1000); +} + +void ir_read_value(char *value) { + int i; + uint8_t port_value = P7->IN; + for (i = 0; i < 8; i++) { + value[i] = !!(port_value & (0x01 << i)); + } +} + +void ir_read_off() { + P5->OUT &= ~0x08; + P9->OUT &= ~0x04; +} diff --git a/ccs/ir.h b/ccs/ir.h new file mode 100644 index 0000000..250b5c9 --- /dev/null +++ b/ccs/ir.h @@ -0,0 +1,12 @@ +#pragma once + +#include "msp.h" +#include + +void ir_init(void); + +void ir_read_ready(void); + +void ir_read_value(char *value); + +void ir_read_off(void); \ No newline at end of file diff --git a/ccs/main.c b/ccs/main.c new file mode 100644 index 0000000..911179e --- /dev/null +++ b/ccs/main.c @@ -0,0 +1,65 @@ +#include + +#include "Clock.h" +#include "msp.h" + +#include "ir.h" +#include "motor.h" +#include "state.h" +#include "util.h" + +#define LOOP_PERIOD_MS 20 + +const float Kp = 0.8f; +const float Kd = 4.5f; + +void main(void) { + Clock_Init48MHz(); + printf("Init Phase Begin\n"); + + ir_init(); + motor_init(); + + SensorBuffer sb; + senbuf_init(&sb); + + printf("Init Phase End\n"); + + uint8_t ir_value; + + int error = 888481557; + int prev_error = 0; + + int output_pid = 0; + + int speed_left; + int speed_right; + + while (1) { + ir_read_ready(); + ir_read_value(ir_value); + ir_read_off(); + int i, j; + + senbuf_push(&sb, ir_value); + if(check_crossroad_robust(&sb)) { + // 교차로 처리 로직 + move_stop(); + while(1) {} // succ + } + + + + error = get_error(ir_value); + output_pid = (int)(Kp * error + Kd * (error - prev_error)); + + + // clamp; + + // motor driverev_error = error; + + Clock_Delay1ms(LOOP_PERIOD_MS); + + + } +} diff --git a/ccs/motor.c b/ccs/motor.c new file mode 100644 index 0000000..eb096ad --- /dev/null +++ b/ccs/motor.c @@ -0,0 +1,135 @@ +#include "motor.h" +#include "Clock.h" + +// Period: 20ms +// MAX speed: 20 + +static void normalize_speed(int *speed) { + if (*speed <= 0) *speed = 0; + else if (*speed > MAX_SPEED) *speed = MAX_SPEED; +} + +void motor_init(void) { + P3->SEL0 &= ~0xc0; + P3->SEL1 &= ~0xc0; + P3->DIR |= 0xc0; + P3->OUT &= ~0xc0; + + P5->SEL0 &= ~0x30; + P5->SEL1 &= ~0x30; + P5->DIR |= 0x30; + P5->OUT &= ~0x30; + + P2->SEL0 &= ~0xc0; + P2->SEL1 &= ~0xc0; + P2->DIR |= 0xc0; + P2->OUT &= ~0xc0; +} + +void move_stop() { + P2->OUT &= ~0xc0; +} + +static void move_forward() { + P5->OUT &= ~0b00110000; + P3->OUT |= 0b11000000; + P2->OUT |= 0b11000000; +} + +static void move_backward() { + P5->OUT |= 0b00110000; + P3->OUT |= 0b11000000; + P2->OUT |= 0b11000000; +} + +static void turn_left() { + P3->OUT |= 0b11000000; + P2->OUT &= ~0b10000000; + P2->OUT |= 0b01000000; +} + +static void turn_right() { + P3->OUT |= 0b11000000; + P2->OUT &= ~0b01000000; + P2->OUT |= 0b10000000; +} + +static void rotate_clockwise() { + P5->OUT &= ~0b00110000; + P5->OUT |= 0b00100000; + P3->OUT |= 0b11000000; + P2->OUT |= 0b11000000; +} + +static void rotate_cclockwise() { + P5->OUT &= ~0b00110000; + P5->OUT |= 0b00010000; + P3->OUT |= 0b11000000; + P2->OUT |= 0b11000000; +} + +void motor_move_forward(int speed) { + normalize_speed(&speed); + + move_forward(); + Clock_Delay1ms(speed); + + move_stop(); + Clock_Delay1ms(PERIOD_ms - speed); +} + +void motor_move_backward(int speed) { + normalize_speed(&speed); + + move_backward(); + Clock_Delay1ms(speed); + + move_stop(); + Clock_Delay1ms(PERIOD_ms - speed); +} + +void motor_turn_left(int speed) { + normalize_speed(&speed); + + turn_left(); + Clock_Delay1ms(speed); + + move_stop(); + Clock_Delay1ms(PERIOD_ms - speed); +} + +void motor_turn_right(int speed) { + normalize_speed(&speed); + + turn_right(); + Clock_Delay1ms(speed); + + move_stop(); + Clock_Delay1ms(PERIOD_ms - speed); +} + +void motor_rotate_clockwise(int speed) { + normalize_speed(&speed); + + rotate_clockwise(); + Clock_Delay1ms(speed); + + move_stop(); + Clock_Delay1ms(PERIOD_ms - speed); + + move_forward(); + move_stop(); +} + +void motor_rotate_cclockwise(int speed) { + normalize_speed(&speed); + + rotate_cclockwise(); + Clock_Delay1ms(speed); + + move_stop(); + Clock_Delay1ms(PERIOD_ms - speed); + + move_forward(); + move_stop(); +} diff --git a/ccs/motor.h b/ccs/motor.h new file mode 100644 index 0000000..2cdcb70 --- /dev/null +++ b/ccs/motor.h @@ -0,0 +1,25 @@ +#ifndef _motor_h_ +#define _motor_h_ + +#include "msp.h" + +#define PERIOD_ms 20 +#define MAX_SPEED PERIOD_ms + +void motor_init(); + +void move_stop(); + +void motor_move_forward(int speed); + +void motor_move_backward(int speed); + +void motor_turn_left(int speed); + +void motor_turn_right(int speed); + +void motor_rotate_clockwise(int speed); + +void motor_rotate_cclockwise(int speed); + +#endif diff --git a/ccs/msp432p401r.cmd b/ccs/msp432p401r.cmd new file mode 100644 index 0000000..895248f --- /dev/null +++ b/ccs/msp432p401r.cmd @@ -0,0 +1,138 @@ +/****************************************************************************** +* +* 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. +* +* Default linker command file for Texas Instruments MSP432P401R +* +* File creation date: 12/06/17 +* +*****************************************************************************/ +/* Suppress warnings and errors: */ +/* #10199-D CRC table operator (crc_table_for_<>) ignored: + CRC table operator cannot be associated with empty output section */ +--diag_suppress=10199 + +--retain=flashMailbox + +MEMORY +{ + MAIN (RX) : origin = 0x00000000, length = 0x00040000 + INFO (RX) : origin = 0x00200000, length = 0x00004000 +#ifdef __TI_COMPILER_VERSION__ +#if __TI_COMPILER_VERSION__ >= 15009000 + ALIAS + { + SRAM_CODE (RWX): origin = 0x01000000 + SRAM_DATA (RW) : origin = 0x20000000 + } length = 0x00010000 +#else + /* Hint: If the user wants to use ram functions, please observe that SRAM_CODE */ + /* and SRAM_DATA memory areas are overlapping. You need to take measures to separate */ + /* data from code in RAM. This is only valid for Compiler version earlier than 15.09.0.STS.*/ + SRAM_CODE (RWX): origin = 0x01000000, length = 0x00010000 + SRAM_DATA (RW) : origin = 0x20000000, length = 0x00010000 +#endif +#endif +} + +/* The following command line options are set as part of the CCS project. */ +/* If you are building using the command line, or for some reason want to */ +/* define them here, you can uncomment and modify these lines as needed. */ +/* If you are using CCS for building, it is probably better to make any such */ +/* modifications in your CCS project and leave this file alone. */ +/* */ +/* A heap size of 1024 bytes is recommended when you plan to use printf() */ +/* for debug output to the console window. */ +/* */ +/* --heap_size=1024 */ +/* --stack_size=512 */ +/* --library=rtsv7M4_T_le_eabi.lib */ + +/* Section allocation in memory */ + +SECTIONS +{ +#ifndef gen_crc_table + .intvecs: > 0x00000000 + .text : > MAIN + .const : > MAIN + .cinit : > MAIN + .pinit : > MAIN + .init_array : > MAIN + .binit : {} > MAIN + + /* The following sections show the usage of the INFO flash memory */ + /* INFO flash memory is intended to be used for the following */ + /* device specific purposes: */ + /* Flash mailbox for device security operations */ + .flashMailbox : > 0x00200000 + /* TLV table for device identification and characterization */ + .tlvTable : > 0x00201000 + /* BSL area for device bootstrap loader */ + .bslArea : > 0x00202000 +#else + .intvecs: > 0x00000000, crc_table(crc_table_for_intvecs) + .text : > MAIN, crc_table(crc_table_for_text) + .const : > MAIN, crc_table(crc_table_for_const) + .cinit : > MAIN, crc_table(crc_table_for_cinit) + .pinit : > MAIN, crc_table(crc_table_for_pinit) + .init_array : > MAIN, crc_table(crc_table_for_init_array) + .binit : {} > MAIN, crc_table(crc_table_for_binit) + + /* The following sections show the usage of the INFO flash memory */ + /* INFO flash memory is intended to be used for the following */ + /* device specific purposes: */ + /* Flash mailbox for device security operations */ + .flashMailbox : > 0x00200000, crc_table(crc_table_for_flashMailbox) + /* TLV table for device identification and characterization */ + /* This one is read only memory in flash - generate no CRC */ + .tlvTable : > 0x00201000 + /* BSL area for device bootstrap loader */ + .bslArea : > 0x00202000, crc_table(crc_table_for_bslArea) + .TI.crctab : > MAIN +#endif + + .vtable : > 0x20000000 + .data : > SRAM_DATA + .bss : > SRAM_DATA + .sysmem : > SRAM_DATA + .stack : > SRAM_DATA (HIGH) + +#ifdef __TI_COMPILER_VERSION__ +#if __TI_COMPILER_VERSION__ >= 15009000 + .TI.ramfunc : {} load=MAIN, run=SRAM_CODE, table(BINIT) +#endif +#endif +} + +/* Symbolic definition of the WDTCTL register for RTS */ +WDTCTL_SYM = 0x4000480C; + diff --git a/ccs/startup_msp432p401r_ccs.c b/ccs/startup_msp432p401r_ccs.c new file mode 100644 index 0000000..fd160bd --- /dev/null +++ b/ccs/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/ccs/state.c b/ccs/state.c new file mode 100644 index 0000000..01ef5e0 --- /dev/null +++ b/ccs/state.c @@ -0,0 +1,38 @@ +#include "state.h" + +void senbuf_init(SensorBuffer *sb) { + sb->front = 0; + sb->rear = 0; + sb->size = 0; +} + +int senbuf_is_full(SensorBuffer *sb) { + return sb->size == STATE_SENSOR_BUFFER_SIZE; +} + +int senbuf_push(SensorBuffer *sb, uint8_t value) { + if (sb->size < STATE_SENSOR_BUFFER_SIZE) { + sb->buffer[sb->rear] = value; + sb->rear = (sb->rear + 1) % STATE_SENSOR_BUFFER_SIZE; + sb->size++; + return 1; // Success + } + return 0; // Buffer full +} + +int senbuf_pop(SensorBuffer *sb) { + if (sb->size > 0) { + sb->front = (sb->front + 1) % STATE_SENSOR_BUFFER_SIZE; + sb->size--; + return 1; // Success + } + return 0; // Buffer empty +} + +void senbuf_get(SensorBuffer *sb, uint8_t *out, int lookahead) { + if (lookahead >= 0 && lookahead < sb->size) { + // 가장 최근에 넣은 것(rear - 1)을 기준으로 lookahead + int index = (sb->rear - 1 - lookahead + STATE_SENSOR_BUFFER_SIZE) % STATE_SENSOR_BUFFER_SIZE; + *out = sb->buffer[index]; + } +} \ No newline at end of file diff --git a/ccs/state.h b/ccs/state.h new file mode 100644 index 0000000..aa5b835 --- /dev/null +++ b/ccs/state.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#define STATE_SENSOR_BUFFER_SIZE 8 + +typedef struct { + uint8_t buffer[STATE_SENSOR_BUFFER_SIZE]; + int front; + int rear; + int size; +} SensorBuffer; + +void senbuf_init(SensorBuffer *sb); + +int senbuf_is_full(SensorBuffer *sb); + +int senbuf_push(SensorBuffer *sb, uint8_t value); + +int senbuf_pop(SensorBuffer *sb); + +void senbuf_get(SensorBuffer *sb, uint8_t *out, int lookahead); diff --git a/ccs/system_msp432p401r.c b/ccs/system_msp432p401r.c new file mode 100644 index 0000000..06079d3 --- /dev/null +++ b/ccs/system_msp432p401r.c @@ -0,0 +1,401 @@ +/****************************************************************************** +* @file system_msp432p401r.c +* @brief CMSIS Cortex-M4F Device Peripheral Access Layer Source File for +* MSP432P401R +* @version 3.231 +* @date 01/26/18 +* +* @note View configuration instructions embedded in comments +* +******************************************************************************/ +//***************************************************************************** +// +// Copyright (C) 2015 - 2018 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 = 0, divider = 0, dividerValue = 0, centeredFreq = 0, calVal = 0; + int16_t dcoTune = 0; + float dcoConst = 0.0; + + 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 = *((volatile const float *) &TLV->DCOER_CONSTK_RSEL04); + calVal = TLV->DCOER_FCAL_RSEL04; + } + /* Internal Resistor */ + else + { + dcoConst = *((volatile const 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 + +} + + diff --git a/ccs/targetConfigs/MSP432P401R.ccxml b/ccs/targetConfigs/MSP432P401R.ccxml new file mode 100644 index 0000000..6821c49 --- /dev/null +++ b/ccs/targetConfigs/MSP432P401R.ccxml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ccs/targetConfigs/readme.txt b/ccs/targetConfigs/readme.txt new file mode 100644 index 0000000..a515923 --- /dev/null +++ b/ccs/targetConfigs/readme.txt @@ -0,0 +1,9 @@ +The 'targetConfigs' folder contains target-configuration (.ccxml) files, automatically generated based +on the device and connection settings specified in your project on the Properties > General page. + +Please note that in automatic target-configuration management, changes to the project's device and/or +connection settings will either modify an existing or generate a new target-configuration file. Thus, +if you manually edit these auto-generated files, you may need to re-apply your changes. Alternatively, +you may create your own target-configuration file for this project and manage it manually. You can +always switch back to automatic target-configuration management by checking the "Manage the project's +target-configuration automatically" checkbox on the project's Properties > General page. \ No newline at end of file diff --git a/ccs/util.c b/ccs/util.c new file mode 100644 index 0000000..d81f197 --- /dev/null +++ b/ccs/util.c @@ -0,0 +1,97 @@ +#include "util.h" + +#include +#include + +// 가중치 설정 (-4000 ~ +4000) +// 중앙(3번과 4번 사이)이 0이 되도록 설정 +// [0] [1] [2] [3] | [4] [5] [6] [7] +const int SENSOR_WEIGHTS[8] = {-4000, -3000, -2000, -1000, 1000, 2000, 3000, 4000}; + +// 선을 완전히 벗어났을 때 반환할 최대 에러 값 +const int MAX_ERROR = 5000; + +int get_error(uint8_t raw) { + // static 변수: 함수가 끝나도 값이 사라지지 않고 기억됨 (로봇의 마지막 위치) + static int last_valid_error = 0; + + // 1. 선이 아예 안 보이는 경우 (Line Lost) + if (raw == 0x00) { + // 마지막에 왼쪽(-값)에 있었다면 -> 계속 왼쪽으로 돌아라 (-MAX_ERROR) + if (last_valid_error < 0) return -MAX_ERROR; + // 마지막에 오른쪽(+값)에 있었다면 -> 계속 오른쪽으로 돌아라 (+MAX_ERROR) + else + return MAX_ERROR; + } + + // 2. 노이즈/갈림길 처리 (Masking) - 사용자가 걱정했던 '1 0 0 0 1 1 0 0' 상황 + // 간단한 로직: 마지막 위치가 양수(오른쪽)였다면, 왼쪽 끝(0,1번) 센서는 노이즈일 확률이 높음 -> 무시 + // 반대의 경우도 마찬가지. + + uint8_t filtered_raw = raw; + + // 로봇이 확실히 오른쪽(>1000)에 있었는데, 갑자기 왼쪽 끝(0,1번 비트)이 켜짐? + if (last_valid_error > 1000 && (raw & 0b00000011)) { + filtered_raw &= ~0b00000011;// 0, 1번 비트 강제 삭제 (Masking) + } + // 로봇이 확실히 왼쪽(<-1000)에 있었는데, 갑자기 오른쪽 끝(6,7번 비트)이 켜짐? + else if (last_valid_error < -1000 && (raw & 0b11000000)) { + filtered_raw &= ~0b11000000;// 6, 7번 비트 강제 삭제 + } + + // 만약 필터링했더니 남는 게 없다면? (노이즈만 떴던 경우) -> 원본 사용 or 이전 값 리턴 + if (filtered_raw == 0x00) filtered_raw = raw; + + // 3. 가중 평균 계산 (Weighted Average) + long sum_weighted = 0; + int sum_active = 0; + + for (int i = 0; i < 8; i++) { + // i번째 비트가 1인지 확인 + if ((filtered_raw >> (7 - i)) & 1) { + sum_weighted += SENSOR_WEIGHTS[i]; + sum_active++; + } + } + + // 예외 처리: 계산 중 비트가 다 사라진 경우 (혹시 모를 상황) + if (sum_active == 0) return last_valid_error; + + // 최종 에러 값 계산 + int current_error = sum_weighted / sum_active; + + // 4. 다음 계산을 위해 현재 위치 기억 + last_valid_error = current_error; + + return current_error; +} + +// 센서 비트 중 1의 개수를 세서 T자/십자 여부 판단 +int is_crossroad(uint8_t raw) { + int count = 0; + for (int i = 0; i < 8; i++) { + if ((raw >> i) & 1) {// i번째 비트가 1이면 카운트 + count++; + } + } + // 8개 중 6개 이상이 검은색이면 교차로(T자)로 인정 + if (count >= 7) return 1; + else + return 0; +} + +int is_crossroad_robust(SensorBuffer *sb) { + int crossroad_count = 0; + int total_count = sb->size; + + for (int i = 0; i < 3; i++) { + uint8_t sensor_value; + senbuf_get(sb, &sensor_value, i); + if (!is_crossroad(sensor_value)) { + goto fail; + } + } + return 1; +fail: + return 0; +} \ No newline at end of file diff --git a/ccs/util.h b/ccs/util.h new file mode 100644 index 0000000..45059a2 --- /dev/null +++ b/ccs/util.h @@ -0,0 +1,11 @@ +#pragma once + +#include "state.h" + +#include + +int get_error(uint8_t raw); + +int is_crossroad(uint8_t raw); + +int is_crossroad_robust(SensorBuffer *sb); \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..512459c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +services: + ccstudio: + image: whuzfb/ccstudio:12.8-ubuntu24.04 + container_name: ccstudio + privileged: true # USB JTAG 장비(XDS110 등) 직접 접근 권한 + network_mode: host # GUI 디스플레이 호환성을 위해 호스트 네트워크 사용 + user: "1000:1000" + environment: + - TZ=Asia/Seoul + volumes: + - /dev/bus/usb:/dev/bus/usb + - ./ccs:/ccs_projects # 프로젝트 디렉토리 (Entrypoint가 여기를 참조) + - ./res:/workspaces # 워크스페이스 및 빌드 결과 저장소 + entrypoint: ["/bin/bash", "-c", "sleep infinity"] + #entrypoint: ["/entrypoint.sh", ".ccsproject", "DEBUG"] # 컨테이너가 계속 실행되도록 설정 \ No newline at end of file