From e0b177423e1b14ab942fbf40b79d60d13ae02eb5 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 15 May 2012 17:01:41 +0000 Subject: Initial STM32F0xx support. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4198 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- boards/ST_STM32F0_DISCOVERY/board.c | 54 + boards/ST_STM32F0_DISCOVERY/board.h | 321 +++ boards/ST_STM32F0_DISCOVERY/board.mk | 5 + os/hal/platforms/STM32F0xx/stm32f0xx.h | 3220 +++++++++++++++++++++++ os/ports/GCC/ARMCMx/STM32F0xx/cmparams.h | 62 + os/ports/GCC/ARMCMx/STM32F0xx/ld/STM32F051x8.ld | 150 ++ os/ports/GCC/ARMCMx/STM32F0xx/port.mk | 15 + os/ports/GCC/ARMCMx/STM32F0xx/vectors.c | 168 ++ 8 files changed, 3995 insertions(+) create mode 100644 boards/ST_STM32F0_DISCOVERY/board.c create mode 100644 boards/ST_STM32F0_DISCOVERY/board.h create mode 100644 boards/ST_STM32F0_DISCOVERY/board.mk create mode 100644 os/hal/platforms/STM32F0xx/stm32f0xx.h create mode 100644 os/ports/GCC/ARMCMx/STM32F0xx/cmparams.h create mode 100644 os/ports/GCC/ARMCMx/STM32F0xx/ld/STM32F051x8.ld create mode 100644 os/ports/GCC/ARMCMx/STM32F0xx/port.mk create mode 100644 os/ports/GCC/ARMCMx/STM32F0xx/vectors.c diff --git a/boards/ST_STM32F0_DISCOVERY/board.c b/boards/ST_STM32F0_DISCOVERY/board.c new file mode 100644 index 000000000..025050af4 --- /dev/null +++ b/boards/ST_STM32F0_DISCOVERY/board.c @@ -0,0 +1,54 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "ch.h" +#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_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH} +}; +#endif + +/* + * Early initialization code. + * This initialization must be performed just after stack setup and before + * any other initialization. + */ +void __early_init(void) { + + stm32_clock_init(); +} + +/* + * Board-specific initialization code. + */ +void boardInit(void) { +} diff --git a/boards/ST_STM32F0_DISCOVERY/board.h b/boards/ST_STM32F0_DISCOVERY/board.h new file mode 100644 index 000000000..af811b057 --- /dev/null +++ b/boards/ST_STM32F0_DISCOVERY/board.h @@ -0,0 +1,321 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * Setup for STMicroelectronics STM32F0-Discovery board. + */ + +/* + * Board identifier. + */ +#define BOARD_ST_STM32L_DISCOVERY +#define BOARD_NAME "ST STM32L-Discovery" + +/* + * Board frequencies. + * NOTE: The both crystals are not fitted by default on the board but there + * the option to both mount an 8MHz HE crystal or drive HSE with an + * 8MHz clock from the on-board ST-Link. LSE can be optionally mounted + * too. + */ +#if defined(DISCOVERY_HSE_MOUNTED) && defined(DISCOVERY_HSE_DRIVEN) +#error "HSE OSC-IN cannot be both crystal equipped and externally driven" +#endif + +#if defined(DISCOVERY_LSE_MOUNTED) +#define STM32_LSECLK 32768 +#else +#define STM32_LSECLK 0 +#endif + +#if defined(DISCOVERY_HSE_MOUNTED) || defined(DISCOVERY_HSE_DRIVEN) +#define STM32_HSECLK 8000000 +#else +#define STM32_HSECLK 0 +#endif + +#if defined(DISCOVERY_HSE_DRIVEN) +#define STM32_HSE_BYPASS +#endif + +/* + * MCU type as defined in the ST header file stm32f0xx.h. + */ +#define STM32F0XX + +/* + * IO pins assignments. + */ +#define GPIOA_BUTTON 0 + +#define GPIOC_LED4 8 +#define GPIOC_LED3 9 + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_400K(n) (0U << ((n) * 2)) +#define PIN_OSPEED_2M(n) (1U << ((n) * 2)) +#define PIN_OSPEED_10M(n) (2U << ((n) * 2)) +#define PIN_OSPEED_40M(n) (3U << ((n) * 2)) +#define PIN_PUDR_FLOATING(n) (0U << ((n) * 2)) +#define PIN_PUDR_PULLUP(n) (1U << ((n) * 2)) +#define PIN_PUDR_PULLDOWN(n) (2U << ((n) * 2)) +#define PIN_AFIO_AF(n, v) ((v##U) << ((n % 8) * 4)) + +/* + * Port A setup. + * All input with pull-up except: + * PA0 - GPIOA_BUTTON (input floating). + * PA13 - JTMS/SWDAT (alternate 0). + * PA14 - JTCK/SWCLK (alternate 0). + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_BUTTON) | \ + PIN_MODE_INPUT(1) | \ + PIN_MODE_INPUT(2) | \ + PIN_MODE_INPUT(3) | \ + PIN_MODE_INPUT(4) | \ + PIN_MODE_INPUT(5) | \ + PIN_MODE_INPUT(6) | \ + PIN_MODE_INPUT(7) | \ + PIN_MODE_INPUT(8) | \ + PIN_MODE_INPUT(9) | \ + PIN_MODE_INPUT(10) | \ + PIN_MODE_INPUT(11) | \ + PIN_MODE_INPUT(12) | \ + PIN_MODE_ALTERNATE(13) | \ + PIN_MODE_ALTERNATE(14) | \ + PIN_MODE_INPUT(15)) +#define VAL_GPIOA_OTYPER 0x00000000 +#define VAL_GPIOA_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOA_PUPDR (PIN_PUDR_FLOATING(GPIOA_BUTTON) | \ + PIN_PUDR_PULLUP(1) | \ + PIN_PUDR_PULLUP(2) | \ + PIN_PUDR_PULLUP(3) | \ + PIN_PUDR_PULLUP(4) | \ + PIN_PUDR_PULLUP(5) | \ + PIN_PUDR_PULLUP(6) | \ + PIN_PUDR_PULLUP(7) | \ + PIN_PUDR_PULLUP(8) | \ + PIN_PUDR_PULLUP(9) | \ + PIN_PUDR_PULLUP(10) | \ + PIN_PUDR_PULLUP(11) | \ + PIN_PUDR_PULLUP(12) | \ + PIN_PUDR_PULLUP(13) | \ + PIN_PUDR_PULLUP(14) | \ + PIN_PUDR_PULLUP(15)) +#define VAL_GPIOA_ODR 0xFFFFFFFF +#define VAL_GPIOA_AFRL 0x00000000 +#define VAL_GPIOA_AFRH 0x00000000 + +/* + * Port B setup. + * All input with pull-up except: + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(0) | \ + PIN_MODE_INPUT(1) | \ + PIN_MODE_INPUT(2) | \ + PIN_MODE_INPUT(3) | \ + PIN_MODE_INPUT(4) | \ + PIN_MODE_INPUT(5) | \ + PIN_MODE_INPUT(6) | \ + PIN_MODE_INPUT(7) | \ + PIN_MODE_INPUT(8) | \ + PIN_MODE_INPUT(9) | \ + PIN_MODE_INPUT(10) | \ + PIN_MODE_INPUT(11) | \ + PIN_MODE_INPUT(12) | \ + PIN_MODE_INPUT(13) | \ + PIN_MODE_INPUT(14) | \ + PIN_MODE_INPUT(15)) +#define VAL_GPIOB_OTYPER 0x00000000 +#define VAL_GPIOB_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOB_PUPDR (PIN_PUDR_PULLUP(0) | \ + PIN_PUDR_PULLUP(1) | \ + PIN_PUDR_PULLUP(2) | \ + PIN_PUDR_PULLUP(3) | \ + PIN_PUDR_PULLUP(4) | \ + PIN_PUDR_PULLUP(5) | \ + PIN_PUDR_PULLUP(6) | \ + PIN_PUDR_PULLUP(7) | \ + PIN_PUDR_PULLUP(8) | \ + PIN_PUDR_PULLUP(9) | \ + PIN_PUDR_PULLUP(10) | \ + PIN_PUDR_PULLUP(11) | \ + PIN_PUDR_PULLUP(12) | \ + PIN_PUDR_PULLUP(13) | \ + PIN_PUDR_PULLUP(14) | \ + PIN_PUDR_PULLUP(15)) +#define VAL_GPIOB_ODR 0xFFFFFFFF +#define VAL_GPIOB_AFRL 0x00000000 +#define VAL_GPIOB_AFRH 0x00000000 + +/* + * Port C setup. + * All input with pull-up except: + * PC8 - GPIOC_LED4 (output push-pull). + * PC9 - GPIOC_LED3 (output push-pull). + * PC13 - OSC32_OUT (input floating). + * PC14 - OSC32_IN (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(0) | \ + PIN_MODE_INPUT(1) | \ + PIN_MODE_INPUT(2) | \ + PIN_MODE_INPUT(3) | \ + PIN_MODE_INPUT(4) | \ + PIN_MODE_INPUT(5) | \ + PIN_MODE_INPUT(6) | \ + PIN_MODE_INPUT(7) | \ + PIN_MODE_OUTPUT(GPIOC_LED4) | \ + PIN_MODE_OUTPUT(GPIOC_LED3) | \ + PIN_MODE_INPUT(10) | \ + PIN_MODE_INPUT(11) | \ + PIN_MODE_INPUT(12) | \ + PIN_MODE_INPUT(13) | \ + PIN_MODE_INPUT(14) | \ + PIN_MODE_INPUT(15)) +#define VAL_GPIOC_OTYPER 0x00000000 +#define VAL_GPIOC_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOC_PUPDR (PIN_PUDR_PULLUP(0) | \ + PIN_PUDR_PULLUP(1) | \ + PIN_PUDR_PULLUP(2) | \ + PIN_PUDR_PULLUP(3) | \ + PIN_PUDR_PULLUP(4) | \ + PIN_PUDR_PULLUP(5) | \ + PIN_PUDR_PULLUP(6) | \ + PIN_PUDR_PULLUP(7) | \ + PIN_PUDR_FLOATING(GPIOC_LED4) | \ + PIN_PUDR_FLOATING(GPIOC_LED3) | \ + PIN_PUDR_PULLUP(10) | \ + PIN_PUDR_PULLUP(11) | \ + PIN_PUDR_PULLUP(12) | \ + PIN_PUDR_PULLUP(13) | \ + PIN_PUDR_FLOATING(14) | \ + PIN_PUDR_FLOATING(15)) +#define VAL_GPIOC_ODR 0xFFFFFCFF +#define VAL_GPIOC_AFRL 0x00000000 +#define VAL_GPIOC_AFRH 0x00000000 + +/* + * Port D setup. + * All input with pull-up. + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(0) | \ + PIN_MODE_INPUT(1) | \ + PIN_MODE_INPUT(2) | \ + PIN_MODE_INPUT(3) | \ + PIN_MODE_INPUT(4) | \ + PIN_MODE_INPUT(5) | \ + PIN_MODE_INPUT(6) | \ + PIN_MODE_INPUT(7) | \ + PIN_MODE_INPUT(8) | \ + PIN_MODE_INPUT(9) | \ + PIN_MODE_INPUT(10) | \ + PIN_MODE_INPUT(11) | \ + PIN_MODE_INPUT(12) | \ + PIN_MODE_INPUT(13) | \ + PIN_MODE_INPUT(14) | \ + PIN_MODE_INPUT(15)) +#define VAL_GPIOD_OTYPER 0x00000000 +#define VAL_GPIOD_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOD_PUPDR (PIN_PUDR_PULLUP(0) | \ + PIN_PUDR_PULLUP(1) | \ + PIN_PUDR_PULLUP(2) | \ + PIN_PUDR_PULLUP(3) | \ + PIN_PUDR_PULLUP(4) | \ + PIN_PUDR_PULLUP(5) | \ + PIN_PUDR_PULLUP(6) | \ + PIN_PUDR_PULLUP(7) | \ + PIN_PUDR_PULLUP(8) | \ + PIN_PUDR_PULLUP(9) | \ + PIN_PUDR_PULLUP(10) | \ + PIN_PUDR_PULLUP(11) | \ + PIN_PUDR_PULLUP(12) | \ + PIN_PUDR_PULLUP(13) | \ + PIN_PUDR_PULLUP(14) | \ + PIN_PUDR_PULLUP(15)) +#define VAL_GPIOD_ODR 0xFFFFFFFF +#define VAL_GPIOD_AFRL 0x00000000 +#define VAL_GPIOD_AFRH 0x00000000 + +/* + * Port F setup. + * All input with pull-up. + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(0) | \ + PIN_MODE_INPUT(1) | \ + PIN_MODE_INPUT(2) | \ + PIN_MODE_INPUT(3) | \ + PIN_MODE_INPUT(4) | \ + PIN_MODE_INPUT(5) | \ + PIN_MODE_INPUT(6) | \ + PIN_MODE_INPUT(7) | \ + PIN_MODE_INPUT(8) | \ + PIN_MODE_INPUT(9) | \ + PIN_MODE_INPUT(10) | \ + PIN_MODE_INPUT(11) | \ + PIN_MODE_INPUT(12) | \ + PIN_MODE_INPUT(13) | \ + PIN_MODE_INPUT(14) | \ + PIN_MODE_INPUT(15)) +#define VAL_GPIOF_OTYPER 0x00000000 +#define VAL_GPIOF_OSPEEDR 0xFFFFFFFF +#define VAL_GPIOF_PUPDR (PIN_PUDR_PULLUP(0) | \ + PIN_PUDR_PULLUP(1) | \ + PIN_PUDR_PULLUP(2) | \ + PIN_PUDR_PULLUP(3) | \ + PIN_PUDR_PULLUP(4) | \ + PIN_PUDR_PULLUP(5) | \ + PIN_PUDR_PULLUP(6) | \ + PIN_PUDR_PULLUP(7) | \ + PIN_PUDR_PULLUP(8) | \ + PIN_PUDR_PULLUP(9) | \ + PIN_PUDR_PULLUP(10) | \ + PIN_PUDR_PULLUP(11) | \ + PIN_PUDR_PULLUP(12) | \ + PIN_PUDR_PULLUP(13) | \ + PIN_PUDR_PULLUP(14) | \ + PIN_PUDR_PULLUP(15)) +#define VAL_GPIOF_ODR 0xFFFFFFFF +#define VAL_GPIOF_AFRL 0x00000000 +#define VAL_GPIOF_AFRH 0x00000000 + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/boards/ST_STM32F0_DISCOVERY/board.mk b/boards/ST_STM32F0_DISCOVERY/board.mk new file mode 100644 index 000000000..144ae4963 --- /dev/null +++ b/boards/ST_STM32F0_DISCOVERY/board.mk @@ -0,0 +1,5 @@ +# List of all the board related files. +BOARDSRC = ${CHIBIOS}/boards/ST_STM32F0_DISCOVERY/board.c + +# Required include directories +BOARDINC = ${CHIBIOS}/boards/ST_STM32F0_DISCOVERY diff --git a/os/hal/platforms/STM32F0xx/stm32f0xx.h b/os/hal/platforms/STM32F0xx/stm32f0xx.h new file mode 100644 index 000000000..07c252c11 --- /dev/null +++ b/os/hal/platforms/STM32F0xx/stm32f0xx.h @@ -0,0 +1,3220 @@ +/** + ****************************************************************************** + * @file stm32f0xx.h + * @author MCD Application Team + * @version V1.0.0 + * @date 23-March-2012 + * @brief CMSIS Cortex-M0 Device Peripheral Access Layer Header File. + * This file contains all the peripheral register's definitions, bits + * definitions and memory mapping for STM32F0xx devices. + * + * The file is the unique include file that the application programmer + * is using in the C source code, usually in main.c. This file contains: + * - Configuration section that allows to select: + * - The device used in the target application + * - To use or not the peripheral’s drivers in application code(i.e. + * code will be based on direct access to peripheral’s registers + * rather than drivers API), this option is controlled by + * "#define USE_STDPERIPH_DRIVER" + * - To change few application-specific parameters such as the HSE + * crystal frequency + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral’s registers hardware + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f0xx + * @{ + */ + +#ifndef __STM32F0XX_H +#define __STM32F0XX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @addtogroup Library_configuration_section + * @{ + */ + +/* Uncomment the line below according to the target STM32F-0 device used in your + application + */ + +#if !defined (STM32F0XX) + #define STM32F0XX /*!< STM32F0XX: STM32F0xx devices */ +#endif +/* Tip: To avoid modifying this file each time you need to switch between these + devices, you can define the device in your toolchain compiler preprocessor. + + - STM32F0xx devices are STM32F050xx microcontrollers where the Flash memory + density ranges between 32 and 64 Kbytes. + */ + +#if !defined (STM32F0XX) + #error "Please select first the target STM32F0xx device used in your application (in stm32f0xx.h file)" +#endif /* STM32F0XX */ + +#if !defined USE_STDPERIPH_DRIVER +/** + * @brief Comment the line below if you will not use the peripherals drivers. + In this case, these drivers will not be included and the application code will + be based on direct access to peripherals registers + */ + /*#define USE_STDPERIPH_DRIVER*/ +#endif /* USE_STDPERIPH_DRIVER */ + +/** + * @brief In the following line adjust the value of External High Speed oscillator (HSE) + used in your application + + Tip: To avoid modifying this file each time you need to use different HSE, you + can define the HSE value in your toolchain compiler preprocessor. + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz*/ +#endif /* HSE_VALUE */ + +/** + * @brief In the following line adjust the External High Speed oscillator (HSE) Startup + Timeout value + */ +#if !defined (HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500) /*!< Time out for HSE start up */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief In the following line adjust the Internal High Speed oscillator (HSI) Startup + Timeout value + */ +#if !defined (HSI_STARTUP_TIMEOUT) +#define HSI_STARTUP_TIMEOUT ((uint16_t)0x0500) /*!< Time out for HSI start up */ +#endif /* HSI_STARTUP_TIMEOUT */ + +#if !defined (HSI_VALUE) +#define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal High Speed oscillator in Hz. + The real value may vary depending on the variations + in voltage and temperature. */ +#endif /* HSI_VALUE */ + +#if !defined (HSI14_VALUE) +#define HSI14_VALUE ((uint32_t)14000000) /*!< Value of the Internal High Speed oscillator for ADC in Hz. + The real value may vary depending on the variations + in voltage and temperature. */ +#endif /* HSI14_VALUE */ + +#if !defined (LSI_VALUE) +#define LSI_VALUE ((uint32_t)40000) /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ +#endif /* LSI_VALUE */ + +#if !defined (LSE_VALUE) +#define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +/** + * @brief STM32F0xx Standard Peripheral Library version number V1.0.0 + */ +#define __STM32F0XX_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __STM32F0XX_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ +#define __STM32F0XX_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __STM32F0XX_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32F0XX_STDPERIPH_VERSION ((__STM32F0XX_STDPERIPH_VERSION_MAIN << 24)\ + |(__STM32F0XX_STDPERIPH_VERSION_SUB1 << 16)\ + |(__STM32F0XX_STDPERIPH_VERSION_SUB2 << 8)\ + |(__STM32F0XX_STDPERIPH_VERSION_RC)) + +/** + * @} + */ + +/** @addtogroup Configuration_section_for_CMSIS + * @{ + */ + +/** + * @brief STM32F0xx Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +#define __CM0_REV 0 /*!< Core Revision r0p0 */ +#define __MPU_PRESENT 0 /*!< STM32F0xx do not provide MPU */ +#define __NVIC_PRIO_BITS 2 /*!< STM32F0xx uses 2 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +/*!< Interrupt Number Definition */ +typedef enum IRQn +{ +/****** Cortex-M0 Processor Exceptions Numbers ******************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */ + SVC_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */ + +/****** STM32F-0 specific Interrupt Numbers *********************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detect Interrupt */ + RTC_IRQn = 2, /*!< RTC through EXTI Line Interrupt */ + FLASH_IRQn = 3, /*!< FLASH Interrupt */ + RCC_IRQn = 4, /*!< RCC Interrupt */ + EXTI0_1_IRQn = 5, /*!< EXTI Line 0 and 1 Interrupts */ + EXTI2_3_IRQn = 6, /*!< EXTI Line 2 and 3 Interrupts */ + EXTI4_15_IRQn = 7, /*!< EXTI Line 4 to 15 Interrupts */ + TS_IRQn = 8, /*!< TS Interrupt */ + DMA1_Channel1_IRQn = 9, /*!< DMA1 Channel 1 Interrupt */ + DMA1_Channel2_3_IRQn = 10, /*!< DMA1 Channel 2 and Channel 3 Interrupts */ + DMA1_Channel4_5_IRQn = 11, /*!< DMA1 Channel 4 and Channel 5 Interrupts */ + ADC1_COMP_IRQn = 12, /*!< ADC1, COMP1 and COMP2 Interrupts */ + TIM1_BRK_UP_TRG_COM_IRQn = 13, /*!< TIM1 Break, Update, Trigger and Commutation Interrupts */ + TIM1_CC_IRQn = 14, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 15, /*!< TIM2 Interrupt */ + TIM3_IRQn = 16, /*!< TIM3 Interrupt */ + TIM6_DAC_IRQn = 17, /*!< TIM6 and DAC Interrupts */ + TIM14_IRQn = 19, /*!< TIM14 Interrupt */ + TIM15_IRQn = 20, /*!< TIM15 Interrupt */ + TIM16_IRQn = 21, /*!< TIM16 Interrupt */ + TIM17_IRQn = 22, /*!< TIM17 Interrupt */ + I2C1_IRQn = 23, /*!< I2C1 Interrupt */ + I2C2_IRQn = 24, /*!< I2C2 Interrupt */ + SPI1_IRQn = 25, /*!< SPI1 Interrupt */ + SPI2_IRQn = 26, /*!< SPI2 Interrupt */ + USART1_IRQn = 27, /*!< USART1 Interrupt */ + USART2_IRQn = 28, /*!< USART2 Interrupt */ + CEC_IRQn = 30 /*!< CEC Interrupt */ +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm0.h" +#include "system_stm32f0xx.h" +#include + +/** @addtogroup Exported_types + * @{ + */ + +typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; + +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus; + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC Interrupt and Status register, Address offset:0x00 */ + __IO uint32_t IER; /*!< ADC Interrupt Enable register, Address offset:0x04 */ + __IO uint32_t CR; /*!< ADC Control register, Address offset:0x08 */ + __IO uint32_t CFGR1; /*!< ADC Configuration register 1, Address offset:0x0C */ + __IO uint32_t CFGR2; /*!< ADC Configuration register 2, Address offset:0x10 */ + __IO uint32_t SMPR; /*!< ADC Sampling time register, Address offset:0x14 */ + uint32_t RESERVED1; /*!< Reserved, 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1C */ + __IO uint32_t TR; /*!< ADC watchdog threshold register, Address offset:0x20 */ + uint32_t RESERVED3; /*!< Reserved, 0x24 */ + __IO uint32_t CHSELR; /*!< ADC channel selection register, Address offset:0x28 */ + uint32_t RESERVED4[5]; /*!< Reserved, 0x2C */ + __IO uint32_t DR; /*!< ADC data register, Address offset:0x40 */ +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; +} ADC_Common_TypeDef; + +/** + * @brief HDMI-CEC + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CEC control register, Address offset:0x00 */ + __IO uint32_t CFGR; /*!< CEC configuration register, Address offset:0x04 */ + __IO uint32_t TXDR; /*!< CEC Tx data register , Address offset:0x08 */ + __IO uint32_t RXDR; /*!< CEC Rx Data Register, Address offset:0x0C */ + __IO uint32_t ISR; /*!< CEC Interrupt and Status Register, Address offset:0x10 */ + __IO uint32_t IER; /*!< CEC interrupt enable register, Address offset:0x14 */ +}CEC_TypeDef; + +/** + * @brief Comparator + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< COMP comparator control and status register, Address offset: 0x1C */ +} COMP_TypeDef; + + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + uint8_t RESERVED0; /*!< Reserved, 0x05 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ +} CRC_TypeDef; + + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + uint32_t RESERVED[6]; /*!< Reserved, 0x14 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + uint32_t RESERVED1; /*!< Reserved, 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ +} DAC_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZ; /*!< Debug MCU APB1 freeze register, Address offset: 0x08 */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x0C */ +}DBGMCU_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CMAR; /*!< DMA channel x memory address register */ +} DMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} DMA_TypeDef; + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR; /*!. +*/ + +/** + * @file GCC/ARMCMx/STM32F0xx/cmparams.h + * @brief ARM Cortex-M0 parameters for the STM32F0xx. + * + * @defgroup ARMCMx_STM32F0xx STM32F0xx Specific Parameters + * @ingroup ARMCMx_SPECIFIC + * @details This file contains the Cortex-M0 specific parameters for the + * STM32F0xx platform. + * @{ + */ + +#ifndef _CMPARAMS_H_ +#define _CMPARAMS_H_ + +/** + * @brief Cortex core model. + */ +#define CORTEX_MODEL CORTEX_M3 + +/** + * @brief Systick unit presence. + */ +#define CORTEX_HAS_ST TRUE + +/** + * @brief Memory Protection unit presence. + */ +#define CORTEX_HAS_MPU FALSE + +/** + * @brief Floating Point unit presence. + */ +#define CORTEX_HAS_FPU FALSE + +/** + * @brief Number of bits in priority masks. + */ +#define CORTEX_PRIORITY_BITS 2 + +#endif /* _CMPARAMS_H_ */ + +/** @} */ diff --git a/os/ports/GCC/ARMCMx/STM32F0xx/ld/STM32F051x8.ld b/os/ports/GCC/ARMCMx/STM32F0xx/ld/STM32F051x8.ld new file mode 100644 index 000000000..beffc882b --- /dev/null +++ b/os/ports/GCC/ARMCMx/STM32F0xx/ld/STM32F051x8.ld @@ -0,0 +1,150 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + * ST32F051x8 memory setup. + */ +__main_stack_size__ = 0x0400; +__process_stack_size__ = 0x0400; + +MEMORY +{ + flash : org = 0x08000000, len = 64k + ram : org = 0x20000000, len = 8k +} + +__ram_start__ = ORIGIN(ram); +__ram_size__ = LENGTH(ram); +__ram_end__ = __ram_start__ + __ram_size__; + +SECTIONS +{ + . = 0; + _text = .; + + startup : ALIGN(16) SUBALIGN(16) + { + KEEP(*(vectors)) + } > flash + + constructors : ALIGN(4) SUBALIGN(4) + { + PROVIDE(__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE(__init_array_end = .); + } > flash + + destructors : ALIGN(4) SUBALIGN(4) + { + PROVIDE(__fini_array_start = .); + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + PROVIDE(__fini_array_end = .); + } > flash + + .text : ALIGN(16) SUBALIGN(16) + { + *(.text.startup.*) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + *(.glue_7t) + *(.glue_7) + *(.gcc*) + } > flash + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > flash + + .ARM.exidx : { + PROVIDE(__exidx_start = .); + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + PROVIDE(__exidx_end = .); + } > flash + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > flash + + .eh_frame : ONLY_IF_RO + { + *(.eh_frame) + } > flash + + .textalign : ONLY_IF_RO + { + . = ALIGN(8); + } > flash + + _etext = .; + _textdata = _etext; + + .stacks : + { + . = ALIGN(8); + __main_stack_base__ = .; + . += __main_stack_size__; + . = ALIGN(8); + __main_stack_end__ = .; + __process_stack_base__ = .; + __main_thread_stack_base__ = .; + . += __process_stack_size__; + . = ALIGN(8); + __process_stack_end__ = .; + __main_thread_stack_end__ = .; + } > ram + + .data : + { + . = ALIGN(4); + PROVIDE(_data = .); + *(.data) + . = ALIGN(4); + *(.data.*) + . = ALIGN(4); + *(.ramtext) + . = ALIGN(4); + PROVIDE(_edata = .); + } > ram AT > flash + + .bss : + { + . = ALIGN(4); + PROVIDE(_bss_start = .); + *(.bss) + . = ALIGN(4); + *(.bss.*) + . = ALIGN(4); + *(COMMON) + . = ALIGN(4); + PROVIDE(_bss_end = .); + } > ram +} + +PROVIDE(end = .); +_end = .; + +__heap_base__ = _end; +__heap_end__ = __ram_end__; diff --git a/os/ports/GCC/ARMCMx/STM32F0xx/port.mk b/os/ports/GCC/ARMCMx/STM32F0xx/port.mk new file mode 100644 index 000000000..d8727e166 --- /dev/null +++ b/os/ports/GCC/ARMCMx/STM32F0xx/port.mk @@ -0,0 +1,15 @@ +# List of the ChibiOS/RT Cortex-M3 STM32 port files. +PORTSRC = $(CHIBIOS)/os/ports/GCC/ARMCMx/crt0.c \ + $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F0xx/vectors.c \ + ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore.c \ + ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore_v6m.c \ + ${CHIBIOS}/os/ports/common/ARMCMx/nvic.c + +PORTASM = + +PORTINC = ${CHIBIOS}/os/ports/common/ARMCMx/CMSIS/include \ + ${CHIBIOS}/os/ports/common/ARMCMx \ + ${CHIBIOS}/os/ports/GCC/ARMCMx \ + ${CHIBIOS}/os/ports/GCC/ARMCMx/STM32F0xx + +PORTLD = ${CHIBIOS}/os/ports/GCC/ARMCMx/STM32F0xx/ld diff --git a/os/ports/GCC/ARMCMx/STM32F0xx/vectors.c b/os/ports/GCC/ARMCMx/STM32F0xx/vectors.c new file mode 100644 index 000000000..48f7ceee4 --- /dev/null +++ b/os/ports/GCC/ARMCMx/STM32F0xx/vectors.c @@ -0,0 +1,168 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file GCC/ARMCMx/STM32F0xx/vectors.c + * @brief Interrupt vectors for the STM32F0xx family. + * + * @defgroup ARMCMx_STM32F0xx_VECTORS STM32F0xx Interrupt Vectors + * @ingroup ARMCMx_SPECIFIC + * @details Interrupt vectors for the STM32F0xx family. + * @{ + */ + +#include "ch.h" + +#if !defined(__DOXYGEN__) +extern void __main_stack_end__(void); +extern void ResetHandler(void); +extern void NMIVector(void); +extern void HardFaultVector(void); +extern void MemManageVector(void); +extern void BusFaultVector(void); +extern void UsageFaultVector(void); +extern void Vector1C(void); +extern void Vector20(void); +extern void Vector24(void); +extern void Vector28(void); +extern void SVCallVector(void); +extern void DebugMonitorVector(void); +extern void Vector34(void); +extern void PendSVVector(void); +extern void SysTickVector(void); +extern void Vector40(void); +extern void Vector44(void); +extern void Vector48(void); +extern void Vector4C(void); +extern void Vector50(void); +extern void Vector54(void); +extern void Vector58(void); +extern void Vector5C(void); +extern void Vector60(void); +extern void Vector64(void); +extern void Vector68(void); +extern void Vector6C(void); +extern void Vector70(void); +extern void Vector74(void); +extern void Vector78(void); +extern void Vector7C(void); +extern void Vector80(void); +extern void Vector84(void); +extern void Vector88(void); +extern void Vector8C(void); +extern void Vector90(void); +extern void Vector94(void); +extern void Vector98(void); +extern void Vector9C(void); +extern void VectorA0(void); +extern void VectorA4(void); +extern void VectorA8(void); +extern void VectorAC(void); +extern void VectorB0(void); +extern void VectorB4(void); +extern void VectorB8(void); +extern void VectorBC(void); +#endif + +/** + * @brief STM32 vectors table. + */ +#if !defined(__DOXYGEN__) +__attribute__ ((section("vectors"))) +#endif +void (*_vectors[])(void) = { + __main_stack_end__, ResetHandler, NMIVector, HardFaultVector, + MemManageVector, BusFaultVector, UsageFaultVector, Vector1C, + Vector20, Vector24, Vector28, SVCallVector, + DebugMonitorVector, Vector34, PendSVVector, SysTickVector, + Vector40, Vector44, Vector48, Vector4C, + Vector50, Vector54, Vector58, Vector5C, + Vector60, Vector64, Vector68, Vector6C, + Vector70, Vector74, Vector78, Vector7C, + Vector80, Vector84, Vector88, Vector8C, + Vector90, Vector94, Vector98, Vector9C, + VectorA0, VectorA4, VectorA8, VectorAC, + VectorB0, VectorB4, VectorB8, VectorBC +}; + +/** + * @brief Unhandled exceptions handler. + * @details Any undefined exception vector points to this function by default. + * This function simply stops the system into an infinite loop. + * + * @notapi + */ +#if !defined(__DOXYGEN__) +__attribute__ ((naked)) +#endif +void _unhandled_exception(void) { + + while (TRUE) + ; +} + +void NMIVector(void) __attribute__((weak, alias("_unhandled_exception"))); +void HardFaultVector(void) __attribute__((weak, alias("_unhandled_exception"))); +void MemManageVector(void) __attribute__((weak, alias("_unhandled_exception"))); +void BusFaultVector(void) __attribute__((weak, alias("_unhandled_exception"))); +void UsageFaultVector(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector1C(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector20(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector24(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector28(void) __attribute__((weak, alias("_unhandled_exception"))); +void SVCallVector(void) __attribute__((weak, alias("_unhandled_exception"))); +void DebugMonitorVector(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector34(void) __attribute__((weak, alias("_unhandled_exception"))); +void PendSVVector(void) __attribute__((weak, alias("_unhandled_exception"))); +void SysTickVector(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector40(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector44(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector48(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector4C(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector50(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector54(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector58(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector5C(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector60(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector64(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector68(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector6C(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector70(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector74(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector78(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector7C(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector80(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector84(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector88(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector8C(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector90(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector94(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector98(void) __attribute__((weak, alias("_unhandled_exception"))); +void Vector9C(void) __attribute__((weak, alias("_unhandled_exception"))); +void VectorA0(void) __attribute__((weak, alias("_unhandled_exception"))); +void VectorA4(void) __attribute__((weak, alias("_unhandled_exception"))); +void VectorA8(void) __attribute__((weak, alias("_unhandled_exception"))); +void VectorAC(void) __attribute__((weak, alias("_unhandled_exception"))); +void VectorB0(void) __attribute__((weak, alias("_unhandled_exception"))); +void VectorB4(void) __attribute__((weak, alias("_unhandled_exception"))); +void VectorB8(void) __attribute__((weak, alias("_unhandled_exception"))); +void VectorBC(void) __attribute__((weak, alias("_unhandled_exception"))); + +/** @} */ -- cgit v1.2.3