mirror of https://github.com/ARMmbed/mbed-os.git
First version of MSP432 support for mbed OS
Removed private TODO file. Fixed cmsis.h so that renaming of CS and DIR_H is not necessary any more. Leave pinmap.h unchanged although it should include stdint.h Moved stdint.h to PinNames.h instead, where it is also used. Reworked system startup (clock configuration) to be more flexible (different clock sources for MCLK and SMCLK, configurable clock dividers). Fixed Copyright headers Changed default clock settings for MSP432 Launchpad to MCLK 48 MHz (HFXT) and SMCLK 24 MHz (HFXT) Remove mbed_rtx.h Added common mbed_rtx.h file (merge with lastest master) Added support for IAR toolchain Fixed some astyle problems. Added support for ARM C5/C6 toolchains Small changes to us_ticker implementation after port testing. Changed default clock configuration to DCO (MCLK 48MHz, SMCLK 24MHz). De-configured the LFXT crysal, because this made the system_reset() test to time out. Removed MPU from device_has list. Changed clock source to HFXT. Reworked startup_msp432p401r.c -> now only one startup file for all compilers. Changed all linker scripts to delete VECTORS stuff (not needed). Moved position of MSP432 in targets.json so TI stuff is in one block.pull/11117/head
parent
e001216b55
commit
8853453ce3
|
@ -0,0 +1,40 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_PERIPHERALNAMES_H
|
||||
#define MBED_PERIPHERALNAMES_H
|
||||
|
||||
/* mbed-os internally uses integer values
|
||||
* for peripheral names. Instead of defining
|
||||
* enums with new names, we simply reuse the
|
||||
* macros for the base addresses of the
|
||||
* peripheral units, which are defined in
|
||||
* msp.h and are self-explanatory (see
|
||||
* PeripheralPins.c).
|
||||
* So the name types are simply typedefs
|
||||
* to integers...
|
||||
*/
|
||||
|
||||
#define DEVICE_SPI_COUNT 4
|
||||
|
||||
typedef uint32_t ADCName;
|
||||
typedef uint32_t UARTName;
|
||||
typedef uint32_t I2CName;
|
||||
typedef uint32_t SPIName;
|
||||
typedef uint32_t PWMName;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,163 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "PeripheralPins.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "cmsis.h"
|
||||
|
||||
const PinMap PinMap_empty[] = {
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
/*** ADC ***/
|
||||
const PinMap PinMap_ADC[] = {
|
||||
{ P5_5, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 0) },
|
||||
{ P5_4, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 1) },
|
||||
{ P5_3, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 2) },
|
||||
{ P5_2, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 3) },
|
||||
{ P5_1, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 4) },
|
||||
{ P5_0, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 5) },
|
||||
{ P4_7, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 6) },
|
||||
{ P4_6, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 7) },
|
||||
{ P4_5, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 8) },
|
||||
{ P4_4, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 9) },
|
||||
{ P4_3, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 10) },
|
||||
{ P4_2, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 11) },
|
||||
{ P4_1, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 12) },
|
||||
{ P4_0, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 13) },
|
||||
{ P6_1, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 14) },
|
||||
{ P6_0, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 15) },
|
||||
{ P9_1, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 16) },
|
||||
{ P9_0, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 17) },
|
||||
{ P8_7, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 18) },
|
||||
{ P8_6, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 19) },
|
||||
{ P8_5, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 20) },
|
||||
{ P8_4, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 21) },
|
||||
{ P8_3, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 22) },
|
||||
{ P8_2, ADC14_BASE, MSP432_PIN_DATA(SEL3, PIN_INPUT, PullNone, 23) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
const PinMap PinMap_ADC_Internal[] = {
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
//*** I2C ***
|
||||
const PinMap PinMap_I2C_SDA[] = {
|
||||
{ P1_6, EUSCI_B0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ P6_4, EUSCI_B1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ P3_6, EUSCI_B2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ P6_6, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL2, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ P10_2, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
const PinMap PinMap_I2C_SCL[] = {
|
||||
{ P1_7, EUSCI_B0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ P6_5, EUSCI_B1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ P3_7, EUSCI_B2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ P6_7, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL2, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ P10_3, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, OpenDrainPullUp, 0) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
//*** SERIAL ***
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
{ P1_3, EUSCI_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 0) },
|
||||
{ P2_3, EUSCI_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 0) },
|
||||
{ P3_3, EUSCI_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 0) },
|
||||
{ P9_7, EUSCI_A3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 0) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
{ P1_2, EUSCI_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 0) },
|
||||
{ P2_2, EUSCI_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 0) },
|
||||
{ P3_2, EUSCI_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 0) },
|
||||
{ P9_6, EUSCI_A3_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 0) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
//*** SPI ***
|
||||
const PinMap PinMap_SPI_MOSI[] = {
|
||||
{ P1_3, EUSCI_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 0) },
|
||||
{ P2_3, EUSCI_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 1) },
|
||||
{ P3_3, EUSCI_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 2) },
|
||||
{ P9_7, EUSCI_A3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 3) },
|
||||
{ P1_6, EUSCI_B0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 4) },
|
||||
{ P6_4, EUSCI_B1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 5) },
|
||||
{ P3_6, EUSCI_B2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 6) },
|
||||
{ P6_6, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL2, PIN_OUTPUT, PullNone, 7) },
|
||||
{ P10_2, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 7) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MISO[] = {
|
||||
{ P1_2, EUSCI_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 0) },
|
||||
{ P2_2, EUSCI_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 1) },
|
||||
{ P3_2, EUSCI_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 2) },
|
||||
{ P9_6, EUSCI_A3_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 3) },
|
||||
{ P1_7, EUSCI_B0_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 4) },
|
||||
{ P6_5, EUSCI_B1_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 5) },
|
||||
{ P3_7, EUSCI_B2_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 6) },
|
||||
{ P6_7, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL2, PIN_INPUT, PullNone, 7) },
|
||||
{ P10_3, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL1, PIN_INPUT, PullNone, 7) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_SCLK[] = {
|
||||
{ P1_1, EUSCI_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 0) },
|
||||
{ P2_1, EUSCI_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 1) },
|
||||
{ P3_1, EUSCI_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 2) },
|
||||
{ P9_5, EUSCI_A3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 3) },
|
||||
{ P1_5, EUSCI_B0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 4) },
|
||||
{ P6_3, EUSCI_B1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 5) },
|
||||
{ P3_5, EUSCI_B2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 6) },
|
||||
{ P8_1, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 7) },
|
||||
{ P10_1, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 7) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_SSEL[] = {
|
||||
{ P1_0, EUSCI_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 0) },
|
||||
{ P2_0, EUSCI_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 1) },
|
||||
{ P3_0, EUSCI_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 2) },
|
||||
{ P9_4, EUSCI_A3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 3) },
|
||||
{ P1_4, EUSCI_B0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 4) },
|
||||
{ P6_2, EUSCI_B1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 5) },
|
||||
{ P3_4, EUSCI_B2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 6) },
|
||||
{ P8_0, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 7) },
|
||||
{ P10_0, EUSCI_B3_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 7) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
||||
const PinMap PinMap_PWM[] = {
|
||||
{ P2_4, TIMER_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 1) },
|
||||
{ P2_5, TIMER_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 2) },
|
||||
{ P2_6, TIMER_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 3) },
|
||||
{ P2_7, TIMER_A0_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 4) },
|
||||
{ P7_7, TIMER_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 1) },
|
||||
{ P7_6, TIMER_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 2) },
|
||||
{ P7_5, TIMER_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 3) },
|
||||
{ P7_4, TIMER_A1_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 4) },
|
||||
{ P5_6, TIMER_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 1) },
|
||||
{ P5_7, TIMER_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 2) },
|
||||
{ P6_6, TIMER_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 3) },
|
||||
{ P6_7, TIMER_A2_BASE, MSP432_PIN_DATA(SEL1, PIN_OUTPUT, PullNone, 4) },
|
||||
{ NC, NC, 0 }
|
||||
};
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_PERIPHERALPINS_H
|
||||
#define MBED_PERIPHERALPINS_H
|
||||
|
||||
#include "pinmap.h"
|
||||
|
||||
typedef enum {
|
||||
SEL0 = 0,
|
||||
SEL1 = 1,
|
||||
SEL2 = 2,
|
||||
SEL3 = 3
|
||||
} pin_sel_t;
|
||||
|
||||
#define MSP432_PIN_DATA(sel, dir, mode, channel) (sel | (dir << 8) | (mode << 16) | (channel << 24))
|
||||
|
||||
#define GET_DATA_SEL(data) ( data & 0xff)
|
||||
#define GET_DATA_DIR(data) ((data >> 8) & 0xff)
|
||||
#define GET_DATA_MODE(data) ((data >> 16) & 0xff)
|
||||
#define GET_DATA_CHAN(data) ((data >> 24) & 0xff)
|
||||
|
||||
extern const PinMap PinMap_empty[];
|
||||
|
||||
//*** ADC ***
|
||||
#if DEVICE_ANALOGIN
|
||||
extern const PinMap PinMap_ADC[];
|
||||
extern const PinMap PinMap_ADC_Internal[];
|
||||
#endif
|
||||
|
||||
//*** I2C ***
|
||||
#if DEVICE_I2C
|
||||
extern const PinMap PinMap_I2C_SDA[];
|
||||
extern const PinMap PinMap_I2C_SCL[];
|
||||
#endif
|
||||
|
||||
//*** PWM ***
|
||||
#if DEVICE_PWMOUT
|
||||
extern const PinMap PinMap_PWM[];
|
||||
#endif
|
||||
|
||||
//*** SERIAL ***
|
||||
#if DEVICE_SERIAL
|
||||
extern const PinMap PinMap_UART_TX[];
|
||||
extern const PinMap PinMap_UART_RX[];
|
||||
#endif
|
||||
|
||||
//*** SPI ***
|
||||
#if DEVICE_SPI
|
||||
extern const PinMap PinMap_SPI_MOSI[];
|
||||
extern const PinMap PinMap_SPI_MISO[];
|
||||
extern const PinMap PinMap_SPI_SCLK[];
|
||||
extern const PinMap PinMap_SPI_SSEL[];
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,152 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_PINNAMES_H
|
||||
#define MBED_PINNAMES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Macros to extract port/pin index from the PinName
|
||||
* MSP432_PORT returns values 0...9, corresponing to P1...P10
|
||||
* MSP432_PIN returns values 0...7, corresponing to pin index
|
||||
*/
|
||||
#define MSP432_PORT_IDX(pin) (((uint32_t)pin & 0xF0) >> 4)
|
||||
#define MSP432_PIN_IDX(pin) ((uint32_t)pin & 0x0F)
|
||||
|
||||
/*
|
||||
* The following defines are used by user applications.
|
||||
* Since PinDirection and PinMode are not part of the
|
||||
* mbed-os interface for GPIOs, care must be taken that
|
||||
* the standard names (e.g. PIN_INPUT) are used so that
|
||||
* cross-platform compatibility of source code is kept!
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
PIN_INPUT = 0,
|
||||
PIN_OUTPUT = 1
|
||||
} PinDirection;
|
||||
|
||||
typedef enum {
|
||||
PullNone,
|
||||
PullUp,
|
||||
PullDown,
|
||||
OpenDrain,
|
||||
OpenDrainPullUp,
|
||||
OpenSource,
|
||||
OpenSourcePullDown,
|
||||
// Alias names
|
||||
PullDefault = PullNone,
|
||||
OpenDrainNoPull = OpenDrain,
|
||||
OpenSourceNoPull = OpenSource
|
||||
} PinMode;
|
||||
|
||||
typedef enum {
|
||||
P1_0 = 0x00,
|
||||
P1_1 = 0x01,
|
||||
P1_2 = 0x02,
|
||||
P1_3 = 0x03,
|
||||
P1_4 = 0x04,
|
||||
P1_5 = 0x05,
|
||||
P1_6 = 0x06,
|
||||
P1_7 = 0x07,
|
||||
P2_0 = 0x10,
|
||||
P2_1 = 0x11,
|
||||
P2_2 = 0x12,
|
||||
P2_3 = 0x13,
|
||||
P2_4 = 0x14,
|
||||
P2_5 = 0x15,
|
||||
P2_6 = 0x16,
|
||||
P2_7 = 0x17,
|
||||
P3_0 = 0x20,
|
||||
P3_1 = 0x21,
|
||||
P3_2 = 0x22,
|
||||
P3_3 = 0x23,
|
||||
P3_4 = 0x24,
|
||||
P3_5 = 0x25,
|
||||
P3_6 = 0x26,
|
||||
P3_7 = 0x27,
|
||||
P4_0 = 0x30,
|
||||
P4_1 = 0x31,
|
||||
P4_2 = 0x32,
|
||||
P4_3 = 0x33,
|
||||
P4_4 = 0x34,
|
||||
P4_5 = 0x35,
|
||||
P4_6 = 0x36,
|
||||
P4_7 = 0x37,
|
||||
P5_0 = 0x40,
|
||||
P5_1 = 0x41,
|
||||
P5_2 = 0x42,
|
||||
P5_3 = 0x43,
|
||||
P5_4 = 0x44,
|
||||
P5_5 = 0x45,
|
||||
P5_6 = 0x46,
|
||||
P5_7 = 0x47,
|
||||
P6_0 = 0x50,
|
||||
P6_1 = 0x51,
|
||||
P6_2 = 0x52,
|
||||
P6_3 = 0x53,
|
||||
P6_4 = 0x54,
|
||||
P6_5 = 0x55,
|
||||
P6_6 = 0x56,
|
||||
P6_7 = 0x57,
|
||||
P7_0 = 0x60,
|
||||
P7_1 = 0x61,
|
||||
P7_2 = 0x62,
|
||||
P7_3 = 0x63,
|
||||
P7_4 = 0x64,
|
||||
P7_5 = 0x65,
|
||||
P7_6 = 0x66,
|
||||
P7_7 = 0x67,
|
||||
P8_0 = 0x70,
|
||||
P8_1 = 0x71,
|
||||
P8_2 = 0x72,
|
||||
P8_3 = 0x73,
|
||||
P8_4 = 0x74,
|
||||
P8_5 = 0x75,
|
||||
P8_6 = 0x76,
|
||||
P8_7 = 0x77,
|
||||
P9_0 = 0x80,
|
||||
P9_1 = 0x81,
|
||||
P9_2 = 0x82,
|
||||
P9_3 = 0x83,
|
||||
P9_4 = 0x84,
|
||||
P9_5 = 0x85,
|
||||
P9_6 = 0x86,
|
||||
P9_7 = 0x87,
|
||||
P10_0 = 0x90,
|
||||
P10_1 = 0x91,
|
||||
P10_2 = 0x92,
|
||||
P10_3 = 0x93,
|
||||
P10_4 = 0x94,
|
||||
P10_5 = 0x95,
|
||||
|
||||
// Not connected
|
||||
NC = (int)0xFFFFFFFF,
|
||||
|
||||
#include "BoardPinNames.h"
|
||||
|
||||
} PinName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_PORTNAMES_H
|
||||
#define MBED_PORTNAMES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
Port1 = 0,
|
||||
Port2 = 1,
|
||||
Port3 = 2,
|
||||
Port4 = 3,
|
||||
Port5 = 4,
|
||||
Port6 = 5,
|
||||
Port7 = 6,
|
||||
Port8 = 7,
|
||||
Port9 = 8,
|
||||
Port10 = 9,
|
||||
} PortName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,46 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* This file will be included in PinNames.h (inside the PinName enum)
|
||||
*
|
||||
* It defines the names of the board-specific components, like
|
||||
* - LEDs
|
||||
* - Buttons
|
||||
* - UARTS connected via e.g. USB
|
||||
*/
|
||||
|
||||
// mbed standard names for UARTs
|
||||
STDIO_UART_TX = P1_3,
|
||||
STDIO_UART_RX = P1_2,
|
||||
USBTX = P1_3,
|
||||
USBRX = P1_2,
|
||||
|
||||
// mbed standard names for LEDs and Buttons
|
||||
LED1 = P1_0,
|
||||
LED2 = P2_0,
|
||||
LED3 = P2_1,
|
||||
LED4 = P2_2,
|
||||
BUTTON1 = P1_1,
|
||||
BUTTON2 = P1_4,
|
||||
|
||||
// Alternative names for LEDs and Buttons
|
||||
LED_RED = P1_0,
|
||||
LED_RGB_RED = P2_0,
|
||||
LED_RGB_GREEN = P2_1,
|
||||
LED_RGB_BLUE = P2_2,
|
||||
S1 = P1_1,
|
||||
S2 = P1_4
|
|
@ -0,0 +1,36 @@
|
|||
#! armcc -E
|
||||
|
||||
/* Device specific values */
|
||||
|
||||
#define ROM_START 0x00000000
|
||||
#define ROM_SIZE 0x00040000
|
||||
#define RAM_START 0x20000000
|
||||
#define RAM_SIZE 0x00010000
|
||||
#define STACK_SIZE 0x00000400
|
||||
|
||||
/* Common - Do not change */
|
||||
|
||||
#if !defined(MBED_APP_START)
|
||||
#define MBED_APP_START ROM_START
|
||||
#endif
|
||||
|
||||
#if !defined(MBED_APP_SIZE)
|
||||
#define MBED_APP_SIZE ROM_SIZE
|
||||
#endif
|
||||
|
||||
LR_IROM1 MBED_APP_START MBED_APP_SIZE {
|
||||
|
||||
ER_IROM1 MBED_APP_START MBED_APP_SIZE {
|
||||
*.o (RESET, +First)
|
||||
*(InRoot$$Sections)
|
||||
.ANY (+RO)
|
||||
}
|
||||
|
||||
RW_IRAM1 RAM_START RAM_SIZE {
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
|
||||
ARM_LIB_STACK (RAM_START+RAM_SIZE) EMPTY -STACK_SIZE {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/******************************************************
|
||||
* GCC linker script for Texas Instruments MSP432P401R
|
||||
******************************************************/
|
||||
|
||||
/* Device specific values */
|
||||
|
||||
#define ROM_START 0x00000000
|
||||
#define ROM_SIZE 0x00040000
|
||||
#define RAM_START 0x20000000
|
||||
#define RAM_SIZE 0x00010000
|
||||
#define INFO_START 0x00200000
|
||||
#define INFO_SIZE 0x00004000
|
||||
|
||||
/* Common - Do not change */
|
||||
|
||||
#if !defined(MBED_APP_START)
|
||||
#define MBED_APP_START ROM_START
|
||||
#endif
|
||||
|
||||
#if !defined(MBED_APP_SIZE)
|
||||
#define MBED_APP_SIZE ROM_SIZE
|
||||
#endif
|
||||
|
||||
#if !defined(MBED_BOOT_STACK_SIZE)
|
||||
#define MBED_BOOT_STACK_SIZE 0x400
|
||||
#endif
|
||||
|
||||
STACK_SIZE = MBED_BOOT_STACK_SIZE;
|
||||
|
||||
/* Linker script to configure memory regions. */
|
||||
/* 0x1AC resevered for vectors; 8-byte aligned = 0x1B0 (0x1AC + 0x4)*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE
|
||||
RAM (rwx) : ORIGIN = RAM_START, LENGTH = RAM_SIZE
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
KEEP(*(.eh_frame*))
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* Location counter can end up 2byte aligned with narrow Thumb code but
|
||||
__etext is assumed by startup code to be the LMA of a section in RAM
|
||||
which must be 4byte aligned */
|
||||
__etext = ALIGN (4);
|
||||
__data_load__ = .;
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP(*(SORT(.fini_array.*)))
|
||||
KEEP(*(.fini_array))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
KEEP(*(.jcr*))
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
. = ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE;
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackLimit = __StackTop - STACK_SIZE;
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* Device specific values */
|
||||
|
||||
define symbol ROM_START = 0x00000000;
|
||||
define symbol ROM_SIZE = 0x00040000;
|
||||
define symbol RAM_START = 0x20000000;
|
||||
define symbol RAM_SIZE = 0x00010000;
|
||||
|
||||
define symbol HEAP_SIZE = 0x8000;
|
||||
define symbol ISR_STACK_SIZE = 0x400;
|
||||
|
||||
/* Common - Do not change */
|
||||
|
||||
if (!isdefinedsymbol(MBED_APP_START)) {
|
||||
define symbol MBED_APP_START = ROM_START;
|
||||
}
|
||||
|
||||
if (!isdefinedsymbol(MBED_APP_SIZE)) {
|
||||
define symbol MBED_APP_SIZE = ROM_SIZE;
|
||||
}
|
||||
|
||||
define symbol RAM_REGION_START = RAM_START;
|
||||
define symbol RAM_REGION_SIZE = RAM_SIZE;
|
||||
|
||||
define memory mem with size = 4G;
|
||||
define region ROM_region = mem:[from MBED_APP_START size MBED_APP_SIZE];
|
||||
define region RAM_region = mem:[from RAM_REGION_START size RAM_REGION_SIZE];
|
||||
|
||||
define block CSTACK with alignment = 8, size = ISR_STACK_SIZE { };
|
||||
define block HEAP with alignment = 8, size = HEAP_SIZE { };
|
||||
|
||||
initialize by copy { readwrite };
|
||||
do not initialize { section .noinit };
|
||||
|
||||
place at address mem: MBED_APP_START { readonly section .intvec };
|
||||
|
||||
place in ROM_region { readonly };
|
||||
place in RAM_region { readwrite, block HEAP };
|
||||
place at end of RAM_region { block CSTACK };
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,325 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (C) 2013 - 2015 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.
|
||||
//
|
||||
// MSP430 intrinsic redefinitions for use with MSP432 Family Devices
|
||||
//
|
||||
//****************************************************************************
|
||||
|
||||
/******************************************************************************
|
||||
* Definitions for 8/16/32-bit wide memory access *
|
||||
******************************************************************************/
|
||||
#define HWREG8(x) (*((volatile uint8_t *)(x)))
|
||||
#define HWREG16(x) (*((volatile uint16_t *)(x)))
|
||||
#define HWREG32(x) (*((volatile uint32_t *)(x)))
|
||||
#define HWREG(x) (HWREG16(x))
|
||||
#define HWREG8_L(x) (*((volatile uint8_t *)((uint8_t *)&x)))
|
||||
#define HWREG8_H(x) (*((volatile uint8_t *)(((uint8_t *)&x)+1)))
|
||||
#define HWREG16_L(x) (*((volatile uint16_t *)((uint16_t *)&x)))
|
||||
#define HWREG16_H(x) (*((volatile uint16_t *)(((uint16_t *)&x)+1)))
|
||||
|
||||
/******************************************************************************
|
||||
* Definitions for 8/16/32-bit wide bit band access *
|
||||
******************************************************************************/
|
||||
#define HWREGBIT8(x, b) (HWREG8(((uint32_t)(x) & 0xF0000000) | 0x02000000 | (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2)))
|
||||
#define HWREGBIT16(x, b) (HWREG16(((uint32_t)(x) & 0xF0000000) | 0x02000000 | (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2)))
|
||||
#define HWREGBIT32(x, b) (HWREG32(((uint32_t)(x) & 0xF0000000) | 0x02000000 | (((uint32_t)(x) & 0x000FFFFF) << 5) | ((b) << 2)))
|
||||
|
||||
// Intrinsics with ARM equivalents
|
||||
#if defined ( __TI_ARM__ ) /* TI CGT Compiler */
|
||||
|
||||
#define __sleep() __wfi()
|
||||
#define __deep_sleep() { (*((volatile uint32_t *)(0xE000ED10))) |= 0x00000004; __wfi(); (*((volatile uint32_t *)(0xE000ED10))) &= ~0x00000004; }
|
||||
#define __low_power_mode_off_on_exit() { (*((volatile uint32_t *)(0xE000ED10))) &= ~0x00000002; }
|
||||
#define __get_SP_register() __get_MSP()
|
||||
#define __set_SP_register(x) __set_MSP(x)
|
||||
#define __get_interrupt_state() __get_PRIMASK()
|
||||
#define __set_interrupt_state(x) __set_PRIMASK(x)
|
||||
#define __enable_interrupt() _enable_IRQ()
|
||||
#define __enable_interrupts() _enable_IRQ()
|
||||
#define __disable_interrupt() _disable_IRQ()
|
||||
#define __disable_interrupts() _disable_IRQ()
|
||||
#define __no_operation() __asm(" nop")
|
||||
|
||||
#elif defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define __INLINE inline
|
||||
#define __sleep() __WFI()
|
||||
#define __deep_sleep() { (*((volatile uint32_t *)(0xE000ED10))) |= 0x00000004; __WFI(); (*((volatile uint32_t *)(0xE000ED10))) &= ~0x00000004; }
|
||||
#define __low_power_mode_off_on_exit() { (*((volatile uint32_t *)(0xE000ED10))) &= ~0x00000002; }
|
||||
|
||||
#if (__VER__ < 8020002)
|
||||
#define __get_SP_register() __get_MSP()
|
||||
#define __set_SP_register() __set_MSP()
|
||||
#define __get_interrupt_state() __get_PRIMASK()
|
||||
#define __set_interrupt_state(x) __set_PRIMASK(x)
|
||||
#define __enable_interrupt() __asm(" cpsie i")
|
||||
#define __enable_interrupts() __asm(" cpsie i")
|
||||
#define __disable_interrupt() __asm(" cpsid i")
|
||||
#define __disable_interrupts() __asm(" cpsid i")
|
||||
#define __no_operation() __asm(" nop")
|
||||
#endif
|
||||
|
||||
// Intrinsics without ARM equivalents
|
||||
#define __bcd_add_short(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bcd_add_long(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bcd_add_long_long(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __even_in_range(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __data20_write_char(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __data20_write_short(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __data20_write_long(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __never_executed() { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __op_code() { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __code_distance() { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bic_SR_register(x) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bis_SR_register(x) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bis_SR_register_on_exit(x) { while(1); /* Using not-supported MSP430 intrinsic. Recommended to write to SCS_SCR register. */ }
|
||||
#define __bic_SR_register_on_exit(x) { while(1); /* Using not-supported MSP430 intrinsic. Recommended to write to SCS_SCR register. */ }
|
||||
#define __delay_cycles(x) { while(1); /* Using not-supported MSP430 intrinsic. Recommended to use a timer or a custom for loop. */ }
|
||||
|
||||
#elif defined ( __CC_ARM ) /* ARM Compiler */
|
||||
|
||||
#define __sleep() __wfi()
|
||||
#define __deep_sleep() { (*((volatile uint32_t *)(0xE000ED10))) |= 0x00000004; __wfi(); (*((volatile uint32_t *)(0xE000ED10))) &= ~0x00000004; }
|
||||
#define __low_power_mode_off_on_exit() { (*((volatile uint32_t *)(0xE000ED10))) &= ~0x00000002; }
|
||||
#define __get_SP_register() __get_MSP()
|
||||
#define __set_SP_register(x) __set_MSP(x)
|
||||
#define __get_interrupt_state() __get_PRIMASK()
|
||||
#define __set_interrupt_state(x) __set_PRIMASK(x)
|
||||
#define __enable_interrupt() __asm(" cpsie i")
|
||||
#define __enable_interrupts() __asm(" cpsie i")
|
||||
#define __disable_interrupt() __asm(" cpsid i")
|
||||
#define __disable_interrupts() __asm(" cpsid i")
|
||||
#define __no_operation() __asm(" nop")
|
||||
|
||||
// Intrinsics without ARM equivalents
|
||||
#define __bcd_add_short(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bcd_add_long(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bcd_add_long_long(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __even_in_range(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __data20_write_char(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __data20_write_short(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __data20_write_long(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __never_executed() { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __op_code() { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __code_distance() { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bic_SR_register(x) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bis_SR_register(x) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bis_SR_register_on_exit(x) { while(1); /* Using not-supported MSP430 intrinsic. Recommended to write to SCS_SCR register. */ }
|
||||
#define __bic_SR_register_on_exit(x) { while(1); /* Using not-supported MSP430 intrinsic. Recommended to write to SCS_SCR register. */ }
|
||||
#define __delay_cycles(x) { while(1); /* Using not-supported MSP430 intrinsic. Recommended to use a timer or a custom for loop. */ }
|
||||
|
||||
#elif defined ( __GNUC__ ) /* GCC Compiler */
|
||||
#undef __wfi
|
||||
// ARM Compiler 6 seems to set __GNUC__ and has own definition of __wfi() ??
|
||||
//#define __wfi() __asm(" wfi")
|
||||
#define __sleep() __wfi()
|
||||
#define __deep_sleep() { (*((volatile uint32_t *)(0xE000ED10))) |= 0x00000004; __wfi(); (*((volatile uint32_t *)(0xE000ED10))) &= ~0x00000004; }
|
||||
#define __low_power_mode_off_on_exit() { (*((volatile uint32_t *)(0xE000ED10))) &= ~0x00000002; }
|
||||
#define __get_SP_register() __get_MSP()
|
||||
#define __set_SP_register(x) __set_MSP(x)
|
||||
#define __get_interrupt_state() __get_PRIMASK()
|
||||
#define __set_interrupt_state(x) __set_PRIMASK(x)
|
||||
#define __enable_interrupt() __asm(" cpsie i")
|
||||
#define __enable_interrupts() __asm(" cpsie i")
|
||||
#define __disable_interrupt() __asm(" cpsid i")
|
||||
#define __disable_interrupts() __asm(" cpsid i")
|
||||
#define __no_operation() __asm(" nop")
|
||||
|
||||
// Intrinsics without ARM equivalents
|
||||
#define __bcd_add_short(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bcd_add_long(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bcd_add_long_long(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __even_in_range(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __data20_write_char(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __data20_write_short(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __data20_write_long(x,y) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __never_executed() { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __op_code() { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __code_distance() { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bic_SR_register(x) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bis_SR_register(x) { while(1); /* Using not-supported MSP430 intrinsic. No replacement available. */ }
|
||||
#define __bis_SR_register_on_exit(x) { while(1); /* Using not-supported MSP430 intrinsic. Recommended to write to SCS_SCR register. */ }
|
||||
#define __bic_SR_register_on_exit(x) { while(1); /* Using not-supported MSP430 intrinsic. Recommended to write to SCS_SCR register. */ }
|
||||
#define __delay_cycles(x) { while(1); /* Using not-supported MSP430 intrinsic. Recommended to use a timer or a custom for loop. */ }
|
||||
|
||||
#endif
|
||||
|
||||
// Intrinsics without ARM equivalents
|
||||
#define __low_power_mode_0() { __sleep(); }
|
||||
#define __low_power_mode_1() { __sleep(); }
|
||||
#define __low_power_mode_2() { __sleep(); }
|
||||
#define __low_power_mode_3() { __deep_sleep(); }
|
||||
#define __low_power_mode_4() { __deep_sleep(); }
|
||||
#define __data16_read_addr(x) (*((volatile uint32_t *)(x)))
|
||||
#define __data20_read_char(x) (*((volatile uint8_t *)(x)))
|
||||
#define __data20_read_short(x) (*((volatile uint16_t *)(x)))
|
||||
#define __data20_read_long(x) (*((volatile uint32_t *)(x)))
|
||||
#define __data16_write_addr(x,y) { (*((volatile uint32_t *)(x))) }
|
||||
#define __get_SR_register() 0
|
||||
#define __get_SR_register_on_exit() 0
|
||||
|
||||
// the following defines are deprecated and will be removed in future releases
|
||||
#define ATLBASE ALTBASE
|
||||
#define CS_CTL1_SELM_7 ((uint32_t)0x00000007) /*!< for future use. Defaults to DCOCLK. Not recommended for use to ensure future */
|
||||
/* compatibilities. */
|
||||
#define CS_CTL1_SELS_7 ((uint32_t)0x00000070) /*!< for furture use. Defaults to DCOCLK. Do not use to ensure future */
|
||||
/* compatibilities. */
|
||||
#define CS_CTL1_SELA_3 ((uint32_t)0x00000300) /*!< for future use. Defaults to REFOCLK. Not recommended for use to ensure future */
|
||||
/* compatibilities. */
|
||||
#define CS_CTL1_SELA_4 ((uint32_t)0x00000400) /*!< for future use. Defaults to REFOCLK. Not recommended for use to ensure future */
|
||||
/* compatibilities. */
|
||||
#define CS_CTL1_SELA_5 ((uint32_t)0x00000500) /*!< for future use. Defaults to REFOCLK. Not recommended for use to ensure future */
|
||||
/* compatibilities. */
|
||||
#define CS_CTL1_SELA_6 ((uint32_t)0x00000600) /*!< for future use. Defaults to REFOCLK. Not recommended for use to ensure future */
|
||||
/* compatibilities. */
|
||||
#define CS_CTL1_SELA_7 ((uint32_t)0x00000700) /*!< for future use. Defaults to REFOCLK. Not recommended for use to ensure future */
|
||||
/* compatibilities. */
|
||||
/* CS_CTL2[LFXTAGCOFF] Bits */
|
||||
#define CS_CTL2_LFXTAGCOFF_OFS ( 7) /*!< LFXTAGCOFF Bit Offset */
|
||||
#define CS_CTL2_LFXTAGCOFF ((uint32_t)0x00000080) /*!< Disables the automatic gain control of the LFXT crystal */
|
||||
|
||||
/* CS_CTL3[FCNTHF2] Bits */
|
||||
#define CS_CTL3_FCNTHF2_OFS ( 8) /*!< FCNTHF2 Bit Offset */
|
||||
#define CS_CTL3_FCNTHF2_MASK ((uint32_t)0x00000300) /*!< FCNTHF2 Bit Mask */
|
||||
#define CS_CTL3_FCNTHF20 ((uint32_t)0x00000100) /*!< FCNTHF2 Bit 0 */
|
||||
#define CS_CTL3_FCNTHF21 ((uint32_t)0x00000200) /*!< FCNTHF2 Bit 1 */
|
||||
#define CS_CTL3_FCNTHF2_0 ((uint32_t)0x00000000) /*!< 2048 cycles */
|
||||
#define CS_CTL3_FCNTHF2_1 ((uint32_t)0x00000100) /*!< 4096 cycles */
|
||||
#define CS_CTL3_FCNTHF2_2 ((uint32_t)0x00000200) /*!< 8192 cycles */
|
||||
#define CS_CTL3_FCNTHF2_3 ((uint32_t)0x00000300) /*!< 16384 cycles */
|
||||
#define CS_CTL3_FCNTHF2__2048 ((uint32_t)0x00000000) /*!< 2048 cycles */
|
||||
#define CS_CTL3_FCNTHF2__4096 ((uint32_t)0x00000100) /*!< 4096 cycles */
|
||||
#define CS_CTL3_FCNTHF2__8192 ((uint32_t)0x00000200) /*!< 8192 cycles */
|
||||
#define CS_CTL3_FCNTHF2__16384 ((uint32_t)0x00000300) /*!< 16384 cycles */
|
||||
/* CS_CTL3[RFCNTHF2] Bits */
|
||||
#define CS_CTL3_RFCNTHF2_OFS (10) /*!< RFCNTHF2 Bit Offset */
|
||||
#define CS_CTL3_RFCNTHF2 ((uint32_t)0x00000400) /*!< Reset start fault counter for HFXT2 */
|
||||
/* CS_CTL3[FCNTHF2_EN] Bits */
|
||||
#define CS_CTL3_FCNTHF2_EN_OFS (11) /*!< FCNTHF2_EN Bit Offset */
|
||||
#define CS_CTL3_FCNTHF2_EN ((uint32_t)0x00000800) /*!< Enable start fault counter for HFXT2 */
|
||||
/* CS_STAT[HFXT2_ON] Bits */
|
||||
#define CS_STAT_HFXT2_ON_OFS ( 3) /*!< HFXT2_ON Bit Offset */
|
||||
#define CS_STAT_HFXT2_ON ((uint32_t)0x00000008) /*!< HFXT2 status */
|
||||
/* CS_IE[HFXT2IE] Bits */
|
||||
#define CS_IE_HFXT2IE_OFS ( 2) /*!< HFXT2IE Bit Offset */
|
||||
#define CS_IE_HFXT2IE ((uint32_t)0x00000004) /*!< HFXT2 oscillator fault flag interrupt enable */
|
||||
/* CS_IE[FCNTHF2IE] Bits */
|
||||
#define CS_IE_FCNTHF2IE_OFS (10) /*!< FCNTHF2IE Bit Offset */
|
||||
#define CS_IE_FCNTHF2IE ((uint32_t)0x00000400) /*!< Start fault counter interrupt enable HFXT2 */
|
||||
/* CS_IE[PLLOOLIE] Bits */
|
||||
#define CS_IE_PLLOOLIE_OFS (12) /*!< PLLOOLIE Bit Offset */
|
||||
#define CS_IE_PLLOOLIE ((uint32_t)0x00001000) /*!< PLL out-of-lock interrupt enable */
|
||||
/* CS_IE[PLLLOSIE] Bits */
|
||||
#define CS_IE_PLLLOSIE_OFS (13) /*!< PLLLOSIE Bit Offset */
|
||||
#define CS_IE_PLLLOSIE ((uint32_t)0x00002000) /*!< PLL loss-of-signal interrupt enable */
|
||||
/* CS_IE[PLLOORIE] Bits */
|
||||
#define CS_IE_PLLOORIE_OFS (14) /*!< PLLOORIE Bit Offset */
|
||||
#define CS_IE_PLLOORIE ((uint32_t)0x00004000) /*!< PLL out-of-range interrupt enable */
|
||||
/* CS_IE[CALIE] Bits */
|
||||
#define CS_IE_CALIE_OFS (15) /*!< CALIE Bit Offset */
|
||||
#define CS_IE_CALIE ((uint32_t)0x00008000) /*!< REFCNT period counter interrupt enable */
|
||||
/* CS_IFG[HFXT2IFG] Bits */
|
||||
#define CS_IFG_HFXT2IFG_OFS ( 2) /*!< HFXT2IFG Bit Offset */
|
||||
#define CS_IFG_HFXT2IFG ((uint32_t)0x00000004) /*!< HFXT2 oscillator fault flag */
|
||||
/* CS_IFG[FCNTHF2IFG] Bits */
|
||||
#define CS_IFG_FCNTHF2IFG_OFS (11) /*!< FCNTHF2IFG Bit Offset */
|
||||
#define CS_IFG_FCNTHF2IFG ((uint32_t)0x00000800) /*!< Start fault counter interrupt flag HFXT2 */
|
||||
/* CS_IFG[PLLOOLIFG] Bits */
|
||||
#define CS_IFG_PLLOOLIFG_OFS (12) /*!< PLLOOLIFG Bit Offset */
|
||||
#define CS_IFG_PLLOOLIFG ((uint32_t)0x00001000) /*!< PLL out-of-lock interrupt flag */
|
||||
/* CS_IFG[PLLLOSIFG] Bits */
|
||||
#define CS_IFG_PLLLOSIFG_OFS (13) /*!< PLLLOSIFG Bit Offset */
|
||||
#define CS_IFG_PLLLOSIFG ((uint32_t)0x00002000) /*!< PLL loss-of-signal interrupt flag */
|
||||
/* CS_IFG[PLLOORIFG] Bits */
|
||||
#define CS_IFG_PLLOORIFG_OFS (14) /*!< PLLOORIFG Bit Offset */
|
||||
#define CS_IFG_PLLOORIFG ((uint32_t)0x00004000) /*!< PLL out-of-range interrupt flag */
|
||||
/* CS_IFG[CALIFG] Bits */
|
||||
#define CS_IFG_CALIFG_OFS (15) /*!< CALIFG Bit Offset */
|
||||
#define CS_IFG_CALIFG ((uint32_t)0x00008000) /*!< REFCNT period counter expired */
|
||||
/* CS_CLRIFG[CLR_HFXT2IFG] Bits */
|
||||
#define CS_CLRIFG_CLR_HFXT2IFG_OFS ( 2) /*!< CLR_HFXT2IFG Bit Offset */
|
||||
#define CS_CLRIFG_CLR_HFXT2IFG ((uint32_t)0x00000004) /*!< Clear HFXT2 oscillator fault interrupt flag */
|
||||
/* CS_CLRIFG[CLR_CALIFG] Bits */
|
||||
#define CS_CLRIFG_CLR_CALIFG_OFS (15) /*!< CLR_CALIFG Bit Offset */
|
||||
#define CS_CLRIFG_CLR_CALIFG ((uint32_t)0x00008000) /*!< REFCNT period counter clear interrupt flag */
|
||||
/* CS_CLRIFG[CLR_FCNTHF2IFG] Bits */
|
||||
#define CS_CLRIFG_CLR_FCNTHF2IFG_OFS (10) /*!< CLR_FCNTHF2IFG Bit Offset */
|
||||
#define CS_CLRIFG_CLR_FCNTHF2IFG ((uint32_t)0x00000400) /*!< Start fault counter clear interrupt flag HFXT2 */
|
||||
/* CS_CLRIFG[CLR_PLLOOLIFG] Bits */
|
||||
#define CS_CLRIFG_CLR_PLLOOLIFG_OFS (12) /*!< CLR_PLLOOLIFG Bit Offset */
|
||||
#define CS_CLRIFG_CLR_PLLOOLIFG ((uint32_t)0x00001000) /*!< PLL out-of-lock clear interrupt flag */
|
||||
/* CS_CLRIFG[CLR_PLLLOSIFG] Bits */
|
||||
#define CS_CLRIFG_CLR_PLLLOSIFG_OFS (13) /*!< CLR_PLLLOSIFG Bit Offset */
|
||||
#define CS_CLRIFG_CLR_PLLLOSIFG ((uint32_t)0x00002000) /*!< PLL loss-of-signal clear interrupt flag */
|
||||
/* CS_CLRIFG[CLR_PLLOORIFG] Bits */
|
||||
#define CS_CLRIFG_CLR_PLLOORIFG_OFS (14) /*!< CLR_PLLOORIFG Bit Offset */
|
||||
#define CS_CLRIFG_CLR_PLLOORIFG ((uint32_t)0x00004000) /*!< PLL out-of-range clear interrupt flag */
|
||||
/* CS_SETIFG[SET_HFXT2IFG] Bits */
|
||||
#define CS_SETIFG_SET_HFXT2IFG_OFS ( 2) /*!< SET_HFXT2IFG Bit Offset */
|
||||
#define CS_SETIFG_SET_HFXT2IFG ((uint32_t)0x00000004) /*!< Set HFXT2 oscillator fault interrupt flag */
|
||||
/* CS_SETIFG[SET_CALIFG] Bits */
|
||||
#define CS_SETIFG_SET_CALIFG_OFS (15) /*!< SET_CALIFG Bit Offset */
|
||||
#define CS_SETIFG_SET_CALIFG ((uint32_t)0x00008000) /*!< REFCNT period counter set interrupt flag */
|
||||
/* CS_SETIFG[SET_FCNTHF2IFG] Bits */
|
||||
#define CS_SETIFG_SET_FCNTHF2IFG_OFS (10) /*!< SET_FCNTHF2IFG Bit Offset */
|
||||
#define CS_SETIFG_SET_FCNTHF2IFG ((uint32_t)0x00000400) /*!< Start fault counter set interrupt flag HFXT2 */
|
||||
/* CS_SETIFG[SET_PLLOOLIFG] Bits */
|
||||
#define CS_SETIFG_SET_PLLOOLIFG_OFS (12) /*!< SET_PLLOOLIFG Bit Offset */
|
||||
#define CS_SETIFG_SET_PLLOOLIFG ((uint32_t)0x00001000) /*!< PLL out-of-lock set interrupt flag */
|
||||
/* CS_SETIFG[SET_PLLLOSIFG] Bits */
|
||||
#define CS_SETIFG_SET_PLLLOSIFG_OFS (13) /*!< SET_PLLLOSIFG Bit Offset */
|
||||
#define CS_SETIFG_SET_PLLLOSIFG ((uint32_t)0x00002000) /*!< PLL loss-of-signal set interrupt flag */
|
||||
/* CS_SETIFG[SET_PLLOORIFG] Bits */
|
||||
#define CS_SETIFG_SET_PLLOORIFG_OFS (14) /*!< SET_PLLOORIFG Bit Offset */
|
||||
#define CS_SETIFG_SET_PLLOORIFG ((uint32_t)0x00004000) /*!< PLL out-of-range set interrupt flag */
|
||||
|
||||
/* EUSCI_x_CTLW0[SSEL] Bits */
|
||||
#define EUSCI_A_CTLW0_SSEL_0 ((uint16_t)0x0000) /*!< Reserved */
|
||||
#define EUSCI_B_CTLW0_SSEL_0 ((uint16_t)0x0000) /*!< Reserved */
|
||||
#define EUSCI_B_CTLW0_SSEL_3 ((uint16_t)0x00C0) /*!< SMCLK */
|
||||
|
||||
/* RSTCTL_PSSRESET_STAT[SVSL] Bits */
|
||||
#define RSTCTL_PSSRESET_STAT_SVSL_OFS ( 0) /*!< SVSL Bit Offset */
|
||||
#define RSTCTL_PSSRESET_STAT_SVSL ((uint32_t)0x00000001) /*!< Indicates if POR was caused by an SVSL trip condition in the PSS */
|
||||
|
||||
/* SYSCTL_SYSTEM_STAT[DBG_SEC_ACT] Bits */
|
||||
#define SYSCTL_SYSTEM_STAT_DBG_SEC_ACT_OFS ( 3) /*!< DBG_SEC_ACT Bit Offset */
|
||||
#define SYSCTL_SYSTEM_STAT_DBG_SEC_ACT ((uint32_t)0x00000008) /*!< Debug Security active */
|
||||
/* SYSCTL_SYSTEM_STAT[JTAG_SWD_LOCK_ACT] Bits */
|
||||
#define SYSCTL_SYSTEM_STAT_JTAG_SWD_LOCK_ACT_OFS ( 4) /*!< JTAG_SWD_LOCK_ACT Bit Offset */
|
||||
#define SYSCTL_SYSTEM_STAT_JTAG_SWD_LOCK_ACT ((uint32_t)0x00000010) /*!< Indicates if JTAG and SWD Lock is active */
|
||||
/* SYSCTL_SYSTEM_STAT[IP_PROT_ACT] Bits */
|
||||
#define SYSCTL_SYSTEM_STAT_IP_PROT_ACT_OFS ( 5) /*!< IP_PROT_ACT Bit Offset */
|
||||
#define SYSCTL_SYSTEM_STAT_IP_PROT_ACT ((uint32_t)0x00000020) /*!< Indicates if IP protection is active */
|
||||
|
|
@ -0,0 +1,338 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "system_msp432p401r.h"
|
||||
#include "msp.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/*******************************************/
|
||||
/* Macro Definitions depending on compiler */
|
||||
/*******************************************/
|
||||
#if defined(__CC_ARM)
|
||||
|
||||
#define WEAK_FUNC(FUN) \
|
||||
void FUN(void) __attribute__ ((weak));
|
||||
#define WEAK_ALIAS_FUNC(FUN, FUN_ALIAS) \
|
||||
void FUN(void) __attribute__ ((weak, alias(#FUN_ALIAS)));
|
||||
|
||||
#elif defined(__ICCARM__)
|
||||
|
||||
#pragma diag_suppress=Pe1665
|
||||
#define WEAK_FUNC(FUN) void FUN(void); \
|
||||
_Pragma(_STRINGIFY(_WEAK_FUNC(FUN)))
|
||||
#define _WEAK_FUNC(FUN) weak FUN
|
||||
#define WEAK_ALIAS_FUNC(FUN, FUN_ALIAS) void FUN(void); \
|
||||
_Pragma(_STRINGIFY(_WEAK_ALIAS_FUNC(FUN, FUN_ALIAS)))
|
||||
#define _WEAK_ALIAS_FUNC(FUN, FUN_ALIAS) weak __WEAK_ALIAS_FUNC(FUN, FUN_ALIAS)
|
||||
#define __WEAK_ALIAS_FUNC(FUN, FUN_ALIAS) FUN##=##FUN_ALIAS
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
#define WEAK_FUNC(FUN) \
|
||||
void FUN(void) __attribute__ ((weak));
|
||||
#define WEAK_ALIAS_FUNC(FUN, FUN_ALIAS) \
|
||||
void FUN(void) __attribute__ ((weak, alias(#FUN_ALIAS)));
|
||||
|
||||
#endif
|
||||
|
||||
/**********************************************************/
|
||||
/* External variables and functions depending on compiler */
|
||||
/**********************************************************/
|
||||
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||
// Entry point for the application.
|
||||
extern void __main(void);
|
||||
/* External symbols */
|
||||
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit;
|
||||
#elif defined(__ICCARM__)
|
||||
// Entry point for the application.
|
||||
extern void __iar_program_start(void);
|
||||
/* External symbols */
|
||||
extern uint32_t CSTACK$$Limit;
|
||||
#elif defined(__GNUC__)
|
||||
/* Entry point for the application. */
|
||||
extern int _start();
|
||||
/* External symbols */
|
||||
extern uint32_t __data_load__;
|
||||
extern uint32_t __data_start__;
|
||||
extern uint32_t __data_end__;
|
||||
extern uint32_t __StackTop;
|
||||
#endif
|
||||
|
||||
typedef void(*pFunc)(void);
|
||||
|
||||
// Forward declaration of the EUSCI dispatch handlers.
|
||||
static void EUSCIA0_IRQHandler(void);
|
||||
static void EUSCIA1_IRQHandler(void);
|
||||
static void EUSCIA2_IRQHandler(void);
|
||||
static void EUSCIA3_IRQHandler(void);
|
||||
static void EUSCIB0_IRQHandler(void);
|
||||
static void EUSCIB1_IRQHandler(void);
|
||||
static void EUSCIB2_IRQHandler(void);
|
||||
static void EUSCIB3_IRQHandler(void);
|
||||
|
||||
// Forward declaration of the default fault/reset handlers.
|
||||
WEAK_FUNC(Default_Handler)
|
||||
WEAK_FUNC(Reset_Handler)
|
||||
|
||||
// Cortex-M4 Processor Exceptions
|
||||
WEAK_ALIAS_FUNC(NMI_Handler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(HardFault_Handler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(MemManage_Handler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(BusFault_Handler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(UsageFault_Handler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(SVC_Handler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(DebugMon_Handler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(PendSV_Handler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(SysTick_Handler, Default_Handler)
|
||||
|
||||
// Device specific interrupt handler
|
||||
WEAK_ALIAS_FUNC(PSS_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(CS_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(PCM_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(WDT_A_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(FPU_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(FLCTL_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(COMP_E0_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(COMP_E1_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(TA0_0_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(TA0_N_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(TA1_0_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(TA1_N_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(TA2_0_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(TA2_N_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(TA3_0_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(TA3_N_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(ADC14_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(T32_INT1_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(T32_INT2_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(T32_INTC_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(AES256_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(RTC_C_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(DMA_ERR_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(DMA_INT3_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(DMA_INT2_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(DMA_INT1_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(DMA_INT0_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(PORT1_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(PORT2_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(PORT3_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(PORT4_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(PORT5_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(PORT6_IRQHandler, Default_Handler)
|
||||
|
||||
// EUSCI specific interrupt handlers
|
||||
WEAK_ALIAS_FUNC(EUSCIA0_UART_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIA1_UART_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIA2_UART_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIA3_UART_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIB0_I2C_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIB1_I2C_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIB2_I2C_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIB3_I2C_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIA0_SPI_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIA1_SPI_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIA2_SPI_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIA3_SPI_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIB0_SPI_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIB1_SPI_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIB2_SPI_IRQHandler, Default_Handler)
|
||||
WEAK_ALIAS_FUNC(EUSCIB3_SPI_IRQHandler, 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.
|
||||
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||
void (* const interruptVectors[])(void) __attribute__((section("RESET"))) = {
|
||||
(pFunc) &Image$$ARM_LIB_STACK$$ZI$$Limit, // The initial stack pointer
|
||||
#elif defined(__ICCARM__)
|
||||
void (* const __vector_table[])(void) @ ".intvec" = {
|
||||
(pFunc) &CSTACK$$Limit, // The initial stack pointer
|
||||
#elif defined(__GNUC__)
|
||||
void (* const interruptVectors[])(void) __attribute__((section(".isr_vector"))) = {
|
||||
(pFunc) &__StackTop, // The initial stack pointer
|
||||
#endif
|
||||
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
|
||||
};
|
||||
|
||||
// The reset irq handler
|
||||
void Reset_Handler(void)
|
||||
{
|
||||
// Halt the WDT already here, because the following copy process
|
||||
// from flash to SRAM might take so long that the WDT kicks in
|
||||
WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;
|
||||
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||
// Call system initialization routine
|
||||
SystemInit();
|
||||
// Jump to the main initialization routine.
|
||||
__main();
|
||||
#elif defined(__ICCARM__)
|
||||
// Call system initialization routine
|
||||
SystemInit();
|
||||
// Jump to the main initialization routine.
|
||||
__iar_program_start();
|
||||
#elif defined(__GNUC__)
|
||||
uint32_t *pui32Src, *pui32Dest;
|
||||
// Copy the data segment initializers from flash to SRAM.
|
||||
pui32Src = &__data_load__;
|
||||
for (pui32Dest = &__data_start__; pui32Dest < &__data_end__;) {
|
||||
*pui32Dest++ = *pui32Src++;
|
||||
}
|
||||
// Call system initialization routine
|
||||
SystemInit();
|
||||
// Jump to the main initialization routine.
|
||||
_start();
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// Enter an infinite loop.
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
// EUSCI interrupt dispatch handlers. These handlers will look at the current
|
||||
// EUSCI mode (SPI, UART, I2C), and forward the call to the specific handlers.
|
||||
void EUSCIA0_IRQHandler(void)
|
||||
{
|
||||
if (EUSCI_A0->CTLW0 & EUSCI_A_CTLW0_SYNC) {
|
||||
EUSCIA0_SPI_IRQHandler();
|
||||
} else {
|
||||
EUSCIA0_UART_IRQHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIA1_IRQHandler(void)
|
||||
{
|
||||
if (EUSCI_A1->CTLW0 & EUSCI_A_CTLW0_SYNC) {
|
||||
EUSCIA1_SPI_IRQHandler();
|
||||
} else {
|
||||
EUSCIA1_UART_IRQHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIA2_IRQHandler(void)
|
||||
{
|
||||
if (EUSCI_A2->CTLW0 & EUSCI_A_CTLW0_SYNC) {
|
||||
EUSCIA2_SPI_IRQHandler();
|
||||
} else {
|
||||
EUSCIA2_UART_IRQHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIA3_IRQHandler(void)
|
||||
{
|
||||
if (EUSCI_A3->CTLW0 & EUSCI_A_CTLW0_SYNC) {
|
||||
EUSCIA3_SPI_IRQHandler();
|
||||
} else {
|
||||
EUSCIA3_UART_IRQHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIB0_IRQHandler(void)
|
||||
{
|
||||
if ((EUSCI_B0->CTLW0 & EUSCI_A_CTLW0_MODE_MASK) == EUSCI_A_CTLW0_MODE_3) {
|
||||
EUSCIB0_I2C_IRQHandler();
|
||||
} else {
|
||||
EUSCIB0_SPI_IRQHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIB1_IRQHandler(void)
|
||||
{
|
||||
if ((EUSCI_B1->CTLW0 & EUSCI_A_CTLW0_MODE_MASK) == EUSCI_A_CTLW0_MODE_3) {
|
||||
EUSCIB1_I2C_IRQHandler();
|
||||
} else {
|
||||
EUSCIB1_SPI_IRQHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIB2_IRQHandler(void)
|
||||
{
|
||||
if ((EUSCI_B2->CTLW0 & EUSCI_A_CTLW0_MODE_MASK) == EUSCI_A_CTLW0_MODE_3) {
|
||||
EUSCIB2_I2C_IRQHandler();
|
||||
} else {
|
||||
EUSCIB2_SPI_IRQHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIB3_IRQHandler(void)
|
||||
{
|
||||
if ((EUSCI_B3->CTLW0 & EUSCI_A_CTLW0_MODE_MASK) == EUSCI_A_CTLW0_MODE_3) {
|
||||
EUSCIB3_I2C_IRQHandler();
|
||||
} else {
|
||||
EUSCIB3_SPI_IRQHandler();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,464 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
////////////////////////////////////
|
||||
// System startup code for MSP432 //
|
||||
////////////////////////////////////
|
||||
|
||||
#include <stdint.h>
|
||||
#include "msp.h"
|
||||
|
||||
// Internal clock frequencies, used for SystemCoreClockUpdate()
|
||||
#define __VLOCLK 9400
|
||||
#define __MODCLK 25000000
|
||||
#define __REFOCLK_L 32768
|
||||
#define __REFOCLK_H 128000
|
||||
#define __SYSCLK 5000000
|
||||
|
||||
// We currently do not support a DCO frequency of 1.5MHz, because the SMCLK
|
||||
// should be at least at 3MHz because of the uTicker, which needs 1MHz.
|
||||
// SMCLK is typically the half of MCLK. The longest PWM periods depend on
|
||||
// SMCLK: Timer A is only 16 bit and has a maximum pre-scaler of 64, so the
|
||||
// longest PWM period is:
|
||||
// With SMCLK = 3MHz, the maximum period is 1.39s.
|
||||
// With SMCLK = 24MHz, the maximum period is (only) 174.8ms
|
||||
|
||||
#define DCO_1500kHz 0
|
||||
#define DCO_3MHz 1
|
||||
#define DCO_6MHz 2
|
||||
#define DCO_12MHz 3
|
||||
#define DCO_24MHz 4
|
||||
#define DCO_48MHz 5
|
||||
|
||||
#define LFXT 0
|
||||
#define VLO 1
|
||||
#define REFO 2
|
||||
#define DCO 3
|
||||
#define MOD 4
|
||||
#define HFXT 5
|
||||
|
||||
#define DIV1 0
|
||||
#define DIV2 1
|
||||
#define DIV4 2
|
||||
#define DIV8 3
|
||||
#define DIV16 4
|
||||
#define DIV32 5
|
||||
#define DIV64 6
|
||||
#define DIV128 7
|
||||
|
||||
// Sanity check for HFXT and LFXT
|
||||
#if ((MBED_CONF_TARGET_MCLK_SELECT == HFXT) || (MBED_CONF_TARGET_SMCLK_SELECT == HFXT))
|
||||
#ifndef MBED_CONF_TARGET_HFXT_HZ
|
||||
#error No HFXT frequency specified (MBED_CONF_TARGET_HFXT_HZ)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ((MBED_CONF_TARGET_MCLK_SELECT == LFXT) || (MBED_CONF_TARGET_SMCLK_SELECT == LFXT))
|
||||
#ifndef MBED_CONF_TARGET_LFXT_HZ
|
||||
#error No LFXT frequency specified (MBED_CONF_TARGET_LFXT_HZ)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Calculate HFXTFREQ bits (for CSCTL2)
|
||||
#if (MBED_CONF_TARGET_HFXT_HZ > 40000000)
|
||||
#define HFXT_FREQ CS_CTL2_HFXTFREQ_6 | CS_CTL2_HFXTDRIVE
|
||||
#elif (MBED_CONF_TARGET_HFXT_HZ > 32000000)
|
||||
#define HFXT_FREQ CS_CTL2_HFXTFREQ_5 | CS_CTL2_HFXTDRIVE
|
||||
#elif (MBED_CONF_TARGET_HFXT_HZ > 2400000)
|
||||
#define HFXT_FREQ CS_CTL2_HFXTFREQ_4 | CS_CTL2_HFXTDRIVE
|
||||
#elif (MBED_CONF_TARGET_HFXT_HZ > 16000000)
|
||||
#define HFXT_FREQ CS_CTL2_HFXTFREQ_3 | CS_CTL2_HFXTDRIVE
|
||||
#elif (MBED_CONF_TARGET_HFXT_HZ > 8000000)
|
||||
#define HFXT_FREQ CS_CTL2_HFXTFREQ_2 | CS_CTL2_HFXTDRIVE
|
||||
#elif (MBED_CONF_TARGET_HFXT_HZ > 4000000)
|
||||
#define HFXT_FREQ CS_CTL2_HFXTFREQ_1 | CS_CTL2_HFXTDRIVE
|
||||
#else
|
||||
#define HFXT_FREQ CS_CTL2_HFXTFREQ_0
|
||||
#endif
|
||||
|
||||
#define MCLK_DIVIDER (1 << MBED_CONF_TARGET_MCLK_DIV)
|
||||
#define SMCLK_DIVIDER (1 << MBED_CONF_TARGET_SMCLK_DIV)
|
||||
|
||||
// Evaluate the MCLK setting
|
||||
#if (MBED_CONF_TARGET_MCLK_SELECT == LFXT)
|
||||
#define __MASTER_CLOCK (MBED_CONF_TARGET_LFXT_HZ / MCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == VLO)
|
||||
#define __MASTER_CLOCK (__VLOCLK / MCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == REFO)
|
||||
#define __MASTER_CLOCK (__REFOCLK_L / MCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == DCO)
|
||||
#define __MASTER_CLOCK ( (3000000 << (MBED_CONF_TARGET_DCO_RSEL-1)) / MCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == MOD)
|
||||
#define __MASTER_CLOCK (__MODCLK / MCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == HFXT)
|
||||
#define __MASTER_CLOCK (MBED_CONF_TARGET_HFXT_HZ / MCLK_DIVIDER)
|
||||
#else
|
||||
#error No MCLK source defined (MBED_CONF_TARGET_MCLK_SELECT)
|
||||
#endif
|
||||
|
||||
// Evaluate the SMCLK setting
|
||||
#if (MBED_CONF_TARGET_MCLK_SELECT == LFXT)
|
||||
#define __SUBSYS_CLOCK (MBED_CONF_TARGET_LFXT_HZ / SMCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == VLO)
|
||||
#define __SUBSYS_CLOCK (__VLOCLK / SMCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == REFO)
|
||||
#define __SUBSYS_CLOCK (__REFOCLK_L / SMCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == DCO)
|
||||
#define __SUBSYS_CLOCK ( (3000000 << (MBED_CONF_TARGET_DCO_RSEL-1)) / SMCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == MOD)
|
||||
#define __SUBSYS_CLOCK (__MODCLK / SMCLK_DIVIDER)
|
||||
#elif (MBED_CONF_TARGET_MCLK_SELECT == HFXT)
|
||||
#define __SUBSYS_CLOCK (MBED_CONF_TARGET_HFXT_HZ / SMCLK_DIVIDER)
|
||||
#else
|
||||
#error No SMCLK source defined (MBED_CONF_TARGET_SMCLK_SELECT)
|
||||
#endif
|
||||
|
||||
// global clock variables
|
||||
uint32_t SystemCoreClock = __MASTER_CLOCK; // the value of MCLK in Hz
|
||||
uint32_t SubsystemMasterClock = __SUBSYS_CLOCK; // the value of SMCLK in Hz
|
||||
|
||||
//
|
||||
// Initialize the system
|
||||
//
|
||||
// @param none
|
||||
// @return none
|
||||
//
|
||||
// @brief Setup the microcontroller system.
|
||||
//
|
||||
// Performs the following initialization steps:
|
||||
// 1. Enables the FPU
|
||||
// 2. Enables all SRAM banks
|
||||
// 3. Sets up power regulator and VCORE
|
||||
// 4. Enable Flash wait states if needed and read buffering
|
||||
// 5. Change MCLK/SMCLK to desired frequency
|
||||
//
|
||||
void SystemInit(void)
|
||||
{
|
||||
// Enable FPU (CP10 full access, CP11 full access)
|
||||
SCB->CPACR |= (SCB_CPACR_CP10_MASK | SCB_CPACR_CP11_MASK);
|
||||
// Enable all SRAM banks
|
||||
SYSCTL->SRAM_BANKEN = SYSCTL_SRAM_BANKEN_BNK7_EN;
|
||||
|
||||
// Unlock CS module
|
||||
CS->KEY = CS_KEY_VAL;
|
||||
|
||||
#if (__MASTER_CLOCK >= 48000000)
|
||||
// Switches to DCDC VCORE1
|
||||
while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY));
|
||||
PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR__AM_DCDC_VCORE1;
|
||||
while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY));
|
||||
// 1 flash wait states (BANK0 VCORE1 max is 16 MHz,
|
||||
// BANK1 VCORE1 max is 32 MHz)
|
||||
FLCTL->BANK0_RDCTL = FLCTL_BANK0_RDCTL_WAIT_1 | FLCTL_BANK0_RDCTL_BUFD
|
||||
| FLCTL_BANK0_RDCTL_BUFI;
|
||||
FLCTL->BANK1_RDCTL = FLCTL_BANK1_RDCTL_WAIT_1 | FLCTL_BANK1_RDCTL_BUFD
|
||||
| FLCTL_BANK1_RDCTL_BUFI;
|
||||
#elif (__MASTER_CLOCK >= 24000000)
|
||||
// Switches to DCDC VCORE0
|
||||
while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY));
|
||||
PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR__AM_DCDC_VCORE0;
|
||||
while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY));
|
||||
// Enable read buffering and 1 flash wait state (BANK0 VCORE0 max is 12 MHz)
|
||||
FLCTL->BANK0_RDCTL = FLCTL_BANK0_RDCTL_WAIT_1 | FLCTL_BANK0_RDCTL_BUFD
|
||||
| FLCTL_BANK0_RDCTL_BUFI;
|
||||
#endif
|
||||
|
||||
#if ((MBED_CONF_TARGET_MCLK_SELECT == HFXT) || (MBED_CONF_TARGET_SMCLK_SELECT == HFXT))
|
||||
// initialize PJ.2 and PJ.3 for HFXT
|
||||
PJ->SEL0 |= BIT3;
|
||||
PJ->SEL1 &= ~BIT3;
|
||||
CS->CTL2 |= CS_CTL2_HFXT_EN | HFXT_FREQ;
|
||||
// Wait for the HFXT to stabilize
|
||||
while (CS->IFG & CS_IFG_HFXTIFG) {
|
||||
CS->CLRIFG |= CS_CLRIFG_CLR_HFXTIFG;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set CTL0 and CTL1
|
||||
CS->CTL0 =(MBED_CONF_TARGET_DCO_RSEL << CS_CTL0_DCORSEL_OFS) |
|
||||
(MBED_CONF_TARGET_DCO_TUNE & 0x3ff);
|
||||
CS->CTL1 = MBED_CONF_TARGET_MCLK_SELECT << CS_CTL1_SELM_OFS |
|
||||
MBED_CONF_TARGET_MCLK_DIV << CS_CTL1_DIVM_OFS |
|
||||
MBED_CONF_TARGET_SMCLK_SELECT << CS_CTL1_SELS_OFS |
|
||||
MBED_CONF_TARGET_SMCLK_DIV << CS_CTL1_DIVS_OFS;
|
||||
|
||||
#ifdef MBED_CONF_TARGET_LFXT_HZ
|
||||
// Configure the 32768Hz source. If the LFXT is not
|
||||
// available, the system will switch automatically to
|
||||
// REFOCLK with 32768Hz mode (less precision...)
|
||||
|
||||
// initialize PJ.0 and PJ.1 for LFXT
|
||||
PJ->SEL0 |= BIT0;
|
||||
PJ->SEL1 &= ~BIT0;
|
||||
// Enable LFXT
|
||||
CS->CTL2 |= CS_CTL2_LFXT_EN; // Enable LFXT
|
||||
// Wait for the XTAL to stabilize
|
||||
while (CS->IFG & CS_IFG_LFXTIFG) {
|
||||
CS->CLRIFG |= CS_CLRIFG_CLR_LFXTIFG;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Lock CS module
|
||||
CS->KEY = 0;
|
||||
// Update the global clock values
|
||||
SystemCoreClockUpdate();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Update SystemCoreClock and SubsystemMasterClock variables
|
||||
//
|
||||
// @param none
|
||||
// @return none
|
||||
//
|
||||
// @brief Updates the SystemCoreClock with current core Clock
|
||||
// retrieved from cpu registers. Also SubsystemMasterClock
|
||||
// is updated, assuming that SMCLK has the same clock source
|
||||
// as MCLK.
|
||||
//
|
||||
void SystemCoreClockUpdate(void)
|
||||
{
|
||||
// Check which source is selected for MCLK
|
||||
switch (CS->CTL1 & CS_CTL1_SELM_MASK) {
|
||||
//////////////////////////
|
||||
case CS_CTL1_SELM__LFXTCLK: {
|
||||
//////////////////////////
|
||||
// Clear pending LFXT fault condition (irq flag)
|
||||
CS->KEY = CS_KEY_VAL;
|
||||
CS->CLRIFG |= CS_CLRIFG_CLR_LFXTIFG;
|
||||
CS->KEY = 0;
|
||||
// Check if we still have a LFXT fault
|
||||
if (BITBAND_PERI(CS->IFG, CS_IFG_LFXTIFG_OFS)) {
|
||||
// According to the TRM, a LFXT fault will
|
||||
// always switch to REFOCLK with 32768Hz
|
||||
SystemCoreClock = __REFOCLK_L;
|
||||
} else {
|
||||
#ifdef MBED_CONF_TARGET_LFXT_HZ
|
||||
SystemCoreClock = MBED_CONF_TARGET_LFXT_HZ;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
/////////////////////////
|
||||
case CS_CTL1_SELM__VLOCLK: {
|
||||
/////////////////////////
|
||||
SystemCoreClock = __VLOCLK;
|
||||
break;
|
||||
}
|
||||
//////////////////////////
|
||||
case CS_CTL1_SELM__REFOCLK: {
|
||||
//////////////////////////
|
||||
if (BITBAND_PERI(CS->CLKEN, CS_CLKEN_REFOFSEL_OFS)) {
|
||||
SystemCoreClock = __REFOCLK_H;
|
||||
} else {
|
||||
SystemCoreClock = __REFOCLK_L;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/////////////////////////
|
||||
case CS_CTL1_SELM__DCOCLK: {
|
||||
/////////////////////////
|
||||
// Set the center frequency
|
||||
SystemCoreClock = 1500000 << ((CS->CTL0 & CS_CTL0_DCORSEL_MASK)
|
||||
>> CS_CTL0_DCORSEL_OFS);
|
||||
// Get DCO tune value
|
||||
int16_t __DCOTUNE = (CS->CTL0 & CS_CTL0_DCOTUNE_MASK)
|
||||
>> CS_CTL0_DCOTUNE_OFS;
|
||||
// Check if we have a nonzero tune value
|
||||
if (__DCOTUNE) {
|
||||
// Convert 10 bits signed int to 16 bits signed int
|
||||
if (__DCOTUNE & 0x200) {
|
||||
__DCOTUNE |= 0xFC00;
|
||||
}
|
||||
// Get calibration data
|
||||
float __DCO_CONSTK;
|
||||
uint32_t __DCO_FCAL;
|
||||
if (CS->CTL0 & CS_CTL0_DCORES) {
|
||||
// external resistor
|
||||
if ((CS->CTL0 & CS_CTL0_DCORSEL_MASK) == CS_CTL0_DCORSEL_5) {
|
||||
// DCORSEL is 5
|
||||
__DCO_CONSTK = TLV->DCOER_CONSTK_RSEL5;
|
||||
__DCO_FCAL = TLV->DCOER_FCAL_RSEL5;
|
||||
} else {
|
||||
// DCORSEL is 0..4
|
||||
__DCO_CONSTK = TLV->DCOER_CONSTK_RSEL04;
|
||||
__DCO_FCAL = TLV->DCOER_FCAL_RSEL04;
|
||||
}
|
||||
} else {
|
||||
// internal resistor
|
||||
if ((CS->CTL0 & CS_CTL0_DCORSEL_MASK) == CS_CTL0_DCORSEL_5) {
|
||||
// DCORSEL is 5
|
||||
__DCO_CONSTK = TLV->DCOIR_CONSTK_RSEL5;
|
||||
__DCO_FCAL = TLV->DCOIR_FCAL_RSEL5;
|
||||
} else {
|
||||
// DCORSEL is 0..4
|
||||
__DCO_CONSTK = TLV->DCOIR_CONSTK_RSEL04;
|
||||
__DCO_FCAL = TLV->DCOIR_FCAL_RSEL04;
|
||||
}
|
||||
}
|
||||
// Calculate tuned frequency
|
||||
float denom = 1.0f / __DCO_CONSTK + 768 - (float)__DCO_FCAL;
|
||||
SystemCoreClock = (float)SystemCoreClock / (1.0f - (float)__DCOTUNE / denom);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/////////////////////////
|
||||
case CS_CTL1_SELM__MODOSC: {
|
||||
/////////////////////////
|
||||
SystemCoreClock = __MODCLK;
|
||||
break;
|
||||
}
|
||||
//////////////////////////
|
||||
case CS_CTL1_SELM__HFXTCLK: {
|
||||
//////////////////////////
|
||||
// Clear pending HFXT fault condition (irq flag)
|
||||
CS->KEY = CS_KEY_VAL;
|
||||
CS->CLRIFG |= CS_CLRIFG_CLR_HFXTIFG;
|
||||
CS->KEY = 0;
|
||||
// Check if we still have a HFXT fault
|
||||
if (BITBAND_PERI(CS->IFG, CS_IFG_HFXTIFG_OFS)) {
|
||||
// According to the TRM, a HFXT fault will
|
||||
// switch over to SYSOSC...
|
||||
SystemCoreClock = __SYSCLK;
|
||||
} else {
|
||||
#ifdef MBED_CONF_TARGET_HFXT_HZ
|
||||
SystemCoreClock = MBED_CONF_TARGET_HFXT_HZ;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Check which source is selected for SMCLK
|
||||
switch (CS->CTL1 & CS_CTL1_SELS_MASK) {
|
||||
//////////////////////////
|
||||
case CS_CTL1_SELS__LFXTCLK: {
|
||||
//////////////////////////
|
||||
// Clear pending LFXT fault condition (irq flag)
|
||||
CS->KEY = CS_KEY_VAL;
|
||||
CS->CLRIFG |= CS_CLRIFG_CLR_LFXTIFG;
|
||||
CS->KEY = 0;
|
||||
// Check if we still have a LFXT fault
|
||||
if (BITBAND_PERI(CS->IFG, CS_IFG_LFXTIFG_OFS)) {
|
||||
// According to the TRM, a LFXT fault will
|
||||
// always switch to REFOCLK with 32768Hz
|
||||
SubsystemMasterClock = __REFOCLK_L;
|
||||
} else {
|
||||
#ifdef MBED_CONF_TARGET_LFXT_HZ
|
||||
SubsystemMasterClock = MBED_CONF_TARGET_LFXT_HZ;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
/////////////////////////
|
||||
case CS_CTL1_SELS__VLOCLK: {
|
||||
/////////////////////////
|
||||
SubsystemMasterClock = __VLOCLK;
|
||||
break;
|
||||
}
|
||||
//////////////////////////
|
||||
case CS_CTL1_SELS__REFOCLK: {
|
||||
//////////////////////////
|
||||
if (BITBAND_PERI(CS->CLKEN, CS_CLKEN_REFOFSEL_OFS)) {
|
||||
SubsystemMasterClock = __REFOCLK_H;
|
||||
} else {
|
||||
SubsystemMasterClock = __REFOCLK_L;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/////////////////////////
|
||||
case CS_CTL1_SELS__DCOCLK: {
|
||||
/////////////////////////
|
||||
// Set the center frequency
|
||||
SubsystemMasterClock = 1500000 << ((CS->CTL0 & CS_CTL0_DCORSEL_MASK)
|
||||
>> CS_CTL0_DCORSEL_OFS);
|
||||
// Get DCO tune value
|
||||
int16_t __DCOTUNE = (CS->CTL0 & CS_CTL0_DCOTUNE_MASK)
|
||||
>> CS_CTL0_DCOTUNE_OFS;
|
||||
// Check if we have a nonzero tune value
|
||||
if (__DCOTUNE) {
|
||||
// Convert 10 bits signed int to 16 bits signed int
|
||||
if (__DCOTUNE & 0x200) {
|
||||
__DCOTUNE |= 0xFC00;
|
||||
}
|
||||
// Get calibration data
|
||||
float __DCO_CONSTK;
|
||||
uint32_t __DCO_FCAL;
|
||||
if (CS->CTL0 & CS_CTL0_DCORES) {
|
||||
// external resistor
|
||||
if ((CS->CTL0 & CS_CTL0_DCORSEL_MASK) == CS_CTL0_DCORSEL_5) {
|
||||
// DCORSEL is 5
|
||||
__DCO_CONSTK = TLV->DCOER_CONSTK_RSEL5;
|
||||
__DCO_FCAL = TLV->DCOER_FCAL_RSEL5;
|
||||
} else {
|
||||
// DCORSEL is 0..4
|
||||
__DCO_CONSTK = TLV->DCOER_CONSTK_RSEL04;
|
||||
__DCO_FCAL = TLV->DCOER_FCAL_RSEL04;
|
||||
}
|
||||
} else {
|
||||
// internal resistor
|
||||
if ((CS->CTL0 & CS_CTL0_DCORSEL_MASK) == CS_CTL0_DCORSEL_5) {
|
||||
// DCORSEL is 5
|
||||
__DCO_CONSTK = TLV->DCOIR_CONSTK_RSEL5;
|
||||
__DCO_FCAL = TLV->DCOIR_FCAL_RSEL5;
|
||||
} else {
|
||||
// DCORSEL is 0..4
|
||||
__DCO_CONSTK = TLV->DCOIR_CONSTK_RSEL04;
|
||||
__DCO_FCAL = TLV->DCOIR_FCAL_RSEL04;
|
||||
}
|
||||
}
|
||||
// Calculate tuned frequency
|
||||
float denom = 1.0f / __DCO_CONSTK + 768 - (float)__DCO_FCAL;
|
||||
SubsystemMasterClock = (float)SubsystemMasterClock / (1.0f - (float)__DCOTUNE / denom);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/////////////////////////
|
||||
case CS_CTL1_SELS__MODOSC: {
|
||||
/////////////////////////
|
||||
SubsystemMasterClock = __MODCLK;
|
||||
break;
|
||||
}
|
||||
//////////////////////////
|
||||
case CS_CTL1_SELS__HFXTCLK: {
|
||||
//////////////////////////
|
||||
// Clear pending HFXT fault condition (irq flag)
|
||||
CS->KEY = CS_KEY_VAL;
|
||||
CS->CLRIFG |= CS_CLRIFG_CLR_HFXTIFG;
|
||||
CS->KEY = 0;
|
||||
// Check if we still have a HFXT fault
|
||||
if (BITBAND_PERI(CS->IFG, CS_IFG_HFXTIFG_OFS)) {
|
||||
// According to the TRM, a HFXT fault will
|
||||
// switch over to SYSOSC...
|
||||
SubsystemMasterClock = __SYSCLK;
|
||||
} else {
|
||||
#ifdef MBED_CONF_TARGET_HFXT_HZ
|
||||
SubsystemMasterClock = MBED_CONF_TARGET_HFXT_HZ;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the MCLK and SMCLK dividers
|
||||
int32_t __DIVM = 1 << ((CS->CTL1 & CS_CTL1_DIVM_MASK) >> CS_CTL1_DIVM_OFS);
|
||||
int32_t __DIVS = 1 << ((CS->CTL1 & CS_CTL1_DIVS_MASK) >> CS_CTL1_DIVS_OFS);
|
||||
|
||||
// Update SystemCoreClock (MCLK) with divider value
|
||||
SystemCoreClock /= __DIVM;
|
||||
// Update SubsystemMasterClock (SMCLK) with divider value
|
||||
SubsystemMasterClock /= __DIVS;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_MSP432P401R_H
|
||||
#define SYSTEM_MSP432P401R_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// global clock variables
|
||||
extern uint32_t SystemCoreClock; // MCLK in Hz
|
||||
extern uint32_t SubsystemMasterClock; // SMCLK in Hz
|
||||
|
||||
// CMSIS standard methods for system init and master clock update
|
||||
extern void SystemInit(void);
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SYSTEM_MSP432P401R_H
|
|
@ -0,0 +1,152 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Low-level implementation of ADC functionality for MSP432. The ADC
|
||||
is very precise and has a resolution of 14 bits. In the default mode,
|
||||
a ADC conversion is triggered when read() or read_u16() is called.
|
||||
The program will then wait until the conversion result is available.
|
||||
|
||||
Alternatively, MBED_CONF_TARGET_ADC_AUTO_SCAN can be set, which will
|
||||
instruct the ADC to scan and convert all configured ADC channels
|
||||
automatically (so the ADC is active all the time). The two read-functions
|
||||
will then only read the result register, which will contain the latest
|
||||
available conversion result. In this case the program will not have to
|
||||
wait for the conversion result and the read-functions are faster!
|
||||
*/
|
||||
|
||||
#if DEVICE_ANALOGIN
|
||||
|
||||
#include "analogin_api.h"
|
||||
#include "mbed_assert.h"
|
||||
#include <stddef.h>
|
||||
|
||||
static uint8_t next_mem_index = 0;
|
||||
|
||||
/** Initialize the analogin peripheral
|
||||
*
|
||||
* Configures the pin used by analogin.
|
||||
* @param obj The analogin object to initialize
|
||||
* @param pin The analogin pin name
|
||||
*/
|
||||
void analogin_init(analogin_t *obj, PinName pin)
|
||||
{
|
||||
/* Check if pin supports ADC function */
|
||||
MBED_ASSERT(pinmap_peripheral(pin, PinMap_ADC) == ADC14_BASE);
|
||||
/* Check if we have used this pin already */
|
||||
uint8_t channel = GET_DATA_CHAN(pinmap_function(pin, PinMap_ADC));
|
||||
uint8_t index;
|
||||
for (index = 0; index < next_mem_index; ++index) {
|
||||
if ((ADC14->MCTL[index] & ADC14_MCTLN_INCH_MASK) == channel) {
|
||||
/* Pin was used before. Set mem register index and return */
|
||||
obj->mem_index = index;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Configure the GPIO pin */
|
||||
pinmap_pinout(pin, PinMap_ADC);
|
||||
/* Fill the obj structure */
|
||||
obj->mem_index = next_mem_index++;
|
||||
/* Reset ENC bit so the ADC can be configured */
|
||||
BITBAND_PERI(ADC14->CTL0, ADC14_CTL0_ENC_OFS) = 0;
|
||||
/* Set up result buffer */
|
||||
ADC14->MCTL[obj->mem_index] = channel;
|
||||
ADC14->MCTL[obj->mem_index] |= ADC14_MCTLN_VRSEL_0;
|
||||
#ifdef MBED_CONF_TARGET_ADC_AUTO_SCAN
|
||||
ADC14->MCTL[obj->mem_index] |= ADC14_MCTLN_EOS;
|
||||
// Clear the former End-Of-Sequence bit
|
||||
if (obj->mem_index) {
|
||||
ADC14->MCTL[obj->mem_index - 1] &= ~ADC14_MCTLN_EOS;
|
||||
}
|
||||
#endif
|
||||
/* Set up the control registers of ADC14 */
|
||||
ADC14->CTL1 = ADC14_CTL1_RES__14BIT | // 14 bit resolution
|
||||
ADC14_CTL1_PWRMD_0; // normal power mode
|
||||
ADC14->CTL0 = ADC14_CTL0_SSEL__MODCLK | // Use MODCLK (25MHz)
|
||||
ADC14_CTL0_PDIV__1 | // clock pre-divider is 1
|
||||
ADC14_CTL0_DIV__1 | // clock divider 1
|
||||
ADC14_CTL0_SHS_0 | // use ADCSC bit as sample/hold trigger
|
||||
ADC14_CTL0_SHP | // use sample/hold counter
|
||||
ADC14_CTL0_SHT1__16 | // 16 cycles for sample/hold
|
||||
ADC14_CTL0_SHT0__16 | // 16 cycles for sample/hold
|
||||
#ifdef MBED_CONF_TARGET_ADC_AUTO_SCAN
|
||||
ADC14_CTL0_CONSEQ_3 | // Repeat sequence of channels
|
||||
ADC14_CTL0_MSC | // Multiple samples and conversion
|
||||
ADC14_CTL0_ENC | // Enable conversion
|
||||
ADC14_CTL0_SC | // Start conversion
|
||||
#else
|
||||
ADC14_CTL0_CONSEQ_0 | // Single channel, single conversion
|
||||
#endif
|
||||
ADC14_CTL0_ON; // switch on ADC module
|
||||
/* Disable interrupts */
|
||||
ADC14->IER0 = 0;
|
||||
ADC14->IER1 = 0;
|
||||
}
|
||||
|
||||
/* Read a 14-bit ADC result from a single channel */
|
||||
uint16_t adc_read_raw(uint8_t mem_index)
|
||||
{
|
||||
#ifndef MBED_CONF_TARGET_ADC_AUTO_SCAN
|
||||
/* Reset ENC bit so the ADC can be configured */
|
||||
BITBAND_PERI(ADC14->CTL0, ADC14_CTL0_ENC_OFS) = 0;
|
||||
// set up start channel
|
||||
ADC14->CTL1 &= ~ADC14_CTL1_CSTARTADD_MASK;
|
||||
ADC14->CTL1 |= (mem_index << ADC14_CTL1_CSTARTADD_OFS);
|
||||
// start the conversion process
|
||||
ADC14->CTL0 |= ADC14_CTL0_SC | ADC14_CTL0_ENC;
|
||||
// wait until active conversion is done
|
||||
while (BITBAND_PERI(ADC14->CTL0, ADC14_CTL0_BUSY_OFS));
|
||||
#endif
|
||||
return ADC14->MEM[mem_index];
|
||||
}
|
||||
|
||||
/** Read the input voltage, represented as a float in the range [0.0, 1.0]
|
||||
*
|
||||
* @param obj The analogin object
|
||||
* @return A floating value representing the current input voltage
|
||||
*/
|
||||
float analogin_read(analogin_t *obj)
|
||||
{
|
||||
uint16_t value = adc_read_raw(obj->mem_index);
|
||||
return (float)value * (1.0f / (float)0x3FFF);
|
||||
}
|
||||
|
||||
/** Read the value from analogin pin, represented as an unsigned 16bit value
|
||||
*
|
||||
* @param obj The analogin object
|
||||
* @return An unsigned 16bit value representing the current input voltage
|
||||
*/
|
||||
uint16_t analogin_read_u16(analogin_t *obj)
|
||||
{
|
||||
uint16_t value = adc_read_raw(obj->mem_index);
|
||||
// 14-bit to 16-bit conversion
|
||||
value = (value << 2) | (value >> 12);
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Get the pins that support analogin
|
||||
*
|
||||
* Return a PinMap array of pins that support analogin. The
|
||||
* array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *analogin_pinmap(void)
|
||||
{
|
||||
return PinMap_ADC;
|
||||
}
|
||||
|
||||
#endif /* DEVICE_ANALOG_IN */
|
|
@ -0,0 +1,25 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Defines for compile-time optimization of us_ticker code.
|
||||
#define US_TICKER_PERIOD_NUM 1
|
||||
#define US_TICKER_PERIOD_DEN 1
|
||||
#define US_TICKER_MASK 0xffff
|
||||
|
||||
#include "objects.h"
|
||||
#include "PeripheralPins.h"
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_CMSIS_H
|
||||
#define MBED_CMSIS_H
|
||||
|
||||
#undef DIR_H
|
||||
|
||||
#include "msp.h"
|
||||
#include "cmsis_nvic.h"
|
||||
|
||||
#undef CS
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_CMSIS_NVIC_H
|
||||
#define MBED_CMSIS_NVIC_H
|
||||
|
||||
// CORE: 16 vectors
|
||||
// MCU Peripherals: 41 vectors
|
||||
// Total: 57 vectors = 228 bytes to be reserved in RAM
|
||||
|
||||
// For MSP432 we do not copy the IRQ vectors to save some bytes in RAM.
|
||||
// Remember to change the linker script if the below lines are uncommented!
|
||||
|
||||
//#define NVIC_NUM_VECTORS 57
|
||||
//#define NVIC_RAM_VECTOR_ADDRESS 0x20000000 // Copy irq vectors to start of RAM
|
||||
|
||||
#endif
|
|
@ -0,0 +1,83 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* MSP432 Family Generic Include File
|
||||
*
|
||||
* File creation date: 12/06/17
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __MSP432_H__
|
||||
#define __MSP432_H__
|
||||
|
||||
/******************************************************************************
|
||||
* MSP432 devices *
|
||||
******************************************************************************/
|
||||
#if defined (__MSP432P401R__)
|
||||
#include "msp432p401r.h"
|
||||
|
||||
#elif defined (__MSP432P401M__)
|
||||
#include "msp432p401m.h"
|
||||
|
||||
#elif defined (__MSP432P401Y__)
|
||||
#include "msp432p401y.h"
|
||||
|
||||
#elif defined (__MSP432P401V__)
|
||||
#include "msp432p401v.h"
|
||||
|
||||
#elif defined (__MSP432P411V__)
|
||||
#include "msp432p411v.h"
|
||||
|
||||
#elif defined (__MSP432P4011__)
|
||||
#include "msp432p4011.h"
|
||||
|
||||
#elif defined (__MSP432P4111__)
|
||||
#include "msp432p4111.h"
|
||||
|
||||
#elif defined (__MSP432P411Y__)
|
||||
#include "msp432p411y.h"
|
||||
|
||||
#elif defined (__MSP432E411Y__)
|
||||
#include "msp432e411y.h"
|
||||
|
||||
#elif defined (__MSP432E401Y__)
|
||||
#include "msp432e401y.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Failed to match a default include file *
|
||||
******************************************************************************/
|
||||
#else
|
||||
#error "Failed to match a default include file"
|
||||
#endif
|
||||
|
||||
#endif /* __MSP432_H__ */
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Low-level implementation of gpio functionality for MSP432.
|
||||
* This implementation uses bit-banding, so no masking of bits
|
||||
* is necessary during simple get/set operations for a single pin.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gpio_api.h"
|
||||
#include "mbed_assert.h"
|
||||
#include "gpio_msp432.h"
|
||||
|
||||
extern uint8_t open_drain[10];
|
||||
extern uint8_t open_source[10];
|
||||
extern uint8_t pull_up[10];
|
||||
extern uint8_t pull_down[10];
|
||||
|
||||
/* Helper macro to access single bits in the
|
||||
* bitmap arrays above
|
||||
*/
|
||||
#define FLAG_SET(array) (array[obj->port_index] & obj->mask)
|
||||
|
||||
/** Set the given pin as GPIO
|
||||
*
|
||||
* @param pin The pin to be set as GPIO
|
||||
* @return The GPIO port mask for this pin
|
||||
**/
|
||||
uint32_t gpio_set(PinName pin)
|
||||
{
|
||||
pin_function(pin, MSP432_PIN_DATA(SEL0, PIN_INPUT, PullNone, 0));
|
||||
return 1 << MSP432_PIN_IDX(pin);
|
||||
}
|
||||
|
||||
/* Checks if gpio object is connected (pin was not initialized with NC)
|
||||
* @param pin The pin to be set as GPIO
|
||||
* @return 0 if port is initialized with NC
|
||||
**/
|
||||
int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
return obj->pin_base != 0;
|
||||
}
|
||||
|
||||
/** Initialize the GPIO pin
|
||||
*
|
||||
* @param obj The GPIO object to initialize
|
||||
* @param pin The GPIO pin to initialize
|
||||
*/
|
||||
void gpio_init(gpio_t *obj, PinName pin)
|
||||
{
|
||||
if (pin == (PinName)NC) {
|
||||
obj->pin_base = 0;
|
||||
return;
|
||||
}
|
||||
uint8_t port_index = MSP432_PORT_IDX(pin);
|
||||
uint8_t pin_index = MSP432_PIN_IDX(pin);
|
||||
if (port_index > 9 || pin_index > 7) {
|
||||
obj->pin_base = 0;
|
||||
return;
|
||||
}
|
||||
/* Initialize the gpio_t object */
|
||||
obj->pin = pin;
|
||||
obj->mask = gpio_set(pin);
|
||||
obj->port_index = port_index;
|
||||
obj->pin_base = PIN_BASE(port_index, pin_index);
|
||||
|
||||
/* Initialize the gpio flags */
|
||||
open_drain[port_index] &= ~obj->mask;
|
||||
open_source[port_index] &= ~obj->mask;
|
||||
pull_up[port_index] &= ~obj->mask;
|
||||
pull_down[port_index] &= ~obj->mask;
|
||||
}
|
||||
|
||||
/** Set the input pin mode
|
||||
*
|
||||
* @param obj The GPIO object
|
||||
* @param mode The pin mode to be set
|
||||
*/
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
{
|
||||
pin_mode(obj->pin, mode);
|
||||
}
|
||||
|
||||
/** Set the pin direction
|
||||
*
|
||||
* @param obj The GPIO object
|
||||
* @param direction The pin direction to be set
|
||||
*/
|
||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||
{
|
||||
PIN_REG(obj->pin_base, REG_DIR) = direction;
|
||||
}
|
||||
|
||||
/** Set the output value
|
||||
*
|
||||
* @param obj The GPIO object
|
||||
* @param value The value to be set
|
||||
*/
|
||||
void gpio_write(gpio_t *obj, int value)
|
||||
{
|
||||
if (FLAG_SET(open_drain)) {
|
||||
if (FLAG_SET(pull_up)) {
|
||||
if (value) {
|
||||
PIN_REG(obj->pin_base, REG_DIR) = 0;
|
||||
PIN_REG(obj->pin_base, REG_OUT) = 1;
|
||||
} else {
|
||||
PIN_REG(obj->pin_base, REG_OUT) = 0;
|
||||
PIN_REG(obj->pin_base, REG_DIR) = 1;
|
||||
}
|
||||
} else {
|
||||
// Open drain without pullup
|
||||
PIN_REG(obj->pin_base, REG_DIR) = !value;
|
||||
}
|
||||
} else if (FLAG_SET(open_source)) {
|
||||
if (FLAG_SET(pull_down)) {
|
||||
if (value) {
|
||||
PIN_REG(obj->pin_base, REG_OUT) = 1;
|
||||
PIN_REG(obj->pin_base, REG_DIR) = 1;
|
||||
} else {
|
||||
PIN_REG(obj->pin_base, REG_DIR) = 0;
|
||||
PIN_REG(obj->pin_base, REG_OUT) = 0;
|
||||
}
|
||||
} else {
|
||||
// Open source without pull down
|
||||
PIN_REG(obj->pin_base, REG_DIR) = value;
|
||||
}
|
||||
} else {
|
||||
// Normal push/pull operation
|
||||
PIN_REG(obj->pin_base, REG_OUT) = value;
|
||||
}
|
||||
}
|
||||
|
||||
/** Read the input value
|
||||
*
|
||||
* @param obj The GPIO object
|
||||
* @return An integer value 1 or 0
|
||||
*/
|
||||
int gpio_read(gpio_t *obj)
|
||||
{
|
||||
return PIN_REG(obj->pin_base, REG_IN);
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Low-level implementation of gpio interrupts for MSP432.
|
||||
* This implementation uses bit-banding, so no masking of bits
|
||||
* is necessary during simple get/set operations for a single pin.
|
||||
*
|
||||
* See hal/gpio_api.h for a detailed description of the following
|
||||
* functions.
|
||||
*/
|
||||
#if DEVICE_INTERRUPTIN
|
||||
|
||||
#include "gpio_irq_api.h"
|
||||
#include "mbed_error.h"
|
||||
#include "gpio_msp432.h"
|
||||
|
||||
static uint32_t irq_ids [6][8] = {0};
|
||||
static uint8_t both_edges[6][8] = {0};
|
||||
|
||||
static gpio_irq_handler irq_handler = 0;
|
||||
|
||||
|
||||
/** Initialize the GPIO IRQ pin
|
||||
*
|
||||
* @param obj The GPIO object to initialize
|
||||
* @param pin The GPIO pin name
|
||||
* @param handler The handler to be attached to GPIO IRQ
|
||||
* @param id The object ID (id != 0, 0 is reserved)
|
||||
* @return -1 if pin is NC, 0 otherwise
|
||||
*/
|
||||
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
|
||||
{
|
||||
if (pin == (PinName)NC) {
|
||||
obj->pin_base = 0;
|
||||
return -1;
|
||||
}
|
||||
uint8_t port_index = MSP432_PORT_IDX(pin);
|
||||
uint8_t pin_index = MSP432_PIN_IDX(pin);
|
||||
if (port_index > 5 || pin_index > 7) {
|
||||
obj->pin_base = 0;
|
||||
error("IRQs not supported on GPIO P%d.%d\r\n", port_index + 1, pin_index);
|
||||
return -1;
|
||||
}
|
||||
// Initialize the gpio_t object
|
||||
obj->pin_base = PIN_BASE(port_index, pin_index);
|
||||
obj->port = port_index;
|
||||
obj->pin = pin_index;
|
||||
obj->rise = 0;
|
||||
obj->fall = 0;
|
||||
// Store irq handler. We do not have to store
|
||||
// a separate handler for every pin, because the
|
||||
// InterruptIn-driver will always use the same one...
|
||||
irq_handler = handler;
|
||||
// Store the ID for this specific pin. It will be
|
||||
// used as a pointer to one InterruptIn instance by
|
||||
// the InterruptIn class.
|
||||
irq_ids[port_index][pin_index] = id;
|
||||
// Clear pending IRQ
|
||||
PIN_REG(obj->pin_base, REG_IFG) = 0;
|
||||
// Enable IRQs on this port
|
||||
NVIC_EnableIRQ((IRQn_Type)(35 + port_index));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Release the GPIO IRQ PIN
|
||||
*
|
||||
* @param obj The gpio object
|
||||
*/
|
||||
void gpio_irq_free(gpio_irq_t *obj)
|
||||
{
|
||||
// Disable the interrupts
|
||||
gpio_irq_disable(obj);
|
||||
// Clear the ID
|
||||
irq_ids[obj->port][obj->pin] = 0;
|
||||
// Clear the gpio_irq_t object
|
||||
obj->pin_base = 0;
|
||||
obj->port = 0;
|
||||
obj->pin = 0;
|
||||
obj->rise = 0;
|
||||
obj->fall = 0;
|
||||
}
|
||||
|
||||
/** Enable/disable pin IRQ event
|
||||
*
|
||||
* @param obj The GPIO object
|
||||
* @param event The GPIO IRQ event
|
||||
* @param enable The enable flag
|
||||
*/
|
||||
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
||||
{
|
||||
// Disable irqs for this pin while we are in the
|
||||
// configuration process (so we have a chance to
|
||||
// clear spurious interrupts.
|
||||
PIN_REG(obj->pin_base, REG_IE) = 0;
|
||||
switch (event) {
|
||||
case IRQ_RISE: {
|
||||
// Listen to rising edges
|
||||
PIN_REG(obj->pin_base, REG_IES) = 0;
|
||||
obj->rise = enable;
|
||||
// Check if we have enabled both edges
|
||||
both_edges[obj->port][obj->pin] = obj->rise && obj->fall;
|
||||
break;
|
||||
}
|
||||
case IRQ_FALL: {
|
||||
// Listen to falling edges
|
||||
PIN_REG(obj->pin_base, REG_IES) = 1;
|
||||
obj->fall = enable;
|
||||
// Check if we have enabled both edges
|
||||
both_edges[obj->port][obj->pin] = obj->rise && obj->fall;
|
||||
break;
|
||||
}
|
||||
case IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Enable IRQ as requested
|
||||
enable ? gpio_irq_enable(obj) : gpio_irq_disable(obj);
|
||||
}
|
||||
|
||||
void gpio_irq_enable(gpio_irq_t *obj)
|
||||
{
|
||||
// Clear pending interrupts (just in case...)
|
||||
PIN_REG(obj->pin_base, REG_IFG) = 0;
|
||||
// Check if both edges need to be detected and
|
||||
// set initial edge select accordingly
|
||||
if (both_edges[obj->port][obj->pin]) {
|
||||
PIN_REG(obj->pin_base, REG_IES) = PIN_REG(obj->pin_base, REG_IN);
|
||||
// Make sure we don't accidently trigger a irq!
|
||||
PIN_REG(obj->pin_base, REG_IFG) = 0;
|
||||
}
|
||||
// Enable irqs for this pin
|
||||
PIN_REG(obj->pin_base, REG_IE) = 1;
|
||||
}
|
||||
|
||||
void gpio_irq_disable(gpio_irq_t *obj)
|
||||
{
|
||||
// Disable irqs for this pin
|
||||
PIN_REG(obj->pin_base, REG_IE) = 0;
|
||||
// Clear pending interrupts
|
||||
PIN_REG(obj->pin_base, REG_IFG) = 0;
|
||||
}
|
||||
|
||||
/**********************************/
|
||||
/* Interrupt handlers for P1...P6 */
|
||||
/**********************************/
|
||||
void handle_interrupt_in(uint8_t port, uint8_t pin)
|
||||
{
|
||||
__IO uint8_t *pin_base = PIN_BASE(port, pin);
|
||||
// Call the second-stage handler
|
||||
if (irq_handler) {
|
||||
irq_handler(irq_ids[port][pin],
|
||||
PIN_REG(pin_base, REG_IN) ? IRQ_RISE : IRQ_FALL);
|
||||
}
|
||||
// Change the edge select when listening on both edges
|
||||
if (both_edges[port][pin]) {
|
||||
PIN_REG(pin_base, REG_IES) = PIN_REG(pin_base, REG_IN);
|
||||
// Make sure we don't accidently trigger a irq!
|
||||
PIN_REG(pin_base, REG_IFG) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PORT1_IRQHandler(void)
|
||||
{
|
||||
uint32_t pin = P1->IV >> 1;
|
||||
if (pin--) {
|
||||
handle_interrupt_in(0, pin);
|
||||
}
|
||||
}
|
||||
void PORT2_IRQHandler(void)
|
||||
{
|
||||
uint32_t pin = P2->IV >> 1;
|
||||
if (pin--) {
|
||||
handle_interrupt_in(1, pin);
|
||||
}
|
||||
}
|
||||
void PORT3_IRQHandler(void)
|
||||
{
|
||||
uint32_t pin = P3->IV >> 1;
|
||||
if (pin--) {
|
||||
handle_interrupt_in(2, pin);
|
||||
}
|
||||
}
|
||||
void PORT4_IRQHandler(void)
|
||||
{
|
||||
uint32_t pin = P4->IV >> 1;
|
||||
if (pin--) {
|
||||
handle_interrupt_in(3, pin);
|
||||
}
|
||||
}
|
||||
void PORT5_IRQHandler(void)
|
||||
{
|
||||
uint32_t pin = P5->IV >> 1;
|
||||
if (pin--) {
|
||||
handle_interrupt_in(4, pin);
|
||||
}
|
||||
}
|
||||
void PORT6_IRQHandler(void)
|
||||
{
|
||||
uint32_t pin = P6->IV >> 1;
|
||||
if (pin--) {
|
||||
handle_interrupt_in(5, pin);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DEVICE_INTERRUPTIN */
|
|
@ -0,0 +1,33 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "cmsis.h"
|
||||
|
||||
// Bit-Band base addresses of the 10 GPIO ports
|
||||
__IO uint8_t *gpio_bitband_base[10] = {
|
||||
&BITBAND_PERI(P1->IN, 0), &BITBAND_PERI(P2->IN, 0),
|
||||
&BITBAND_PERI(P3->IN, 0), &BITBAND_PERI(P4->IN, 0),
|
||||
&BITBAND_PERI(P5->IN, 0), &BITBAND_PERI(P6->IN, 0),
|
||||
&BITBAND_PERI(P7->IN, 0), &BITBAND_PERI(P8->IN, 0),
|
||||
&BITBAND_PERI(P9->IN, 0), &BITBAND_PERI(P10->IN, 0)
|
||||
};
|
||||
|
||||
// Standard base addresses of the 10 ports
|
||||
__I uint8_t *port_base[10] = {
|
||||
&P1->IN, &P2->IN, &P3->IN, &P4->IN, &P5->IN,
|
||||
&P6->IN, &P7->IN, &P8->IN, &P9->IN, &P10->IN
|
||||
};
|
|
@ -0,0 +1,80 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains some bitband alias helper macros,
|
||||
* so that the source code is more readable.
|
||||
*/
|
||||
|
||||
#ifndef GPIO_MSP432_H
|
||||
#define GPIO_MSP432_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "cmsis.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// GPIO register offsets
|
||||
#define REG_IN 0x00
|
||||
#define REG_OUT 0x02
|
||||
#define REG_DIR 0x04
|
||||
#define REG_REN 0x06
|
||||
#define REG_SEL0 0x0a
|
||||
#define REG_SEL1 0x0c
|
||||
#define REG_IES 0x18
|
||||
#define REG_IE 0x1a
|
||||
#define REG_IFG 0x1c
|
||||
|
||||
/*
|
||||
* Bit-Band base addresses of the 10 GPIO ports
|
||||
*/
|
||||
extern __IO uint8_t *gpio_bitband_base[10];
|
||||
|
||||
/*
|
||||
* Port base addresses of the 10 GPIO ports
|
||||
*/
|
||||
extern __IO uint8_t *port_base[10];
|
||||
|
||||
/*
|
||||
* Macro to calculate the bitband base address of a single pin.
|
||||
* (within the IN-register, which has an offset of 0)
|
||||
* port range: 0..10, corresponding to P1...P10,PJ
|
||||
* pin range: 0..7 , corresponding to pin index
|
||||
*/
|
||||
#define PIN_BASE(port,pin) ((__IO uint8_t *) (gpio_bitband_base[port] + (pin<<2) ))
|
||||
|
||||
/*
|
||||
* Macro to calculate the adrdess of a pin within a given register.
|
||||
* base: pin base address
|
||||
* reg: offset to a specific register (REG_xxx)
|
||||
*/
|
||||
#define PIN_REG(base,reg) (*(base + (reg<<5)))
|
||||
|
||||
/*
|
||||
* Macro to calculate the adrdess of a port register.
|
||||
* base: port base address
|
||||
* reg: offset to a specific register (REG_xxx)
|
||||
*/
|
||||
#define PORT_REG(base,reg) (base + reg)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,616 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Low-level implementation of I2C functionality for MSP432 */
|
||||
|
||||
#if DEVICE_I2C
|
||||
|
||||
#include "i2c_api.h"
|
||||
#include "mbed_assert.h"
|
||||
|
||||
/* With I2C_ASYNCH, our type i2c_s is embedded
|
||||
* into a bigger structure (see i2c_api.h). So we
|
||||
* need a macro to extract the i2c_s object.
|
||||
*/
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
#define I2C_S(obj) (&((obj)->i2c))
|
||||
#else
|
||||
#define I2C_S(obj) (obj)
|
||||
#endif
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
// Array with object pointers for ISR
|
||||
i2c_t *i2c_objects[4] = {0};
|
||||
#endif
|
||||
|
||||
/** Initialize the I2C peripheral. It sets the default parameters for I2C
|
||||
* peripheral, and configures its specifieds pins.
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @param sda The sda pin
|
||||
* @param scl The scl pin
|
||||
*/
|
||||
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
|
||||
/* Check if the pins support I2C */
|
||||
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
|
||||
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
|
||||
objs->i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
|
||||
MBED_ASSERT(objs->i2c != (I2CName)NC);
|
||||
|
||||
/* Configure I2C pins */
|
||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
||||
pin_mode(sda, GET_DATA_MODE(pinmap_function(sda, PinMap_I2C_SDA)));
|
||||
pin_mode(scl, GET_DATA_MODE(pinmap_function(scl, PinMap_I2C_SCL)));
|
||||
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Put EUSCI to reset state */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_SWRST_OFS) = 1;
|
||||
/* Configure I2C mode */
|
||||
EUSCI->CTLW0 |= EUSCI_B_CTLW0_MST | /* master mode */
|
||||
EUSCI_B_CTLW0_MODE_3 | /* I2C mode */
|
||||
EUSCI_B_CTLW0_SSEL__SMCLK; /* SMCLK */
|
||||
EUSCI->CTLW1 = 0;
|
||||
/* Set i2c clock to default 100 kHz */
|
||||
i2c_frequency(obj, 100000);
|
||||
/* Disable and clear interrupts */
|
||||
EUSCI->IE = 0;
|
||||
EUSCI->IFG = 0;
|
||||
/* Clear the EUSCI reset state (enable module)*/
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_SWRST_OFS) = 0;
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
// Store the object pointer for the ISR
|
||||
int index = (((uint32_t)(objs->i2c)) >> 10) & 0x3;
|
||||
i2c_objects[index] = obj;
|
||||
objs->active = false;
|
||||
/* Enable the NVIC irq for this I2C module */
|
||||
NVIC_EnableIRQ((IRQn_Type)(EUSCIB0_IRQn + index));
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Configure the I2C frequency
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @param hz Frequency in Hz
|
||||
*/
|
||||
void i2c_frequency(i2c_t *obj, int hz)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Set I2C speed */
|
||||
EUSCI->BRW = SubsystemMasterClock / hz;
|
||||
}
|
||||
|
||||
/** Send START command
|
||||
* This method will also send the I2C address, along
|
||||
* with the R/W bit!
|
||||
*
|
||||
* @param obj The I2C object
|
||||
*/
|
||||
int i2c_start(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Trigger a START condition */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTT_OFS) = 1;
|
||||
/* Wait until START condition and device address has been sent */
|
||||
while (BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTT_OFS)) ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Send STOP command
|
||||
*
|
||||
* @param obj The I2C object
|
||||
*/
|
||||
int i2c_stop(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Trigger a STOP condition */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTP_OFS) = 1;
|
||||
/* Wait until STOP condition has been sent */
|
||||
while (BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTP_OFS)) ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Blocking reading data
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @param address 7-bit address (last bit is 1)
|
||||
* @param data The buffer for receiving
|
||||
* @param length Number of bytes to read
|
||||
* @param stop Stop to be generated after the transfer is done
|
||||
* @return Number of read bytes
|
||||
*/
|
||||
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
||||
{
|
||||
/* This I2C implementation does not support a missing STOP
|
||||
* condition after a master read operation. To send the final
|
||||
* NACK, we will always have to trigger a STOP condition! */
|
||||
MBED_ASSERT(stop);
|
||||
/* Get the I2C base */
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Clear interrupt status and set slave address */
|
||||
EUSCI->IFG = 0;
|
||||
EUSCI->I2CSA = address >> 1;
|
||||
/* Set receiver mode and send START condition */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TR_OFS) = 0;
|
||||
i2c_start(obj);
|
||||
int i;
|
||||
for (i = 0; i < length; ++i) {
|
||||
// Check if last byte to receive
|
||||
if (i + 1 == length) {
|
||||
// We have to trigger a STOP condition to
|
||||
// send the final NACK so the slave knows
|
||||
// we do not want any more data.
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTP_OFS) = 1;
|
||||
}
|
||||
// Wait until data is available
|
||||
while (!BITBAND_PERI(EUSCI->IFG, EUSCI_B_IFG_RXIFG0_OFS));
|
||||
// read the data
|
||||
data[i] = EUSCI->RXBUF;
|
||||
}
|
||||
if (!length) {
|
||||
i2c_stop(obj);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Blocking sending data
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @param address 7-bit address (last bit is 0)
|
||||
* @param data The buffer for sending
|
||||
* @param length Number of bytes to write
|
||||
* @param stop Stop to be generated after the transfer is done
|
||||
* @return
|
||||
* zero or non-zero - Number of written bytes
|
||||
* negative - I2C_ERROR_XXX status
|
||||
*/
|
||||
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
||||
{
|
||||
/* Get the I2C base */
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Clear interrupt status and set slave address */
|
||||
EUSCI->IFG = 0;
|
||||
EUSCI->I2CSA = address >> 1;
|
||||
/* Set transmitter mode and send START condition */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TR_OFS) = 1;
|
||||
i2c_start(obj);
|
||||
int i;
|
||||
for (i = 0; i < length; ++i) {
|
||||
// Fill transmit buffer
|
||||
EUSCI->TXBUF = data[i];
|
||||
// Wait until data is available or NACK
|
||||
while (!(EUSCI->IFG & (EUSCI_B_IFG_TXIFG0 | EUSCI_B_IFG_NACKIFG)));
|
||||
// Check NACK condition
|
||||
if (BITBAND_PERI(EUSCI->IFG, EUSCI_B_IFG_NACKIFG_OFS)) {
|
||||
// Generate STOP condition if requested
|
||||
if (stop) {
|
||||
i2c_stop(obj);
|
||||
}
|
||||
return i ? i - 1 : I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
}
|
||||
/* Generate STOP condition if requested */
|
||||
if (stop) {
|
||||
i2c_stop(obj);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Reset I2C peripheral. TODO: The action here. Most of the implementation sends stop()
|
||||
*
|
||||
* @param obj The I2C object
|
||||
*/
|
||||
void i2c_reset(i2c_t *obj)
|
||||
{
|
||||
i2c_stop(obj);
|
||||
}
|
||||
|
||||
/** Read one byte
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @param last Acknoledge
|
||||
* @return The read byte
|
||||
*/
|
||||
int i2c_byte_read(i2c_t *obj, int last)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Trigger STOP if we receive the last byte */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTP_OFS) = last;
|
||||
/* Wait until data is available */
|
||||
while (!BITBAND_PERI(EUSCI->IFG, EUSCI_B_IFG_RXIFG0_OFS));
|
||||
// Return byte
|
||||
return EUSCI->RXBUF;
|
||||
}
|
||||
|
||||
/** Write one byte
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @param data Byte to be written
|
||||
* @return 0 if NAK was received, 1 if ACK was received, 2 for timeout.
|
||||
*/
|
||||
int i2c_byte_write(i2c_t *obj, int data)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Place character in buffer */
|
||||
EUSCI->TXBUF = data;
|
||||
// Wait until byte has been sent or NACK
|
||||
while (!(EUSCI->IFG & (EUSCI_B_IFG_TXIFG0 | EUSCI_B_IFG_NACKIFG)));
|
||||
// return 1 if write was successfull
|
||||
return BITBAND_PERI(EUSCI->IFG, EUSCI_B_IFG_NACKIFG_OFS) ? 0 : 1;
|
||||
}
|
||||
|
||||
/** Get the pins that support I2C SDA
|
||||
*
|
||||
* Return a PinMap array of pins that support I2C SDA in
|
||||
* master mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *i2c_master_sda_pinmap(void)
|
||||
{
|
||||
return PinMap_I2C_SDA;
|
||||
}
|
||||
|
||||
/** Get the pins that support I2C SCL
|
||||
*
|
||||
* Return a PinMap array of pins that support I2C SCL in
|
||||
* master mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *i2c_master_scl_pinmap(void)
|
||||
{
|
||||
return PinMap_I2C_SCL;
|
||||
}
|
||||
|
||||
#if DEVICE_I2CSLAVE
|
||||
|
||||
/** Configure I2C as slave or master.
|
||||
* @param obj The I2C object
|
||||
* @param enable_slave Enable i2c hardware so you can receive events with ::i2c_slave_receive
|
||||
* @return non-zero if a value is available
|
||||
*/
|
||||
void i2c_slave_mode(i2c_t *obj, int enable_slave)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Set master/slave mode */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_MST_OFS) = !enable_slave;
|
||||
}
|
||||
|
||||
/** Check to see if the I2C slave has been addressed.
|
||||
* @param obj The I2C object
|
||||
* @return The status - 1 - read addresses, 2 - write to all slaves,
|
||||
* 3 write addressed, 0 - the slave has not been addressed
|
||||
*/
|
||||
int i2c_slave_receive(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Check irq flags */
|
||||
if (EUSCI->IFG & EUSCI_B_IFG_TXIFG0) {
|
||||
/* master wants to read, slave has to transmit */
|
||||
return 1;
|
||||
}
|
||||
if (EUSCI->IFG & EUSCI_B_IFG_RXIFG0) {
|
||||
/* master has written, slave has to receive */
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** I2C slave reads data from master.
|
||||
* @param obj The I2C object
|
||||
* @param data The buffer for receiving
|
||||
* @param length Number of bytes to read
|
||||
* @return non-zero if a value is available
|
||||
*/
|
||||
int i2c_slave_read(i2c_t *obj, char *data, int length)
|
||||
{
|
||||
/* Get the I2C base */
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
int i;
|
||||
for (i = 0; i < length; ++i) {
|
||||
// Wait until data is available
|
||||
while (!BITBAND_PERI(EUSCI->IFG, EUSCI_B_IFG_RXIFG0_OFS));
|
||||
// read the data
|
||||
data[i] = EUSCI->RXBUF;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/** I2C slave writes data to master.
|
||||
* @param obj The I2C object
|
||||
* @param data The buffer for sending
|
||||
* @param length Number of bytes to write
|
||||
* @return non-zero if a value is available
|
||||
*/
|
||||
int i2c_slave_write(i2c_t *obj, const char *data, int length)
|
||||
{
|
||||
/* Get the I2C base */
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
int i;
|
||||
for (i = 0; i < length; ++i) {
|
||||
// Wait until data may be sent
|
||||
while (!BITBAND_PERI(EUSCI->IFG, EUSCI_B_IFG_TXIFG0_OFS));
|
||||
// Fill transmit buffer
|
||||
EUSCI->TXBUF = data[i];
|
||||
}
|
||||
// Discard the next TXIFG, which is automatically triggered
|
||||
// after sending the last byte. Without doing this, the
|
||||
// receive()-method would detect a false slave-write!
|
||||
while (!BITBAND_PERI(EUSCI->IFG, EUSCI_B_IFG_TXIFG0_OFS));
|
||||
BITBAND_PERI(EUSCI->IFG, EUSCI_B_IFG_TXIFG0_OFS) = 0;
|
||||
return length;
|
||||
}
|
||||
|
||||
/** Configure I2C address.
|
||||
* @param obj The I2C object
|
||||
* @param idx Currently not used
|
||||
* @param address The address to be set
|
||||
* @param mask Currently not used
|
||||
*/
|
||||
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
/* Put EUSCI to reset state */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_SWRST_OFS) = 1;
|
||||
/* Set own address. The EUSCI in I2C mode could
|
||||
* also support multiple addresses (idx parameter)
|
||||
* and an address mask, but this is currently not
|
||||
* used by mbed-os drivers. */
|
||||
EUSCI->I2COA0 = (address >> 1) | EUSCI_B_I2COA0_OAEN;
|
||||
/* Clear EUSCI reset state) */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_SWRST_OFS) = 0;
|
||||
}
|
||||
|
||||
/** Get the pins that support I2C SDA as slave
|
||||
*
|
||||
* Return a PinMap array of pins that support I2C SDA in
|
||||
* slave mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *i2c_slave_sda_pinmap(void)
|
||||
{
|
||||
return PinMap_I2C_SDA;
|
||||
}
|
||||
|
||||
/** Get the pins that support I2C SCL as slave
|
||||
*
|
||||
* Return a PinMap array of pins that support I2C SCL in
|
||||
* slave mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *i2c_slave_scl_pinmap(void)
|
||||
{
|
||||
return PinMap_I2C_SCL;
|
||||
}
|
||||
|
||||
#endif /* DEVICE_I2CSLAVE */
|
||||
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
|
||||
/** Start I2C asynchronous transfer
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @param tx The transmit buffer
|
||||
* @param tx_length The number of bytes to transmit
|
||||
* @param rx The receive buffer
|
||||
* @param rx_length The number of bytes to receive
|
||||
* @param address The address to be set - 7bit or 9bit
|
||||
* @param stop If true, stop will be generated after the transfer is done
|
||||
* @param handler The I2C IRQ handler to be set
|
||||
* @param event Event mask for the transfer. See \ref hal_I2CEvents
|
||||
* @param hint DMA hint usage
|
||||
*/
|
||||
void i2c_transfer_asynch(i2c_t *obj,
|
||||
const void *tx, size_t tx_length,
|
||||
void *rx, size_t rx_length,
|
||||
uint32_t address, uint32_t stop,
|
||||
uint32_t handler, uint32_t event,
|
||||
DMAUsage hint)
|
||||
{
|
||||
// We ignore DMA for now
|
||||
(void) hint;
|
||||
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
/* Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
|
||||
// Update object
|
||||
obj->tx_buff.buffer = (void *)tx;
|
||||
obj->tx_buff.length = tx_length;
|
||||
obj->tx_buff.pos = 0;
|
||||
obj->tx_buff.width = 8;
|
||||
|
||||
obj->rx_buff.buffer = (void *)rx;
|
||||
obj->rx_buff.length = rx_length;
|
||||
obj->rx_buff.pos = 0;
|
||||
obj->rx_buff.width = 8;
|
||||
|
||||
objs->send_stop = stop;
|
||||
objs->handler = (void (*)(void))handler;
|
||||
objs->event = 0;
|
||||
objs->available_events = event;
|
||||
|
||||
/* Clear interrupt status and set slave address */
|
||||
EUSCI->IFG = 0;
|
||||
EUSCI->I2CSA = address >> 1;
|
||||
|
||||
// Start the ball rolling by either enabling TX or RX interrupts
|
||||
if (tx_length) {
|
||||
objs->active = true;
|
||||
/* Set transmitter mode and send START condition */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TR_OFS) = 1;
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTT_OFS) = 1;
|
||||
EUSCI->IE = EUSCI_B_IE_TXIE | EUSCI_B_IE_NACKIE;
|
||||
} else if (rx_length) {
|
||||
objs->active = true;
|
||||
/* Set receiver mode and send START condition */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TR_OFS) = 0;
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTT_OFS) = 1;
|
||||
EUSCI->IE = EUSCI_B_IE_RXIE;
|
||||
}
|
||||
}
|
||||
|
||||
/** The asynchronous IRQ handler
|
||||
*
|
||||
* @param obj The I2C object which holds the transfer information
|
||||
* @return Event flags if a transfer termination condition was met, otherwise return 0.
|
||||
*/
|
||||
uint32_t i2c_irq_handler_asynch(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
return (objs->event & objs->available_events);
|
||||
}
|
||||
|
||||
/** Attempts to determine if the I2C peripheral is already in use
|
||||
*
|
||||
* @param obj The I2C object
|
||||
* @return Non-zero if the I2C module is active or zero if it is not
|
||||
*/
|
||||
uint8_t i2c_active(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
return objs->active;
|
||||
}
|
||||
|
||||
/** Abort asynchronous transfer
|
||||
*
|
||||
* This function does not perform any check - that should happen in upper layers.
|
||||
* @param obj The I2C object
|
||||
*/
|
||||
void i2c_abort_asynch(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
// Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
EUSCI->IE = 0;
|
||||
EUSCI->IFG = 0;
|
||||
objs->active = false;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/* I2C interrupt handler */
|
||||
/*************************/
|
||||
void handle_I2C_Interrupt(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *objs = I2C_S(obj);
|
||||
// Get the I2C base */
|
||||
EUSCI_B_Type *EUSCI = (EUSCI_B_Type *)objs->i2c;
|
||||
uint16_t vector = EUSCI->IV;
|
||||
switch (vector) {
|
||||
/* UCNACKIFG */
|
||||
case 0x04: {
|
||||
objs->event = I2C_EVENT_TRANSFER_EARLY_NACK;
|
||||
objs->handler();
|
||||
break;
|
||||
}
|
||||
/* UCRXIFG0 */
|
||||
case 0x16: {
|
||||
struct buffer_s *rx_buff = &obj->rx_buff;
|
||||
if (rx_buff->pos < rx_buff->length) {
|
||||
((uint8_t *)rx_buff->buffer)[rx_buff->pos] = EUSCI->RXBUF;
|
||||
rx_buff->pos++;
|
||||
}
|
||||
if (rx_buff->pos + 1 == rx_buff->length) {
|
||||
EUSCI->CTLW0 |= EUSCI_B_CTLW0_TXSTP;
|
||||
}
|
||||
if (rx_buff->pos == rx_buff->length) {
|
||||
BITBAND_PERI(EUSCI->IE, EUSCI_B_IE_TXIE_OFS) = 0;
|
||||
objs->active = false;
|
||||
objs->event = I2C_EVENT_TRANSFER_COMPLETE;
|
||||
objs->handler();
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* UCTXIFG0 */
|
||||
case 0x18: {
|
||||
struct buffer_s *tx_buff = &obj->tx_buff;
|
||||
if (tx_buff->pos < tx_buff->length) {
|
||||
EUSCI->TXBUF = ((uint8_t *)tx_buff->buffer)[tx_buff->pos];
|
||||
tx_buff->pos++;
|
||||
} else {
|
||||
if (objs->send_stop) {
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTP_OFS) = 1;
|
||||
}
|
||||
// Disable interrupts
|
||||
EUSCI->IE = 0;
|
||||
// Check if we have to receive data
|
||||
if (obj->rx_buff.length) {
|
||||
/* Set transmitter mode and send START condition */
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TR_OFS) = 0;
|
||||
BITBAND_PERI(EUSCI->CTLW0, EUSCI_B_CTLW0_TXSTT_OFS) = 1;
|
||||
// Enable the RX interrupts
|
||||
EUSCI->IE = EUSCI_B_IE_RXIE;
|
||||
} else {
|
||||
objs->active = false;
|
||||
objs->event = I2C_EVENT_TRANSFER_COMPLETE;
|
||||
objs->handler();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIB0_I2C_IRQHandler(void)
|
||||
{
|
||||
handle_I2C_Interrupt(i2c_objects[0]);
|
||||
}
|
||||
void EUSCIB1_I2C_IRQHandler(void)
|
||||
{
|
||||
handle_I2C_Interrupt(i2c_objects[1]);
|
||||
}
|
||||
void EUSCIB2_I2C_IRQHandler(void)
|
||||
{
|
||||
handle_I2C_Interrupt(i2c_objects[2]);
|
||||
}
|
||||
void EUSCIB3_I2C_IRQHandler(void)
|
||||
{
|
||||
handle_I2C_Interrupt(i2c_objects[3]);
|
||||
}
|
||||
|
||||
#endif // DEVICE_I2C_ASYNCH
|
||||
|
||||
#endif // DEVICE_I2C
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_OBJECTS_H
|
||||
#define MBED_OBJECTS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "cmsis.h"
|
||||
#include "PortNames.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "PinNames.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
uint8_t mask;
|
||||
uint8_t port_index;
|
||||
__IO uint8_t *pin_base;
|
||||
} gpio_t;
|
||||
|
||||
struct gpio_irq_s {
|
||||
uint8_t pin;
|
||||
uint8_t port;
|
||||
bool rise;
|
||||
bool fall;
|
||||
__IO uint8_t *pin_base;
|
||||
};
|
||||
|
||||
struct port_s {
|
||||
PortName port;
|
||||
uint8_t mask;
|
||||
__IO uint8_t *port_in;
|
||||
__IO uint8_t *port_out;
|
||||
__IO uint8_t *port_dir;
|
||||
};
|
||||
|
||||
struct serial_s {
|
||||
UARTName uart;
|
||||
PinName pin_tx;
|
||||
PinName pin_rx;
|
||||
};
|
||||
|
||||
struct analogin_s {
|
||||
uint8_t mem_index;
|
||||
};
|
||||
|
||||
struct i2c_s {
|
||||
I2CName i2c;
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
bool active;
|
||||
bool send_stop;
|
||||
void (*handler)();
|
||||
uint8_t event;
|
||||
uint8_t available_events;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct spi_s {
|
||||
SPIName spi;
|
||||
uint8_t module;
|
||||
PinName pin_miso;
|
||||
PinName pin_mosi;
|
||||
PinName pin_sclk;
|
||||
PinName pin_ssel;
|
||||
// Addresses of needed HW-registers
|
||||
__IO uint16_t *EUSCI_CTLW0;
|
||||
__IO uint16_t *EUSCI_BRW;
|
||||
__IO uint16_t *EUSCI_STATW;
|
||||
__I uint16_t *EUSCI_RXBUF;
|
||||
__IO uint16_t *EUSCI_TXBUF;
|
||||
__IO uint16_t *EUSCI_IE;
|
||||
__IO uint16_t *EUSCI_IFG;
|
||||
__I uint16_t *EUSCI_IV;
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
bool active;
|
||||
void (*handler)();
|
||||
uint8_t event;
|
||||
uint8_t available_events;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct pwmout_s {
|
||||
PWMName pwm;
|
||||
PinName pin;
|
||||
uint8_t ccr_index;
|
||||
uint32_t divider;
|
||||
uint32_t pulse;
|
||||
uint32_t ccr0;
|
||||
float dutyCycle;
|
||||
};
|
||||
|
||||
struct flash_s {
|
||||
/* nothing to be stored for now */
|
||||
uint32_t dummy;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,116 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "pinmap.h"
|
||||
#include "mbed_assert.h"
|
||||
#include "PeripheralPins.h"
|
||||
#include "gpio_msp432.h"
|
||||
|
||||
/*
|
||||
* Bitmask arrays for gpio mode configuration
|
||||
*/
|
||||
uint8_t open_drain[10] = {0};
|
||||
uint8_t open_source[10] = {0};
|
||||
uint8_t pull_up[10] = {0};
|
||||
uint8_t pull_down[10] = {0};
|
||||
|
||||
/*
|
||||
* Configure pin (SEL function and direction)
|
||||
*/
|
||||
void pin_function(PinName pin, int data)
|
||||
{
|
||||
MBED_ASSERT(pin != (PinName)NC);
|
||||
uint8_t port_index = MSP432_PORT_IDX(pin);
|
||||
uint8_t pin_index = MSP432_PIN_IDX(pin);
|
||||
MBED_ASSERT(port_index < 10 && pin_index < 8);
|
||||
|
||||
__IO uint8_t *pin_base = PIN_BASE(port_index, pin_index);
|
||||
|
||||
// Set the SEL bits
|
||||
uint8_t sel = GET_DATA_SEL(data);
|
||||
PIN_REG(pin_base, REG_SEL0) = sel & 1;
|
||||
PIN_REG(pin_base, REG_SEL1) = sel >> 1;
|
||||
|
||||
// Set gpio direction
|
||||
PIN_REG(pin_base, REG_DIR) = GET_DATA_DIR(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pin pull-up/pull-down
|
||||
*/
|
||||
void pin_mode(PinName pin, PinMode mode)
|
||||
{
|
||||
MBED_ASSERT(pin != (PinName)NC);
|
||||
uint8_t port_index = MSP432_PORT_IDX(pin);
|
||||
uint8_t pin_index = MSP432_PIN_IDX(pin);
|
||||
MBED_ASSERT(port_index < 10 && pin_index < 8);
|
||||
|
||||
__IO uint8_t *pin_base = PIN_BASE(port_index, pin_index);
|
||||
|
||||
uint8_t mask = 1 << pin_index;
|
||||
|
||||
// Set mode to default state
|
||||
open_drain[port_index] &= ~mask;
|
||||
open_source[port_index] &= ~mask;
|
||||
pull_up[port_index] &= ~mask;
|
||||
pull_down[port_index] &= ~mask;
|
||||
PIN_REG(pin_base, REG_REN) = 0;
|
||||
|
||||
switch (mode) {
|
||||
case PullNone: {
|
||||
break;
|
||||
}
|
||||
case PullUp: {
|
||||
pull_up[port_index] |= mask;
|
||||
PIN_REG(pin_base, REG_REN) = 1;
|
||||
PIN_REG(pin_base, REG_OUT) = 1;
|
||||
break;
|
||||
}
|
||||
case PullDown: {
|
||||
pull_down[port_index] |= mask;
|
||||
PIN_REG(pin_base, REG_REN) = 1;
|
||||
PIN_REG(pin_base, REG_OUT) = 0;
|
||||
break;
|
||||
}
|
||||
case OpenDrain: {
|
||||
PIN_REG(pin_base, REG_DIR) = !PIN_REG(pin_base, REG_OUT);
|
||||
open_drain[port_index] |= mask;
|
||||
break;
|
||||
}
|
||||
case OpenDrainPullUp: {
|
||||
open_drain[port_index] |= mask;
|
||||
pull_up[port_index] |= mask;
|
||||
PIN_REG(pin_base, REG_REN) = 1;
|
||||
PIN_REG(pin_base, REG_DIR) = !PIN_REG(pin_base, REG_OUT);
|
||||
break;
|
||||
}
|
||||
case OpenSource: {
|
||||
open_source[port_index] |= mask;
|
||||
PIN_REG(pin_base, REG_DIR) = PIN_REG(pin_base, REG_OUT);
|
||||
break;
|
||||
}
|
||||
case OpenSourcePullDown: {
|
||||
open_source[port_index] |= mask;
|
||||
pull_down[port_index] |= mask;
|
||||
PIN_REG(pin_base, REG_REN) = 1;
|
||||
PIN_REG(pin_base, REG_DIR) = PIN_REG(pin_base, REG_OUT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "port_api.h"
|
||||
#include "gpio_msp432.h"
|
||||
|
||||
#if DEVICE_PORTIN || DEVICE_PORTOUT
|
||||
|
||||
/** Get the pin name from the port's pin number
|
||||
*
|
||||
* @param port The port name
|
||||
* @param pin_n The pin number within the specified port
|
||||
* @return The pin name for the port's pin number
|
||||
*/
|
||||
PinName port_pin(PortName port, int pin_n)
|
||||
{
|
||||
return (PinName)((port << 4) + pin_n);
|
||||
}
|
||||
|
||||
/** Initilize the port
|
||||
*
|
||||
* @param obj The port object to initialize
|
||||
* @param port The port name
|
||||
* @param mask The bitmask to identify which bits in the port should be included (0 - ignore)
|
||||
* @param dir The port direction
|
||||
*/
|
||||
void port_init(port_t *obj, PortName port, int mask, PinDirection dir)
|
||||
{
|
||||
/* Initialize the port object */
|
||||
obj->port = port;
|
||||
obj->mask = mask;
|
||||
obj->port_in = PORT_REG(port_base[port], REG_IN);
|
||||
obj->port_out = PORT_REG(port_base[port], REG_OUT);
|
||||
obj->port_dir = PORT_REG(port_base[port], REG_DIR);
|
||||
port_dir(obj, dir);
|
||||
}
|
||||
|
||||
/** Set the input port mode
|
||||
*
|
||||
* @param obj The port object
|
||||
* @param mode THe port mode to be set
|
||||
*/
|
||||
void port_mode(port_t *obj, PinMode mode)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
/* Is pin used ? */
|
||||
if (obj->mask & (1 << i)) {
|
||||
pin_mode(port_pin(obj->port, i), mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Set port direction (in/out)
|
||||
*
|
||||
* @param obj The port object
|
||||
* @param dir The port direction to be set
|
||||
*/
|
||||
void port_dir(port_t *obj, PinDirection dir)
|
||||
{
|
||||
if (dir == PIN_OUTPUT) {
|
||||
*obj->port_dir |= (obj->mask);
|
||||
} else {
|
||||
*obj->port_dir &= ~(obj->mask);
|
||||
}
|
||||
}
|
||||
|
||||
/** Write value to the port
|
||||
*
|
||||
* @param obj The port object
|
||||
* @param value The value to be set
|
||||
*/
|
||||
void port_write(port_t *obj, int value)
|
||||
{
|
||||
*obj->port_out = (*obj->port_out & ~obj->mask) | (value & obj->mask);
|
||||
}
|
||||
|
||||
/** Read the current value on the port
|
||||
*
|
||||
* @param obj The port object
|
||||
* @return An integer with each bit corresponding to an associated port pin setting
|
||||
*/
|
||||
int port_read(port_t *obj)
|
||||
{
|
||||
return *obj->port_in & obj->mask;
|
||||
}
|
||||
|
||||
#endif /* DEVICE_PORTIN || DEVICE_PORTOUT */
|
|
@ -0,0 +1,213 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Low-level implementation of PWM functionality for MSP432.
|
||||
Only TIMER A0..A2 are used for PWM, because TIMER A3 is
|
||||
already used for the us ticker. SMCLK is typically 3 MHz,
|
||||
and the maximum pre-divider is 64. With TIMER A being a
|
||||
16 bit counter, we have a maximum period of
|
||||
64 * 65536 / 3000000 = 1.39 seconds!
|
||||
In total there are 12 PWM outputs. Each 4 outputs
|
||||
from one Timer-A module (A0..A2) shared the same period!
|
||||
*/
|
||||
|
||||
#include "pwmout_api.h"
|
||||
#include "mbed_assert.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#if DEVICE_PWMOUT
|
||||
|
||||
/** Initialize the pwm out peripheral and configure the pin
|
||||
*
|
||||
* @param obj The pwmout object to initialize
|
||||
* @param pin The pwmout pin to initialize
|
||||
*/
|
||||
void pwmout_init(pwmout_t *obj, PinName pin)
|
||||
{
|
||||
/* Get the peripheral name */
|
||||
obj->pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
|
||||
MBED_ASSERT(obj->pwm != (PWMName)NC);
|
||||
/* Fill obj (get the index of the Capture/Compare Register (CCR)) */
|
||||
obj->pin = pin;
|
||||
obj->ccr_index = GET_DATA_CHAN(pinmap_function(pin, PinMap_PWM));
|
||||
obj->pulse = 0;
|
||||
obj->dutyCycle = 0.0f;
|
||||
/* Configure PWM pin */
|
||||
pinmap_pinout(pin, PinMap_PWM);
|
||||
/* Get the TIMER A base */
|
||||
Timer_A_Type *TA = (Timer_A_Type *)obj->pwm;
|
||||
/* Configure the TIMER A and the CCR */
|
||||
TA->CTL = TIMER_A_CTL_SSEL__SMCLK | /* SMCLK clock source */
|
||||
TIMER_A_CTL_MC__UP | /* Up-mode (count to CCR0) */
|
||||
TIMER_A_CTL_CLR; /* Reset counter */
|
||||
/* Use reset/set mode (mode 7) */
|
||||
TA->CCTL[obj->ccr_index] = TIMER_A_CCTLN_OUTMOD_7;
|
||||
// Set default period (20ms)
|
||||
pwmout_period_us(obj, 20000);
|
||||
}
|
||||
|
||||
/** Deinitialize the pwmout object
|
||||
*
|
||||
* @param obj The pwmout object
|
||||
*/
|
||||
void pwmout_free(pwmout_t *obj)
|
||||
{
|
||||
/* Get the TIMER A base */
|
||||
Timer_A_Type *TA = (Timer_A_Type *)obj->pwm;
|
||||
/* Stop the timer */
|
||||
TA->CTL = 0;
|
||||
/* De-configure the pin */
|
||||
pin_function(obj->pin, MSP432_PIN_DATA(SEL0, PIN_INPUT, PullNone, 0));
|
||||
}
|
||||
|
||||
/** Set the output duty-cycle in range <0.0f, 1.0f>
|
||||
*
|
||||
* Value 0.0f represents 0 percentage, 1.0f represents 100 percent.
|
||||
* @param obj The pwmout object
|
||||
* @param percent The floating-point percentage number
|
||||
*/
|
||||
void pwmout_write(pwmout_t *obj, float percent)
|
||||
{
|
||||
obj->dutyCycle = percent;
|
||||
obj->pulse = (float)obj->ccr0 * percent;
|
||||
/* Get the TIMER A base */
|
||||
Timer_A_Type *TA = (Timer_A_Type *)obj->pwm;
|
||||
// Set the CCR register
|
||||
TA->CCR[obj->ccr_index] = obj->pulse;
|
||||
}
|
||||
|
||||
/** Read the current float-point output duty-cycle
|
||||
*
|
||||
* @param obj The pwmout object
|
||||
* @return A floating-point output duty-cycle
|
||||
*/
|
||||
float pwmout_read(pwmout_t *obj)
|
||||
{
|
||||
return obj->dutyCycle;
|
||||
}
|
||||
|
||||
/** Set the PWM period specified in seconds, keeping the duty cycle the same
|
||||
*
|
||||
* Periods smaller than microseconds (the lowest resolution) are set to zero.
|
||||
* @param obj The pwmout object
|
||||
* @param seconds The floating-point seconds period
|
||||
*/
|
||||
void pwmout_period(pwmout_t *obj, float seconds)
|
||||
{
|
||||
pwmout_period_us(obj, seconds * 1000000.0f);
|
||||
}
|
||||
|
||||
/** Set the PWM period specified in miliseconds, keeping the duty cycle the same
|
||||
*
|
||||
* @param obj The pwmout object
|
||||
* @param ms The milisecond period
|
||||
*/
|
||||
void pwmout_period_ms(pwmout_t *obj, int ms)
|
||||
{
|
||||
pwmout_period_us(obj, ms * 1000);
|
||||
}
|
||||
|
||||
/** Set the PWM period specified in microseconds, keeping the duty cycle the same
|
||||
*
|
||||
* @param obj The pwmout object
|
||||
* @param us The microsecond period
|
||||
*/
|
||||
void pwmout_period_us(pwmout_t *obj, int us)
|
||||
{
|
||||
/* Calculate dividers and CCR0 */
|
||||
uint32_t clock_MHz = SubsystemMasterClock / 1000000;
|
||||
clock_MHz *= us;
|
||||
uint16_t id, ex0;
|
||||
bool found = false;
|
||||
for (id = 0; id < 4; id++) {
|
||||
for (ex0 = 0; ex0 < 8; ex0++) {
|
||||
obj->divider = (1 << id) * (ex0 + 1);
|
||||
obj->ccr0 = clock_MHz / obj->divider;
|
||||
if (obj->ccr0 < 0x10000) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
MBED_ASSERT(found);
|
||||
/* Get the TIMER A base */
|
||||
Timer_A_Type *TA = (Timer_A_Type *)obj->pwm;
|
||||
// Set the calculated results
|
||||
TA->CTL &= ~TIMER_A_CTL_ID_MASK;
|
||||
TA->CTL |= (id << TIMER_A_CTL_ID_OFS);
|
||||
TA->EX0 = ex0;
|
||||
TA->CCR[0] = obj->ccr0 - 1;
|
||||
/* Set the former duty cycle */
|
||||
pwmout_write(obj, obj->dutyCycle);
|
||||
}
|
||||
|
||||
/** Set the PWM pulsewidth specified in seconds, keeping the period the same.
|
||||
*
|
||||
* @param obj The pwmout object
|
||||
* @param seconds The floating-point pulsewidth in seconds
|
||||
*/
|
||||
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
|
||||
{
|
||||
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
|
||||
}
|
||||
|
||||
/** Set the PWM pulsewidth specified in miliseconds, keeping the period the same.
|
||||
*
|
||||
* @param obj The pwmout object
|
||||
* @param ms The floating-point pulsewidth in miliseconds
|
||||
*/
|
||||
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
|
||||
{
|
||||
pwmout_pulsewidth_us(obj, ms * 1000);
|
||||
}
|
||||
|
||||
/** Set the PWM pulsewidth specified in microseconds, keeping the period the same.
|
||||
*
|
||||
* @param obj The pwmout object
|
||||
* @param us The floating-point pulsewidth in microseconds
|
||||
*/
|
||||
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
|
||||
{
|
||||
obj->pulse = SubsystemMasterClock / 1000000;
|
||||
obj->pulse *= us;
|
||||
obj->pulse /= obj->divider;
|
||||
MBED_ASSERT(obj->pulse <= obj->ccr0);
|
||||
/* Set the new duty cycle */
|
||||
obj->dutyCycle = (float)obj->pulse / (float)obj->ccr0;
|
||||
/* Get the TIMER A base */
|
||||
Timer_A_Type *TA = (Timer_A_Type *)obj->pwm;
|
||||
// Set the CCR register
|
||||
TA->CCR[obj->ccr_index] = obj->pulse;
|
||||
}
|
||||
|
||||
/** Get the pins that support PWM
|
||||
*
|
||||
* Return a PinMap array of pins that support PWM.
|
||||
* The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *pwmout_pinmap(void)
|
||||
{
|
||||
return PinMap_PWM;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,406 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Low-level implementation of uart functionality for MSP432.
|
||||
* This implementation does not (yet) support SERIAL_ASYNCH and SERIAL_FC.
|
||||
*/
|
||||
|
||||
#if DEVICE_SERIAL
|
||||
|
||||
#include "serial_api.h"
|
||||
#include "mbed_assert.h"
|
||||
#include "mbed_error.h"
|
||||
#include <string.h>
|
||||
|
||||
/* With SERIAL_ASYNCH, our type serial_s is embedded
|
||||
* into a bigger structure (see serial_api.h). So we
|
||||
* need a macro to extract the serial_s object.
|
||||
*/
|
||||
#if DEVICE_SERIAL_ASYNCH
|
||||
#define SERIAL_S(obj) (&((obj)->serial))
|
||||
#else
|
||||
#define SERIAL_S(obj) (obj)
|
||||
#endif
|
||||
|
||||
int stdio_uart_inited = 0; // used in mbed_retarget.cpp
|
||||
serial_t stdio_uart;
|
||||
|
||||
uart_irq_handler uart_handler = 0;
|
||||
uint32_t serial_irq_ids[4] = {0};
|
||||
|
||||
/** Initialize the serial peripheral. It sets the default parameters for serial
|
||||
* peripheral, and configures its specifieds pins.
|
||||
*
|
||||
* @param obj The serial object
|
||||
* @param tx The TX pin name
|
||||
* @param rx The RX pin name
|
||||
*/
|
||||
void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
uint8_t stdio_config = 0;
|
||||
|
||||
/* Determine the UART to use (UART_A0...UART_A3) */
|
||||
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
|
||||
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
|
||||
UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
|
||||
MBED_ASSERT(objs->uart != (UARTName)NC);
|
||||
/* Fill the obj structure */
|
||||
objs->uart = uart;
|
||||
objs->pin_tx = tx;
|
||||
objs->pin_rx = rx;
|
||||
|
||||
/* Check if we selected the STDIO UART */
|
||||
if ((tx == STDIO_UART_TX) || (rx == STDIO_UART_RX)) {
|
||||
stdio_config = 1;
|
||||
}
|
||||
/* Configure the TX and RX pins */
|
||||
pinmap_pinout(tx, PinMap_UART_TX);
|
||||
pinmap_pinout(rx, PinMap_UART_RX);
|
||||
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
/* put EUSCI module in reset state */
|
||||
EUSCI->CTLW0 = EUSCI_A_CTLW0_SWRST;
|
||||
/* Configure SMCLK as clock source */
|
||||
EUSCI->CTLW0 |= EUSCI_A_CTLW0_SSEL__SMCLK;
|
||||
/* Disable modulation stages */
|
||||
EUSCI->MCTLW &= ~(EUSCI_A_MCTLW_BRS_MASK |
|
||||
EUSCI_A_MCTLW_BRF_MASK |
|
||||
EUSCI_A_MCTLW_OS16);
|
||||
/* Disable interrupts */
|
||||
EUSCI->IE = 0;
|
||||
/* enable the UART module again */
|
||||
EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_SWRST;
|
||||
/* Set default baud rate */
|
||||
serial_baud(obj, 9600);
|
||||
/* Copy config to stdio structure if needed */
|
||||
if (stdio_config) {
|
||||
memcpy(&stdio_uart, obj, sizeof(serial_t));
|
||||
stdio_uart_inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Release the serial peripheral, not currently invoked. It requires further
|
||||
* resource management.
|
||||
*
|
||||
* @param obj The serial object
|
||||
*/
|
||||
void serial_free(serial_t *obj)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
/* Wait for pending operations */
|
||||
while (EUSCI->STATW & EUSCI_A_STATW_BUSY);
|
||||
/* Put UART to reset state */
|
||||
EUSCI->CTLW0 = EUSCI_A_CTLW0_SWRST;
|
||||
/* De-configure the RX/TX lines */
|
||||
pin_function(objs->pin_tx, MSP432_PIN_DATA(SEL0, PIN_INPUT, PullNone, 0));
|
||||
pin_function(objs->pin_rx, MSP432_PIN_DATA(SEL0, PIN_INPUT, PullNone, 0));
|
||||
}
|
||||
|
||||
/** Configure the baud rate
|
||||
*
|
||||
* @param obj The serial object
|
||||
* @param baudrate The baud rate to be configured
|
||||
*/
|
||||
void serial_baud(serial_t *obj, int baudrate)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
EUSCI->BRW = (uint16_t)(SubsystemMasterClock / baudrate);
|
||||
}
|
||||
|
||||
/** Configure the format. Set the number of bits, parity and the number of stop bits
|
||||
*
|
||||
* @param obj The serial object
|
||||
* @param data_bits The number of data bits
|
||||
* @param parity The parity
|
||||
* @param stop_bits The number of stop bits
|
||||
*/
|
||||
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
/* put module in reset state */
|
||||
EUSCI->CTLW0 |= EUSCI_A_CTLW0_SWRST;
|
||||
/* Configure data bits */
|
||||
switch (data_bits) {
|
||||
case 7:
|
||||
EUSCI->CTLW0 |= EUSCI_A_CTLW0_SEVENBIT;
|
||||
break;
|
||||
case 8:
|
||||
EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_SEVENBIT;
|
||||
break;
|
||||
default:
|
||||
error("Unsupported UART data-bit size");
|
||||
}
|
||||
/* Configure parity */
|
||||
switch (parity) {
|
||||
case ParityNone:
|
||||
EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_PEN;
|
||||
break;
|
||||
case ParityOdd:
|
||||
EUSCI->CTLW0 |= EUSCI_A_CTLW0_PEN;
|
||||
EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_PAR;
|
||||
break;
|
||||
case ParityEven:
|
||||
EUSCI->CTLW0 |= EUSCI_A_CTLW0_PEN;
|
||||
EUSCI->CTLW0 |= EUSCI_A_CTLW0_PAR;
|
||||
break;
|
||||
case ParityForced1:
|
||||
case ParityForced0:
|
||||
default:
|
||||
error("Unsupported UART parity selection");
|
||||
}
|
||||
/* Configure stop bits */
|
||||
switch (data_bits) {
|
||||
case 1:
|
||||
EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_SPB;
|
||||
break;
|
||||
case 2:
|
||||
EUSCI->CTLW0 |= EUSCI_A_CTLW0_SPB;
|
||||
break;
|
||||
default:
|
||||
error("Unsupported UART stop-bit size");
|
||||
}
|
||||
/* re-enable the UART module */
|
||||
EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_SWRST;
|
||||
}
|
||||
|
||||
/** The serial interrupt handler registration
|
||||
*
|
||||
* @param obj The serial object
|
||||
* @param handler The interrupt handler which will be invoked when the interrupt fires
|
||||
* @param id The SerialBase object
|
||||
*/
|
||||
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
uart_handler = handler;
|
||||
/* UART base addresses are
|
||||
* EUSCI_A0 0x40001000
|
||||
* EUSCI_A1 0x40001400
|
||||
* EUSCI_A2 0x40001800
|
||||
* EUSCI_A3 0x40001c00 */
|
||||
uint8_t index = (((uint32_t)(objs->uart)) >> 10) & 0x3;
|
||||
serial_irq_ids[index] = id;
|
||||
/* Enable the NVIC irq for this UART */
|
||||
NVIC_EnableIRQ((IRQn_Type)(EUSCIA0_IRQn + index));
|
||||
}
|
||||
|
||||
/** Configure serial interrupt. This function is used for word-approach
|
||||
*
|
||||
* @param obj The serial object
|
||||
* @param irq The serial IRQ type (RX or TX)
|
||||
* @param enable Set to non-zero to enable events, or zero to disable them
|
||||
*/
|
||||
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
switch (irq) {
|
||||
case RxIrq:
|
||||
BITBAND_PERI(EUSCI->IE, EUSCI_A_IE_RXIE_OFS) = enable;
|
||||
break;
|
||||
case TxIrq:
|
||||
BITBAND_PERI(EUSCI->IE, EUSCI_A_IE_TXIE_OFS) = enable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get character. This is a blocking call, waiting for a character
|
||||
*
|
||||
* @param obj The serial object
|
||||
*/
|
||||
int serial_getc(serial_t *obj)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
/* Wait until the RX Buffer is filled.... */
|
||||
while ((EUSCI->IFG & EUSCI_A_IFG_RXIFG) == 0);
|
||||
/*Transfer single char from RX buffer */
|
||||
return EUSCI->RXBUF;
|
||||
}
|
||||
|
||||
/** Send a character. This is a blocking call, waiting for a peripheral to be available
|
||||
* for writing
|
||||
*
|
||||
* @param obj The serial object
|
||||
* @param c The character to be sent
|
||||
*/
|
||||
void serial_putc(serial_t *obj, int c)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
/* Wait until the TX Buffer is empty.... */
|
||||
while ((EUSCI->IFG & EUSCI_A_IFG_TXIFG) == 0);
|
||||
/* Transfer single char to TX buffer */
|
||||
EUSCI->TXBUF = (uint16_t)c;
|
||||
}
|
||||
|
||||
/** Check if the serial peripheral is readable
|
||||
*
|
||||
* @param obj The serial object
|
||||
* @return Non-zero value if a character can be read, 0 if nothing to read
|
||||
*/
|
||||
int serial_readable(serial_t *obj)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
return EUSCI->IFG & EUSCI_A_IFG_RXIFG;
|
||||
}
|
||||
|
||||
/** Check if the serial peripheral is writable
|
||||
*
|
||||
* @param obj The serial object
|
||||
* @return Non-zero value if a character can be written, 0 otherwise.
|
||||
*/
|
||||
int serial_writable(serial_t *obj)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
return EUSCI->IFG & EUSCI_A_IFG_TXIFG;
|
||||
}
|
||||
|
||||
/** Clear the serial peripheral
|
||||
*
|
||||
* @param obj The serial object
|
||||
*/
|
||||
void serial_clear(serial_t *obj)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
/* Clear all flags */
|
||||
EUSCI->IFG = 0;
|
||||
}
|
||||
|
||||
/** Set the break
|
||||
*
|
||||
* @param obj The serial object
|
||||
*/
|
||||
void serial_break_set(serial_t *obj)
|
||||
{
|
||||
struct serial_s *objs = SERIAL_S(obj);
|
||||
/* Get the UART base */
|
||||
EUSCI_A_Type *EUSCI = (EUSCI_A_Type *)objs->uart;
|
||||
/* Wait until the TX Buffer is empty.... */
|
||||
while ((EUSCI->IFG & EUSCI_A_IFG_TXIFG) == 0);
|
||||
/* Send break (automatically cleared) */
|
||||
EUSCI->CTLW0 |= EUSCI_A_CTLW0_TXBRK;
|
||||
}
|
||||
|
||||
/** Clear the break
|
||||
*
|
||||
* @param obj The serial object
|
||||
*/
|
||||
void serial_break_clear(serial_t *obj)
|
||||
{
|
||||
/* Not needed because break flag is automatically cleared */
|
||||
}
|
||||
|
||||
/** Configure the TX pin for UART function.
|
||||
*
|
||||
* @param tx The pin name used for TX
|
||||
*/
|
||||
void serial_pinout_tx(PinName tx)
|
||||
{
|
||||
pinmap_pinout(tx, PinMap_UART_TX);
|
||||
}
|
||||
|
||||
/** Configure the serial for the flow control. It sets flow control in the hardware
|
||||
* if a serial peripheral supports it, otherwise software emulation is used.
|
||||
*
|
||||
* @param obj The serial object
|
||||
* @param type The type of the flow control. Look at the available FlowControl types.
|
||||
* @param rxflow The TX pin name
|
||||
* @param txflow The RX pin name
|
||||
*/
|
||||
//void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
|
||||
//{
|
||||
// /* not used so far */
|
||||
//}
|
||||
|
||||
/** Get the pins that support Serial TX
|
||||
*
|
||||
* Return a PinMap array of pins that support Serial TX. The
|
||||
* array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *serial_tx_pinmap(void)
|
||||
{
|
||||
return PinMap_UART_TX;
|
||||
}
|
||||
|
||||
/** Get the pins that support Serial RX
|
||||
*
|
||||
* Return a PinMap array of pins that support Serial RX. The
|
||||
* array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *serial_rx_pinmap(void)
|
||||
{
|
||||
return PinMap_UART_RX;
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/* UART interrupt handler */
|
||||
/**************************/
|
||||
void handle_UART_Interrupt(uint8_t index, uint8_t vector)
|
||||
{
|
||||
if (uart_handler) {
|
||||
switch (vector) {
|
||||
case 2:
|
||||
uart_handler(serial_irq_ids[index], RxIrq);
|
||||
break;
|
||||
case 4:
|
||||
uart_handler(serial_irq_ids[index], TxIrq);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIA0_UART_IRQHandler(void)
|
||||
{
|
||||
handle_UART_Interrupt(0, EUSCI_A0->IV);
|
||||
}
|
||||
void EUSCIA1_UART_IRQHandler(void)
|
||||
{
|
||||
handle_UART_Interrupt(1, EUSCI_A1->IV);
|
||||
}
|
||||
void EUSCIA2_UART_IRQHandler(void)
|
||||
{
|
||||
handle_UART_Interrupt(2, EUSCI_A2->IV);
|
||||
}
|
||||
void EUSCIA3_UART_IRQHandler(void)
|
||||
{
|
||||
handle_UART_Interrupt(3, EUSCI_A3->IV);
|
||||
}
|
||||
|
||||
#endif /* DEVICE_SERIAL */
|
||||
|
|
@ -0,0 +1,642 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "spi_api.h"
|
||||
#include "mbed_assert.h"
|
||||
|
||||
#if DEVICE_SPI
|
||||
|
||||
//#define SPI_EVENT_ERROR (1 << 1)
|
||||
//#define SPI_EVENT_COMPLETE (1 << 2)
|
||||
//#define SPI_EVENT_RX_OVERFLOW (1 << 3)
|
||||
//#define SPI_EVENT_ALL (SPI_EVENT_ERROR | SPI_EVENT_COMPLETE | SPI_EVENT_RX_OVERFLOW)
|
||||
//
|
||||
//#define SPI_EVENT_INTERNAL_TRANSFER_COMPLETE (1 << 30) // Internal flag to report that an event occurred
|
||||
//
|
||||
//#define SPI_FILL_WORD (0xFFFF)
|
||||
//#define SPI_FILL_CHAR (0xFF)
|
||||
|
||||
|
||||
/* With SPI_ASYNCH, our type spi_s is embedded
|
||||
* into a bigger structure (see spi_api.h). So we
|
||||
* need a macro to extract the spi_s object.
|
||||
*/
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
#define SPI_S(obj) (&((obj)->spi))
|
||||
#else
|
||||
#define SPI_S(obj) (obj)
|
||||
#endif
|
||||
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
// Array with object pointers for ISR
|
||||
spi_t *spi_objects[8] = {0};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns a variant of the SPIName enum uniquely identifying a SPI peripheral of the device.
|
||||
* @param[in] mosi The pin to use for MOSI
|
||||
* @param[in] miso The pin to use for MISO
|
||||
* @param[in] sclk The pin to use for SCLK
|
||||
* @return An SPI peripheral identifier
|
||||
*/
|
||||
SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk)
|
||||
{
|
||||
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
|
||||
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
|
||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
||||
|
||||
SPIName spi_per, spi_data;
|
||||
// miso or mosi might be NC (3 wire SPI)
|
||||
spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
|
||||
MBED_ASSERT(spi_data != (SPIName)NC);
|
||||
spi_per = (SPIName)pinmap_merge(spi_data, spi_sclk);
|
||||
return spi_per;
|
||||
}
|
||||
|
||||
/** Initialize the SPI peripheral
|
||||
*
|
||||
* Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
|
||||
* @param[out] obj The SPI object to initialize
|
||||
* @param[in] mosi The pin to use for MOSI
|
||||
* @param[in] miso The pin to use for MISO
|
||||
* @param[in] sclk The pin to use for SCLK
|
||||
* @param[in] ssel The pin to use for SSEL
|
||||
*/
|
||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
// Get the SPI peripheral
|
||||
objs->spi = spi_get_peripheral_name(mosi, miso, sclk);
|
||||
// Check if SSEL/CS fits
|
||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
||||
objs->spi = pinmap_merge(objs->spi, spi_ssel);
|
||||
MBED_ASSERT(objs->spi != (SPIName)NC);
|
||||
// Get the type of EUSCI interface (Type A or B)
|
||||
objs->module = GET_DATA_CHAN(pinmap_function(mosi, PinMap_SPI_MOSI));
|
||||
// Set register addresses
|
||||
if (objs->module < 4) {
|
||||
// Get the SPI base
|
||||
EUSCI_A_SPI_Type *EUSCI = (EUSCI_A_SPI_Type *)objs->spi;
|
||||
objs->EUSCI_CTLW0 = &EUSCI->CTLW0;
|
||||
objs->EUSCI_BRW = &EUSCI->BRW;
|
||||
objs->EUSCI_STATW = &EUSCI->STATW;
|
||||
objs->EUSCI_RXBUF = &EUSCI->RXBUF;
|
||||
objs->EUSCI_TXBUF = &EUSCI->TXBUF;
|
||||
objs->EUSCI_IE = &EUSCI->IE;
|
||||
objs->EUSCI_IFG = &EUSCI->IFG;
|
||||
objs->EUSCI_IV = &EUSCI->IV;
|
||||
} else {
|
||||
// Get the SPI base
|
||||
EUSCI_B_SPI_Type *EUSCI = (EUSCI_B_SPI_Type *)objs->spi;
|
||||
objs->EUSCI_CTLW0 = &EUSCI->CTLW0;
|
||||
objs->EUSCI_BRW = &EUSCI->BRW;
|
||||
objs->EUSCI_STATW = &EUSCI->STATW;
|
||||
objs->EUSCI_RXBUF = &EUSCI->RXBUF;
|
||||
objs->EUSCI_TXBUF = &EUSCI->TXBUF;
|
||||
objs->EUSCI_IE = &EUSCI->IE;
|
||||
objs->EUSCI_IFG = &EUSCI->IFG;
|
||||
objs->EUSCI_IV = &EUSCI->IV;
|
||||
}
|
||||
/* Configure SPI pins */
|
||||
pinmap_pinout(mosi, PinMap_SPI_MOSI);
|
||||
pinmap_pinout(miso, PinMap_SPI_MISO);
|
||||
pinmap_pinout(sclk, PinMap_SPI_SCLK);
|
||||
pinmap_pinout(ssel, PinMap_SPI_SSEL);
|
||||
// Store pins in SPI object
|
||||
objs->pin_miso = miso;
|
||||
objs->pin_mosi = mosi;
|
||||
objs->pin_sclk = sclk;
|
||||
objs->pin_ssel = ssel;
|
||||
/* Put EUSCI to reset state */
|
||||
BITBAND_PERI(*(objs->EUSCI_CTLW0), EUSCI_B_CTLW0_SWRST_OFS) = 1;
|
||||
/* Configure basic SPI mode */
|
||||
uint16_t ctlw0;
|
||||
if (ssel == (PinName)NC) {
|
||||
ctlw0 = EUSCI_B_CTLW0_MODE_0; // 3 pin SPI mode
|
||||
} else {
|
||||
ctlw0 = EUSCI_B_CTLW0_MODE_2 | // 4 pin SPI mode
|
||||
EUSCI_A_CTLW0_STEM; // use STE as SSEL/CS
|
||||
}
|
||||
ctlw0 |= EUSCI_A_CTLW0_MSB | // MSB first
|
||||
EUSCI_A_CTLW0_SYNC | // SYNC mode (SPI)
|
||||
EUSCI_B_CTLW0_SSEL__SMCLK; // SMCLK as clock source
|
||||
|
||||
*(objs->EUSCI_CTLW0) = ctlw0;
|
||||
// Set SPI clock to default 1 MHz */
|
||||
spi_frequency(obj, 1000000);
|
||||
// Disable and clear interrupts
|
||||
*(objs->EUSCI_IE) = 0;
|
||||
*(objs->EUSCI_IFG) = 0;
|
||||
// Clear the EUSCI reset state (enable module)
|
||||
BITBAND_PERI(*(objs->EUSCI_CTLW0), EUSCI_B_CTLW0_SWRST_OFS) = 0;
|
||||
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
// Store the object pointer for the ISR
|
||||
spi_objects[objs->module] = obj;
|
||||
objs->active = false;
|
||||
/* Enable the NVIC irq for this SPI module */
|
||||
NVIC_EnableIRQ((IRQn_Type)(EUSCIA0_IRQn + objs->module));
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Release a SPI object
|
||||
*
|
||||
* TODO: spi_free is currently unimplemented
|
||||
* This will require reference counting at the C++ level to be safe
|
||||
*
|
||||
* Return the pins owned by the SPI object to their reset state
|
||||
* Disable the SPI peripheral
|
||||
* Disable the SPI clock
|
||||
* @param[in] obj The SPI object to deinitialize
|
||||
*/
|
||||
void spi_free(spi_t *obj)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
// Put EUSCI to reset state
|
||||
BITBAND_PERI(*(objs->EUSCI_CTLW0), EUSCI_B_CTLW0_SWRST_OFS) = 1;
|
||||
// Put pins to default state
|
||||
int pin_data = MSP432_PIN_DATA(SEL0, PIN_INPUT, PullNone, 0);
|
||||
pin_function(objs->pin_miso, pin_data);
|
||||
pin_function(objs->pin_mosi, pin_data);
|
||||
pin_function(objs->pin_sclk, pin_data);
|
||||
pin_function(objs->pin_ssel, pin_data);
|
||||
}
|
||||
|
||||
/** Configure the SPI format
|
||||
*
|
||||
* Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode.
|
||||
* The default bit order is MSB.
|
||||
* @param[in,out] obj The SPI object to configure
|
||||
* @param[in] bits The number of bits per frame
|
||||
* @param[in] mode The SPI mode (clock polarity, phase, and shift direction)
|
||||
* @param[in] slave Zero for master mode or non-zero for slave mode
|
||||
*/
|
||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
// Put the EUSCI to reset state
|
||||
BITBAND_PERI(*(objs->EUSCI_CTLW0), EUSCI_B_CTLW0_SWRST_OFS) = 1;
|
||||
// Set bit size
|
||||
MBED_ASSERT((bits >= 7) && (bits <= 8));
|
||||
BITBAND_PERI(*(objs->EUSCI_CTLW0), EUSCI_B_CTLW0_SEVENBIT_OFS) = (bits == 7);
|
||||
// Set SPI clock polarity
|
||||
BITBAND_PERI(*(objs->EUSCI_CTLW0), EUSCI_B_CTLW0_CKPL_OFS) = (mode >> 1);
|
||||
// Set SPI clock phase
|
||||
BITBAND_PERI(*(objs->EUSCI_CTLW0), EUSCI_B_CTLW0_CKPH_OFS) = (mode ^ 1);
|
||||
// Set master/slave mode
|
||||
BITBAND_PERI(*(objs->EUSCI_CTLW0), EUSCI_B_CTLW0_MST_OFS) = !slave;
|
||||
// Clear the EUSCI reset state (enable module)
|
||||
BITBAND_PERI(*(objs->EUSCI_CTLW0), EUSCI_B_CTLW0_SWRST_OFS) = 0;
|
||||
}
|
||||
|
||||
/** Set the SPI baud rate
|
||||
*
|
||||
* Actual frequency may differ from the desired frequency due to available dividers and bus clock
|
||||
* Configures the SPI peripheral's baud rate
|
||||
* @param[in,out] obj The SPI object to configure
|
||||
* @param[in] hz The baud rate in Hz
|
||||
*/
|
||||
void spi_frequency(spi_t *obj, int hz)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
*(objs->EUSCI_BRW) = SubsystemMasterClock / hz;
|
||||
}
|
||||
|
||||
/** Write a byte out in master mode and receive a value
|
||||
*
|
||||
* @param[in] obj The SPI peripheral to use for sending
|
||||
* @param[in] value The value to send
|
||||
* @return Returns the value received during send
|
||||
*/
|
||||
int spi_master_write(spi_t *obj, int value)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
*(objs->EUSCI_IFG) = 0;
|
||||
*(objs->EUSCI_STATW) = 0;
|
||||
/* Place character in buffer */
|
||||
*(objs->EUSCI_TXBUF) = value;
|
||||
// Wait until byte has been received
|
||||
while (!BITBAND_PERI(*(objs->EUSCI_IFG), EUSCI_B_IFG_RXIFG_OFS));
|
||||
return *(objs->EUSCI_RXBUF);
|
||||
}
|
||||
|
||||
/** Write a block out in master mode and receive a value
|
||||
*
|
||||
* The total number of bytes sent and received will be the maximum of
|
||||
* tx_length and rx_length. The bytes written will be padded with the
|
||||
* value 0xff.
|
||||
*
|
||||
* @param[in] obj The SPI peripheral to use for sending
|
||||
* @param[in] tx_buffer Pointer to the byte-array of data to write to the device
|
||||
* @param[in] tx_length Number of bytes to write, may be zero
|
||||
* @param[in] rx_buffer Pointer to the byte-array of data to read from the device
|
||||
* @param[in] rx_length Number of bytes to read, may be zero
|
||||
* @param[in] write_fill Default data transmitted while performing a read
|
||||
* @returns
|
||||
* The number of bytes written and read from the device. This is
|
||||
* maximum of tx_length and rx_length.
|
||||
*/
|
||||
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
|
||||
char *rx_buffer, int rx_length,
|
||||
char write_fill)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
// Clear interrupt status
|
||||
*(objs->EUSCI_IFG) = 0;
|
||||
*(objs->EUSCI_STATW) = 0;
|
||||
// Calculate maximum transfer length
|
||||
int i, total = (tx_length > rx_length) ? tx_length : rx_length;
|
||||
for (i = 0; i < total; i++) {
|
||||
// Place character in buffer
|
||||
*(objs->EUSCI_TXBUF) = (i < tx_length) ? tx_buffer[i] : write_fill;
|
||||
// Wait until byte has been received
|
||||
while (!BITBAND_PERI(*(objs->EUSCI_IFG), EUSCI_B_IFG_RXIFG_OFS));
|
||||
// Fill receive buffer
|
||||
if (i < rx_length) {
|
||||
rx_buffer[i] = *(objs->EUSCI_RXBUF);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
/** Checks if the specified SPI peripheral is in use
|
||||
*
|
||||
* @param[in] obj The SPI peripheral to check
|
||||
* @return non-zero if the peripheral is currently transmitting
|
||||
*/
|
||||
int spi_busy(spi_t *obj)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
return *(objs->EUSCI_STATW) & EUSCI_B_STATW_SPI_BUSY;
|
||||
}
|
||||
|
||||
/** Get the module number
|
||||
*
|
||||
* @param[in] obj The SPI peripheral to check
|
||||
* @return The module number
|
||||
*/
|
||||
uint8_t spi_get_module(spi_t *obj)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
return objs->module;
|
||||
}
|
||||
|
||||
/** Get the pins that support SPI MOSI
|
||||
*
|
||||
* Return a PinMap array of pins that support SPI MOSI in
|
||||
* master mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *spi_master_mosi_pinmap(void)
|
||||
{
|
||||
return PinMap_SPI_MOSI;
|
||||
}
|
||||
|
||||
/** Get the pins that support SPI MISO
|
||||
*
|
||||
* Return a PinMap array of pins that support SPI MISO in
|
||||
* master mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *spi_master_miso_pinmap(void)
|
||||
{
|
||||
return PinMap_SPI_MISO;
|
||||
}
|
||||
|
||||
/** Get the pins that support SPI CLK
|
||||
*
|
||||
* Return a PinMap array of pins that support SPI CLK in
|
||||
* master mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *spi_master_clk_pinmap(void)
|
||||
{
|
||||
return PinMap_SPI_SCLK;
|
||||
}
|
||||
|
||||
/** Get the pins that support SPI CS
|
||||
*
|
||||
* Return a PinMap array of pins that support SPI CS in
|
||||
* master mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *spi_master_cs_pinmap(void)
|
||||
{
|
||||
return PinMap_SPI_SSEL;
|
||||
}
|
||||
|
||||
#if DEVICE_SPISLAVE
|
||||
|
||||
/** Check if a value is available to read
|
||||
*
|
||||
* @param[in] obj The SPI peripheral to check
|
||||
* @return non-zero if a value is available
|
||||
*/
|
||||
int spi_slave_receive(spi_t *obj)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
return BITBAND_PERI(*(objs->EUSCI_IFG), EUSCI_B_IFG_RXIFG_OFS);
|
||||
}
|
||||
|
||||
/** Get a received value out of the SPI receive buffer in slave mode
|
||||
*
|
||||
* Blocks until a value is available
|
||||
* @param[in] obj The SPI peripheral to read
|
||||
* @return The value received
|
||||
*/
|
||||
int spi_slave_read(spi_t *obj)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
while (!BITBAND_PERI(*(objs->EUSCI_IFG), EUSCI_B_IFG_RXIFG_OFS)) ;
|
||||
return *(objs->EUSCI_RXBUF);
|
||||
}
|
||||
|
||||
/** Write a value to the SPI peripheral in slave mode
|
||||
*
|
||||
* Blocks until the SPI peripheral can be written to
|
||||
* @param[in] obj The SPI peripheral to write
|
||||
* @param[in] value The value to write
|
||||
*/
|
||||
void spi_slave_write(spi_t *obj, int value)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
while (!BITBAND_PERI(*(objs->EUSCI_IFG), EUSCI_B_IFG_TXIFG_OFS)) ;
|
||||
*(objs->EUSCI_TXBUF) = value;
|
||||
}
|
||||
|
||||
/** Get the pins that support SPI MOSI
|
||||
*
|
||||
* Return a PinMap array of pins that support SPI MOSI in
|
||||
* slave mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *spi_slave_mosi_pinmap(void)
|
||||
{
|
||||
return PinMap_SPI_MOSI;
|
||||
}
|
||||
|
||||
/** Get the pins that support SPI MISO
|
||||
*
|
||||
* Return a PinMap array of pins that support SPI MISO in
|
||||
* slave mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *spi_slave_miso_pinmap(void)
|
||||
{
|
||||
return PinMap_SPI_MISO;
|
||||
}
|
||||
|
||||
/** Get the pins that support SPI CLK
|
||||
*
|
||||
* Return a PinMap array of pins that support SPI CLK in
|
||||
* slave mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *spi_slave_clk_pinmap(void)
|
||||
{
|
||||
return PinMap_SPI_SCLK;
|
||||
}
|
||||
|
||||
/** Get the pins that support SPI CS
|
||||
*
|
||||
* Return a PinMap array of pins that support SPI CS in
|
||||
* slave mode. The array is terminated with {NC, NC, 0}.
|
||||
*
|
||||
* @return PinMap array
|
||||
*/
|
||||
const PinMap *spi_slave_cs_pinmap(void)
|
||||
{
|
||||
return PinMap_SPI_SSEL;
|
||||
}
|
||||
|
||||
#endif // DEVICE_SPISLAVE
|
||||
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
/**
|
||||
* \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff
|
||||
*
|
||||
* @param[in] obj The SPI object that holds the transfer information
|
||||
* @param[in] tx The transmit buffer
|
||||
* @param[in] tx_length The number of bytes to transmit
|
||||
* @param[in] rx The receive buffer
|
||||
* @param[in] rx_length The number of bytes to receive
|
||||
* @param[in] bit_width The bit width of buffer words
|
||||
* @param[in] event The logical OR of events to be registered
|
||||
* @param[in] handler SPI interrupt handler
|
||||
* @param[in] hint A suggestion for how to use DMA with this transfer
|
||||
*/
|
||||
void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length,
|
||||
uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
|
||||
{
|
||||
// We ignore DMA for now
|
||||
(void) hint;
|
||||
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
|
||||
// Update object
|
||||
obj->tx_buff.buffer = (void *)tx;
|
||||
obj->tx_buff.length = tx_length;
|
||||
obj->tx_buff.pos = 0;
|
||||
obj->tx_buff.width = bit_width;
|
||||
|
||||
obj->rx_buff.buffer = (void *)rx;
|
||||
obj->rx_buff.length = rx_length;
|
||||
obj->rx_buff.pos = 0;
|
||||
obj->rx_buff.width = bit_width;
|
||||
|
||||
objs->handler = (void (*)(void))handler;
|
||||
objs->event = 0;
|
||||
objs->available_events = event;
|
||||
|
||||
// Start the ball rolling by enabling TX/RX interrupts
|
||||
uint16_t ie = 0;
|
||||
if (tx_length) {
|
||||
ie |= EUSCI_B_IE_TXIE;
|
||||
}
|
||||
if (rx_length) {
|
||||
ie |= EUSCI_B_IE_RXIE;
|
||||
}
|
||||
if (ie) {
|
||||
objs->active = true;
|
||||
*(objs->EUSCI_IE) = ie;
|
||||
}
|
||||
}
|
||||
|
||||
/** The asynchronous IRQ handler
|
||||
*
|
||||
* Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination
|
||||
* conditions, such as buffer overflows or transfer complete.
|
||||
* @param[in] obj The SPI object that holds the transfer information
|
||||
* @return Event flags if a transfer termination condition was met; otherwise 0.
|
||||
*/
|
||||
uint32_t spi_irq_handler_asynch(spi_t *obj)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
return (objs->event & objs->available_events);
|
||||
}
|
||||
|
||||
/** Attempts to determine if the SPI peripheral is already in use
|
||||
*
|
||||
* If a temporary DMA channel has been allocated, peripheral is in use.
|
||||
* If a permanent DMA channel has been allocated, check if the DMA channel is in use. If not, proceed as though no DMA
|
||||
* channel were allocated.
|
||||
* If no DMA channel is allocated, check whether tx and rx buffers have been assigned. For each assigned buffer, check
|
||||
* if the corresponding buffer position is less than the buffer length. If buffers do not indicate activity, check if
|
||||
* there are any bytes in the FIFOs.
|
||||
* @param[in] obj The SPI object to check for activity
|
||||
* @return Non-zero if the SPI port is active or zero if it is not.
|
||||
*/
|
||||
uint8_t spi_active(spi_t *obj)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
return objs->active;
|
||||
}
|
||||
|
||||
/** Abort an SPI transfer
|
||||
*
|
||||
* @param obj The SPI peripheral to stop
|
||||
*/
|
||||
void spi_abort_asynch(spi_t *obj)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
*(objs->EUSCI_IE) = 0;
|
||||
*(objs->EUSCI_IFG) = 0;
|
||||
objs->active = false;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/* SPI interrupt handler */
|
||||
/*************************/
|
||||
void handle_SPI_Interrupt(spi_t *obj)
|
||||
{
|
||||
struct spi_s *objs = SPI_S(obj);
|
||||
|
||||
#if 0
|
||||
uint16_t ifg = *(objs->EUSCI_IFG);
|
||||
if (ifg & EUSCI_B_IFG_RXIFG) {
|
||||
struct buffer_s *rx_buff = &obj->rx_buff;
|
||||
if (rx_buff->pos < rx_buff->length) {
|
||||
((uint8_t *)rx_buff->buffer)[rx_buff->pos] = *(objs->EUSCI_RXBUF);
|
||||
rx_buff->pos++;
|
||||
}
|
||||
if (rx_buff->pos >= rx_buff->length) {
|
||||
// Disable RX interrupts
|
||||
*(objs->EUSCI_IE) &= ~EUSCI_B_IE_RXIE;
|
||||
}
|
||||
}
|
||||
if (ifg & EUSCI_B_IFG_TXIFG) {
|
||||
struct buffer_s *tx_buff = &obj->tx_buff;
|
||||
if (tx_buff->pos < tx_buff->length) {
|
||||
*(objs->EUSCI_TXBUF) = ((uint8_t *)tx_buff->buffer)[tx_buff->pos];
|
||||
tx_buff->pos++;
|
||||
} else {
|
||||
// Disable interrupts
|
||||
*(objs->EUSCI_IE) = 0;
|
||||
objs->active = false;
|
||||
objs->event = SPI_EVENT_COMPLETE;
|
||||
objs->handler();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t vector = *(objs->EUSCI_IV);
|
||||
|
||||
switch (vector) {
|
||||
/* UCRXIFG */
|
||||
case 0x02: {
|
||||
struct buffer_s *rx_buff = &obj->rx_buff;
|
||||
if (*(objs->EUSCI_STATW) & EUSCI_B_STATW_OE) {
|
||||
objs->event = SPI_EVENT_RX_OVERFLOW;
|
||||
objs->handler();
|
||||
}
|
||||
if (rx_buff->pos < rx_buff->length) {
|
||||
((uint8_t *)rx_buff->buffer)[rx_buff->pos] = *(objs->EUSCI_RXBUF);
|
||||
rx_buff->pos++;
|
||||
}
|
||||
if (rx_buff->pos >= rx_buff->length) {
|
||||
// Disable RX interrupts
|
||||
*(objs->EUSCI_IE) &= ~EUSCI_B_IE_RXIE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* UCTXIFG */
|
||||
case 0x04: {
|
||||
struct buffer_s *tx_buff = &obj->tx_buff;
|
||||
if (tx_buff->pos < tx_buff->length) {
|
||||
*(objs->EUSCI_TXBUF) = ((uint8_t *)tx_buff->buffer)[tx_buff->pos];
|
||||
tx_buff->pos++;
|
||||
} else {
|
||||
// Disable interrupts
|
||||
*(objs->EUSCI_IE) = 0;
|
||||
objs->active = false;
|
||||
objs->event = SPI_EVENT_COMPLETE;
|
||||
objs->handler();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EUSCIA0_SPI_IRQHandler(void)
|
||||
{
|
||||
handle_SPI_Interrupt(spi_objects[0]);
|
||||
}
|
||||
void EUSCIA1_SPI_IRQHandler(void)
|
||||
{
|
||||
handle_SPI_Interrupt(spi_objects[1]);
|
||||
}
|
||||
void EUSCIA2_SPI_IRQHandler(void)
|
||||
{
|
||||
handle_SPI_Interrupt(spi_objects[2]);
|
||||
}
|
||||
void EUSCIA3_SPI_IRQHandler(void)
|
||||
{
|
||||
handle_SPI_Interrupt(spi_objects[3]);
|
||||
}
|
||||
void EUSCIB0_SPI_IRQHandler(void)
|
||||
{
|
||||
handle_SPI_Interrupt(spi_objects[4]);
|
||||
}
|
||||
void EUSCIB1_SPI_IRQHandler(void)
|
||||
{
|
||||
handle_SPI_Interrupt(spi_objects[5]);
|
||||
}
|
||||
void EUSCIB2_SPI_IRQHandler(void)
|
||||
{
|
||||
handle_SPI_Interrupt(spi_objects[6]);
|
||||
}
|
||||
void EUSCIB3_SPI_IRQHandler(void)
|
||||
{
|
||||
handle_SPI_Interrupt(spi_objects[7]);
|
||||
}
|
||||
|
||||
#endif // DEVICE_SPI_ASYNCH
|
||||
|
||||
#endif // DEVICE_SPI
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Low-level implementation of the us ticker for MSP432. The Timer32
|
||||
* modules can not be used for this purpose, because they do not
|
||||
* generate irqs in free-running mode. So the only remaing choice
|
||||
* are the Timer A modules, which are only 16 bit, but support irqs
|
||||
* when operated in continuous mode. Timer A3 is choosen here, which
|
||||
* could be made configurable in the future.
|
||||
*
|
||||
* See hal/us_ticker_api.h for a detailed description of the following
|
||||
* functions.
|
||||
*/
|
||||
|
||||
#if DEVICE_USTICKER
|
||||
|
||||
#include <stdint.h>
|
||||
#include "us_ticker_api.h"
|
||||
#include "mbed_assert.h"
|
||||
|
||||
extern void us_ticker_irq_handler(void);
|
||||
|
||||
void us_ticker_init(void)
|
||||
{
|
||||
// Calculate the Timer A divisors (shift and remainder)
|
||||
uint32_t prescale = SubsystemMasterClock / 1000000;
|
||||
int shifts = 0;
|
||||
for (shifts = 0; shifts < 3; shifts++) {
|
||||
if (prescale & 0x1) {
|
||||
break;
|
||||
} else {
|
||||
prescale >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that we have at least a 1MHz clock
|
||||
MBED_ASSERT(prescale && (prescale < 9));
|
||||
|
||||
// initialize the registers and set prescalers
|
||||
TIMER_A3->CTL = (shifts << TIMER_A_CTL_ID_OFS) |
|
||||
TIMER_A_CTL_SSEL__SMCLK |
|
||||
TIMER_A_CTL_MC__CONTINUOUS;
|
||||
TIMER_A3->CCTL[0] = 0;
|
||||
TIMER_A3->EX0 = prescale - 1;
|
||||
|
||||
// enable IRQ in NVIC
|
||||
NVIC_EnableIRQ(TA3_0_IRQn);
|
||||
}
|
||||
|
||||
void us_ticker_free(void)
|
||||
{
|
||||
// Reset the ctrl registers to default value
|
||||
TIMER_A3->CTL = 0;
|
||||
TIMER_A3->CCTL[0] = 0;
|
||||
|
||||
// Disable timer interrupt
|
||||
NVIC_DisableIRQ(TA3_0_IRQn);
|
||||
}
|
||||
|
||||
uint32_t us_ticker_read(void)
|
||||
{
|
||||
return TIMER_A3->R;
|
||||
}
|
||||
|
||||
void us_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
TIMER_A3->CCR [0] = timestamp;
|
||||
TIMER_A3->CCTL[0] = TIMER_A_CCTLN_CCIE;
|
||||
}
|
||||
|
||||
void us_ticker_disable_interrupt(void)
|
||||
{
|
||||
TIMER_A3->CCTL[0] &= ~TIMER_A_CCTLN_CCIE;
|
||||
}
|
||||
|
||||
void us_ticker_clear_interrupt(void)
|
||||
{
|
||||
TIMER_A3->CCTL[0] &= ~TIMER_A_CCTLN_CCIFG;
|
||||
}
|
||||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
NVIC_SetPendingIRQ(TA3_0_IRQn);
|
||||
}
|
||||
|
||||
const ticker_info_t *us_ticker_get_info(void)
|
||||
{
|
||||
static const ticker_info_t info = {
|
||||
1000000, // 1 MHz
|
||||
16 // 16 bit counter
|
||||
};
|
||||
return &info;
|
||||
}
|
||||
|
||||
/* Timer_A3 interrupt handler */
|
||||
void TA3_0_IRQHandler()
|
||||
{
|
||||
us_ticker_irq_handler();
|
||||
}
|
||||
|
||||
#endif /* DEVICE_USTICKER */
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2016 ARM Limited
|
||||
* Copyright (c) 2019 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -19,12 +19,18 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(TARGET_CC3220SF)
|
||||
|
||||
#ifndef INITIAL_SP
|
||||
#define INITIAL_SP (0x20040000UL)
|
||||
|
||||
#if defined(TARGET_CC3220SF)
|
||||
#define INITIAL_SP (0x20040000UL)
|
||||
|
||||
#elif defined(TARGET_MSP432P401R)
|
||||
#define INITIAL_SP (0x20010000UL)
|
||||
|
||||
#else
|
||||
#error "INITIAL_SP is not defined for this target in the mbed_rtx.h file"
|
||||
#endif
|
||||
|
||||
#endif /* defined(TARGET_CC3220SF) */
|
||||
#endif // INITIAL_SP
|
||||
|
||||
#endif /* MBED_MBED_RTX_H */
|
||||
#endif // MBED_MBED_RTX_H
|
||||
|
|
|
@ -9106,6 +9106,93 @@
|
|||
"network-default-interface-type": "WIFI"
|
||||
}
|
||||
},
|
||||
"MSP432": {
|
||||
"inherits": ["TI"],
|
||||
"core": "Cortex-M4F",
|
||||
"public": false,
|
||||
"extra_labels": ["MSP432"],
|
||||
"macros": ["MBED_MPU_CUSTOM"],
|
||||
"supported_toolchains": ["GCC_ARM", "ARM", "IAR"],
|
||||
"config": {
|
||||
"hfxt_hz": {
|
||||
"help": "Defines the HFXT frequency in Hz (e.g. 48000000)",
|
||||
"value" : null
|
||||
},
|
||||
"lfxt_hz": {
|
||||
"help": "Defines the LFXT frequency in Hz (e.g. 32768)",
|
||||
"value": null
|
||||
},
|
||||
"dco_rsel": {
|
||||
"help": "Defines the DCO center frequency (3/6/12/24/48 MHz)",
|
||||
"accepted_values": "DCO_1500kHz|DCO_3MHz|DCO_6MHz|DCO_12MHz|DCO_24MHz|DCO_48MHz",
|
||||
"value": "DCO_3MHz"
|
||||
},
|
||||
"dco_tune": {
|
||||
"help": "Defines the DCO tuning value (-512...511)",
|
||||
"value": 0
|
||||
},
|
||||
"mclk_select": {
|
||||
"help": "Selects the MCLK source",
|
||||
"accepted_values": "LFXT, VLO, REFO, DCO, MOD, HFXT",
|
||||
"value": "DCO"
|
||||
},
|
||||
"mclk_div": {
|
||||
"help": "Selects the MCLK divider (1/2/4/8/16/32/64/128)",
|
||||
"accepted_values": "DIV1, DIV2, DIV4, DIV8, DIV16, DIV32, DIV64, DIV128",
|
||||
"value": "DIV1"
|
||||
},
|
||||
"smclk_select": {
|
||||
"help": "Selects the SMCLK source",
|
||||
"accepted_values": "LFXT, VLO, REFO, DCO, MOD, HFXT",
|
||||
"value": "DCO"
|
||||
},
|
||||
"smclk_div": {
|
||||
"help": "Selects the SMCLK divider (1/2/4/8/16/32/64/128)",
|
||||
"accepted_values": "DIV1, DIV2, DIV4, DIV8, DIV16, DIV32, DIV64, DIV128",
|
||||
"value": "DIV1"
|
||||
},
|
||||
"adc_auto_scan": {
|
||||
"help": "Enables automatic conversion of all ADC channels",
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"device_has": [
|
||||
"ANALOGIN",
|
||||
"I2C",
|
||||
"I2C_ASYNCH",
|
||||
"I2CSLAVE",
|
||||
"INTERRUPTIN",
|
||||
"PORTIN",
|
||||
"PORTINOUT",
|
||||
"PORTOUT",
|
||||
"PWMOUT",
|
||||
"SERIAL",
|
||||
"SPI",
|
||||
"SPI_ASYNCH",
|
||||
"SPISLAVE",
|
||||
"STDIO_MESSAGES",
|
||||
"USTICKER"
|
||||
]
|
||||
},
|
||||
"MSP432P401R": {
|
||||
"inherits": ["MSP432"],
|
||||
"extra_labels_add": ["MSP432P401R"],
|
||||
"macros_add": ["__MSP432P401R__"],
|
||||
"device_name": "MSP432P401R"
|
||||
},
|
||||
"MSP432_LAUNCHPAD": {
|
||||
"inherits": ["MSP432P401R"],
|
||||
"supported_form_factors": ["LAUNCHPAD_40"],
|
||||
"overrides": {
|
||||
"hfxt_hz" : 48000000,
|
||||
"mclk_select" : "HFXT",
|
||||
"smclk_select" : "HFXT",
|
||||
"smclk_div" : "DIV2",
|
||||
"adc_auto_scan" : 1
|
||||
},
|
||||
"default_lib": "std",
|
||||
"release_versions": ["2", "5"]
|
||||
},
|
||||
"NUMAKER_IOT_M263A": {
|
||||
"core": "Cortex-M23",
|
||||
"default_toolchain": "ARMC6",
|
||||
|
|
Loading…
Reference in New Issue