diff --git a/demos/MSP430X/NIL-EXP430FR5969/Makefile b/demos/MSP430X/NIL-EXP430FR5969/Makefile new file mode 100644 index 00000000..2b7605a2 --- /dev/null +++ b/demos/MSP430X/NIL-EXP430FR5969/Makefile @@ -0,0 +1,205 @@ +############################################################################## +# Build global options +# NOTE: Can be overridden externally. +# + +# Optimization level, can be [0, 1, 2, 3, s]. +# 0 = turn off optimization. s = optimize for size. +# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) +OPTIMIZE = 1 + +# Debugging format. +DEBUG = +#DEBUG = stabs + +# Memory/data model +MODEL = large + +# Object files directory +# To put object files in current directory, use a dot (.), do NOT make +# this an empty or blank macro! +OBJDIR = . + +# Compiler flag to set the C Standard level. +# c89 = "ANSI" C +# gnu89 = c89 plus GCC extensions +# c99 = ISO C99 standard (not yet fully implemented) +# gnu99 = c99 plus GCC extensions +CSTANDARD = -std=gnu11 + +# Compiler options here. +ifeq ($(USE_OPT),) + USE_OPT = -O$(OPTIMIZE) -g$(DEBUG) + USE_OPT += -fsigned-char -fshort-enums +endif + +# C specific options here (added to USE_OPT). +ifeq ($(USE_COPT),) + USE_COPT = +endif + +# C++ specific options here (added to USE_OPT). +ifeq ($(USE_CPPOPT),) + USE_CPPOPT = -fno-rtti +endif + +# Enable this if you want the linker to remove unused code and data +ifeq ($(USE_LINK_GC),) + USE_LINK_GC = yes +endif + +# Linker extra options here. +ifeq ($(USE_LDOPT),) + USE_LDOPT = +endif + +# Enable this if you want link time optimizations (LTO) +ifeq ($(USE_LTO),) + USE_LTO = no +endif + +# Enable the selected hardware multiplier +ifeq ($(USE_HWMULT),) + USE_HWMULT = f5series +endif + +# Enable this if you want to see the full log while compiling. +ifeq ($(USE_VERBOSE_COMPILE),) + USE_VERBOSE_COMPILE = yes +endif + +# If enabled, this option makes the build process faster by not compiling +# modules not used in the current configuration. +ifeq ($(USE_SMART_BUILD),) + USE_SMART_BUILD = yes +endif + +# +# Build global options +############################################################################## + +############################################################################## +# Architecture or project specific options +# + +# Stack size to be allocated to the idle thread stack. This stack is +# the stack used by the main() thread. +ifeq ($(USE_IDLE_STACKSIZE),) + USE_IDLE_STACKSIZE = 0xC00 +endif + +# +# Architecture or project specific options +############################################################################## + +############################################################################## +# Project, sources and paths +# + +# Define project name here +PROJECT = nil + +# Imported source files and paths +CHIBIOS = ../../../../ChibiOS-RT +CHIBIOS_CONTRIB = ../../.. +# Startup files. +include $(CHIBIOS_CONTRIB)/os/common/startup/MSP430X/compilers/GCC/mk/startup_msp430fr5xxx.mk +# HAL-OSAL files (optional). +include $(CHIBIOS)/os/hal/hal.mk +include $(CHIBIOS_CONTRIB)/os/hal/boards/EXP430FR5969/board.mk +include $(CHIBIOS_CONTRIB)/os/hal/ports/MSP430X/platform.mk +include $(CHIBIOS)/os/hal/osal/nil/osal.mk +# RTOS files (optional). +include $(CHIBIOS)/os/nil/nil.mk +include $(CHIBIOS_CONTRIB)/os/common/ports/MSP430X/compilers/GCC/mk/port.mk +# Other files (optional). +include $(CHIBIOS)/test/nil/test.mk + +# Define linker script file here +LDSCRIPT = $(STARTUPLD)/msp430fr5969.ld + +# C sources +CSRC = $(STARTUPSRC) \ + $(KERNSRC) \ + $(PORTSRC) \ + $(OSALSRC) \ + $(HALSRC) \ + $(PLATFORMSRC) \ + $(BOARDSRC) \ + $(TESTSRC) \ + main.c + +# C++ sources +CPPSRC = + +# List ASM source files here +ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) + +INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ + $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \ + $(CHIBIOS)/os/various + +# +# Project, sources and paths +############################################################################## + +############################################################################## +# Compiler settings +# + +MCU = msp430fr5969 + +TRGT = msp430-elf- +CC = $(TRGT)gcc +CPPC = $(TRGT)g++ +# Enable loading with g++ only if you need C++ runtime support. +# NOTE: You can use C++ even without C++ support if you are careful. C++ +# runtime support makes code size explode. +LD = $(TRGT)gcc +#LD = $(TRGT)g++ +CP = $(TRGT)objcopy +AS = $(TRGT)gcc -x assembler-with-cpp +AR = $(TRGT)ar +OD = $(TRGT)objdump +SZ = $(TRGT)size +HEX = $(CP) -O ihex +BIN = $(CP) -O binary + +# MSP430-specific options here +MOPT = -m$(MODEL) + +# Define C warning options here +CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes + +# Define C++ warning options here +CPPWARN = -Wall -Wextra -Wundef + +# +# Compiler settings +############################################################################## + +############################################################################## +# Start of user section +# + +# List all user C define here, like -D_DEBUG=1 +UDEFS = + +# Define ASM defines here +UADEFS = + +# List all user directories here +UINCDIR = + +# List the user directory to look for the libraries here +ULIBDIR = + +# List all user libraries here +ULIBS = + +# +# End of user defines +############################################################################## + +RULESPATH = $(CHIBIOS_CONTRIB)/os/common/startup/MSP430X/compilers/GCC +include $(RULESPATH)/rules.mk diff --git a/demos/MSP430X/NIL-EXP430FR5969/chconf.h b/demos/MSP430X/NIL-EXP430FR5969/chconf.h new file mode 100644 index 00000000..bf2ad1bb --- /dev/null +++ b/demos/MSP430X/NIL-EXP430FR5969/chconf.h @@ -0,0 +1,274 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file nilconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_NIL_CONF_ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Number of user threads in the application. + * @note This number is not inclusive of the idle thread which is + * Implicitly handled. + */ +#define CH_CFG_NUM_THREADS 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name System timer settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 16 + +/** + * @brief System tick frequency. + * @note This value together with the @p CH_CFG_ST_RESOLUTION + * option defines the maximum amount of time allowed for + * timeouts. + */ +#define CH_CFG_ST_FREQUENCY 1000 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 0 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note Feature not currently implemented. + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note Feature not currently implemented. + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief System assertions. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Stack check. + * + *@note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_STACK_CHECK TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System initialization hook. + */ +#if !defined(CH_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__) +#define CH_CFG_SYSTEM_INIT_HOOK() { \ +} +#endif + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXT_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + */ +#define CH_CFG_THREAD_EXT_INIT_HOOK(tr) { \ + /* Add custom threads initialization code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ +} + +/** + * @brief System halt hook. + */ +#if !defined(CH_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ +} +#endif + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in nilcore.h). */ +/*===========================================================================*/ + +#endif /* _CHCONF_H_ */ + +/** @} */ diff --git a/demos/MSP430X/NIL-EXP430FR5969/halconf.h b/demos/MSP430X/NIL-EXP430FR5969/halconf.h new file mode 100644 index 00000000..b15e6891 --- /dev/null +++ b/demos/MSP430X/NIL-EXP430FR5969/halconf.h @@ -0,0 +1,381 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the EXT subsystem. + */ +#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) +#define HAL_USE_EXT FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB FALSE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB FALSE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE FALSE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS FALSE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING FALSE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING FALSE +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 256 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +#endif /* _HALCONF_H_ */ + +/** @} */ diff --git a/demos/MSP430X/NIL-EXP430FR5969/main.c b/demos/MSP430X/NIL-EXP430FR5969/main.c new file mode 100644 index 00000000..27f0e520 --- /dev/null +++ b/demos/MSP430X/NIL-EXP430FR5969/main.c @@ -0,0 +1,76 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + 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 "hal.h" +#include "ch.h" +#include "ch_test.h" +#include "test_root.h" + +/* + * Thread 2. + */ +THD_WORKING_AREA(waThread2, 2048); +THD_FUNCTION(Thread2, arg) { + + (void)arg; + + /* + * Activate the serial driver 0 using the driver default configuration. + */ + sdStart(&SD0, NULL); + + while (chnGetTimeout(&SD0, TIME_INFINITE)) { + chnWrite(&SD0, (const uint8_t *)"Hello World!\r\n", 14); + test_execute((void*)&SD0); + chThdSleepMilliseconds(2000); + } +} + +/* + * Threads static table, one entry per thread. The number of entries must + * match NIL_CFG_NUM_THREADS. + */ +THD_TABLE_BEGIN + THD_TABLE_ENTRY(wa_test_support, "test_support", test_support, + (void *)&nil.threads[1]) + THD_TABLE_ENTRY(waThread2, "hello", Thread2, NULL) +THD_TABLE_END + +/* + * Application entry point. + */ +int main(void) { + + /* + * System initializations. + * - HAL initialization, this also initializes the configured device drivers + * and performs the board-specific initializations. + * - Kernel initialization, the main() function becomes a thread and the + * RTOS is active. + */ + WDTCTL = WDTPW | WDTHOLD; + + + halInit(); + chSysInit(); + + /* This is now the idle thread loop, you may perform here a low priority + task but you must never try to sleep or wait in this loop. Note that + this tasks runs at the lowest priority level so any instruction added + here will be executed after all other tasks have been started.*/ + while (true) { + } +} diff --git a/demos/MSP430X/NIL-EXP430FR5969/mcuconf.h b/demos/MSP430X/NIL-EXP430FR5969/mcuconf.h new file mode 100644 index 00000000..f47ee126 --- /dev/null +++ b/demos/MSP430X/NIL-EXP430FR5969/mcuconf.h @@ -0,0 +1,55 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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 MCUCONF_H +#define MCUCONF_H + +/* + * MSP430X drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the driver + * is enabled in halconf.h. + * + */ + +#define MSP430X_MCUCONF + +/* HAL driver system settings */ +#define MSP430X_ACLK_SRC MSP430X_VLOCLK +#define MSP430X_LFXTCLK_FREQ 0 +#define MSP430X_HFXTCLK_FREQ 0 +#define MSP430X_DCOCLK_FREQ 8000000 +#define MSP430X_MCLK_DIV 1 +#define MSP430X_SMCLK_DIV 32 + +/* + * SERIAL driver system settings. + */ +#define MSP430X_SERIAL_USE_USART0 TRUE +#define MSP430X_USART0_CLK_SRC MSP430X_SMCLK_SRC +#define MSP430X_SERIAL_USE_USART1 FALSE +#define MSP430X_SERIAL_USE_USART2 FALSE +#define MSP430X_SERIAL_USE_USART3 FALSE + +/* + * ST driver system settings. + */ +#define MSP430X_ST_CLK_SRC MSP430X_SMCLK_SRC +#define MSP430X_ST_TIMER_TYPE B +#define MSP430X_ST_TIMER_INDEX 0 + +#endif /* _MCUCONF_H_ */ diff --git a/os/common/ports/MSP430X/chcore.c b/os/common/ports/MSP430X/chcore.c new file mode 100644 index 00000000..4e09b8fc --- /dev/null +++ b/os/common/ports/MSP430X/chcore.c @@ -0,0 +1,103 @@ +/* + ChibiOS/HAL - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/nilcore.c + * @brief MSP430X port code. + * + * @addtogroup MSP430X_CORE + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +#if !defined(__DOXYGEN__) && defined(__OPTIMIZE__) +__attribute__((naked)) +#endif +void _port_switch(thread_t *ntp, thread_t *otp) { +#if !defined(__OPTIMIZE__) + asm volatile ("add #4, r1"); +#endif + (void)(ntp); + (void)(otp); +#if defined(__MSP430X_LARGE__) + asm volatile ("pushm.a #7, R10"); + asm volatile ("mova r1, @R13"); + asm volatile ("mova @R12, r1"); + asm volatile ("popm.a #7, R10"); + asm volatile ("reta"); +#else + asm volatile ("pushm.w #7, R10"); + asm volatile ("mov r1, @R13"); + asm volatile ("mov @R12, r1"); + asm volatile ("popm.w #7, R10"); + asm volatile ("ret"); +#endif +} + +/** + * @brief Start a thread by invoking its work function. + * @details If the work function returns @p chThdExit() is automatically + * invoked. + */ +void _port_thread_start(void) { + + /* See PORT_SETUP_CONTEXT in nilcore.h */ + chSysUnlock(); +#if defined(__MSP430X_LARGE__) + asm volatile ("mova R5, R12"); + asm volatile ("calla R4"); +#else + asm volatile ("mov R5, R12"); + asm volatile ("call R4"); +#endif + chSysHalt(0); +} +/** @} */ diff --git a/os/common/ports/MSP430X/chcore.h b/os/common/ports/MSP430X/chcore.h new file mode 100644 index 00000000..09f87c4c --- /dev/null +++ b/os/common/ports/MSP430X/chcore.h @@ -0,0 +1,437 @@ +/* + ChibiOS/HAL - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/nilcore.h + * @brief MSP430X port macros and structures. + * + * @addtogroup MSP430X_CORE + * @{ + */ + +#ifndef CHCORE_H +#define CHCORE_H + +#include +#include + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Architecture and Compiler + * @{ + */ +/** + * @brief Macro defining the port architecture. + */ +#define PORT_ARCHITECTURE_MSP430X + +/** + * @brief Name of the implemented architecture. + */ +#define PORT_ARCHITECTURE_NAME "MSP430X" + +/** + * @brief Name of the architecture variant. + */ +#define PORT_CORE_VARIANT_NAME "MSP430Xv2" + +/* The following code is not processed when the file is included from an + * asm module because those intrinsic macrosa re not necessarily defined + * by the assembler too.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Compiler name and version. + */ +#if defined(__GNUC__) || defined(__DOXYGEN__) +#define PORT_COMPILER_NAME "GCC " __VERSION__ + +#else +#error "unsupported compiler" +#endif + +#endif /* !defined(_FROM_ASM_) */ +/** + * @brief Port-specific information string. + */ +#define PORT_INFO "16 bits code addressing" + +/** + * @brief This port supports a realtime counter. + */ +#define PORT_SUPPORTS_RT FALSE +/** @} */ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + * @note In this port it is set to 8. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) +#define PORT_IDLE_THREAD_STACK_SIZE 8 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * @note In this port the default is 32 bytes per thread. + */ +#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) +#define PORT_INT_REQUIRED_STACK 32 +#endif + +/** + * @brief Enables an alternative timer implementation. + * @details Usually the port uses a timer interface defined in the file + * @p nilcore_timer.h, if this option is enabled then the file + * @p nilcore_timer_alt.h is included instead. + */ +#if !defined(PORT_USE_ALT_TIMER) +#define PORT_USE_ALT_TIMER FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Type of stack and memory alignment enforcement. + */ +typedef uint16_t stkalign_t; + +/** + * @brief Type of natural register size - depends on memory model. + */ +#if defined(__MSP430X_LARGE__) +typedef unsigned __int20 reg_t; +#else +typedef uint16_t reg_t; +#endif + +/** + * @brief Natural alignment constant. + * @note It is the minimum alignment for pointer-size variables. + */ +#define PORT_NATURAL_ALIGN 2U + +/** + * @brief Stack alignment constant. + * @note It is the alignement required for the stack pointer. + */ +#define PORT_STACK_ALIGN 2U + +/** + * @brief Working Areas alignment constant. + * @note It is the alignment to be enforced for thread working areas. + */ +#define PORT_WORKING_AREA_ALIGN 2U +/** @} */ + +/** + * @brief System saved context. + * @details This structure represents the inner stack frame during a context + * switching. + */ +struct port_intctx { + reg_t r4; + reg_t r5; + reg_t r6; + reg_t r7; + reg_t r8; + reg_t r9; + reg_t r10; + reg_t r0; /* program counter */ +}; + +/** + * @brief Platform dependent part of the @p thread_t structure. + * @details This structure usually contains just the saved stack pointer + * defined as a pointer to a @p port_intctx structure. + */ +struct port_context { + struct port_intctx *sp; +}; + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Platform dependent thread stack setup. + * @details This code usually setup the context switching frame represented + * by an @p port_intctx structure. + */ +#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ + (tp)->ctx.sp = (struct port_intctx*)(((uint8_t *)(wtop)) - \ + sizeof(struct port_intctx)); \ + (tp)->ctx.sp->r4 = (reg_t)pf; \ + (tp)->ctx.sp->r5 = (reg_t)arg; \ + (tp)->ctx.sp->r0 = (reg_t)_port_thread_start; \ +} + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + */ +#define PORT_WORKING_AREA(s, n) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] + +/** + * @brief Computes the thread working area global size. + * @note There is no need to perform alignments in this macro. + */ +#define PORT_WA_SIZE(n) ((sizeof(struct port_intctx) - 1) + \ + (n) + (PORT_INT_REQUIRED_STACK)) + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_PROLOGUE() + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_EPILOGUE() chSchRescheduleS() + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_IRQ_HANDLER(id) __attribute__ ((interrupt(id))) \ + void ISR_ ## id (void) + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_FAST_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id) + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +#define port_switch(ntp, otp) _port_switch(ntp, otp) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +#ifdef __cplusplus +extern "C" { +#endif + void _port_irq_epilogue(void); + void _port_switch(thread_t *ntp, thread_t *otp); + void _port_thread_start(void); +#ifdef __cplusplus +} +#endif + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Port-related initialization code. + */ +static inline void port_init(void) { + +} + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +static inline syssts_t port_get_irq_status(void) { + + return __get_SR_register(); +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retvel false the word specified a disabled interrupts status. + * @retvel true the word specified an enabled interrupts status. + */ +static inline bool port_irq_enabled(syssts_t sts) { + + return sts & GIE; +} + +/** + * @brief Determines the current execution context. + * + * @return The execution context. + * @retval false not running in ISR mode. + * @retval true running in ISR mode. + */ +static inline bool port_is_isr_context(void) { + /* Efficiency would be enhanced by not doing this, + * because of implementation details */ + return __get_SR_register() & GIE; +} + +/** + * @brief Kernel-lock action. + */ +static inline void port_lock(void) { + + _disable_interrupts(); + asm volatile("nop"); +} + +/** + * @brief Kernel-unlock action. + */ +static inline void port_unlock(void) { + asm volatile("nop"); + _enable_interrupts(); +} + +/** + * @brief Kernel-lock action from an interrupt handler. + * @note This function is empty in this port. + */ +static inline void port_lock_from_isr(void) { + +} + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @note This function is empty in this port. + */ +static inline void port_unlock_from_isr(void) { + +} + +/** + * @brief Disables all the interrupt sources. + */ +static inline void port_disable(void) { + + _disable_interrupts(); + asm volatile("nop"); +} + +/** + * @brief Disables the interrupt sources below kernel-level priority. + */ +static inline void port_suspend(void) { + + _disable_interrupts(); + asm volatile("nop"); +} + +/** + * @brief Enables all the interrupt sources. + */ +static inline void port_enable(void) { + + asm volatile("nop"); + _enable_interrupts(); +} + +/** + * @brief Enters an architecture-dependent IRQ-waiting mode. + * @details The function is meant to return when an interrupt becomes pending. + * The simplest implementation is an empty function or macro but this + * would not take advantage of architecture-specific power saving + * modes. + */ +static inline void port_wait_for_interrupt(void) { + +} + +/** + * @brief Returns the current value of the realtime counter. + * + * @return The realtime counter value. + */ +static inline rtcnt_t port_rt_get_counter_value(void) { + /* TODO implement realtime counter */ + return 0; +} + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module late inclusions. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) + +#if CH_CFG_ST_TIMEDELTA > 0 +#if !PORT_USE_ALT_TIMER +#include "chcore_timer.h" +#else /* PORT_USE_ALT_TIMER */ +#include "chcore_timer_alt.h" +#endif /* PORT_USE_ALT_TIMER */ +#endif /* CH_CFG_ST_TIMEDELTA > 0 */ + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* CHCORE_H */ + +/** @} */ diff --git a/os/common/ports/MSP430X/chcore_timer.h b/os/common/ports/MSP430X/chcore_timer.h new file mode 100644 index 00000000..87ea5146 --- /dev/null +++ b/os/common/ports/MSP430X/chcore_timer.h @@ -0,0 +1,119 @@ +/* + ChibiOS/HAL - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/chcore_timer.h + * @brief System timer header file. + * + * @addtogroup MSP430X_TIMER + * @{ + */ + +#ifndef CHCORE_TIMER_H +#define CHCORE_TIMER_H + +#include "hal_st.h" + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] abstime the time to be set for the first alarm + * + * @notapi + */ +static inline void port_timer_start_alarm(systime_t abstime) { + + stStartAlarm(abstime); +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void port_timer_stop_alarm(void) { + stStopAlarm(); +} + +/** + * @brief Sets the alarm time. + * + * @param[in] abstime the time to be set for the next alarm + * + * @notapi + */ +static inline void port_timer_set_alarm(systime_t abstime) { + + stSetAlarm(abstime); +} + +/** + * @brief Returns the system time. + * + * @return The system time. + * + * @notapi + */ +static inline systime_t port_timer_get_time(void) { + + return stGetCounter(); +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t port_timer_get_alarm(void) { + + return stGetAlarm(); +} + +#endif /* CHCORE_TIMER_H */ + +/** @} */ diff --git a/os/common/ports/MSP430X/compilers/GCC/chtypes.h b/os/common/ports/MSP430X/compilers/GCC/chtypes.h new file mode 100644 index 00000000..11cc9802 --- /dev/null +++ b/os/common/ports/MSP430X/compilers/GCC/chtypes.h @@ -0,0 +1,99 @@ +/* + ChibiOS/HAL - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/compilers/GCC/chtypes.h + * @brief MSP430X port system types. + * + * @addtogroup MSP430X_GCC_CORE + * @{ + */ + +#ifndef CHTYPES_H +#define CHTYPES_H + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint16_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint16_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint8_t tprio_t; /**< Thread priority. */ +typedef int16_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint8_t eventmask_t; /**< Mask of event identifiers. */ +typedef int16_t cnt_t; /**< Generic signed counter. */ +typedef uint16_t ucnt_t; /**< Generic unsigned counter. */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE __attribute__((noinline)) + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) \ + void tname(void *arg) + +/** + * @brief Packed variable specifier. + */ +#define PACKED_VAR __attribute__((packed)) + +/** + * @brief Memory alignment enforcement for variables. + */ +#define ALIGNED_VAR(n) __attribute__((aligned(n))) + +#endif /* _NILTYPES_H_ */ + +/** @} */ diff --git a/os/common/ports/MSP430X/compilers/GCC/mk/port.mk b/os/common/ports/MSP430X/compilers/GCC/mk/port.mk new file mode 100644 index 00000000..0ef53785 --- /dev/null +++ b/os/common/ports/MSP430X/compilers/GCC/mk/port.mk @@ -0,0 +1,7 @@ +# List of the ChibiOS/RT MSP430X port files. +PORTSRC = ${CHIBIOS_CONTRIB}/os/common/ports/MSP430X/chcore.c + +PORTASM = + +PORTINC = ${CHIBIOS_CONTRIB}/os/common/ports/MSP430X \ + ${CHIBIOS_CONTRIB}/os/common/ports/MSP430X/compilers/GCC diff --git a/os/common/startup/MSP430X/compilers/GCC/ld/msp430fr5969.ld b/os/common/startup/MSP430X/compilers/GCC/ld/msp430fr5969.ld new file mode 100644 index 00000000..b6184554 --- /dev/null +++ b/os/common/startup/MSP430X/compilers/GCC/ld/msp430fr5969.ld @@ -0,0 +1,390 @@ +/* This file supports MSP430FR5969 devices. */ +/* Version: 1.0 */ +/* ChibiOS linker script, for normal executables */ + +OUTPUT_ARCH(msp430) +ENTRY(_start) + +MEMORY { + SFR : ORIGIN = 0x0000, LENGTH = 0x0010 /* END=0x0010, size 16 */ + PERIPHERAL_8BIT : ORIGIN = 0x0010, LENGTH = 0x00F0 /* END=0x0100, size 240 */ + PERIPHERAL_16BIT : ORIGIN = 0x0100, LENGTH = 0x0100 /* END=0x0200, size 256 */ + RAM : ORIGIN = 0x1C00, LENGTH = 0x0800 /* END=0x23FF, size 2048 */ + INFOMEM : ORIGIN = 0x1800, LENGTH = 0x0200 /* END=0x19FF, size 512 as 4 128-byte segments */ + INFOA : ORIGIN = 0x1980, LENGTH = 0x0080 /* END=0x19FF, size 128 */ + INFOB : ORIGIN = 0x1900, LENGTH = 0x0080 /* END=0x197F, size 128 */ + INFOC : ORIGIN = 0x1880, LENGTH = 0x0080 /* END=0x18FF, size 128 */ + INFOD : ORIGIN = 0x1800, LENGTH = 0x0080 /* END=0x187F, size 128 */ + FRAM (rxw) : ORIGIN = 0x4400, LENGTH = 0xBB80 /* END=0xFF7F, size 48000 */ + VECT1 : ORIGIN = 0xFF90, LENGTH = 0x0002 + VECT2 : ORIGIN = 0xFF92, LENGTH = 0x0002 + VECT3 : ORIGIN = 0xFF94, LENGTH = 0x0002 + VECT4 : ORIGIN = 0xFF96, LENGTH = 0x0002 + VECT5 : ORIGIN = 0xFF98, LENGTH = 0x0002 + VECT6 : ORIGIN = 0xFF9A, LENGTH = 0x0002 + VECT7 : ORIGIN = 0xFF9C, LENGTH = 0x0002 + VECT8 : ORIGIN = 0xFF9E, LENGTH = 0x0002 + VECT9 : ORIGIN = 0xFFA0, LENGTH = 0x0002 + VECT10 : ORIGIN = 0xFFA2, LENGTH = 0x0002 + VECT11 : ORIGIN = 0xFFA4, LENGTH = 0x0002 + VECT12 : ORIGIN = 0xFFA6, LENGTH = 0x0002 + VECT13 : ORIGIN = 0xFFA8, LENGTH = 0x0002 + VECT14 : ORIGIN = 0xFFAA, LENGTH = 0x0002 + VECT15 : ORIGIN = 0xFFAC, LENGTH = 0x0002 + VECT16 : ORIGIN = 0xFFAE, LENGTH = 0x0002 + VECT17 : ORIGIN = 0xFFB0, LENGTH = 0x0002 + VECT18 : ORIGIN = 0xFFB2, LENGTH = 0x0002 + VECT19 : ORIGIN = 0xFFB4, LENGTH = 0x0002 + VECT20 : ORIGIN = 0xFFB6, LENGTH = 0x0002 + VECT21 : ORIGIN = 0xFFB8, LENGTH = 0x0002 + VECT22 : ORIGIN = 0xFFBA, LENGTH = 0x0002 + VECT23 : ORIGIN = 0xFFBC, LENGTH = 0x0002 + VECT24 : ORIGIN = 0xFFBE, LENGTH = 0x0002 + VECT25 : ORIGIN = 0xFFC0, LENGTH = 0x0002 + VECT26 : ORIGIN = 0xFFC2, LENGTH = 0x0002 + VECT27 : ORIGIN = 0xFFC4, LENGTH = 0x0002 + VECT28 : ORIGIN = 0xFFC6, LENGTH = 0x0002 + VECT29 : ORIGIN = 0xFFC8, LENGTH = 0x0002 + VECT30 : ORIGIN = 0xFFCA, LENGTH = 0x0002 + VECT31 : ORIGIN = 0xFFCC, LENGTH = 0x0002 + VECT32 : ORIGIN = 0xFFCE, LENGTH = 0x0002 + VECT33 : ORIGIN = 0xFFD0, LENGTH = 0x0002 + VECT34 : ORIGIN = 0xFFD2, LENGTH = 0x0002 + VECT35 : ORIGIN = 0xFFD4, LENGTH = 0x0002 + VECT36 : ORIGIN = 0xFFD6, LENGTH = 0x0002 + VECT37 : ORIGIN = 0xFFD8, LENGTH = 0x0002 + VECT38 : ORIGIN = 0xFFDA, LENGTH = 0x0002 + VECT39 : ORIGIN = 0xFFDC, LENGTH = 0x0002 + VECT40 : ORIGIN = 0xFFDE, LENGTH = 0x0002 + VECT41 : ORIGIN = 0xFFE0, LENGTH = 0x0002 + VECT42 : ORIGIN = 0xFFE2, LENGTH = 0x0002 + VECT43 : ORIGIN = 0xFFE4, LENGTH = 0x0002 + VECT44 : ORIGIN = 0xFFE6, LENGTH = 0x0002 + VECT45 : ORIGIN = 0xFFE8, LENGTH = 0x0002 + VECT46 : ORIGIN = 0xFFEA, LENGTH = 0x0002 + VECT47 : ORIGIN = 0xFFEC, LENGTH = 0x0002 + VECT48 : ORIGIN = 0xFFEE, LENGTH = 0x0002 + VECT49 : ORIGIN = 0xFFF0, LENGTH = 0x0002 + VECT50 : ORIGIN = 0xFFF2, LENGTH = 0x0002 + VECT51 : ORIGIN = 0xFFF4, LENGTH = 0x0002 + VECT52 : ORIGIN = 0xFFF6, LENGTH = 0x0002 + VECT53 : ORIGIN = 0xFFF8, LENGTH = 0x0002 + VECT54 : ORIGIN = 0xFFFA, LENGTH = 0x0002 + VECT55 : ORIGIN = 0xFFFC, LENGTH = 0x0002 + RESETVEC : ORIGIN = 0xFFFE, LENGTH = 0x0002 + BSL : ORIGIN = 0x1000, LENGTH = 0x0800 + HIFRAM (rxw) : ORIGIN = 0x00010000, LENGTH = 0x00003FFF +} + +PHDRS { + vectors PT_LOAD ; + stack PT_LOAD ; + rodata PT_LOAD ; + data PT_LOAD ; + text PT_LOAD ; + upper_rodata PT_LOAD ; + upper_data PT_LOAD ; + upper_text PT_LOAD ; +} + +SECTIONS +{ + __interrupt_vector_1 : { KEEP (*(__interrupt_vector_1 )) } > VECT1 :vectors =0x3C00 + __interrupt_vector_2 : { KEEP (*(__interrupt_vector_2 )) } > VECT2 =0x3C00 + __interrupt_vector_3 : { KEEP (*(__interrupt_vector_3 )) } > VECT3 =0x3C00 + __interrupt_vector_4 : { KEEP (*(__interrupt_vector_4 )) } > VECT4 =0x3C00 + __interrupt_vector_5 : { KEEP (*(__interrupt_vector_5 )) } > VECT5 =0x3C00 + __interrupt_vector_6 : { KEEP (*(__interrupt_vector_6 )) } > VECT6 =0x3C00 + __interrupt_vector_7 : { KEEP (*(__interrupt_vector_7 )) } > VECT7 =0x3C00 + __interrupt_vector_8 : { KEEP (*(__interrupt_vector_8 )) } > VECT8 =0x3C00 + __interrupt_vector_9 : { KEEP (*(__interrupt_vector_9 )) } > VECT9 =0x3C00 + __interrupt_vector_10 : { KEEP (*(__interrupt_vector_10)) } > VECT10 =0x3C00 + __interrupt_vector_11 : { KEEP (*(__interrupt_vector_11)) } > VECT11 =0x3C00 + __interrupt_vector_12 : { KEEP (*(__interrupt_vector_12)) } > VECT12 =0x3C00 + __interrupt_vector_13 : { KEEP (*(__interrupt_vector_13)) } > VECT13 =0x3C00 + __interrupt_vector_14 : { KEEP (*(__interrupt_vector_14)) } > VECT14 =0x3C00 + __interrupt_vector_15 : { KEEP (*(__interrupt_vector_15)) } > VECT15 =0x3C00 + __interrupt_vector_16 : { KEEP (*(__interrupt_vector_16)) } > VECT16 =0x3C00 + __interrupt_vector_17 : { KEEP (*(__interrupt_vector_17)) } > VECT17 =0x3C00 + __interrupt_vector_18 : { KEEP (*(__interrupt_vector_18)) } > VECT18 =0x3C00 + __interrupt_vector_19 : { KEEP (*(__interrupt_vector_19)) } > VECT19 =0x3C00 + __interrupt_vector_20 : { KEEP (*(__interrupt_vector_20)) } > VECT20 =0x3C00 + __interrupt_vector_21 : { KEEP (*(__interrupt_vector_21)) } > VECT21 =0x3C00 + __interrupt_vector_22 : { KEEP (*(__interrupt_vector_22)) } > VECT22 =0x3C00 + __interrupt_vector_23 : { KEEP (*(__interrupt_vector_23)) } > VECT23 =0x3C00 + __interrupt_vector_24 : { KEEP (*(__interrupt_vector_24)) } > VECT24 =0x3C00 + __interrupt_vector_25 : { KEEP (*(__interrupt_vector_25)) } > VECT25 =0x3C00 + __interrupt_vector_26 : { KEEP (*(__interrupt_vector_26)) } > VECT26 =0x3C00 + __interrupt_vector_27 : { KEEP (*(__interrupt_vector_27)) } > VECT27 =0x3C00 + __interrupt_vector_28 : { KEEP (*(__interrupt_vector_28)) } > VECT28 =0x3C00 + __interrupt_vector_29 : { KEEP (*(__interrupt_vector_29)) } > VECT29 =0x3C00 + __interrupt_vector_30 : { KEEP (*(__interrupt_vector_30)) } > VECT30 =0x3C00 + __interrupt_vector_31 : { KEEP (*(__interrupt_vector_31)) KEEP (*(__interrupt_vector_aes256)) } > VECT31 =0x3C00 + __interrupt_vector_32 : { KEEP (*(__interrupt_vector_32)) KEEP (*(__interrupt_vector_rtc)) } > VECT32 =0x3C00 + __interrupt_vector_33 : { KEEP (*(__interrupt_vector_33)) KEEP (*(__interrupt_vector_port4)) } > VECT33 =0x3C00 + __interrupt_vector_34 : { KEEP (*(__interrupt_vector_34)) KEEP (*(__interrupt_vector_port3)) } > VECT34 =0x3C00 + __interrupt_vector_35 : { KEEP (*(__interrupt_vector_35)) KEEP (*(__interrupt_vector_timer3_a1)) } > VECT35 =0x3C00 + __interrupt_vector_36 : { KEEP (*(__interrupt_vector_36)) KEEP (*(__interrupt_vector_timer3_a0)) } > VECT36 =0x3C00 + __interrupt_vector_37 : { KEEP (*(__interrupt_vector_37)) KEEP (*(__interrupt_vector_port2)) } > VECT37 =0x3C00 + __interrupt_vector_38 : { KEEP (*(__interrupt_vector_38)) KEEP (*(__interrupt_vector_timer2_a1)) } > VECT38 =0x3C00 + __interrupt_vector_39 : { KEEP (*(__interrupt_vector_39)) KEEP (*(__interrupt_vector_timer2_a0)) } > VECT39 =0x3C00 + __interrupt_vector_40 : { KEEP (*(__interrupt_vector_40)) KEEP (*(__interrupt_vector_port1)) } > VECT40 =0x3C00 + __interrupt_vector_41 : { KEEP (*(__interrupt_vector_41)) KEEP (*(__interrupt_vector_timer1_a1)) } > VECT41 =0x3C00 + __interrupt_vector_42 : { KEEP (*(__interrupt_vector_42)) KEEP (*(__interrupt_vector_timer1_a0)) } > VECT42 =0x3C00 + __interrupt_vector_43 : { KEEP (*(__interrupt_vector_43)) KEEP (*(__interrupt_vector_dma)) } > VECT43 =0x3C00 + __interrupt_vector_44 : { KEEP (*(__interrupt_vector_44)) KEEP (*(__interrupt_vector_usci_a1)) } > VECT44 =0x3C00 + __interrupt_vector_45 : { KEEP (*(__interrupt_vector_45)) KEEP (*(__interrupt_vector_timer0_a1)) } > VECT45 =0x3C00 + __interrupt_vector_46 : { KEEP (*(__interrupt_vector_46)) KEEP (*(__interrupt_vector_timer0_a0)) } > VECT46 =0x3C00 + __interrupt_vector_47 : { KEEP (*(__interrupt_vector_47)) KEEP (*(__interrupt_vector_adc12)) } > VECT47 =0x3C00 + __interrupt_vector_48 : { KEEP (*(__interrupt_vector_48)) KEEP (*(__interrupt_vector_usci_b0)) } > VECT48 =0x3C00 + __interrupt_vector_49 : { KEEP (*(__interrupt_vector_49)) KEEP (*(__interrupt_vector_usci_a0)) } > VECT49 =0x3C00 + __interrupt_vector_50 : { KEEP (*(__interrupt_vector_50)) KEEP (*(__interrupt_vector_wdt)) } > VECT50 =0x3C00 + __interrupt_vector_51 : { KEEP (*(__interrupt_vector_51)) KEEP (*(__interrupt_vector_timer0_b1)) } > VECT51 =0x3C00 + __interrupt_vector_52 : { KEEP (*(__interrupt_vector_52)) KEEP (*(__interrupt_vector_timer0_b0)) } > VECT52 =0x3C00 + __interrupt_vector_53 : { KEEP (*(__interrupt_vector_53)) KEEP (*(__interrupt_vector_comp_e)) } > VECT53 =0x3C00 + __interrupt_vector_54 : { KEEP (*(__interrupt_vector_54)) KEEP (*(__interrupt_vector_unmi)) } > VECT54 =0x3C00 + __interrupt_vector_55 : { KEEP (*(__interrupt_vector_55)) KEEP (*(__interrupt_vector_sysnmi)) } > VECT55 =0x3C00 + __reset_vector : + { + KEEP (*(__interrupt_vector_56)) + KEEP (*(__interrupt_vector_reset)) + KEEP (*(.resetvec)) + } > RESETVEC + + .stack : + { + __main_thread_stack_base__ = .; + *(.stack) + . += __idle_stack_size__; + PROVIDE (__stack = .); + . = ALIGN(2); + __main_thread_stack_end__ = .; + } > FRAM :stack + + .rodata : + { + . = ALIGN(2); + *(.plt) + *(.rodata .rodata.* .gnu.linkonce.r.* .const .const:*) + *(.rodata1) + *(.lower.rodata.* .lower.rodata) + + *(.eh_frame_hdr) + KEEP (*(.eh_frame)) + KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + LONG(0); /* Sentinel. */ + + /* gcc uses crtbegin.o to find the start of the constructors, so + we make sure it is first. Because this is a wildcard, it + doesn't matter if the user does not actually link against + crtbegin.o; the linker won't look for a file to match a + wildcard. The wildcard also means that it doesn't matter which + directory crtbegin.o is in. */ + KEEP (*crtbegin*.o(.ctors)) + + /* We don't want to include the .ctor section from from the + crtend.o file until after the sorted ctors. The .ctor section + from the crtend file contains the end of ctors marker and it + must be last */ + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + + KEEP (*crtbegin*.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > FRAM :rodata + + .data : + { + . = ALIGN(2); + PROVIDE (__datastart = .); + + KEEP (*(.jcr)) + *(.data.rel.ro.local) *(.data.rel.ro*) + *(.dynamic) + + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + *(.got.plt) *(.got) + + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + . = ALIGN(2); + *(.sdata .sdata.* .gnu.linkonce.s.* D_2 D_1) + + . = ALIGN(2); + *(.lower.data.* .lower.data) + . = ALIGN(2); + + _edata = .; + PROVIDE (edata = .); + PROVIDE (__dataend = .); + } > FRAM :data + + /* Note that crt0 assumes this is a multiple of two; all the + start/stop symbols are also assumed word-aligned. */ + PROVIDE(__romdatastart = LOADADDR(.data)); + PROVIDE (__romdatacopysize = SIZEOF(.data)); + + .bss : + { + . = ALIGN(2); + PROVIDE (__bssstart = .); + *(.dynbss) + *(.sbss .sbss.*) + *(.bss .bss.* .gnu.linkonce.b.*) + *(.lower.bss.* .lower.bss) + . = ALIGN(2); + *(COMMON) + PROVIDE (__bssend = .); + } > FRAM + PROVIDE (__bsssize = SIZEOF(.bss)); + + /* This section contains data that is not initialised at startup. */ + .noinit (NOLOAD) : + { + . = ALIGN(2); + PROVIDE (__noinit_start = .); + *(.noinit) + . = ALIGN(2); + PROVIDE (__noinit_end = .); + } > FRAM /* Because I think this has to go right above .bss */ + + _end = .; + PROVIDE (end = .); + + .text : + { + PROVIDE (_start = .); + + . = ALIGN(2); + KEEP (*(SORT(.crt_*))) + + . = ALIGN(2); + KEEP (*(.lowtext)) + + . = ALIGN(2); + *(.lower.text.* .lower.text) + + . = ALIGN(2); + *(.text .stub .text.* .gnu.linkonce.t.* .text:*) + + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.interp .hash .dynsym .dynstr .gnu.version*) + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + . = ALIGN(2); + KEEP (*(.init)) + KEEP (*(.fini)) + KEEP (*(.tm_clone_table)) + } > FRAM :text + + .upper.rodata : + { + *(.upper.rodata.* .upper.rodata) + } > HIFRAM :upper_rodata + + .upper.data : + { + __upper_data_init = LOADADDR (.upper.data); + /* Status word. */ + SHORT(1); + __high_datastart = .; + *(.upper.data.* .upper.data) + __high_dataend = .; + } > HIFRAM :upper_data + + __rom_highdatacopysize = SIZEOF(.upper.data) - 2; + __rom_highdatastart = LOADADDR(.upper.data) + 2; + + .upper.bss : + { + . = ALIGN(2); + __high_bssstart = .; + *(.upper.bss.* .upper.bss) + . = ALIGN(2); + __high_bssend = .; + } > HIFRAM + + .upper.text : + { + . = ALIGN(2); + *(.upper.text.* .upper.text) + } > HIFRAM :upper_text + + .infoA : {} > INFOA /* MSP430 INFO FLASH MEMORY SEGMENTS */ + .infoB : {} > INFOB + .infoC : {} > INFOC + .infoD : {} > INFOD + + /* The rest are all not normally part of the runtime image. */ + + .MP430.attributes 0 : + { + KEEP (*(.MSP430.attributes)) + KEEP (*(.gnu.attributes)) + KEEP (*(__TI_build_attributes)) + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1. */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions. */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2. */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2. */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions. */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + + /DISCARD/ : { *(.note.GNU-stack) } +} + +INCLUDE msp430fr5969_symbols.ld diff --git a/os/common/startup/MSP430X/compilers/GCC/mk/startup_msp430fr5xxx.mk b/os/common/startup/MSP430X/compilers/GCC/mk/startup_msp430fr5xxx.mk new file mode 100644 index 00000000..9c063cda --- /dev/null +++ b/os/common/startup/MSP430X/compilers/GCC/mk/startup_msp430fr5xxx.mk @@ -0,0 +1,10 @@ +# List of the ChibiOS generic MSP430X startup and linker files. +STARTUPSRC = +#$(CHIBIOS_CONTRIB)/os/common/startup/MSP430X/compilers/GCC/vectors.c + +STARTUPASM = + +STARTUPINC = $(CHIBIOS_CONTRIB)/os/common/startup/MSP430X/compilers/GCC + +STARTUPLD = $(CHIBIOS_CONTRIB)/os/common/startup/MSP430X/compilers/GCC/ld + diff --git a/os/common/startup/MSP430X/compilers/GCC/rules.mk b/os/common/startup/MSP430X/compilers/GCC/rules.mk new file mode 100644 index 00000000..a431b96c --- /dev/null +++ b/os/common/startup/MSP430X/compilers/GCC/rules.mk @@ -0,0 +1,269 @@ +# ARM Cortex-Mx common makefile scripts and rules. + +############################################################################## +# Processing options coming from the upper Makefile. +# + +# Compiler options +OPT = $(USE_OPT) +COPT = $(USE_COPT) +CPPOPT = $(USE_CPPOPT) + +# Garbage collection +ifeq ($(USE_LINK_GC),yes) + OPT += -ffunction-sections -fdata-sections -fno-common + LDOPT := ,--gc-sections +else + LDOPT := +endif + +# Linker extra options +ifneq ($(USE_LDOPT),) + LDOPT := $(LDOPT),$(USE_LDOPT) +endif + +# Link time optimizations +ifeq ($(USE_LTO),yes) + OPT += -flto +endif + +# HWMULT-related options +ifeq ($(USE_HWMULT),) + USE_HWMULT = none +endif +ifneq ($(USE_HWMULT),none) + OPT += -mhwmult=$(USE_HWMULT) +endif + +# Idle thread stack size +ifeq ($(USE_IDLE_STACKSIZE),) + LDOPT := $(LDOPT),--defsym=__idle_stack_size__=0x40 +else + LDOPT := $(LDOPT),--defsym=__idle_stack_size__=$(USE_IDLE_STACKSIZE) +endif + +# Output directory and files +ifeq ($(BUILDDIR),) + BUILDDIR = build +endif +ifeq ($(BUILDDIR),.) + BUILDDIR = build +endif +OUTFILES = $(BUILDDIR)/$(PROJECT).elf \ + $(BUILDDIR)/$(PROJECT).hex \ + $(BUILDDIR)/$(PROJECT).bin \ + $(BUILDDIR)/$(PROJECT).dmp \ + $(BUILDDIR)/$(PROJECT).list + +ifdef SREC + OUTFILES += $(BUILDDIR)/$(PROJECT).srec +endif + +# Source files groups and paths +ACSRC = $(CSRC) +ACPPSRC = $(CPPSRC) +ASRC = $(CSRC)$(CPPSRC) +SRCPATHS = $(sort $(dir $(ASMXSRC)) $(dir $(ASMSRC)) $(dir $(ASRC)) $(dir $(TSRC))) + +# Various directories +OBJDIR = $(BUILDDIR)/obj +LSTDIR = $(BUILDDIR)/lst + +# Object files groups +ACOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ACSRC:.c=.o))) +ACPPOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ACPPSRC:.cpp=.o))) +ASMOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ASMSRC:.s=.o))) +ASMXOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ASMXSRC:.S=.o))) +OBJS = $(ASMXOBJS) $(ASMOBJS) $(ACOBJS) $(TCOBJS) $(ACPPOBJS) $(TCPPOBJS) + +# Paths +IINCDIR = $(patsubst %,-I%,$(INCDIR) $(DINCDIR) $(UINCDIR)) +LLIBDIR = $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR)) + +# Macros +DEFS = $(DDEFS) $(UDEFS) +ADEFS = $(DADEFS) $(UADEFS) + +# Libs +LIBS = $(DLIBS) $(ULIBS) + +# Various settings +MCFLAGS = -mmcu=$(MCU) $(MOPT) +ODFLAGS = -x --syms +ASFLAGS = $(MCFLAGS) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.s=.lst)) $(ADEFS) +ASXFLAGS = $(MCFLAGS) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.S=.lst)) $(ADEFS) +CFLAGS = $(MCFLAGS) $(OPT) $(COPT) $(CWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.c=.lst)) $(DEFS) +CPPFLAGS = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.cpp=.lst)) $(DEFS) +LDFLAGS = $(MCFLAGS) $(OPT) -minrt $(LLIBDIR) -Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--no-warn-mismatch,--library-path=$(RULESPATH)/ld,--script=$(LDSCRIPT)$(LDOPT) + +# Temporary specfile to deal with messed-up msp430-elf default spec file +SPECFILE := $(shell mktemp -u) + +# Generate dependency information +ASFLAGS += -MD -MP -MF .dep/$(@F).d +CFLAGS += -MD -MP -MF .dep/$(@F).d +CPPFLAGS += -MD -MP -MF .dep/$(@F).d + +# Paths where to search for sources +VPATH = $(SRCPATHS) + +# +# Makefile rules +# + +all: PRE_MAKE_ALL_RULE_HOOK $(OBJS) $(OUTFILES) POST_MAKE_ALL_RULE_HOOK + +PRE_MAKE_ALL_RULE_HOOK: + +POST_MAKE_ALL_RULE_HOOK: + +$(OBJS): | $(BUILDDIR) $(OBJDIR) $(LSTDIR) + +$(BUILDDIR): +ifneq ($(USE_VERBOSE_COMPILE),yes) + @echo Compiler Options + @echo $(CC) -c $(CFLAGS) -I. $(IINCDIR) main.c -o main.o + @echo +endif + @mkdir -p $(BUILDDIR) + +$(OBJDIR): + @mkdir -p $(OBJDIR) + +$(LSTDIR): + @mkdir -p $(LSTDIR) + +$(ACPPOBJS) : $(OBJDIR)/%.o : %.cpp Makefile +ifeq ($(USE_VERBOSE_COMPILE),yes) + @echo + $(CPPC) -c $(CPPFLAGS) $(AOPT) -I. $(IINCDIR) $< -o $@ +else + @echo Compiling $( $(SPECFILE) + sed -i 's/%{!T.*}//' $(SPECFILE) + +$(BUILDDIR)/$(PROJECT).elf: $(OBJS) $(LDSCRIPT) $(SPECFILE) +ifeq ($(USE_VERBOSE_COMPILE),yes) + @echo + $(LD) $(LDFLAGS) -specs=$(SPECFILE) $(OBJS) $(LIBS) -o $@ +else + @echo Linking $@ + @$(LD) $(LDFLAGS) -specs=$(SPECFILE) $(OBJS) $(LIBS) -o $@ +endif + +%.hex: %.elf +ifeq ($(USE_VERBOSE_COMPILE),yes) + $(HEX) $< $@ +else + @echo Creating $@ + @$(HEX) $< $@ +endif + +%.bin: %.elf +ifeq ($(USE_VERBOSE_COMPILE),yes) + $(BIN) $< $@ +else + @echo Creating $@ + @$(BIN) $< $@ +endif + +%.srec: %.elf +ifdef SREC + ifeq ($(USE_VERBOSE_COMPILE),yes) + $(SREC) $< $@ + else + @echo Creating $@ + @$(SREC) $< $@ + endif +endif + +%.dmp: %.elf +ifeq ($(USE_VERBOSE_COMPILE),yes) + $(OD) $(ODFLAGS) $< > $@ + $(SZ) $< +else + @echo Creating $@ + @$(OD) $(ODFLAGS) $< > $@ + @echo + @$(SZ) $< +endif + +%.list: %.elf +ifeq ($(USE_VERBOSE_COMPILE),yes) + $(OD) -S $< > $@ +else + @echo Creating $@ + @$(OD) -S $< > $@ + @echo + @echo Done +endif + +lib: $(OBJS) $(BUILDDIR)/lib$(PROJECT).a + +$(BUILDDIR)/lib$(PROJECT).a: $(OBJS) + @$(AR) -r $@ $^ + @echo + @echo Done + +clean: + @echo Cleaning + -rm -fR .dep $(BUILDDIR) + @echo + @echo Done + +# +# Include the dependency files, should be the last of the makefile +# +-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) + +# *** EOF *** diff --git a/os/hal/boards/EXP430FR5969/board.c b/os/hal/boards/EXP430FR5969/board.c new file mode 100644 index 00000000..ac48ba06 --- /dev/null +++ b/os/hal/boards/EXP430FR5969/board.c @@ -0,0 +1,46 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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 "hal.h" + +/** + * @brief PAL setup. + * @details Digital I/O ports static configuration as defined in @p board.h. + * This variable is used by the HAL when initializing the PAL driver. + */ +#if HAL_USE_PAL || defined(__DOXYGEN__) +const PALConfig pal_default_config = +{ + {VAL_IOPORT1_OUT, VAL_IOPORT1_DIR, VAL_IOPORT1_REN, VAL_IOPORT1_SEL0, + VAL_IOPORT1_SEL1, VAL_IOPORT1_IES, VAL_IOPORT1_IE}, + {VAL_IOPORT2_OUT, VAL_IOPORT2_DIR, VAL_IOPORT2_REN, VAL_IOPORT2_SEL0, + VAL_IOPORT2_SEL1, VAL_IOPORT2_IES, VAL_IOPORT2_IE}, + {VAL_IOPORT0_OUT, VAL_IOPORT0_DIR, VAL_IOPORT0_REN, VAL_IOPORT0_SEL0, + VAL_IOPORT0_SEL1, VAL_IOPORT0_IES, VAL_IOPORT0_IE} +}; /* Set UART TX pin correctly */ +#endif /* HAL_USE_PAL */ + +/** + * Board-specific initialization code. + */ +void boardInit(void) { + + /* + * External interrupts setup, all disabled initially. + */ + _disable_interrupts(); + +} diff --git a/os/hal/boards/EXP430FR5969/board.h b/os/hal/boards/EXP430FR5969/board.h new file mode 100644 index 00000000..6b53f4b5 --- /dev/null +++ b/os/hal/boards/EXP430FR5969/board.h @@ -0,0 +1,129 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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 _BOARD_H_ +#define _BOARD_H_ + +/* + * Setup for the Arduino Uno or board. + */ + +/* + * Board identifier. + */ +#define BOARD_EXP430FR5959 +#define BOARD_NAME "MSP430FR5969 LaunchPad" + +/* + * IO lines assignments. + */ +#define LINE_LED_G PAL_LINE(IOPORT1, 0U) +#define LINE_LED_R PAL_LINE(IOPORT2, 14U) +#define LINE_SW_S1 PAL_LINE(IOPORT2, 13U) +#define LINE_SW_S2 PAL_LINE(IOPORT1, 1U) + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the MSP430X Family Users Guide for details. + */ +/* + * Port A setup: + * + * P1.0 - Green LED (output low) + * P1.1 - Switch S2 (input pullup falling-edge interrupt) + * P1.2 - BoosterPack BP19 (input pullup) + * P1.3 - BoosterPack BP11 (input pullup) + * P1.4 - BoosterPack BP12 (input pullup) + * P1.5 - BoosterPack BP13 (input pullup) + * P1.6 - BoosterPack BP15 (input pullup) + * P1.7 - BoosterPack BP14 (input pullup) + * P2.0 - Application UART TX (alternate 2) + * P2.1 - Application UART RX (alternate 2) + * P2.2 - BoosterPack BP7 (input pullup) + * P2.3 - N/C (input pullup) + * P2.4 - BoosterPack BP6 (input pullup) + * P2.5 - BoosterPack BP4 (input pullup) + * P2.6 - BoosterPack BP3 (input pullup) + * P2.7 - N/C (input pullup) + */ +#define VAL_IOPORT1_OUT 0xFCFE +#define VAL_IOPORT1_DIR 0x0001 +#define VAL_IOPORT1_REN 0xFCFE +#define VAL_IOPORT1_SEL0 0x0000 +#define VAL_IOPORT1_SEL1 0x0300 +#define VAL_IOPORT1_IES 0x0002 +#define VAL_IOPORT1_IE 0x0002 + +/* + * Port B setup: + * + * P3.0 - BoosterPack BP18 (input pullup) + * P3.1 - N/C (input pullup) + * P3.2 - N/C (input pullup) + * P3.3 - N/C (input pullup) + * P3.4 - BoosterPack BP8 (input pullup) + * P3.5 - BoosterPack BP9 (input pullup) + * P3.6 - BoosterPack BP10 (input pullup) + * P3.7 - N/C (input pullup) + * P4.0 - Application UART CTS (input pullup falling-edge interrupt) + * P4.1 - Application UART RTS (output high) + * P4.2 - BoosterPack BP2 (input pullup) + * P4.3 - BoosterPack BP5 (input pullup) + * P4.4 - N/C (input pullup) + * P4.5 - Switch S1 (input pullup falling-edge interrupt) + * P4.6 - Red LED (output low) + * P4.7 - N/C (input pullup) + */ +#define VAL_IOPORT2_OUT 0xBFFF +#define VAL_IOPORT2_DIR 0x4200 +#define VAL_IOPORT2_REN 0xBDFF +#define VAL_IOPORT2_SEL0 0x0000 +#define VAL_IOPORT2_SEL1 0x0000 +#define VAL_IOPORT2_IES 0x2100 +#define VAL_IOPORT2_IE 0x2100 + +/* + * Port J setup: + * + * PJ.0 - TDO (input pullup) + * PJ.1 - TDI (input pullup) + * PJ.2 - TMS (input pullup) + * PJ.3 - TCK (input pullup) + * PJ.4 - LFXIN (alternate 1) + * PJ.5 - LFXOUT (alternate 1) + * PJ.6 - HFXIN (N/C) (input pullup) + * PJ.7 - HFXOUT (N/C) (input pullup) + */ +#define VAL_IOPORT0_OUT 0x00FF +#define VAL_IOPORT0_DIR 0x0000 +#define VAL_IOPORT0_REN 0x00CF +#define VAL_IOPORT0_SEL0 0x0030 +#define VAL_IOPORT0_SEL1 0x0000 +#define VAL_IOPORT0_IES 0x0000 +#define VAL_IOPORT0_IE 0x0000 + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/os/hal/boards/EXP430FR5969/board.mk b/os/hal/boards/EXP430FR5969/board.mk new file mode 100644 index 00000000..c629257b --- /dev/null +++ b/os/hal/boards/EXP430FR5969/board.mk @@ -0,0 +1,5 @@ +# List of all the board related files. +BOARDSRC = ${CHIBIOS_CONTRIB}/os/hal/boards/EXP430FR5969/board.c + +# Required include directories +BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/EXP430FR5969 diff --git a/os/hal/ports/MSP430X/hal_lld.c b/os/hal/ports/MSP430X/hal_lld.c new file mode 100644 index 00000000..872fe97c --- /dev/null +++ b/os/hal/ports/MSP430X/hal_lld.c @@ -0,0 +1,87 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/hal_lld.c + * @brief MSP430X HAL subsystem low level driver source. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * + * @notapi + */ +void hal_lld_init(void) { + /* Disable watchdog */ + /* TODO Real watchdog support */ + WDTCTL = WDTPW | WDTHOLD; + /* Init clock system */ + CSCTL0 = CSKEY; /* unlock clock system */ + CSCTL1 = MSP430X_DCOSEL; + CSCTL2 = (MSP430X_ACLK_SRC << 8) | (MSP430X_SMCLK_SRC << 4) | (MSP430X_MCLK_SRC); + CSCTL3 = (DIVIDER(MSP430X_ACLK_DIV) << 8) | (DIVIDER(MSP430X_SMCLK_DIV) << 4) | (DIVIDER(MSP430X_MCLK_DIV)); + CSCTL4 = (MSP430X_HFXTCLK_DRIVE << 14) | (MSP430X_HFXTCLK_BYPASS << 12) | (MSP430X_HFFREQ << 10) | HFXTOFF | \ + (MSP430X_LFXTCLK_DRIVE << 6) | (MSP430X_LFXTCLK_BYPASS << 4) | VLOOFF | LFXTOFF; + CSCTL6 = (MODCLKREQEN) | (SMCLKREQEN) | (MCLKREQEN) | (ACLKREQEN); + #if defined(MSP430X_USE_HFXT) && defined(MSP430X_USE_LFXT) + do { + CSCTL5 &= ~(HFXTOFFG | LFXTOFFG); + SFRIFG1 &= ~OFIFG; + } while (SFRIFG1 & OFIFG); + #elif defined(MSP430X_USE_HFXT) + do { + CSCTL5 &= ~(HFXTOFFG); + SFRIFG1 &= ~OFIFG; + } while (SFRIFG1 & OFIFG); + #elif defined(MSP430X_USE_LFXT) + do { + CSCTL5 &= ~(LFXTOFFG); + SFRIFG1 &= ~OFIFG; + } while (SFRIFG1 & OFIFG); + #endif + CSCTL0_H = 0xFF; /* Lock clock system */ +} + +/** @} */ diff --git a/os/hal/ports/MSP430X/hal_lld.h b/os/hal/ports/MSP430X/hal_lld.h new file mode 100644 index 00000000..9549453e --- /dev/null +++ b/os/hal/ports/MSP430X/hal_lld.h @@ -0,0 +1,245 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/hal_lld.h + * @brief MSP430X HAL subsystem low level driver header. + * + * @addtogroup HAL + * @{ + */ + +#ifndef _HAL_LLD_H_ +#define _HAL_LLD_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Defines the support for realtime counters in the HAL. + */ +/* someday*/ +#define HAL_IMPLEMENTS_COUNTERS FALSE + +/** + * @name Platform identification macros + * @{ + */ +#define PLATFORM_NAME "MSP430X" +/** @} */ + +#define MSP430X_LFXTCLK 0 +#define MSP430X_VLOCLK 1 +#define MSP430X_LFMODCLK 2 +#define MSP430X_DCOCLK 3 +#define MSP430X_MODCLK 4 +#define MSP430X_HFXTCLK 5 + +#if !defined(MSP430X_LFXTCLK_FREQ) + #define MSP430X_LFXTCLK_FREQ 32768 + #warning "LFXTCLK freqency not defined - assuming 32768 Hz" +#endif +#define MSP430X_VLOCLK_FREQ 10000 +#define MSP430X_MODCLK_FREQ 5000000 +#define MSP430X_LFMODCLK_FREQ (MSP430X_MODCLK_FREQ/128) +#if !defined(MSP430X_DCOCLK_FREQ) + #define MSP430X_DCOCLK_FREQ 8000000 + #warning "DCOCLK frequency not defined - assuming 8 MHz" +#endif +#if !defined(MSP430X_HFXTCLK_FREQ) + #define MSP430X_HFXTCLK_FREQ 0 + #warning "HFXTCLK frequency not defined - assuming disabled" +#endif + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name MSP430X configuration options + * @{ + */ + +/* Clock dividers */ +#if !defined(MSP430X_ACLK_DIV) + #define MSP430X_ACLK_DIV 1 +#endif +#if !defined(MSP430X_MCLK_DIV) + #define MSP430X_MCLK_DIV 8 +#endif +#if !defined(MSP430X_SMCLK_DIV) + #define MSP430X_SMCLK_DIV 8 +#endif + +/* Clock sources */ +#if !defined(MSP430X_ACLK_SRC) + #define MSP430X_ACLK_SRC MSP430X_LFXTCLK +#endif +#if !defined(MSP430X_MCLK_SRC) + #define MSP430X_MCLK_SRC MSP430X_DCOCLK +#endif +#if !defined(MSP430X_SMCLK_SRC) + #define MSP430X_SMCLK_SRC MSP430X_DCOCLK +#endif + +/* HFXT and LFXT settings */ +#if !defined(MSP430X_LFXTCLK_BYPASS) + #define MSP430X_LFXTCLK_BYPASS 0 +#endif +#if !defined(MSP430X_LFXTCLK_DRIVE) + #define MSP430X_LFXTCLK_DRIVE 3 +#endif +#if !defined(MSP430X_HFXTCLK_BYPASS) + #define MSP430X_HFXTCLK_BYPASS 0 +#endif +#if !defined(MSP430X_HFXTCLK_DRIVE) + #define MSP430X_HFXTCLK_DRIVE 3 +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Configuration-related checks. + */ +#if (MSP430X_ACLK_SRC == MSP430X_LFXTCLK) || (MSP430X_MCLK_SRC == MSP430X_LFXTCLK) || (MSP430X_SMCLK_SRC == MSP430X_LFXTCLK) + #define MSP430X_USE_LFXTCLK +#endif +#if (MSP430X_MCLK_SRC == MSP430X_HFXTCLK) || (MSP430X_SMCLK_SRC == MSP430X_HFXTCLK) + #define MSP430X_USE_HFXTCLK +#endif + +#if defined(MSP430X_USE_HFXTCLK) && MSP430X_HFXTCLK_FREQ == 0 + #error "HFXT requested as clock source but disabled" +#endif + +/* Clock speeds */ +#if (MSP430X_ACLK_SRC == MSP430X_LFXTCLK) + #define MSP430X_ACLK_FREQ (MSP430X_LFXTCLK_FREQ / MSP430X_ACLK_DIV) +#elif (MSP430X_ACLK_SRC == MSP430X_VLOCLK) + #define MSP430X_ACLK_FREQ (MSP430X_VLOCLK_FREQ / MSP430X_ACLK_DIV) +#elif (MSP430X_ACLK_SRC == MSP430X_LFMODCLK) + #define MSP430X_ACLK_FREQ (MSP430X_LFMODCLK_FREQ / MSP430X_ACLK_DIV) +#else + #error "ACLK source invalid!" +#endif +#if (MSP430X_MCLK_SRC == MSP430X_LFXTCLK) + #define MSP430X_MCLK_FREQ (MSP430X_LFXTCLK_FREQ / MSP430X_MCLK_DIV) +#elif (MSP430X_MCLK_SRC == MSP430X_VLOCLK) + #define MSP430X_MCLK_FREQ (MSP430X_VLOCLK_FREQ / MSP430X_MCLK_DIV) +#elif (MSP430X_MCLK_SRC == MSP430X_LFMODCLK) + #define MSP430X_MCLK_FREQ (MSP430X_LFMODCLK_FREQ / MSP430X_MCLK_DIV) +#elif (MSP430X_MCLK_SRC == MSP430X_DCOCLK) + #define MSP430X_MCLK_FREQ (MSP430X_DCOCLK_FREQ / MSP430X_MCLK_DIV) +#elif (MSP430X_MCLK_SRC == MSP430X_MODCLK) + #define MSP430X_MCLK_FREQ (MSP430X_MODCLK_FREQ / MSP430X_MCLK_DIV) +#elif (MSP430X_MCLK_SRC == MSP430X_HFXTCLK) + #define MSP430X_MCLK_FREQ (MSP430X_HFXTCLK_FREQ / MSP430X_MCLK_DIV) +#else + #error "MCLK source invalid!" +#endif +#if (MSP430X_SMCLK_SRC == MSP430X_LFXTCLK) + #define MSP430X_SMCLK_FREQ (MSP430X_LFXTCLK_FREQ / MSP430X_SMCLK_DIV) +#elif (MSP430X_SMCLK_SRC == MSP430X_VLOCLK) + #define MSP430X_SMCLK_FREQ (MSP430X_VLOCLK_FREQ / MSP430X_SMCLK_DIV) +#elif (MSP430X_SMCLK_SRC == MSP430X_LFMODCLK) + #define MSP430X_SMCLK_FREQ (MSP430X_LFMODCLK_FREQ / MSP430X_SMCLK_DIV) +#elif (MSP430X_SMCLK_SRC == MSP430X_DCOCLK) + #define MSP430X_SMCLK_FREQ (MSP430X_DCOCLK_FREQ / MSP430X_SMCLK_DIV) +#elif (MSP430X_SMCLK_SRC == MSP430X_MODCLK) + #define MSP430X_SMCLK_FREQ (MSP430X_MODCLK_FREQ / MSP430X_SMCLK_DIV) +#elif (MSP430X_SMCLK_SRC == MSP430X_HFXTCLK) + #define MSP430X_SMCLK_FREQ (MSP430X_HFXTCLK_FREQ / MSP430X_SMCLK_DIV) +#else + #error "SMCLK source invalid!" +#endif + +#if !defined(MSP430X_MCUCONF) +#error "Using an incorrect mcuconf.h file, MSP430X_MCUCONF not defined" +#endif + +/* HFXT-specific settings */ +#if MSP430X_HFXTCLK_FREQ <= 4000000 + #define MSP430X_HFFREQ HFFREQ_0 +#elif MSP430X_HFXTCLK_FREQ <= 8000000 + #define MSP430X_HFFREQ HFFREQ_1 +#elif MSP430X_HFXTCLK_FREQ <= 16000000 + #define MSP430X_HFFREQ HFFREQ_2 +#elif MSP430X_HFXTCLK_FREQ <= 24000000 + #define MSP430X_HFFREQ HFFREQ_3 +#else + #error "HFXT frequency too high - must be <= 24000000" +#endif + +/* DCO-specific settings */ +#if MSP430X_DCOCLK_FREQ == 1000000 + #define MSP430X_DCOSEL DCOFSEL_0 +#elif MSP430X_DCOCLK_FREQ == 2670000 + #define MSP430X_DCOSEL DCOFSEL_1 +#elif MSP430X_DCOCLK_FREQ == 3330000 + #define MSP430X_DCOSEL DCOFSEL_2 +#elif MSP430X_DCOCLK_FREQ == 4000000 + #define MSP430X_DCOSEL DCOFSEL_3 +#elif MSP430X_DCOCLK_FREQ == 5330000 + #define MSP430X_DCOSEL DCOFSEL_4 +#elif MSP430X_DCOCLK_FREQ == 6670000 + #define MSP430X_DCOSEL DCOFSEL_5 +#elif MSP430X_DCOCLK_FREQ == 8000000 + #define MSP430X_DCOSEL DCOFSEL_6 +#elif MSP430X_DCOCLK_FREQ == 16000000 + #define MSP430X_DCOSEL (DCORSEL | DCOFSEL_4) +#elif MSP430X_DCOCLK_FREQ == 21000000 + #define MSP430X_DCOSEL (DCORSEL | DCOFSEL_5) +#elif MSP430X_DCOCLK_FREQ == 24000000 + #define MSP430X_DCOSEL (DCORSEL | DCOFSEL_6) +#else + #error "DCO frequency invalid" +#endif + +#if MSP430X_LFXTCLK_FREQ > 50000 + #error "LFXT frequency too high - must be <= 5000" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +#define DIVIDER(x) DIV_HELPER(x) +#define DIV_HELPER(x) DIVM__ ## x + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void hal_lld_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* _HAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MSP430X/hal_pal_lld.c b/os/hal/ports/MSP430X/hal_pal_lld.c new file mode 100644 index 00000000..4cfff3b9 --- /dev/null +++ b/os/hal/ports/MSP430X/hal_pal_lld.c @@ -0,0 +1,215 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/hal_pal_lld.c + * @brief MSP430X PAL subsystem low level driver source. + * + * @addtogroup PAL + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief MSP430X I/O ports configuration. + * @details GPIO registers initialization + * + * @param[in] config the MSP430X ports configuration + * + * @notapi + */ +void _pal_lld_init(const PALConfig *config) { + +#if defined(PA_BASE) || defined(__DOXYGEN__) + PAOUT = config->porta.out; + PADIR = config->porta.dir; + PAREN = config->porta.ren; + PASEL0 = config->porta.sel0; + PASEL1 = config->porta.sel1; + PAIES = config->porta.ies; + PAIE = config->porta.ie; +#endif +#if defined(PB_BASE) || defined(__DOXYGEN__) + PBOUT = config->portb.out; + PBDIR = config->portb.dir; + PBREN = config->portb.ren; + PBSEL0 = config->portb.sel0; + PBSEL1 = config->portb.sel1; + PBIES = config->portb.ies; + PBIE = config->portb.ie; +#endif +#if defined(PC_BASE) || defined(__DOXYGEN__) + PCOUT = config->portc.out; + PCDIR = config->portc.dir; + PCREN = config->portc.ren; + PCSEL0 = config->portc.sel0; + PCSEL1 = config->portc.sel1; + PCIES = config->portc.ies; + PCIE = config->portc.ie; +#endif +#if defined(PD_BASE) || defined(__DOXYGEN__) + PDOUT = config->portd.out; + PDDIR = config->portd.dir; + PDREN = config->portd.ren; + PDSEL0 = config->portd.sel0; + PDSEL1 = config->portd.sel1; + PDIES = config->portd.ies; + PDIE = config->portd.ie; +#endif +#if defined(PE_BASE) || defined(__DOXYGEN__) + PEOUT = config->porte.out; + PEDIR = config->porte.dir; + PEREN = config->porte.ren; + PESEL0 = config->porte.sel0; + PESEL1 = config->porte.sel1; + PEIES = config->porte.ies; + PEIE = config->porte.ie; +#endif +#if defined(PF_BASE) || defined(__DOXYGEN__) + PFOUT = config->portf.out; + PFDIR = config->portf.dir; + PFREN = config->portf.ren; + PFSEL0 = config->portf.sel0; + PFSEL1 = config->portf.sel1; + PFIES = config->portf.ies; + PFIE = config->portf.ie; +#endif + PJOUT = config->portj.out; + PJDIR = config->portj.dir; + PJREN = config->portj.ren; + PJSEL0 = config->portj.sel0; + PJSEL1 = config->portj.sel1; + + PM5CTL0 &= ~LOCKLPM5; +} + +/** + * @brief Pads mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note @p PAL_MODE_UNCONNECTED is implemented as input with pullup. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the mode + * + * @notapi + */ +void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode) { + + switch (mode) { + case PAL_MODE_RESET: + case PAL_MODE_INPUT: + port->dir &= ~mask; + port->ren &= ~mask; + if ((port->sel0 & mask) && (port->sel1 & mask)) + port->selc = mask; + else { + port->sel0 &= ~mask; + port->sel1 &= ~mask; + } + break; + case PAL_MODE_UNCONNECTED: + case PAL_MODE_INPUT_PULLUP: + port->dir &= ~mask; + port->ren |= mask; + port->out |= mask; + if ((port->sel0 & mask) && (port->sel1 & mask)) + port->selc = mask; + else { + port->sel0 &= ~mask; + port->sel1 &= ~mask; + } + break; + case PAL_MODE_INPUT_PULLDOWN: + port->dir &= ~mask; + port->ren |= mask; + port->out &= ~mask; + if ((port->sel0 & mask) && (port->sel1 & mask)) + port->selc = mask; + else { + port->sel0 &= ~mask; + port->sel1 &= ~mask; + } + break; + case PAL_MODE_OUTPUT_PUSHPULL: + port->dir |= mask; + if ((port->sel0 & mask) && (port->sel1 & mask)) + port->selc = mask; + else { + port->sel0 &= ~mask; + port->sel1 &= ~mask; + } + break; + case PAL_MSP430X_ALTERNATE_1: + if (!(port->sel0 & mask) && (port->sel1 & mask)) + port->selc = mask; + else { + port->sel0 |= mask; + port->sel1 &= ~mask; + } + break; + case PAL_MSP430X_ALTERNATE_2: + if ((port->sel0 & mask) && !(port->sel1 & mask)) + port->selc = mask; + else { + port->sel0 &= ~mask; + port->sel1 |= mask; + } + break; + case PAL_MSP430X_ALTERNATE_3: + if (!(port->sel0 & mask) && !(port->sel1 & mask)) + port->selc = mask; + else { + port->sel0 |= mask; + port->sel1 |= mask; + } + break; + } +} + +#endif /* HAL_USE_PAL == TRUE */ + +/** @} */ diff --git a/os/hal/ports/MSP430X/hal_pal_lld.h b/os/hal/ports/MSP430X/hal_pal_lld.h new file mode 100644 index 00000000..8789ed18 --- /dev/null +++ b/os/hal/ports/MSP430X/hal_pal_lld.h @@ -0,0 +1,390 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/hal_pal_lld.h + * @brief MSP430X PAL subsystem low level driver header. + * + * @addtogroup PAL + * @{ + */ + +#ifndef HAL_PAL_LLD_H +#define HAL_PAL_LLD_H + +#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +#undef PAL_MODE_INPUT_ANALOG /* configure this through the ALTERNATE macros */ +#undef PAL_MODE_OUTPUT_OPENDRAIN + +/** + * @name MSP430X-specific I/O mode flags + * @{ + */ + +/** + * @brief Alternate mode 1 + */ +#define PAL_MSP430X_ALTERNATE_1 8 + +/** + * @brief Alternate mode 2 + */ +#define PAL_MSP430X_ALTERNATE_2 9 + +/** + * @brief Alternate mode 3 + */ +#define PAL_MSP430X_ALTERNATE_3 10 + +#define ALTERNATE_HELP(n) (PAL_MSP430X_ALTERNATE_ ## n) +/** + * @brief Alternate function. + * + * @param[in] n alternate function selector - 1 through 3 + */ +#define PAL_MODE_ALTERNATE(n) (ALTERNATE_HELP(n)) + +/** @} */ + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @name Port related definitions + * @{ + */ +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 16U + +/** + * @brief Whole port mask. + * @details This macro specifies all the valid bits into a port. + */ +#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFU) + +/** @} */ + + +/** + * @name Line handling macros + * @{ + */ +/** + * @brief Forms a line identifier. + * @details A port/pad pair are encoded into an @p ioline_t type. The encoding + * of this type is platform-dependent. + * @note In this driver the pad number is encoded in the upper 4 bits of + * the GPIO address which are guaranteed to be zero. + */ +#define PAL_LINE(port, pad) \ + ((ioline_t)((uint16_t)(port)) | (((uint16_t)(pad)) << 12)) + +/** + * @brief Decodes a port identifier from a line identifier. + */ +#define PAL_PORT(line) \ + ((msp430x_gpio_registers_t *)(((uint16_t)(line)) & 0x0FFFU)) + +/** + * @brief Decodes a pad identifier from a line identifier. + */ +#define PAL_PAD(line) \ + ((uint16_t)((uint16_t)(line) >> 12)) + +/** + * @brief Value identifying an invalid line. + */ +#define PAL_NOLINE 0U +/** @} */ + +/** + * @brief MSP430X register initialization + */ +typedef struct { + /** Initial value for OUT register.*/ + uint16_t out; + /** Initial value for DIR register.*/ + uint16_t dir; + /** Initial value for REN register.*/ + uint16_t ren; + /** Initial value for SEL0 register.*/ + uint16_t sel0; + /** Initial value for SEL1 register.*/ + uint16_t sel1; + /** Initial value for IES register.*/ + uint16_t ies; + /** Initial value for IE register.*/ + uint16_t ie; +} msp430x_gpio_setup_t; + +/** + * @brief MSP430X registers block + * @note Some ports do not support all of these fields. + */ +typedef struct { + volatile uint16_t in; + volatile uint16_t out; + volatile uint16_t dir; + volatile uint16_t _padding; + volatile uint16_t ren; + volatile uint16_t sel0; + volatile uint16_t sel1; + volatile uint16_t _padding1; + volatile uint16_t _padding2; + volatile uint16_t _padding3; + volatile uint16_t _padding4; + volatile uint16_t selc; + volatile uint16_t ies; + volatile uint16_t ie; + volatile uint16_t ifg; +} msp430x_gpio_registers_t; + +/** + * @brief MSP430X I/O ports static initializer. + * @details An instance of this structure must be passed to @p palInit() at + * system startup time in order to initialized the digital I/O + * subsystem. This represents only the initial setup, specific pads + * or whole ports can be reprogrammed at later time. + */ +typedef struct { +#if defined(PA_BASE) || defined(__DOXYGEN__) + msp430x_gpio_setup_t porta; +#endif +#if defined(PB_BASE) || defined(__DOXYGEN__) + msp430x_gpio_setup_t portb; +#endif +#if defined(PC_BASE) || defined(__DOXYGEN__) + msp430x_gpio_setup_t portc; +#endif +#if defined(PD_BASE) || defined(__DOXYGEN__) + msp430x_gpio_setup_t portd; +#endif +#if defined(PE_BASE) || defined(__DOXYGEN__) + msp430x_gpio_setup_t porte; +#endif +#if defined(PF_BASE) || defined(__DOXYGEN__) + msp430x_gpio_setup_t portf; +#endif + msp430x_gpio_setup_t portj; +} PALConfig; + +/** + * @brief Digital I/O port sized unsigned type. + */ +typedef uint16_t ioportmask_t; + +/** + * @brief Digital I/O modes. + */ +typedef uint16_t iomode_t; + +/** + * @brief Type of an I/O line. + */ +typedef uint16_t ioline_t; + +/** + * @brief Port Identifier. + * @details This type can be a scalar or some kind of pointer, do not make + * any assumption about it, use the provided macros when populating + * variables of this type. + */ +typedef msp430x_gpio_registers_t * ioportid_t; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/*===========================================================================*/ + +/** + * @brief GPIO port A identifier. + */ +#if defined(PA_BASE) || defined(__DOXYGEN__) +#define IOPORT1 ((volatile msp430x_gpio_registers_t *)PA_BASE) +#endif + +/** + * @brief GPIO port B identifier. + */ +#if defined(PB_BASE) || defined(__DOXYGEN__) +#define IOPORT2 ((volatile msp430x_gpio_registers_t *)PB_BASE) +#endif + +/** + * @brief GPIO port C identifier. + */ +#if defined(PC_BASE) || defined(__DOXYGEN__) +#define IOPORT3 ((volatile msp430x_gpio_registers_t *)PC_BASE) +#endif + +/** + * @brief GPIO port D identifier. + */ +#if defined(PD_BASE) || defined(__DOXYGEN__) +#define IOPORT4 ((volatile msp430x_gpio_registers_t *)PD_BASE) +#endif + +/** + * @brief GPIO port E identifier. + */ +#if defined(PE_BASE) || defined(__DOXYGEN__) +#define IOPORT5 ((volatile msp430x_gpio_registers_t *)PE_BASE) +#endif + +/** + * @brief GPIO port F identifier. + */ +#if defined(PF_BASE) || defined(__DOXYGEN__) +#define IOPORT6 ((volatile msp430x_gpio_registers_t *)PF_BASE +#endif + +/** + * @brief GPIO port J identifier. + */ +#define IOPORT0 ((volatile msp430x_gpio_registers_t *)PJ_BASE) + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, if so please put them in pal_lld.c. */ +/*===========================================================================*/ + +/** + * @brief Low level PAL subsystem initialization. + * + * @param[in] config architecture-dependent ports configuration + * + * @notapi + */ +#define pal_lld_init(config) _pal_lld_init(config) + +/** + * @brief Reads the physical I/O port states. + * + * @param[in] port port identifier + * @return The port bits. + * + * @notapi + */ +#define pal_lld_readport(port) ((port)->in) + +/** + * @brief Reads the output latch. + * @details The purpose of this function is to read back the latched output + * value. + * + * @param[in] port port identifier + * @return The latched logical states. + * + * @notapi + */ +#define pal_lld_readlatch(port) ((port)->out) + +/** + * @brief Writes a bits mask on a I/O port. + * + * @param[in] port port identifier + * @param[in] bits bits to be written on the specified port + * + * @notapi + */ +#define pal_lld_writeport(port, bits) ((port)->out = (bits)) + + +/** + * @brief Sets a bits mask on a I/O port. + * + * @param[in] port port identifier + * @param[in] bits bits to be ORed on the specified port + * + * @notapi + */ +#define pal_lld_setport(port, bits) ((port)->out |= (bits)) + +/** + * @brief Clears a bits mask on a I/O port. + * + * @param[in] port port identifier + * @param[in] bits bits to be cleared on the specified port + * + * @notapi + */ +#define pal_lld_clearport(port, bits) ((port)->out &= ~(bits)) + +/** + * @brief Toggles a bits mask on a I/O port. + * + * @param[in] port port identifier + * @param[in] bits bits to be XORed on the specified port + * + * @notapi + */ +#define pal_lld_toggleport(port, bits) ((port)->out ^= (bits)) + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] mask group mask + * @param[in] offset group bit offset within the port + * @param[in] mode group mode + * + * @notapi + */ +#define pal_lld_setgroupmode(port, mask, offset, mode) \ + _pal_lld_setgroupmode(port, mask << offset, mode) + +/** + * @brief Clears a pad logical state to @p PAL_LOW. + * @details This function is implemented in a way which should + * produce a BIC instruction rather than an AND + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_clearpad(port, pad) ((port)->out &= ~(BIT ## pad)) + +#if !defined(__DOXYGEN__) +extern const PALConfig pal_default_config; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(const PALConfig *config); + void _pal_lld_setgroupmode(ioportid_t port, + ioportmask_t mask, + iomode_t mode); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PAL == TRUE */ + +#endif /* _PAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MSP430X/hal_serial_lld.c b/os/hal/ports/MSP430X/hal_serial_lld.c new file mode 100644 index 00000000..277f6d29 --- /dev/null +++ b/os/hal/ports/MSP430X/hal_serial_lld.c @@ -0,0 +1,657 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/hal_serial_lld.c + * @brief MSP430X serial subsystem low level driver source. + * + * @addtogroup SERIAL + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USART0 serial driver identifier.*/ +#if (MSP430X_SERIAL_USE_USART0 == TRUE) || defined(__DOXYGEN__) +#ifndef __MSP430_HAS_EUSCI_A0__ + #error "Cannot find USCI module to use for SD0" +#endif +SerialDriver SD0; +#endif + +/** @brief USART1 serial driver identifier.*/ +#if (MSP430X_SERIAL_USE_USART1 == TRUE) || defined(__DOXYGEN__) +#ifndef __MSP430_HAS_EUSCI_A1__ + #error "Cannot find USCI module to use for SD1" +#endif +SerialDriver SD1; +#endif + +/** @brief USART2 serial driver identifier.*/ +#if (MSP430X_SERIAL_USE_USART2 == TRUE) || defined(__DOXYGEN__) +#ifndef __MSP430_HAS_EUSCI_A2__ + #error "Cannot find USCI module to use for SD2" +#endif +SerialDriver SD2; +#endif + +/** @brief USART3 serial driver identifier.*/ +#if (MSP430X_SERIAL_USE_USART3 == TRUE) || defined(__DOXYGEN__) +#ifndef __MSP430_HAS_EUSCI_A3__ + #error "Cannot find USCI module to use for SD3" +#endif +SerialDriver SD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Driver default configuration. + */ +static const SerialConfig default_config = { + SERIAL_DEFAULT_BITRATE +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief UCBRS calculation. + * @details This function calculates the UCBRS value for oversampled baud + * rates. + * + * @param[in] frac Fractional part of baud rate division, times 10000. + */ +static uint8_t UCBRS(uint16_t frac) { + /* TODO there must be a better way */ + if (frac < 529) + return 0x00; + else if (frac < 715) + return 0x01; + else if (frac < 835) + return 0x02; + else if (frac < 1001) + return 0x04; + else if (frac < 1252) + return 0x08; + else if (frac < 1430) + return 0x10; + else if (frac < 1670) + return 0x20; + else if (frac < 2147) + return 0x11; + else if (frac < 2224) + return 0x21; + else if (frac < 2503) + return 0x22; + else if (frac < 3000) + return 0x44; + else if (frac < 3335) + return 0x25; + else if (frac < 3575) + return 0x49; + else if (frac < 3753) + return 0x4A; + else if (frac < 4003) + return 0x52; + else if (frac < 4286) + return 0x92; + else if (frac < 4378) + return 0x53; + else if (frac < 5002) + return 0x55; + else if (frac < 5715) + return 0xAA; + else if (frac < 6003) + return 0x6B; + else if (frac < 6254) + return 0xAD; + else if (frac < 6432) + return 0xB5; + else if (frac < 6667) + return 0xB6; + else if (frac < 7001) + return 0xD6; + else if (frac < 7147) + return 0xB7; + else if (frac < 7503) + return 0xBB; + else if (frac < 7861) + return 0xDD; + else if (frac < 8004) + return 0xED; + else if (frac < 8333) + return 0xEE; + else if (frac < 8464) + return 0xBF; + else if (frac < 8572) + return 0xDF; + else if (frac < 8751) + return 0xEF; + else if (frac < 9004) + return 0xF7; + else if (frac < 9170) + return 0xFB; + else if (frac < 9288) + return 0xFD; + else + return 0xFE; +} + +/** + * @brief Modulation control word calculator. + * @details This function calculates the modulation control word from the + * input clock frequency and the requested baud rate. + * + * @param[in] baud Requested baud rate + * @param[in] freq Frequency of the clock driving the USCI module + */ +static uint16_t UCAxMCTLW(uint32_t baud, uint32_t freq) { + + uint16_t n = freq/baud; + /*uint16_t frac = (freq * 10000 / baud) - ((freq / baud) * 10000);*/ + uint16_t frac = (freq - (n * baud)) * 10000 / baud; + if (n > 16) { + while (n > 16) { + n -= 16; + } + return (UCBRS(frac) << 8) | (n << 4) | UCOS16; + } + return UCBRS(frac) << 8; +} + +/** + * @brief UCBRW calculation. + * @details This function calculates the UCBRW value for all baud + * rates. + * + * @param[in] baud Requested baud rate + * @param[in] freq Frequency of the clock driving the USCI module + */ +static uint16_t UCAxBRW(uint32_t baud, uint32_t freq) { + uint16_t n = freq/baud; + if (n > 16) { + return n >> 4; + } + return n; +} + +#if (MSP430X_SERIAL_USE_USART0 == TRUE) || defined(__DOXYGEN__) +static void usart0_init(const SerialConfig *config) { + UCA0BRW = UCAxBRW(config->sc_bitrate, MSP430X_USART0_CLK_FREQ); + UCA0MCTLW = UCAxMCTLW(config->sc_bitrate, MSP430X_USART0_CLK_FREQ); + UCA0STATW = 0; + UCA0ABCTL = 0; + UCA0IRCTL = 0; + UCA0CTLW0 = (MSP430X_USART0_PARITY << 14) | (MSP430X_USART0_ORDER << 13) | \ + (MSP430X_USART0_SIZE << 12) | (MSP430X_USART0_STOP << 11) | \ + (MSP430X_USART0_UCSSEL); + UCA0IE = UCRXIE; +} +#endif + +#if (MSP430X_SERIAL_USE_USART1 == TRUE) || defined(__DOXYGEN__) +static void usart1_init(const SerialConfig *config) { + UCA1BRW = UCAxBRW(config->sc_bitrate, MSP430X_USART1_CLK_FREQ); + UCA1MCTLW = UCAxMCTLW(config->sc_bitrate, MSP430X_USART1_CLK_FREQ); + UCA1STATW = 0; + UCA1ABCTL = 0; + UCA1IRCTL = 0; + UCA1IE = UCRXIE; + UCA1CTLW0 = (MSP430X_USART1_PARITY << 14) | (MSP430X_USART1_ORDER << 13) | \ + (MSP430X_USART1_SIZE << 12) | (MSP430X_USART1_STOP << 11) | \ + (MSP430X_USART1_UCSSEL); +} +#endif + +#if (MSP430X_SERIAL_USE_USART2 == TRUE) || defined(__DOXYGEN__) +static void usart2_init(const SerialConfig *config) { + UCA2BRW = UCAxBRW(config->sc_bitrate, MSP430X_USART2_CLK_FREQ); + UCA2MCTLW = UCAxMCTLW(config->sc_bitrate); + UCA2STATW = 0; + UCA2ABCTL = 0; + UCA2IRCTL = 0; + UCA2IE = UCRXIE; + UCA2CTLW0 = (MSP430X_USART2_PARITY << 14) | (MSP430X_USART2_ORDER << 13) | \ + (MSP430X_USART2_SIZE << 12) | (MSP430X_USART2_STOP << 11) | \ + (MSP430X_USART2_UCSSEL); +} +#endif + +#if (MSP430X_SERIAL_USE_USART3 == TRUE) || defined(__DOXYGEN__) +static void usart3_init(const SerialConfig *config) { + UCA3BRW = UCAxBRW(config->sc_bitrate, MSP430X_USART3_CLK_FREQ); + UCA3MCTLW = UCAxMCTLW(config->sc_bitrate, MSP430X_USART3_CLK_FREQ); + UCA3STATW = 0; + UCA3ABCTL = 0; + UCA3IRCTL = 0; + UCA3IE = UCRXIE; + UCA3CTLW0 = (MSP430X_USART3_PARITY << 14) | (MSP430X_USART3_ORDER << 13) | \ + (MSP430X_USART3_SIZE << 12) | (MSP430X_USART3_STOP << 11) | \ + (MSP430X_USART3_UCSSEL); +} +#endif + +#if (MSP430X_SERIAL_USE_USART0 == TRUE) || defined(__DOXYGEN__) +static void notify0(io_queue_t *qp) { + + (void)qp; + UCA0IE |= UCTXIE; +} +#endif + +#if (MSP430X_SERIAL_USE_USART1 == TRUE) || defined(__DOXYGEN__) +static void notify1(io_queue_t *qp) { + + (void)qp; + UCA1IE |= UCTXIE; +} +#endif + +#if (MSP430X_SERIAL_USE_USART2 == TRUE) || defined(__DOXYGEN__) +static void notify2(io_queue_t *qp) { + + (void)qp; + UCA2IE |= UCTXIE; +} +#endif + +#if (MSP430X_SERIAL_USE_USART3 == TRUE) || defined(__DOXYGEN__) +static void notify3(io_queue_t *qp) { + + (void)qp; + UCA3IE |= UCTXIE; +} +#endif + +/** + * @brief Error handling routine. + * + * @param[in] sra USCI status register containing errors + * @param[in] sdp pointer to a @p SerialDriver object + */ +static void set_error(uint16_t sra, SerialDriver *sdp) { + eventflags_t sts = 0; + + if (sra & UCOE) + sts |= SD_OVERRUN_ERROR; + if (sra & UCPE) + sts |= SD_PARITY_ERROR; + if (sra & UCFE) + sts |= SD_FRAMING_ERROR; + osalSysLockFromISR(); + chnAddFlagsI(sdp, sts); + osalSysUnlockFromISR(); +} + + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if MSP430X_SERIAL_USE_USART0 || defined(__DOXYGEN__) +/** + * @brief USART0 interrupt handler. + * + * @isr + */ +PORT_IRQ_HANDLER(USCI_A0_VECTOR) { + msg_t b; + + OSAL_IRQ_PROLOGUE(); + + switch (__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG)) { + case USCI_UART_UCRXIFG: /* RX interrupt */ + + /* Detect errors */ + if (UCA0STATW & UCRXERR) + set_error(UCA0STATW, &SD0); + + /* Data available */ + osalSysLockFromISR(); + sdIncomingDataI(&SD0, UCA0RXBUF); + osalSysUnlockFromISR(); + break; + + case USCI_UART_UCTXIFG: /* TX interrupt */ + + /* Transmission buffer empty */ + osalSysLockFromISR(); + b = sdRequestDataI(&SD0); + if (b < Q_OK) { + chnAddFlagsI(&SD0, CHN_OUTPUT_EMPTY); + UCA0IE = (UCA0IE & ~UCTXIE) | UCTXCPTIE; + UCA0IFG |= UCTXIFG; /* If we don't write to TXBUF, IFG won't get set */ + } + else + UCA0TXBUF = b; + osalSysUnlockFromISR(); + break; + + case USCI_UART_UCTXCPTIFG: /* TX complete interrupt */ + + /* Physical transmission end */ + osalSysLockFromISR(); + if (oqIsEmptyI(&SD0.oqueue)) + chnAddFlagsI(&SD0, CHN_TRANSMISSION_END); + UCA0IE &= ~UCTXCPTIE; + break; + + default: /* other interrupts */ + while (1); + break; + } + + OSAL_IRQ_EPILOGUE(); + +} +#endif + +#if MSP430X_SERIAL_USE_USART1 || defined(__DOXYGEN__) +/** + * @brief USART1 interrupt handler. + * + * @isr + */ +PORT_IRQ_HANDLER(USCI_A1_VECTOR) { + msg_t b; + + OSAL_IRQ_PROLOGUE(); + + switch (__even_in_range(UCA1IV,USCI_UART_UCTXCPTIFG)) { + case USCI_UART_UCRXIFG: /* RX interrupt */ + + /* Detect errors */ + if (UCA1STATW & UCRXERR) + set_error(UCA1STATW, &SD1); + + /* Data available */ + osalSysLockFromISR(); + sdIncomingDataI(&SD1, UCA1RXBUF); + osalSysUnlockFromISR(); + break; + + case USCI_UART_UCTXIFG: /* TX interrupt */ + + /* Transmission buffer empty */ + osalSysLockFromISR(); + b = sdRequestDataI(&SD1); + if (b < Q_OK) { + chnAddFlagsI(&SD1, CHN_OUTPUT_EMPTY); + UCA1IE = (UCA1IE & ~UCTXIE) | UCTXCPTIE; + UCA1IFG |= UCTXIFG; /* If we don't write to TXBUF, IFG won't get set */ + } + else + UCA1TXBUF = b; + osalSysUnlockFromISR(); + break; + + case USCI_UART_UCTXCPTIFG: /* TX complete interrupt */ + + /* Physical transmission end */ + osalSysLockFromISR(); + if (oqIsEmptyI(&SD1.oqueue)) + chnAddFlagsI(&SD1, CHN_TRANSMISSION_END); + UCA1IE &= ~UCTXCPTIE; + break; + + default: /* other interrupts */ + while (1); + break; + } + + OSAL_IRQ_EPILOGUE(); + +} +#endif + +#if MSP430X_SERIAL_USE_USART2 || defined(__DOXYGEN__) +/** + * @brief USART2 interrupt handler. + * + * @isr + */ +PORT_IRQ_HANDLER(USCI_A2_VECTOR) { + msg_t b; + + OSAL_IRQ_PROLOGUE(); + + switch (__even_in_range(UCA2IV,USCI_UART_UCTXCPTIFG)) { + case USCI_UART_UCRXIFG: /* RX interrupt */ + + /* Detect errors */ + if (UCA2STATW & UCRXERR) + set_error(UCA2STATW, &SD2); + + /* Data available */ + osalSysLockFromISR(); + sdIncomingDataI(&SD2, UCA2RXBUF); + osalSysUnlockFromISR(); + break; + + case USCI_UART_UCTXIFG: /* TX interrupt */ + + /* Transmission buffer empty */ + osalSysLockFromISR(); + b = sdRequestDataI(&SD2); + if (b < Q_OK) { + chnAddFlagsI(&SD2, CHN_OUTPUT_EMPTY); + UCA2IE = (UCA2IE & ~UCTXIE) | UCTXCPTIE; + UCA2IFG |= UCTXIFG; /* If we don't write to TXBUF, IFG won't get set */ + } + else + UCA2TXBUF = b; + osalSysUnlockFromISR(); + break; + + case USCI_UART_UCTXCPTIFG: /* TX complete interrupt */ + + /* Physical transmission end */ + osalSysLockFromISR(); + if (oqIsEmptyI(&SD2.oqueue)) + chnAddFlagsI(&SD2, CHN_TRANSMISSION_END); + UCA2IE &= ~UCTXCPTIE; + break; + + default: /* other interrupts */ + while (1); + break; + } + + OSAL_IRQ_EPILOGUE(); + +} +#endif + +#if MSP430X_SERIAL_USE_USART3 || defined(__DOXYGEN__) +/** + * @brief USART3 interrupt handler. + * + * @isr + */ +PORT_IRQ_HANDLER(USCI_A3_VECTOR) { + msg_t b; + + OSAL_IRQ_PROLOGUE(); + + switch (__even_in_range(UCA3IV,USCI_UART_UCTXCPTIFG)) { + case USCI_UART_UCRXIFG: /* RX interrupt */ + + /* Detect errors */ + if (UCA3STATW & UCRXERR) + set_error(UCA3STATW, &SD3); + + /* Data available */ + osalSysLockFromISR(); + sdIncomingDataI(&SD3, UCA3RXBUF); + osalSysUnlockFromISR(); + break; + + case USCI_UART_UCTXIFG: /* TX interrupt */ + + /* Transmission buffer empty */ + osalSysLockFromISR(); + b = sdRequestDataI(&SD3); + if (b < Q_OK) { + chnAddFlagsI(&SD3, CHN_OUTPUT_EMPTY); + UCA3IE = (UCA3IE & ~UCTXIE) | UCTXCPTIE; + UCA3IFG |= UCTXIFG; /* If we don't write to TXBUF, IFG won't get set */ + } + else + UCA3TXBUF = b; + osalSysUnlockFromISR(); + break; + + case USCI_UART_UCTXCPTIFG: /* TX complete interrupt */ + + /* Physical transmission end */ + osalSysLockFromISR(); + if (oqIsEmptyI(&SD3.oqueue)) + chnAddFlagsI(&SD3, CHN_TRANSMISSION_END); + UCA3IE &= ~UCTXCPTIE; + break; + + default: /* other interrupts */ + while (1); + break; + } + + OSAL_IRQ_EPILOGUE(); + +} +#endif + + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level serial driver initialization. + * + * @notapi + */ +void sd_lld_init(void) { + +#if MSP430X_SERIAL_USE_USART0 == TRUE + sdObjectInit(&SD0, NULL, notify0); +#endif + +#if MSP430X_SERIAL_USE_USART1 == TRUE + sdObjectInit(&SD1, NULL, notify1); +#endif + +#if MSP430X_SERIAL_USE_USART2 == TRUE + sdObjectInit(&SD2, NULL, notify2); +#endif + +#if MSP430X_SERIAL_USE_USART3 == TRUE + sdObjectInit(&SD3, NULL, notify3); +#endif +} + +/** + * @brief Low level serial driver configuration and (re)start. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @notapi + */ +void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { + + if (config == NULL) { + config = &default_config; + } + + + if (sdp->state == SD_STOP) { +#if MSP430X_SERIAL_USE_USART0 == TRUE + if (&SD0 == sdp) { + usart0_init(config); + } +#endif +#if MSP430X_SERIAL_USE_USART1 == TRUE + if (&SD1 == sdp) { + usart1_init(config); + } +#endif +#if MSP430X_SERIAL_USE_USART2 == TRUE + if (&SD2 == sdp) { + usart2_init(config); + } +#endif +#if MSP430X_SERIAL_USE_USART3 == TRUE + if (&SD3 == sdp) { + usart3_init(config); + } +#endif + } +} + +/** + * @brief Low level serial driver stop. + * @details De-initializes the USART, stops the associated clock, resets the + * interrupt vector. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @notapi + */ +void sd_lld_stop(SerialDriver *sdp) { + + if (sdp->state == SD_READY) { +#if MSP430X_SERIAL_USE_USART0 == TRUE + if (&SD0 == sdp) { + UCA0CTLW0 = UCSWRST; + } +#endif +#if MSP430X_SERIAL_USE_USART1 == TRUE + if (&SD1 == sdp) { + UCA1CTLW0 = UCSWRST; + } +#endif +#if MSP430X_SERIAL_USE_USART2 == TRUE + if (&SD2 == sdp) { + UCA2CTLW0 = UCSWRST; + } +#endif +#if MSP430X_SERIAL_USE_USART3 == TRUE + if (&SD3 == sdp) { + UCA3CTLW0 = UCSWRST; + } +#endif + } +} + +#endif /* HAL_USE_SERIAL == TRUE */ + +/** @} */ diff --git a/os/hal/ports/MSP430X/hal_serial_lld.h b/os/hal/ports/MSP430X/hal_serial_lld.h new file mode 100644 index 00000000..389e5c8f --- /dev/null +++ b/os/hal/ports/MSP430X/hal_serial_lld.h @@ -0,0 +1,320 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/hal_serial_lld.h + * @brief MSP430X serial subsystem low level driver header. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef _SERIAL_LLD_H_ +#define _SERIAL_LLD_H_ + +#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define NONE 0 +#define ODD 2 +#define EVEN 3 + +#define MSB 1 +#define LSB 0 + +#define SEVEN 1 +#define EIGHT 0 + +#define ONE 0 +#define TWO 1 + +#define MSP430X_SERIAL_SMCLK UCSSEL__SMCLK +#define MSP430X_SERIAL_UCLK UCSSEL__UCLK +#define MSP430X_SERIAL_ACLK UCSSEL__ACLK + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name USART0 configuration options + * @{ + */ +/** + * @brief USART0 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(MSP430X_SERIAL_USE_USART0) || defined(__DOXYGEN__) +#define MSP430X_SERIAL_USE_USART0 FALSE +#endif +/** @} */ + +/** + * @name USART1 configuration options + * @{ + */ +/** + * @brief USART1 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(MSP430X_SERIAL_USE_USART1) || defined(__DOXYGEN__) +#define MSP430X_SERIAL_USE_USART1 FALSE +#endif +/** @} */ + +/** + * @name USART2 configuration options + * @{ + */ +/** + * @brief USART2 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(MSP430X_SERIAL_USE_USART2) || defined(__DOXYGEN__) +#define MSP430X_SERIAL_USE_USART2 FALSE +#endif +/** @} */ + +/** + * @name USART3 configuration options + * @{ + */ +/** + * @brief USART3 driver enable switch. + * @details If set to @p TRUE the support for USART1 is included. + * @note The default is @p FALSE. + */ +#if !defined(MSP430X_SERIAL_USE_USART3) || defined(__DOXYGEN__) +#define MSP430X_SERIAL_USE_USART3 FALSE +#endif + +#if MSP430X_SERIAL_USE_USART0 + #if !defined(MSP430X_USART0_PARITY) + #define MSP430X_USART0_PARITY NONE + #endif + #if !defined(MSP430X_USART0_ORDER) + #define MSP430X_USART0_ORDER LSB + #endif + #if !defined(MSP430X_USART0_SIZE) + #define MSP430X_USART0_SIZE EIGHT + #endif + #if !defined(MSP430X_USART0_STOP) + #define MSP430X_USART0_STOP ONE + #endif + #if !defined(MSP430X_USART0_CLK_SRC) + #define MSP430X_USART0_CLK_SRC MSP430X_UCLK_SRC + #ifndef MSP430X_USART0_CLK_FREQ + #error "Requested external UART0 clock but no frequency given" + #endif + #define MSP430X_USART0_UCSSEL UCSSEL__UCLK + #elif MSP430X_USART0_CLK_SRC == MSP430X_ACLK_SRC + #define MSP430X_USART0_CLK_SRC MSP430X_ACLK_SRC + #define MSP430X_USART0_CLK_FREQ MSP430X_ACLK_FREQ + #define MSP430X_USART0_UCSSEL UCSSEL__ACLK + #elif MSP430X_USART0_CLK_SRC == MSP430X_SMCLK_SRC + #define MSP430X_USART0_CLK_SRC MSP430X_SMCLK_SRC + #define MSP430X_USART0_CLK_FREQ MSP430X_SMCLK_FREQ + #define MSP430X_USART0_UCSSEL UCSSEL__SMCLK + #else + #error "MSP430X_USART0_CLK_SRC invalid" + #endif +#endif + +#if MSP430X_SERIAL_USE_USART1 + #if !defined(MSP430X_USART1_PARITY) + #define MSP430X_USART1_PARITY NONE + #endif + #if !defined(MSP430X_USART1_ORDER) + #define MSP430X_USART1_ORDER LSB + #endif + #if !defined(MSP430X_USART1_SIZE) + #define MSP430X_USART1_SIZE EIGHT + #endif + #if !defined(MSP430X_USART1_STOP) + #define MSP430X_USART1_STOP ONE + #endif + #if !defined(MSP430X_USART1_CLK_SRC) + #define MSP430X_USART1_CLK_SRC MSP430X_UCLK_SRC + #ifndef MSP430X_USART1_CLK_FREQ + #error "Requested external UART0 clock but no frequency given" + #endif + #define MSP430X_USART1_UCSSEL UCSSEL__UCLK + #elif MSP430X_USART1_CLK_SRC == MSP430X_ACLK_SRC + #define MSP430X_USART1_CLK_SRC MSP430X_ACLK_SRC + #define MSP430X_USART1_CLK_FREQ MSP430X_ACLK_FREQ + #define MSP430X_USART1_UCSSEL UCSSEL__ACLK + #elif MSP430X_USART1_CLK_SRC == MSP430X_SMCLK_SRC + #define MSP430X_USART1_CLK_SRC MSP430X_SMCLK_SRC + #define MSP430X_USART1_CLK_FREQ MSP430X_SMCLK_FREQ + #define MSP430X_USART1_UCSSEL UCSSEL__SMCLK + #else + #error "MSP430X_USART1_CLK_SRC invalid" + #endif +#endif + +#if MSP430X_SERIAL_USE_USART2 + #if !defined(MSP430X_USART2_PARITY) + #define MSP430X_USART2_PARITY NONE + #endif + #if !defined(MSP430X_USART2_ORDER) + #define MSP430X_USART2_ORDER LSB + #endif + #if !defined(MSP430X_USART2_SIZE) + #define MSP430X_USART2_SIZE EIGHT + #endif + #if !defined(MSP430X_USART2_STOP) + #define MSP430X_USART2_STOP ONE + #endif + #if !defined(MSP430X_USART2_CLK_SRC) + #define MSP430X_USART2_CLK_SRC MSP430X_UCLK_SRC + #ifndef MSP430X_USART2_CLK_FREQ + #error "Requested external UART0 clock but no frequency given" + #endif + #define MSP430X_USART2_UCSSEL UCSSEL__UCLK + #elif MSP430X_USART2_CLK_SRC == MSP430X_ACLK_SRC + #define MSP430X_USART2_CLK_SRC MSP430X_ACLK_SRC + #define MSP430X_USART2_CLK_FREQ MSP430X_ACLK_FREQ + #define MSP430X_USART2_UCSSEL UCSSEL__ACLK + #elif MSP430X_USART2_CLK_SRC == MSP430X_SMCLK_SRC + #define MSP430X_USART2_CLK_SRC MSP430X_SMCLK_SRC + #define MSP430X_USART2_CLK_FREQ MSP430X_SMCLK_FREQ + #define MSP430X_USART2_UCSSEL UCSSEL__SMCLK + #else + #error "MSP430X_USART2_CLK_SRC invalid" + #endif +#endif + +#if MSP430X_SERIAL_USE_USART3 + #if !defined(MSP430X_USART3_PARITY) + #define MSP430X_USART3_PARITY NONE + #endif + #if !defined(MSP430X_USART3_ORDER) + #define MSP430X_USART3_ORDER LSB + #endif + #if !defined(MSP430X_USART3_SIZE) + #define MSP430X_USART3_SIZE EIGHT + #endif + #if !defined(MSP430X_USART3_STOP) + #define MSP430X_USART3_STOP ONE + #endif + #if !defined(MSP430X_USART3_CLK_SRC) + #define MSP430X_USART3_CLK_SRC MSP430X_UCLK_SRC + #ifndef MSP430X_USART3_CLK_FREQ + #error "Requested external UART0 clock but no frequency given" + #endif + #define MSP430X_USART3_UCSSEL UCSSEL__UCLK + #elif MSP430X_USART3_CLK_SRC == MSP430X_ACLK_SRC + #define MSP430X_USART3_CLK_SRC MSP430X_ACLK_SRC + #define MSP430X_USART3_CLK_FREQ MSP430X_ACLK_FREQ + #define MSP430X_USART3_UCSSEL UCSSEL__ACLK + #elif MSP430X_USART3_CLK_SRC == MSP430X_SMCLK_SRC + #define MSP430X_USART3_CLK_SRC MSP430X_SMCLK_SRC + #define MSP430X_USART3_CLK_FREQ MSP430X_SMCLK_FREQ + #define MSP430X_USART3_UCSSEL UCSSEL__SMCLK + #else + #error "MSP430X_USART3_CLK_SRC invalid" + #endif +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief MSP430X Serial Driver configuration structure. + * @details An insance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * @note This structure content is architecture dependent, each driver + * implementation defines its own version and the custom static + * initializers. + */ +typedef struct { + /** + * @brief Bit rate. + */ + uint32_t sc_bitrate; + + /* End of the mandatory fields.*/ +} SerialConfig; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdstate_t state; \ + /* Input queue.*/ \ + input_queue_t iqueue; \ + /* Output queue.*/ \ + output_queue_t oqueue; \ + /* Input circular buffer.*/ \ + uint8_t ib[SERIAL_BUFFERS_SIZE]; \ + /* Output circular buffer.*/ \ + uint8_t ob[SERIAL_BUFFERS_SIZE]; \ + /* End of the mandatory fields.*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (MSP430X_SERIAL_USE_USART0 == TRUE) && !defined(__DOXYGEN__) +extern SerialDriver SD0; +#endif + +#if (MSP430X_SERIAL_USE_USART1 == TRUE) && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif + +#if (MSP430X_SERIAL_USE_USART2 == TRUE) && !defined(__DOXYGEN__) +extern SerialDriver SD2; +#endif + +#if (MSP430X_SERIAL_USE_USART3 == TRUE) && !defined(__DOXYGEN__) +extern SerialDriver SD3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); + void sd_lld_stop(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL == TRUE */ + +#endif /* _SERIAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MSP430X/hal_st_lld.c b/os/hal/ports/MSP430X/hal_st_lld.c new file mode 100644 index 00000000..8ea1b9df --- /dev/null +++ b/os/hal/ports/MSP430X/hal_st_lld.c @@ -0,0 +1,206 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/hal_st_lld.c + * @brief MSP430X ST subsystem low level driver source. + * + * @addtogroup ST + * @{ + */ + +#include "hal.h" +#include + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__) + #define MSP430X_ST_DIV_CALC(x) ((MSP430X_ST_CLK_FREQ / OSAL_ST_FREQUENCY) == x) +#endif + + +#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) + #if ((MSP430X_ST_CLK_FREQ / OSAL_ST_FREQUENCY / 64) > MSP_TIMER_COUNTER_MAX) + #error "Frequency too low for timer - please set OSAL_ST_FREQUENCY to a higher value" + #endif + + #define MSP430X_ST_DIV_CALC(x) ((MSP430X_ST_CLK_FREQ / OSAL_ST_FREQUENCY / x) <= MSP_TIMER_COUNTER_MAX) +#endif + +/* Find suitable prescaler setting */ +#if MSP430X_ST_DIV_CALC(1) + #define MSP430X_ST_DIV 1 + #define MSP430X_ST_DIV_BITS ID__1 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_0 +#elif MSP430X_ST_DIV_CALC(2) + #define MSP430X_ST_DIV 2 + #define MSP430X_ST_DIV_BITS ID__1 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_1 +#elif MSP430X_ST_DIV_CALC(3) + #define MSP430X_ST_DIV 3 + #define MSP430X_ST_DIV_BITS ID__1 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_2 +#elif MSP430X_ST_DIV_CALC(4) + #define MSP430X_ST_DIV 4 + #define MSP430X_ST_DIV_BITS ID__1 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_3 +#elif MSP430X_ST_DIV_CALC(5) + #define MSP430X_ST_DIV 5 + #define MSP430X_ST_DIV_BITS ID__1 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_4 +#elif MSP430X_ST_DIV_CALC(6) + #define MSP430X_ST_DIV 6 + #define MSP430X_ST_DIV_BITS ID__1 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_5 +#elif MSP430X_ST_DIV_CALC(7) + #define MSP430X_ST_DIV 7 + #define MSP430X_ST_DIV_BITS ID__1 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_6 +#elif MSP430X_ST_DIV_CALC(8) + #define MSP430X_ST_DIV 8 + #define MSP430X_ST_DIV_BITS ID__1 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_7 +#elif MSP430X_ST_DIV_CALC(10) + #define MSP430X_ST_DIV 10 + #define MSP430X_ST_DIV_BITS ID__2 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_4 +#elif MSP430X_ST_DIV_CALC(12) + #define MSP430X_ST_DIV 12 + #define MSP430X_ST_DIV_BITS ID__2 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_5 +#elif MSP430X_ST_DIV_CALC(14) + #define MSP430X_ST_DIV 14 + #define MSP430X_ST_DIV_BITS ID__2 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_6 +#elif MSP430X_ST_DIV_CALC(16) + #define MSP430X_ST_DIV 16 + #define MSP430X_ST_DIV_BITS ID__2 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_7 +#elif MSP430X_ST_DIV_CALC(20) + #define MSP430X_ST_DIV 20 + #define MSP430X_ST_DIV_BITS ID__4 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_4 +#elif MSP430X_ST_DIV_CALC(24) + #define MSP430X_ST_DIV 24 + #define MSP430X_ST_DIV_BITS ID__4 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_5 +#elif MSP430X_ST_DIV_CALC(28) + #define MSP430X_ST_DIV 28 + #define MSP430X_ST_DIV_BITS ID__4 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_6 +#elif MSP430X_ST_DIV_CALC(32) + #define MSP430X_ST_DIV 32 + #define MSP430X_ST_DIV_BITS ID__4 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_7 +#elif MSP430X_ST_DIV_CALC(40) + #define MSP430X_ST_DIV 40 + #define MSP430X_ST_DIV_BITS ID__8 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_4 +#elif MSP430X_ST_DIV_CALC(48) + #define MSP430X_ST_DIV 48 + #define MSP430X_ST_DIV_BITS ID__8 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_5 +#elif MSP430X_ST_DIV_CALC(56) + #define MSP430X_ST_DIV 56 + #define MSP430X_ST_DIV_BITS ID__8 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_6 +#elif MSP430X_ST_DIV_CALC(64) + #define MSP430X_ST_DIV 64 + #define MSP430X_ST_DIV_BITS ID__8 + #define MSP430X_ST_DIV_EX_BITS TAIDEX_7 +#else + #error "Error in calculating dividers - check OSAL_ST_FREQUENCY and frequency of input clock" +#endif +/* ugh never again*/ + +#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) + #define MSP_TIMER_COUNTER (MSP430X_ST_CLK_FREQ / OSAL_ST_FREQUENCY / MSP430X_ST_DIV) + #define MSP430X_ST_CLK_FREQ_ (MSP_TIMER_COUNTER * MSP430X_ST_DIV * OSAL_ST_FREQUENCY) + #if (MSP430X_ST_CLK_FREQ != MSP430X_ST_CLK_FREQ_) + #warning "OSAL_ST_FREQUENCY cannot be generated exactly using timer" + #endif + #undef MSP430X_ST_CLK_FREQ_ +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief Timer handler for both modes + */ + +PORT_IRQ_HANDLER( MSP430X_ST_ISR ) { + + OSAL_IRQ_PROLOGUE(); + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ST driver initialization. + * + * @notapi + */ +void st_lld_init(void) { + #if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined (__DOXYGEN__) + /* Start disabled */ + MSP430X_ST_CCR(MSP430X_ST_TIMER) = 0; + MSP430X_ST_CCTL(MSP430X_ST_TIMER) = 0; + MSP430X_ST_EX(MSP430X_ST_TIMER) = MSP430X_ST_DIV_EX_BITS; + MSP430X_ST_CTL(MSP430X_ST_TIMER) = (TACLR | MC_2 | MSP430X_ST_DIV_BITS | MSP430X_ST_TASSEL); + #endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */ + + #if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined (__DOXYGEN__) + /* Start enabled */ + MSP430X_ST_CCR(MSP430X_ST_TIMER) = MSP_TIMER_COUNTER - 1; + MSP430X_ST_CCTL(MSP430X_ST_TIMER) = CCIE; + MSP430X_ST_EX(MSP430X_ST_TIMER) = MSP430X_ST_DIV_EX_BITS; + MSP430X_ST_CTL(MSP430X_ST_TIMER) = (TACLR | MC_1 | MSP430X_ST_DIV_BITS | MSP430X_ST_TASSEL); + #endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ +} + +#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ + +/** @} */ diff --git a/os/hal/ports/MSP430X/hal_st_lld.h b/os/hal/ports/MSP430X/hal_st_lld.h new file mode 100644 index 00000000..32ad9703 --- /dev/null +++ b/os/hal/ports/MSP430X/hal_st_lld.h @@ -0,0 +1,216 @@ +/* + ChibiOS - Copyright (C) 2016 Andrew Wygle aka awygle + + 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. +*/ + +/** + * @file MSP430X/hal_st_lld.h + * @brief MSP430X ST subsystem low level driver header. + * @details This header is designed to be include-able without having to + * include other files from the HAL. + * + * @addtogroup MSP430X + * @{ + */ + +#ifndef _ST_LLD_H_ +#define _ST_LLD_H_ + +#include + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Timer maximum value + */ +#define MSP_TIMER_COUNTER_MAX 65535 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief System timer clock source. + * + * @note Legal values are undefined, MSP430X_ACLK_SRC, and + * MSP430X_SMCLK_SRC. + * @note If undefined, must define MSP430X_ST_CLK_FREQ as frequency of + * external clock and configure PAL appropriately. + */ +#if !defined (MSP430X_ST_CLK_SRC) + #ifndef MSP430X_ST_CLK_FREQ + #warning "Requested external source for ST but no frequency given" + #warning "- assuming OSAL_ST_FREQUENCY" + #define MSP430X_ST_CLK_FREQ OSAL_ST_FREQUENCY + #endif + #define MSP430X_ST_TASSEL TASSEL__TACLK +#elif MSP430X_ST_CLK_SRC == MSP430X_ACLK_SRC + #define MSP430X_ST_CLK_FREQ MSP430X_ACLK_FREQ + #define MSP430X_ST_TASSEL TASSEL__ACLK +#elif MSP430X_ST_CLK_SRC == MSP430X_SMCLK_SRC + #define MSP430X_ST_CLK_FREQ MSP430X_SMCLK_FREQ + #define MSP430X_ST_TASSEL TASSEL__SMCLK +#endif + +/* Timers */ +/** + * @brief Timer type (by letter) to be used for ST. + * @note Legal values are A and B. D support not yet implemented. + * @note Defaults to A + */ +#if !defined(MSP430X_ST_TIMER_TYPE) + #define MSP430X_ST_TIMER_TYPE A +#endif +/** + * @brief Timer instance (by number) to be used for ST. + * @note Defaults to 0 + */ +#if !defined (MSP430X_ST_TIMER_INDEX) + #define MSP430X_ST_TIMER_INDEX 0 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#define TIMER_HELPER2(x, y) x ## y +#define TIMER_HELPER(x, y) TIMER_HELPER2(x, y) +#define MSP430X_ST_TIMER TIMER_HELPER(MSP430X_ST_TIMER_TYPE, MSP430X_ST_TIMER_INDEX) +#define CCR_HELPER(x) T ## x ## CCR0 +#define MSP430X_ST_CCR(x) CCR_HELPER(x) +#define CCTL_HELPER(x) T ## x ## CCTL0 +#define MSP430X_ST_CCTL(x) CCTL_HELPER(x) +#define EX_HELPER(x) T ## x ## EX0 +#define MSP430X_ST_EX(x) EX_HELPER(x) +#define CTL_HELPER(x) T ## x ## CTL +#define MSP430X_ST_CTL(x) CTL_HELPER(x) +#define R_HELPER(x) T ## x ## R +#define MSP430X_ST_R(x) R_HELPER(x) +#define ISR_HELPER2(x, y) TIMER ## y ## _ ## x ## 0_VECTOR +#define ISR_HELPER(x, y) ISR_HELPER2(x, y) +#define MSP430X_ST_ISR ISR_HELPER(MSP430X_ST_TIMER_TYPE, MSP430X_ST_TIMER_INDEX) + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void st_lld_init(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Driver inline functions. */ +/*===========================================================================*/ + +/** + * @brief Returns the time counter value. + * + * @return The counter value. + * + * @notapi + */ +static inline systime_t st_lld_get_counter(void) { + + return (systime_t)MSP430X_ST_R(MSP430X_ST_TIMER); +} + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] abstime the time to be set for the first alarm + * + * @notapi + */ +static inline void st_lld_start_alarm(systime_t abstime) { + + MSP430X_ST_CCR(MSP430X_ST_TIMER) = abstime; + + /* Reset pending interrupt */ + MSP430X_ST_CCTL(MSP430X_ST_TIMER) &= (~CCIFG); + + /* Enable interrupt */ + MSP430X_ST_CCTL(MSP430X_ST_TIMER) |= CCIE; +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void st_lld_stop_alarm(void) { + + MSP430X_ST_CCTL(MSP430X_ST_TIMER) &= (~CCIE); +} + +/** + * @brief Sets the alarm time. + * + * @param[in] abstime the time to be set for the next alarm + * + * @notapi + */ +static inline void st_lld_set_alarm(systime_t abstime) { + + MSP430X_ST_CCR(MSP430X_ST_TIMER) = abstime; +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t st_lld_get_alarm(void) { + + return MSP430X_ST_CCR(MSP430X_ST_TIMER); +} + +/** + * @brief Determines if the alarm is active. + * + * @return The alarm status. + * @retval false if the alarm is not active. + * @retval true is the alarm is active + * + * @notapi + */ +static inline bool st_lld_is_alarm_active(void) { + + return (bool)((MSP430X_ST_CCTL(MSP430X_ST_TIMER) & CCIE) != 0); +} + +#endif /* _ST_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MSP430X/platform.mk b/os/hal/ports/MSP430X/platform.mk new file mode 100644 index 00000000..b0f256ed --- /dev/null +++ b/os/hal/ports/MSP430X/platform.mk @@ -0,0 +1,8 @@ +# List of all the MSP430X platform files. +PLATFORMSRC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_st_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_serial_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X/hal_pal_lld.c + +# Required include directories +PLATFORMINC = ${CHIBIOS_CONTRIB}/os/hal/ports/MSP430X