diff options
| author | bnewbold <bnewbold@robocracy.org> | 2010-03-30 20:52:45 -0400 | 
|---|---|---|
| committer | bnewbold <bnewbold@robocracy.org> | 2010-03-30 20:52:45 -0400 | 
| commit | e7d600494579ef319b20221769c3b2fe12962243 (patch) | |
| tree | 5c95101e295bcfdd7f9f4292ce9204ddf7e7f662 /libmaple | |
| parent | 8d6bf3b196c2a0bc1adda4a04669e54fdc5b65cb (diff) | |
| download | librambutan-e7d600494579ef319b20221769c3b2fe12962243.tar.gz librambutan-e7d600494579ef319b20221769c3b2fe12962243.zip | |
Major hierarchy reorganization; see README.
copy-to-ide and Makefile updated to conform; .gitignore added;
LICENSE added
Diffstat (limited to 'libmaple')
| -rw-r--r-- | libmaple/adc.c | 97 | ||||
| -rw-r--r-- | libmaple/adc.h | 93 | ||||
| -rw-r--r-- | libmaple/bootVect.h | 52 | ||||
| -rw-r--r-- | libmaple/exti.c | 279 | ||||
| -rw-r--r-- | libmaple/exti.h | 152 | ||||
| -rw-r--r-- | libmaple/gpio.c | 55 | ||||
| -rw-r--r-- | libmaple/gpio.h | 97 | ||||
| -rw-r--r-- | libmaple/libmaple.h | 33 | ||||
| -rw-r--r-- | libmaple/libmaple_types.h | 42 | ||||
| -rw-r--r-- | libmaple/nvic.c | 59 | ||||
| -rw-r--r-- | libmaple/nvic.h | 67 | ||||
| -rw-r--r-- | libmaple/stm32f10x_conf.h | 132 | ||||
| -rw-r--r-- | libmaple/stm32f10x_it.c | 252 | ||||
| -rw-r--r-- | libmaple/syscalls.c | 157 | ||||
| -rw-r--r-- | libmaple/systick.c | 52 | ||||
| -rw-r--r-- | libmaple/systick.h | 62 | ||||
| -rw-r--r-- | libmaple/timers.c | 192 | ||||
| -rw-r--r-- | libmaple/timers.h | 145 | ||||
| -rw-r--r-- | libmaple/usart.c | 345 | ||||
| -rw-r--r-- | libmaple/usart.h | 53 | ||||
| -rw-r--r-- | libmaple/usb.c | 83 | ||||
| -rw-r--r-- | libmaple/usb.h | 32 | ||||
| -rw-r--r-- | libmaple/usb_regs.h | 555 | ||||
| -rw-r--r-- | libmaple/util.c | 103 | ||||
| -rw-r--r-- | libmaple/util.h | 82 | 
25 files changed, 3271 insertions, 0 deletions
| diff --git a/libmaple/adc.c b/libmaple/adc.c new file mode 100644 index 0000000..7169824 --- /dev/null +++ b/libmaple/adc.c @@ -0,0 +1,97 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:34:47 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file adc.c + * + *  @brief Analog to digital converter routines + */ + +#include "stm32f10x_rcc.h" +#include "adc.h" +#include <stdio.h> +#include <inttypes.h> + +/* The ADC input clock is generated from PCLK2/APB2 divided by a prescaler + * and it must not exceed 14MHz. + * + * ADC1 and ADC2 are clocked by APB2 + * + * 1) Power on by setting ADON in ADC_CR2 + * Conversion starts when ADON is set for a second time after some + * time t > t_stab. + * + * Up to 16 selected conversion must be selected in ADC_SQRx + * + * Single conversion mode: + * Set the ADON bit in the ADC_CR2 register + * Once the conversion is complete: + *  Converted data is stored in ADC_DR + *  EOC flag is set + *  Interrupt is generated if EOCIE is set + * + * Calibration: + * Calibration is started by setting the CAL bit in the ADC_CR2 register. + * Once calibration is over, the CAL bit is reset by hardware and normal + * conversion can be performed. Calibrate at power-on. + * + * ALIGN in ADC_CR2 selects the alignment of data + * + * IMPORTANT: maximum external impedance must be below 0.4kOhms for 1.5 + * sample conversion time. + * + * At 55.5 cycles/sample, the external input impedance < 50kOhms*/ + +void adc_init(void) { +    /* PCLK2 is the APB2 clock */ +    RCC_ADCCLKConfig(RCC_PCLK2_Div6); + +    /* Enable ADC1 clock so that we can talk to it */ +    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); + +    /* Put everything back to power-on defaults */ +    RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE); +    RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); + +    ADC_CR1  = 0; +    ADC_CR2  = CR2_EXTSEL_SWSTART | CR2_EXTTRIG;  // Software triggers conversions +    ADC_SQR1 = 0; + +    /* Up the sample conversion time to 55.5 cycles/sec, see note above  */ +    /* TODO: fix magic numbers  */ +    ADC_SMPR1 = 0xB6DB6D; +    ADC_SMPR2 = 0x2DB6DB6D; + +    /* Enable the ADC  */ +    CR2_ADON_BIT = 1; + +    /* Reset the calibration registers and then perform a reset  */ +    CR2_RSTCAL_BIT = 1; +    while(CR2_RSTCAL_BIT) +        ; + +    CR2_CAL_BIT = 1; +    while(CR2_CAL_BIT) +        ; +} + + +void adc_disable(void) { +    CR2_ADON_BIT = 0; +} diff --git a/libmaple/adc.h b/libmaple/adc.h new file mode 100644 index 0000000..d554b02 --- /dev/null +++ b/libmaple/adc.h @@ -0,0 +1,93 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:35:10 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file adc.h + * + *  @brief ADC prototypes and defines + */ + +#ifndef _ADC_H_ +#define _ADC_H_ +#include <inttypes.h> +#include "util.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +/* Notes: + * The maximum input impedance on each channel MUST be below .4kohms, + * or face the wrath of incorrect readings... + * This can be changed at the expense of sample time... see datasheet + * + * Need to up the sample time if otherwise... see datasheet */ + +/* We'll only use ADC1 for now...  */ +#define ADC_BASE                 0x40012400 +#define ADC_SR                   *(volatile uint32_t*)(ADC_BASE + 0) +#define ADC_CR1                  *(volatile uint32_t*)(ADC_BASE + 0x4) +#define ADC_CR2                  *(volatile uint32_t*)(ADC_BASE + 0x8) +#define ADC_SMPR1                *(volatile uint32_t*)(ADC_BASE + 0xC) +#define ADC_SMPR2                *(volatile uint32_t*)(ADC_BASE + 0x10) +#define ADC_SQR1                 *(volatile uint32_t*)(ADC_BASE + 0x2C) +#define ADC_SQR3                 *(volatile uint32_t*)(ADC_BASE + 0x34) +#define ADC_DR                   *(volatile uint32_t*)(ADC_BASE + 0x4C) + +#define CR2_EXTSEL_SWSTART       (0xE << 16) +#define CR2_RSTCAL               (BIT(3)) +#define CR2_EXTTRIG              (BIT(20)) + +/* Bit banded bits  */ +#define CR2_ADON_BIT             *(volatile uint32_t*)(BITBAND_PERI(ADC_BASE+0x8, 0)) +#define CR2_CAL_BIT              *(volatile uint32_t*)(BITBAND_PERI(ADC_BASE+0x8, 2)) +#define CR2_RSTCAL_BIT           *(volatile uint32_t*)(BITBAND_PERI(ADC_BASE+0x8, 3)) +#define CR2_SWSTART_BIT          *(volatile uint32_t*)(BITBAND_PERI(ADC_BASE+0x8 + 2, 6)) +#define SR_EOC_BIT               *(volatile uint32_t*)(BITBAND_PERI(ADC_BASE+0, 1)) + +#define NR_ANALOG_PINS           16 + +/* Initialize ADC1 to do one-shot conversions  */ +void adc_init(void); +void adc_disable(void); + +/* Perform a single conversion on ADC[0-16], + * PRECONDITIONS: + *   adc initialized */ +static inline int adc_read(int channel) { +    /* Set channel  */ +    ADC_SQR3 = channel; + +    /* Start the conversion  */ +    CR2_SWSTART_BIT = 1; + +    /* Wait for it to finish  */ +    while(SR_EOC_BIT == 0) +        ; + +    return ADC_DR; +} + + + +#ifdef __cplusplus +} // extern "C" +#endif +#endif + diff --git a/libmaple/bootVect.h b/libmaple/bootVect.h new file mode 100644 index 0000000..5bcb42b --- /dev/null +++ b/libmaple/bootVect.h @@ -0,0 +1,52 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + * ****************************************************************************/ + +/** + *  @file HardwareUsb.h + * + *  @brief Defines the maple boot vector structure + */ + +#ifndef _BOOTVECT_H_ +#define _BOOTVECT_H_ + +#define BOOTLOADER_VECT_TABLE ((uint32_t*)0x20000000) + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef void (*FuncPtr)(void); + +typedef struct { +  FuncPtr serial_tx_cb; +  FuncPtr serial_rx_cb; +  FuncPtr serial_linecoding_cb; +  uint32_t* serial_count_in; +  uint32_t* serial_count_out; +  uint8_t* serial_buffer_out; +  void* linecoding; +  uint8_t major_rev; +  uint8_t minor_rev; +  void* usb_device_ptr; +  void* usb_local_obj_ptr; +} BootVectTable; + +#ifdef __cplusplus +} +#endif + +#endif // _BOOTVECT_H_ diff --git a/libmaple/exti.c b/libmaple/exti.c new file mode 100644 index 0000000..bdaa204 --- /dev/null +++ b/libmaple/exti.c @@ -0,0 +1,279 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:35:22 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file exti.c + * + *  @brief External interrupt control routines + */ + +#include "libmaple.h" +#include "exti.h" +#include "nvic.h" + +volatile static voidFuncPtr exti_handlers[NR_EXTI_CHANNELS]; + +static inline void clear_pending(int bit) { +    REG_SET(EXTI_PR, BIT(bit)); +    /* If the pending bit is cleared as the last instruction in an ISR, +     * it won't actually be cleared in time and the ISR will fire again. +     * Insert a 2-cycle buffer to allow it to take effect. */ +    asm volatile("nop"); +    asm volatile("nop"); +} + +/* For EXTI0 through EXTI4, only one handler + * is associated with each channel, so we + * don't have to keep track of which channel + * we came from */ +void EXTI0_IRQHandler(void) { +    ASSERT(exti_handlers[EXTI0]); +    if (exti_handlers[EXTI0]) { +        exti_handlers[EXTI0](); +    } + +    /* Clear pending bit*/ +    clear_pending(EXTI0); +} + +void EXTI1_IRQHandler(void) { +    ASSERT(exti_handlers[EXTI1]); +    /* Call registered handler  */ +    if (exti_handlers[EXTI1]) { +        exti_handlers[EXTI1](); +    } + +    /* Clear pending bit*/ +    clear_pending(EXTI1); +} + +void EXTI2_IRQHandler(void) { +    ASSERT(exti_handlers[EXTI2]); +    /* Call registered handler  */ +    if (exti_handlers[EXTI2]) { +        exti_handlers[EXTI2](); +    } + +    /* Clear pending bit*/ +    clear_pending(EXTI2); +} + +void EXTI3_IRQHandler(void) { +    ASSERT(exti_handlers[EXTI3]); +    /* Call registered handler  */ +    if (exti_handlers[EXTI3]) { +        exti_handlers[EXTI3](); +    } + +    /* Clear pending bit*/ +    clear_pending(EXTI3); +} + +void EXTI4_IRQHandler(void) { +    ASSERT(exti_handlers[EXTI4]); +    /* Call registered handler  */ +    if (exti_handlers[EXTI4]) { +        exti_handlers[EXTI4](); +    } + +    /* Clear pending bit*/ +    clear_pending(EXTI4); +} + +void EXTI9_5_IRQHandler(void) { +    /* Figure out which channel it came from  */ +    uint32_t pending; +    uint32_t i; +    pending = REG_GET(EXTI_PR); +    pending = GET_BITS(pending, 5, 9); + +    /* Dispatch every handler if the pending bit is set */ +    for (i = 0; i < 5; i++) { +        if (pending & 0x1) { +            ASSERT(exti_handlers[EXTI5 + i]); +            exti_handlers[EXTI5 + i](); +            clear_pending(EXTI5 + i); +        } +        pending >>= 1; +    } +} + +void EXTI15_10_IRQHandler(void) { +    /* Figure out which channel it came from  */ +    uint32_t pending; +    uint32_t i; +    pending = REG_GET(EXTI_PR); +    pending = GET_BITS(pending, 10, 15); + +    /* Dispatch every handler if the pending bit is set */ +    for (i = 0; i < 6; i++) { +        if (pending & 0x1) { +            ASSERT(exti_handlers[EXTI10 + i]); +            exti_handlers[EXTI10 + i](); +            clear_pending(EXTI10 + i); +        } +        pending >>= 1; +    } +} + + +void exti_attach_interrupt(uint8_t channel, uint8_t port, voidFuncPtr handler, uint8_t mode) { +    ASSERT(channel < NR_EXTI_CHANNELS); +    ASSERT(port < NR_EXTI_PORTS); +    ASSERT(mode < NR_EXTI_MODES); +    ASSERT(EXTI0 == 0); +    ASSERT(handler); + +    /* Note: All of the following code assumes that EXTI0 = 0  */ + +    /* Map port to the correct EXTI channel */ +    switch (channel) { +    case EXTI0: +    case EXTI1: +    case EXTI2: +    case EXTI3: +        REG_SET_MASK(AFIO_EXTICR1, BIT_MASK_SHIFT(port, channel*4)); +        break; + +    case EXTI4: +    case EXTI5: +    case EXTI6: +    case EXTI7: +        REG_SET_MASK(AFIO_EXTICR2, BIT_MASK_SHIFT(port, (channel-4)*4)); +        break; + +    case EXTI8: +    case EXTI9: +    case EXTI10: +    case EXTI11: +        REG_SET_MASK(AFIO_EXTICR3, BIT_MASK_SHIFT(port, (channel-8)*4)); +        break; + +    case EXTI12: +    case EXTI13: +    case EXTI14: +    case EXTI15: +        REG_SET_MASK(AFIO_EXTICR4, BIT_MASK_SHIFT(port, (channel-12)*4)); +        break; +    } + +    /* Unmask appropriate interrupt line  */ +    REG_SET_BIT(EXTI_IMR, channel); + +    /* Set trigger mode  */ +    switch (mode) { +    case EXTI_RISING: +        REG_SET_BIT(EXTI_RTSR, channel); +        break; + +    case EXTI_FALLING: +        REG_SET_BIT(EXTI_FTSR, channel); +        break; + +    case EXTI_RISING_FALLING: +        REG_SET_BIT(EXTI_RTSR, channel); +        REG_SET_BIT(EXTI_FTSR, channel); +        break; +    } + +    /* Configure the enable interrupt bits for the NVIC  */ +    switch (channel) { +    case EXTI0: +    case EXTI1: +    case EXTI2: +    case EXTI3: +    case EXTI4: +        REG_SET(NVIC_ISER0, BIT(channel + 6)); +        break; + +    /* EXTI5-9 map to the same isr */ +    case EXTI5: +    case EXTI6: +    case EXTI7: +    case EXTI8: +    case EXTI9: +        REG_SET(NVIC_ISER0, BIT(23)); +        break; + +    /* EXTI10-15 map to the same isr */ +    case EXTI10: +    case EXTI11: +    case EXTI12: +    case EXTI13: +    case EXTI14: +    case EXTI15: +        REG_SET(NVIC_ISER1, BIT(8)); +        break; +    } + +    /* Register the handler  */ +    exti_handlers[channel] = handler; +} + + +void exti_detach_interrupt(uint8_t channel) { +    ASSERT(channel < NR_EXTI_CHANNELS); +    ASSERT(EXTI0 == 0); +    /* Is this interrupt actually on?  */ +    ASSERT((REG_GET(EXTI_IMR) >> channel) & 0x01); + +    /* Clear EXTI_IMR line  */ +    REG_CLEAR_BIT(EXTI_IMR, channel); + +    /* Clear triggers  */ +    REG_CLEAR_BIT(EXTI_FTSR, channel); +    REG_CLEAR_BIT(EXTI_RTSR, channel); + +    /* Turn off the associated interrupt */ +    switch (channel) { +    case EXTI0: +    case EXTI1: +    case EXTI2: +    case EXTI3: +    case EXTI4: +        REG_SET(NVIC_ICER0, BIT(channel + 6)); +        break; +    case EXTI5: +    case EXTI6: +    case EXTI7: +    case EXTI8: +    case EXTI9: +        /* Are there any other channels enabled? +         * If so, don't disable the interrupt handler */ +        if (GET_BITS(REG_GET(EXTI_IMR), 5, 9) == 0) { +            REG_SET(NVIC_ICER0, BIT(23)); +        } +        break; +    case EXTI10: +    case EXTI11: +    case EXTI12: +    case EXTI13: +    case EXTI14: +    case EXTI15: +        /* Are there any other channels enabled? +         * If so, don't disable the interrupt handler */ +        if (GET_BITS(REG_GET(EXTI_IMR), 10, 15) == 0) { +            REG_SET(NVIC_ICER1, BIT(8)); +        } +        break; +    } + +    /* Clear handler function pointer  */ +    exti_handlers[channel] = 0; +} diff --git a/libmaple/exti.h b/libmaple/exti.h new file mode 100644 index 0000000..c728454 --- /dev/null +++ b/libmaple/exti.h @@ -0,0 +1,152 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:35:33 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file exti.h + * + *  @brief External interrupt control prototypes and defines + */ + +#ifndef _EXTI_H_ +#define _EXTI_H_ + +#include <inttypes.h> +/* Notes: + * + * To generate the interrupt, the interrupt line should be configured and + * enabled. This is done by programming the two trigger registers with the + * desired edge detection and by enabling the interrupt request by writing a + * '1' to the corresponding bit in the interrupt mask register.  When the + * selected edge occurs on the external interrupt line, an interrupt request is + * generated. The pending bit corresponding to the interrupt line is also set. + * This request is reset by writing a '1' in the pending register. + * + * Hardware interrupt selection: + * To configure the 20 lines as interrupt sources, use the following procedure: + * 1) Configure AFIO_EXTIICR[y] to select the source input for EXTIx external  + *    interrupt + * 2) Configure the mask bits of the 20 interrupt lines (EXTI_IMR) + * 3) Configure the trigger selection bits of the interrupt lines (EXTI_RTSR and EXTI_FTSR) + * 4) Configure the enable and mask bits that control the NVIC_IRQ channel mapped to the External + * Interrupt Controller (EXTI) so that an inerrupt coming from one of the 20 lines + * can be correctly acknowledged. + * + * AFIO clock must be on. + * + * RM0008, page 107: "PD0, PD1 cannot be used for external interrupt/event generation + * on 36, 48, 64-bin packages." + * + * ---------------------------------------------------------------------------- + * Pin to EXTI Line Mappings: + * EXTI0          EXTI1          EXTI2           EXTI3             EXTI4 + * ---------------------------------------------------------------------------- + * D2/PA0         D3/PA1         D1/PA2          D0/A6/PA3         D10/A10/PA4 + * D26/EXT7/PB0   D27/EXT8/PB1   D16/A2/PC2      D17/A3/PC3        D18/A4/PC4 + * D14/A0/PC0     D15/PC1        D25/EXT5/PD2 + * + * EXTI5          EXTI6          EXTI7           EXTI8             EXTI9 + * ---------------------------------------------------------------------------- + * D13/A13/PA5    D12/A12/PA6    D11/A11/PA7     D6/PA8            D7/PA9 + * D4/PB5         D5/PB6         D9/PB7          D38/PB8           D23/EXT4/PB9 + * D19/A5/PC5     D34/EXTI15/PC6 D35/EXT16/PC7   D36/PC8           D37/EXT18/PC9 + * + * EXTI10         EXTI11         EXTI12          EXTI13            EXTI14 + * ---------------------------------------------------------------------------- + * D8/PA10        D29/EXT10/PB11 D30/EXTI1/PB12  D31/EXTI12/PB13   D32/EXT13/PB14 + * D28/PB10                                      D20/EXTI1/PC13    D21/EXT2/PC14 + * D25/PC10 + * + * EXTI15 + * ---------------------------------------------------------------------------- + * D33/EXTI14/PB15 + * D22/EXT3/PC15 + * + * + * The 16 EXTI interrupts are mapped to 7 interrupt handlers. + * + * EXTI Lines to Interrupt Mapping: + * EXTI0 -> EXTI0 + * EXTI1 -> EXTI1 + * EXTI2 -> EXTI2 + * EXTI3 -> EXTI3 + * EXTI4 -> EXTI4 + * EXTI[5-9] -> EXT9_5 + * EXTI[10-15] -> EXT15_10 + * + * + * */ + +#define NR_EXTI_CHANNELS         16 +#define NR_EXTI_PORTS             4 +#define NR_EXTI_MODES             3 + +#define EXTI_IMR        0x40010400                   // Interrupt mask register +#define EXTI_EMR        (EXTI_IMR + 0x04)            // Event mask register +#define EXTI_RTSR       (EXTI_IMR + 0x08)            // Rising trigger selection register +#define EXTI_FTSR       (EXTI_IMR + 0x0C)            // Falling trigger selection register +#define EXTI_SWIER      (EXTI_IMR + 0x10)            // Software interrupt event register +#define EXTI_PR         (EXTI_IMR + 0x14)            // Pending register + +#define AFIO_EVCR       0x40010000 +#define AFIO_EXTICR1    (AFIO_EVCR + 0x08) +#define AFIO_EXTICR2    (AFIO_EVCR + 0x0C) +#define AFIO_EXTICR3    (AFIO_EVCR + 0x10) +#define AFIO_EXTICR4    (AFIO_EVCR + 0x14) + +#define EXTI_RISING                     0 +#define EXTI_FALLING                    1 +#define EXTI_RISING_FALLING             2 + +#define EXTI0  0 +#define EXTI1  1 +#define EXTI2  2 +#define EXTI3  3 +#define EXTI4  4 +#define EXTI5  5 +#define EXTI6  6 +#define EXTI7  7 +#define EXTI8  8 +#define EXTI9  9 +#define EXTI10 10 +#define EXTI11 11 +#define EXTI12 12 +#define EXTI13 13 +#define EXTI14 14 +#define EXTI15 15 + +#define EXTI_CONFIG_PORTA 0 +#define EXTI_CONFIG_PORTB 1 +#define EXTI_CONFIG_PORTC 2 +#define EXTI_CONFIG_PORTD 3 + + +#ifdef __cplusplus +extern "C"{ +#endif + +void exti_attach_interrupt(uint8_t, uint8_t, voidFuncPtr, uint8_t); +void exti_detach_interrupt(uint8_t); + +#ifdef __cplusplus +} // extern "C" +#endif + + +#endif + diff --git a/libmaple/gpio.c b/libmaple/gpio.c new file mode 100644 index 0000000..facb514 --- /dev/null +++ b/libmaple/gpio.c @@ -0,0 +1,55 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:35:49 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file gpio.c + * + *  @brief GPIO initialization routine + */ + +#include "libmaple.h" +#include "stm32f10x_rcc.h" +#include "gpio.h" + +void gpio_init(void) { +   /* Turn on clocks for GPIO  */ +   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | +                          RCC_APB2Periph_GPIOB | +                          RCC_APB2Periph_GPIOC | +                          RCC_APB2Periph_GPIOD | +                          RCC_APB2Periph_AFIO, +                          ENABLE); +} + +void gpio_set_mode(GPIO_Port* port, uint8 gpio_pin, uint8 mode) { +    uint32_t tmp; +    uint32_t shift = POS(gpio_pin % 8); +    GPIOReg CR; + +    ASSERT(port); +    ASSERT(gpio_pin < 16); + +    CR = (gpio_pin < 8) ? &(port->CRL) : &(port->CRH); + +    tmp = *CR; +    tmp &= POS_MASK(shift); +    tmp |= mode << shift; + +    *CR = tmp; +} diff --git a/libmaple/gpio.h b/libmaple/gpio.h new file mode 100644 index 0000000..5e7cf29 --- /dev/null +++ b/libmaple/gpio.h @@ -0,0 +1,97 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:36:01 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file gpio.h + * + *  @brief GPIO prototypes, defines, and inlined access functions + */ + +#ifndef _GPIO_H +#define _GPIO_H + +/* Each of the GPIO port bits can be in the following modes (STM32 138/995): + *      Input floating + *      Input pull-up + *      Input pull-down + *      Analog Input + *      Output open-drain + *      Output push-pull + *      Alternate function push-pull + *      Alternate function open-drain + * + * - After reset, the alternate functions are not active and IO prts + * are set to Input Floating mode */ + +#define GPIOA_BASE               (GPIO_Port*)0x40010800 +#define GPIOB_BASE               (GPIO_Port*)0x40010C00 +#define GPIOC_BASE               (GPIO_Port*)0x40011000 +#define GPIOD_BASE               (GPIO_Port*)0x40011400 + +/* Pin modes are set by [CNFx[1:0] : MODEx[1:0]] */ +#define GPIO_SPEED_50MHZ            (0x3) // Max output speed 50 MHz +#define GPIO_MODE_OUTPUT_PP         ((0x00 << 2) | GPIO_SPEED_50MHZ) +#define GPIO_MODE_OUTPUT_OD         ((0x01 << 2) | GPIO_SPEED_50MHZ) + +#define GPIO_MODE_AF_OUTPUT_PP      ((0x02 << 2) | GPIO_SPEED_50MHZ) +#define GPIO_MODE_AF_OUTPUT_OD      ((0x03 << 2) | GPIO_SPEED_50MHZ) + +/* Note: mode bits must be set to zero for input mode  */ +#define GPIO_MODE_INPUT_ANALOG      (0x00 << 2) +#define GPIO_MODE_INPUT_FLOATING    (0x01 << 2) +#define GPIO_MODE_INPUT_PD          (0x02 << 2) +#define GPIO_MODE_INPUT_PU          (0x02 << 2) + +typedef struct { +    volatile uint32 CRL;      // Port configuration register low +    volatile uint32 CRH;      // Port configuration register high +    volatile uint32 IDR;      // Port input data register +    volatile uint32 ODR;      // Port output data register +    volatile uint32 BSRR;     // Port bit set/reset register +    volatile uint32 BRR;      // Port bit reset register +    volatile uint32 LCKR;     // Port configuration lock register +} GPIO_Port; + +typedef volatile uint32* GPIOReg; + +#define POS_MASK(shift) (~(0xF << shift)) +#define POS(val)        (val << 2) + +#ifdef __cplusplus +extern "C"{ +#endif + +void gpio_init(void); +void gpio_set_mode(GPIO_Port* port, uint8 gpio_pin, uint8 mode); + +static inline void gpio_write_bit(GPIO_Port *port, uint8 gpio_pin, uint8 val) { +    if (val){ +        port->BSRR = BIT(gpio_pin); +    } else { +        port->BRR = BIT(gpio_pin); +    } +} + +#ifdef __cplusplus +} // extern "C" +#endif + + +#endif + diff --git a/libmaple/libmaple.h b/libmaple/libmaple.h new file mode 100644 index 0000000..dc9ffd2 --- /dev/null +++ b/libmaple/libmaple.h @@ -0,0 +1,33 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/19/09 02:37:22 EST + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file libmaple.h + * + *  @brief general include file for libmaple + */ + +#ifndef _LIBMAPLE_H_ +#define _LIBMAPLE_H_ + +#include "libmaple_types.h" +#include "util.h" + +#endif + diff --git a/libmaple/libmaple_types.h b/libmaple/libmaple_types.h new file mode 100644 index 0000000..b798587 --- /dev/null +++ b/libmaple/libmaple_types.h @@ -0,0 +1,42 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/19/09 02:35:14 EST + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file libmaple_types.h + * + *  @brief libmaple types + */ + +#ifndef _LIBMAPLE_TYPES_H_ +#define _LIBMAPLE_TYPES_H_ + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef unsigned long long uint64; + +typedef signed char int8; +typedef short int16; +typedef int int32; +typedef long long int64; + +typedef void (*voidFuncPtr)(void); + +#endif + diff --git a/libmaple/nvic.c b/libmaple/nvic.c new file mode 100644 index 0000000..9b8c84f --- /dev/null +++ b/libmaple/nvic.c @@ -0,0 +1,59 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:36:19 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file nvic.c + * + *  @brief Nested interrupt controller routines + */ + +#include "libmaple.h" +#include "nvic.h" +#include "systick.h" + +void nvic_disable_interrupts(void) { +    /* Turn off all interrupts  */ +    REG_SET(NVIC_ICER0, 0xFFFFFFFF); +    REG_SET(NVIC_ICER1, 0xFFFFFFFF); + +    /* Turn off systick exception  */ +    REG_CLEAR_BIT(SYSTICK_CSR, 0); +} + + +void nvic_set_vector_table(uint32_t *addr, uint32_t offset) { +//    SCB->VTOR = NVIC_VectTab | (Offset & (u32)0x1FFFFF80); +} + + +/** + *  @brief turn on interrupt number n + *  @param[in] n interrupt number + */ +void nvic_enable_interrupt(uint32 n) { +    if (n >= NVIC_NR_INTERRUPTS) { +        return; +    } + +    if (n < 32) { +        REG_SET_BIT(NVIC_ISER0, n); +    } else { +        REG_SET_BIT(NVIC_ISER1, n - 32); +    } +} diff --git a/libmaple/nvic.h b/libmaple/nvic.h new file mode 100644 index 0000000..5908e9c --- /dev/null +++ b/libmaple/nvic.h @@ -0,0 +1,67 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:36:47 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file nvic.h + * + *  @brief Nested interrupt controller defines and prototypes + */ + +#ifndef _NVIC_H_ +#define _NVIC_H_ + +#define NVIC_INT_USBHP      19 +#define NVIC_INT_USBLP      20 +#define NVIC_EXTI1_OFFSET   (NVIC_ISER0 + 0x07) +#define NVIC_EXTI9_5_OFFSET (NVIC_ISER0 + 0x17) + +/* NVIC Interrupt Enable registers  */ +#define NVIC_ISER0          0xE000E100 +#define NVIC_ISER1          0xE000E104 +#define NVIC_ISER2          0xE000E108 +#define NVIC_ISER3          0xE000E10C + +/* NVIC Interrupt Clear registers  */ +#define NVIC_ICER0          0xE000E180 +#define NVIC_ICER1          0xE000E184 +#define NVIC_ICER2          0xE000E188 +#define NVIC_ICER3          0xE000E18C + +/* System control registers  */ +#define SCB_VTOR            0xE000ED08  // Vector table offset register + +#define NVIC_VectTab_RAM             ((u32)0x20000000) +#define NVIC_VectTab_FLASH           ((u32)0x08000000) + +#define NVIC_NR_INTERRUPTS        60 + +#ifdef __cplusplus +extern "C"{ +#endif + +void nvic_disable_interrupts(void); +void nvic_enable_interrupt(uint32); + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/libmaple/stm32f10x_conf.h b/libmaple/stm32f10x_conf.h new file mode 100644 index 0000000..ddd1833 --- /dev/null +++ b/libmaple/stm32f10x_conf.h @@ -0,0 +1,132 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
 +* File Name          : stm32f10x_conf.h
 +* Author             : MCD Application Team
 +* Version            : V2.0.2
 +* Date               : 07/11/2008
 +* Description        : Library configuration file.
 +********************************************************************************
 +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
 +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
 +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
 +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
 +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
 +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
 +*******************************************************************************/
 +
 +/* Define to prevent recursive inclusion -------------------------------------*/
 +#ifndef __STM32F10x_CONF_H
 +#define __STM32F10x_CONF_H
 +
 +/* Includes ------------------------------------------------------------------*/
 +#include "stm32f10x_type.h"
 +
 +/* Exported types ------------------------------------------------------------*/
 +/* Exported constants --------------------------------------------------------*/
 +/* Uncomment the line below to compile the library in DEBUG mode, this will expanse
 +   the "assert_param" macro in the firmware library code (see "Exported macro"
 +   section below) */
 +/* #define DEBUG    1*/
 +
 +/* Comment the line below to disable the specific peripheral inclusion */
 +/************************************* ADC ************************************/
 +//#define _ADC
 +//#define _ADC1
 +//#define _ADC2
 +//#define _ADC3
 +//#define _BKP 
 +//#define _CAN
 +//#define _CRC
 +//#define _DAC
 +//#define _DBGMCU
 +//#define _DMA
 +//#define _DMA1_Channel1
 +//#define _DMA1_Channel2
 +//#define _DMA1_Channel3
 +//#define _DMA1_Channel4
 +//#define _DMA1_Channel5
 +//#define _DMA1_Channel6
 +//#define _DMA1_Channel7
 +//#define _DMA2_Channel1
 +//#define _DMA2_Channel2
 +//#define _DMA2_Channel3
 +//#define _DMA2_Channel4
 +//#define _DMA2_Channel5
 +#define _EXTI
 +#define _FLASH
 +
 +/* Uncomment the line below to enable FLASH program/erase/protections functions,
 +   otherwise only FLASH configuration (latency, prefetch, half cycle) functions
 +   are enabled */
 +/* #define _FLASH_PROG */
 +
 +#if 0
 +#define _FSMC
 +#define _GPIO
 +#define _GPIOA
 +#define _GPIOB
 +#define _GPIOC
 +#define _GPIOD
 +#define _GPIOE
 +#define _GPIOF
 +#define _GPIOG
 +#define _I2C
 +#define _I2C1
 +#define _I2C2
 +#define _IWDG
 +#define _PWR
 +#define _RTC
 +#define _SDIO
 +#define _SPI
 +#define _SPI1
 +#define _SPI2
 +#define _SPI3
 +#define _SysTick
 +#define _TIM
 +#define _TIM1
 +#define _TIM2
 +#define _TIM3
 +#define _TIM4
 +#define _TIM5
 +#define _TIM6
 +#define _TIM7
 +#define _TIM8
 +#define _USART
 +#define _USART1
 +#define _USART3
 +#define _UART4
 +#define _UART5
 +#endif
 +#define _USART2
 +#define _NVIC
 +#define _RCC
 +#define _AFIO
 +
 +/************************************* WWDG ***********************************/
 +#define _WWDG
 +
 +/* In the following line adjust the value of External High Speed oscillator (HSE)
 +   used in your application */
 +#define HSE_Value    ((u32)8000000) /* Value of the External oscillator in Hz*/
 +
 +/* Exported macro ------------------------------------------------------------*/
 +#ifdef  DEBUG
 +/*******************************************************************************
 +* Macro Name     : assert_param
 +* Description    : The assert_param macro is used for function's parameters check.
 +*                  It is used only if the library is compiled in DEBUG mode. 
 +* Input          : - expr: If expr is false, it calls assert_failed function
 +*                    which reports the name of the source file and the source
 +*                    line number of the call that failed. 
 +*                    If expr is true, it returns no value.
 +* Return         : None
 +*******************************************************************************/ 
 +  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((u8 *)__FILE__, __LINE__))
 +/* Exported functions ------------------------------------------------------- */
 +  void assert_failed(u8* file, u32 line);
 +#else
 +  #define assert_param(expr) ((void)0)
 +#endif /* DEBUG */
 +
 +#endif /* __STM32F10x_CONF_H */
 +
 +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
 diff --git a/libmaple/stm32f10x_it.c b/libmaple/stm32f10x_it.c new file mode 100644 index 0000000..70d3269 --- /dev/null +++ b/libmaple/stm32f10x_it.c @@ -0,0 +1,252 @@ +void NMIException(void) {
 +}
 +void HardFaultException(void) {
 +  while (1) {
 +  }
 +}
 +
 +void MemManageException(void) {
 +  while (1) {
 +  }
 +}
 +
 +void BusFaultException(void) {
 +  while (1) {
 +  }
 +}
 +
 +void UsageFaultException(void) {
 +  while (1) {
 +  }
 +}
 +
 +#if 0
 +void DebugMonitor(void) {
 +}
 +
 +void SVCHandler(void) {
 +}
 +
 +void PendSVC(void) {
 +}
 +
 +void WWDG_IRQHandler(void) {
 +}
 +
 +void PVD_IRQHandler(void) {
 +}
 +
 +void TAMPER_IRQHandler(void) {
 +}
 +
 +void RTC_IRQHandler(void) {
 +}
 +
 +void FLASH_IRQHandler(void) {
 +}
 +
 +void RCC_IRQHandler(void) {
 +}
 +
 +void DMA1_Channel1_IRQHandler(void) {
 +}
 +
 +void DMA1_Channel2_IRQHandler(void) {
 +}
 +
 +void DMA1_Channel3_IRQHandler(void) {
 +}
 +
 +void DMA1_Channel4_IRQHandler(void) {
 +}
 +
 +void DMA1_Channel5_IRQHandler(void) {
 +}
 +
 +void DMA1_Channel6_IRQHandler(void) {
 +}
 +
 +void DMA1_Channel7_IRQHandler(void) {
 +}
 +
 +void ADC1_2_IRQHandler(void) {
 +}
 +
 +void USB_HP_CAN_TX_IRQHandler(void) {
 +}
 +
 +void USB_LP_CAN_RX0_IRQHandler(void) {
 +}
 +
 +void CAN_RX1_IRQHandler(void) {
 +}
 +
 +void CAN_SCE_IRQHandler(void) {
 +}
 +
 +void TIM1_BRK_IRQHandler(void) {
 +}
 +
 +void TIM1_UP_IRQHandler(void) {
 +    while(1) {
 +    }
 +}
 +
 +void TIM1_TRG_COM_IRQHandler(void) {
 +}
 +
 +void TIM1_CC_IRQHandler(void) {
 +    while(1)
 +        ;
 +}
 +
 +void TIM2_IRQHandler(void) {
 +}
 +
 +void TIM3_IRQHandler(void) {
 +}
 +
 +void TIM4_IRQHandler(void) {
 +}
 +
 +void I2C1_EV_IRQHandler(void) {
 +}
 +
 +void I2C1_ER_IRQHandler(void) {
 +}
 +
 +void I2C2_EV_IRQHandler(void) {
 +}
 +
 +void I2C2_ER_IRQHandler(void) {
 +}
 +
 +void SPI1_IRQHandler(void) {
 +}
 +
 +void SPI2_IRQHandler(void) {
 +}
 +
 +void USART1_IRQHandler(void) {
 +#if 0
 +  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
 +  {
 +    /* Read one byte from the receive data register */
 +    RxBuffer[RxCounter++] = (USART_ReceiveData(USART1) & 0x7F);         
 +
 +    if(RxCounter == NbrOfDataToRead)
 +    {
 +      /* Disable the USART Receive interrupt */
 +      USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
 +    }
 +  }
 +
 +  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
 +  {   
 +    /* Write one byte to the transmit data register */
 +    USART_SendData(USART1, TxBuffer[TxCounter++]);                    
 +
 +    if(TxCounter == NbrOfDataToTransfer)
 +    {
 +      /* Disable the USART1 Transmit interrupt */
 +      USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
 +    }    
 +  }
 +#endif
 +}
 +
 +void USART2_IRQHandler(void) {
 +#if 0
 +  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
 +  {
 +      /* Echo the character back  */
 +      RxBuffer[0] = (USART_ReceiveData(USART2) & 0x7F);         
 +      USART_SendData(USART2, RxBuffer[0]);
 +  //  /* Read one byte from the receive data register */
 +  //  RxBuffer[RxCounter++] = (USART_ReceiveData(USART2) & 0x7F);         
 +
 +  //  if(RxCounter == NbrOfDataToRead)
 +  //  {
 +  //    /* Disable the USART Receive interrupt */
 +  //    USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
 +  //  }
 +  }
 +
 +#endif
 + 
 +#if 0
 +  if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)
 +  {   
 +    /* Write one byte to the transmit data register */
 +    USART_SendData(USART2, 'Y');                    
 +    TxCounter++;
 +//    USART_SendData(USART2, TxBuffer[TxCounter++]);                    
 +
 +    if(TxCounter == NbrOfDataToTransfer) {
 +      /* Disable the USART1 Transmit interrupt */
 +      USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
 +    }
 +  }
 +#endif
 +}
 +
 +void USART3_IRQHandler(void) {
 +}
 +
 +void RTCAlarm_IRQHandler(void) {
 +}
 +
 +void USBWakeUp_IRQHandler(void) {
 +}
 +
 +void TIM8_BRK_IRQHandler(void) {
 +}
 +
 +void TIM8_UP_IRQHandler(void) {
 +}
 +
 +void TIM8_TRG_COM_IRQHandler(void) {
 +}
 +
 +void TIM8_CC_IRQHandler(void) {
 +}
 +
 +void ADC3_IRQHandler(void) {
 +}
 +
 +void FSMC_IRQHandler(void) {
 +}
 +
 +void SDIO_IRQHandler(void) {
 +}
 +
 +void TIM5_IRQHandler(void) {
 +}
 +
 +void SPI3_IRQHandler(void) {
 +}
 +
 +void UART4_IRQHandler(void) {
 +}
 +
 +void UART5_IRQHandler(void) {
 +}
 +
 +void TIM6_IRQHandler(void) {
 +}
 +
 +void TIM7_IRQHandler(void) {
 +}
 +
 +void DMA2_Channel1_IRQHandler(void) {
 +}
 +
 +void DMA2_Channel2_IRQHandler(void) {
 +}
 +
 +void DMA2_Channel3_IRQHandler(void) {
 +}
 +
 +void DMA2_Channel4_5_IRQHandler(void) {
 +}
 +#endif
 diff --git a/libmaple/syscalls.c b/libmaple/syscalls.c new file mode 100644 index 0000000..390cecd --- /dev/null +++ b/libmaple/syscalls.c @@ -0,0 +1,157 @@ +#include "libmaple.h" +#include <sys/stat.h> + +/* _end is set in the linker command file */ +extern caddr_t _end; + +/* just in case, most boards have at least some memory */ +#ifndef RAMSIZE +#  define RAMSIZE             (caddr_t)0x50000 +#endif + +#define STACK_TOP 0x20000800 + +void uart_send(const char*str); + +/* + * sbrk -- changes heap size size. Get nbytes more + *         RAM. We just increment a pointer in what's + *         left of memory on the board. + */ +caddr_t +_sbrk(nbytes) +int nbytes; +{ +    static caddr_t heap_ptr = NULL; +    caddr_t        base; + +    if (heap_ptr == NULL) { +        heap_ptr = (caddr_t)&_end; +    } + +    if ((STACK_TOP - (unsigned int)heap_ptr) >= 0) { +        base = heap_ptr; +        heap_ptr += nbytes; +        return (base); +    } else { +        uart_send("heap full!\r\n"); +        return ((caddr_t)-1); +    } +} + +int _open(const char *path, int flags, ...) +{ +    return 1; +} + +int _close(int fd) +{ +    return 0; +} + +int _fstat(int fd, struct stat *st) +{ +    st->st_mode = S_IFCHR; +    return 0; +} + +int _isatty(int fd) +{ +    return 1; +} + +int isatty(int fd) +{ +    return 1; +} + +int _lseek(int fd, off_t pos, int whence) +{ +    return -1; +} + +unsigned char getch(void) +{ +//    while (!(USART2->SR & USART_FLAG_RXNE)); +//    return USART2->DR; +    return 0; +} + + +int _read(int fd, char *buf, size_t cnt) +{ +    *buf = getch(); + +    return 1; +} + +void putch(unsigned char c) +{ +//    if (c == '\n') putch('\r'); + +//    while (!(USART2->SR & USART_FLAG_TXE)); +//    USART2->DR = c; +} + +void cgets(char *s, int bufsize) +{ +    char *p; +    int c; +    int i; + +    for (i = 0; i < bufsize; i++) { +        *(s+i) = 0; +    } +//    memset(s, 0, bufsize); + +    p = s; + +    for (p = s; p < s + bufsize-1;) +    { +        c = getch(); +        switch (c) +        { +        case '\r' : +        case '\n' : +            putch('\r'); +            putch('\n'); +            *p = '\n'; +            return; + +        case '\b' : +            if (p > s) +            { +                *p-- = 0; +                putch('\b'); +                putch(' '); +                putch('\b'); +            } +            break; + +        default : +            putch(c); +            *p++ = c; +            break; +        } +    } +    return; +} + +int _write(int fd, const char *buf, size_t cnt) +{ +    int i; +//    uart_send("_write\r\n"); + +    for (i = 0; i < cnt; i++) +        putch(buf[i]); + +    return cnt; +} + +/* Override fgets() in newlib with a version that does line editing */ +char *fgets(char *s, int bufsize, void *f) +{ +//    uart_send("fgets\r\n"); +    cgets(s, bufsize); +    return s; +} diff --git a/libmaple/systick.c b/libmaple/systick.c new file mode 100644 index 0000000..47be69e --- /dev/null +++ b/libmaple/systick.c @@ -0,0 +1,52 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:37:24 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file systick.c + * + *  @brief System timer interrupt handler and initialization routines + */ + +#include "libmaple.h" +#include "systick.h" + +#define MILLIS_INC 1 + +volatile uint32_t systick_timer_millis = 0; + +void systick_init(void) { +    /* Set the reload counter to tick every 1ms  */ +    REG_SET_MASK(SYSTICK_RELOAD, MAPLE_RELOAD_VAL); +//    SYSTICK_RELOAD = MAPLE_RELOAD_VAL; + +    /* Clock the system timer with the core clock +     * and turn it on, interrrupt every 1ms to keep track of millis()*/ +    REG_SET(SYSTICK_CSR, SYSTICK_SRC_HCLK | +                         SYSTICK_ENABLE   | +                         SYSTICK_TICKINT); +//    SYSTICK_CSR = SYSTICK_SRC_HCLK | +//                  SYSTICK_ENABLE   | +//                  SYSTICK_TICKINT; +} + +void SysTickHandler(void) { +    systick_timer_millis++; +} + + diff --git a/libmaple/systick.h b/libmaple/systick.h new file mode 100644 index 0000000..61789c4 --- /dev/null +++ b/libmaple/systick.h @@ -0,0 +1,62 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:37:37 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file systick.h + * + *  @brief Various system timer definitions + */ + +#ifndef _SYSTICK_H_ +#define _SYSTICK_H_ + +#include "libmaple.h" + +/* To the ARM technical manual... there's nearly nothing on the systick + * timer in the stm32 manual */ + +#define SYSTICK_CSR       0xE000E010  // Control and status register +#define SYSTICK_RELOAD    0xE000E014  // Reload value register +#define SYSTICK_CNT       0xE000E018  // Current value register +#define SYSTICK_CALIB     0xE000E01C  // Calibration value register + +#define SYSTICK_SRC_HCLK  BIT(2)    // Use core clock +#define SYSTICK_TICKINT   BIT(1)    // Interrupt on systick countdown +#define SYSTICK_ENABLE    BIT(0)    // Turn on the counter + +/* We use the systick timer to tick once + * every millisecond */ +#define MAPLE_RELOAD_VAL     72000 + +#ifdef __cplusplus +extern "C"{ +#endif + +void systick_init(void); + +static inline uint32_t systick_get_count(void) { +    return (uint32_t)*(volatile uint32*)SYSTICK_CNT; +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + diff --git a/libmaple/timers.c b/libmaple/timers.c new file mode 100644 index 0000000..773ae36 --- /dev/null +++ b/libmaple/timers.c @@ -0,0 +1,192 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:37:54 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file timers.c + * + *  @brief General timer routines + */ + +#include "libmaple.h" +#include "stm32f10x_rcc.h" +#include "timers.h" + +typedef struct { +    volatile uint16_t CR1; +    uint16_t  RESERVED0; +    volatile uint16_t CR2; +    uint16_t  RESERVED1; +    volatile uint16_t SMCR; +    uint16_t  RESERVED2; +    volatile uint16_t DIER; +    uint16_t  RESERVED3; +    volatile uint16_t SR; +    uint16_t  RESERVED4; +    volatile uint16_t EGR; +    uint16_t  RESERVED5; +    volatile uint16_t CCMR1; +    uint16_t  RESERVED6; +    volatile uint16_t CCMR2; +    uint16_t  RESERVED7; +    volatile uint16_t CCER; +    uint16_t  RESERVED8; +    volatile uint16_t CNT; +    uint16_t  RESERVED9; +    volatile uint16_t PSC; +    uint16_t  RESERVED10; +    volatile uint16_t ARR; +    uint16_t  RESERVED11; +    volatile uint16_t RCR; +    uint16_t  RESERVED12; +    volatile uint16_t CCR1; +    uint16_t  RESERVED13; +    volatile uint16_t CCR2; +    uint16_t  RESERVED14; +    volatile uint16_t CCR3; +    uint16_t  RESERVED15; +    volatile uint16_t CCR4; +    uint16_t  RESERVED16; +    volatile uint16_t BDTR;   // Not used in general purpose timers +    uint16_t  RESERVED17;     // Not used in general purpose timers +    volatile uint16_t DCR; +    uint16_t  RESERVED18; +    volatile uint16_t DMAR; +    uint16_t  RESERVED19; +} Timer; + +void timer_init(uint8_t timer_num, uint16_t prescale) { +    Timer *timer; +    uint32_t is_advanced = 0; + +    ASSERT(timer_num > 0 && timer_num <= 4); + +    switch(timer_num) { +    case 1: +        timer = (Timer*)TIMER1_BASE; +        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); +        is_advanced = 1; +        break; +    case 2: +        timer = (Timer*)TIMER2_BASE; +        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); +        break; +    case 3: +        timer = (Timer*)TIMER3_BASE; +        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); +        break; +    case 4: +        timer = (Timer*)TIMER4_BASE; +        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); +        break; +    } + +    timer->CR1 = ARPE;        // No clock division +                              // Do not buffer auto-reload preload +                              // Edge aligned +                              // Upcounter +                              // Do not stop counter at update event +                              // Update events enabled (etc, see bits [1:2]) +                              // Counter disabled for now + +    timer->PSC = prescale;    // Prescaling by prescale (duh) +    timer->ARR = 0xFFFF;      // Max reload cont + +    /* initialize all the channels to 50% duty cycle, +     * TODO: none of them actually get output unless the gpio pin +     * is set, this will probably consume a bit more power but +     * we'll worry about that later. */ +    timer->CCR1   = 0x8FFF;     // PWM start value +    timer->CCMR1 |= 0x68;       // PWM mode 1, enable preload register. +    timer->CCER  |= 0x001;      // enable ch + +    timer->CCR2   = 0x8FFF;     // PWM start value +    timer->CCMR1 |= (0x68 << 8);// PWM mode 1, enable preload register. +    timer->CCER  |= 0x010;      // enable ch + +    timer->CCR3   = 0x8FFF;     // PWM start value +    timer->CCMR2 |= 0x68;       // PWM mode 1, enable preload register. +    timer->CCER  |= 0x100;      // enable ch + +    timer->CCR4   = 0x8FFF;     // PWM start value +    timer->CCMR2 |= (0x68 << 8);// PWM mode 1, enable preload register. +    timer->CCER  |= 0x1000;      // enable ch + +    /* Advanced timer?  */ +    if (is_advanced) { +        timer->BDTR = 0x8000;     // moe enable +    } + +    timer->DIER = 0;          // disable update interrupt +    timer->EGR  = 1;          // Initialize update event and shadow registers +    timer->CR1  |= 1;         // Enable timer +} + +void timers_disable(void) { +    Timer *timer; +    int i; +    Timer *timers[4] = { +        (Timer*)TIMER1_BASE, +        (Timer*)TIMER2_BASE, +        (Timer*)TIMER3_BASE, +        (Timer*)TIMER4_BASE, +    }; + +    for (i = 0; i < 4; i++) { +        timer = timers[i]; +        timer->CR1 = 0; +        timer->CCER = 0; +    } +} + +void timers_disable_channel(uint8 timer_num, uint8 channel) { +    Timer *timer; +    switch (timer_num) { +    case 1: +        timer = (Timer*)TIMER1_BASE; +        break; +    case 2: +        timer = (Timer*)TIMER2_BASE; +        break; +    case 3: +        timer = (Timer*)TIMER3_BASE; +        break; +    case 4: +        timer = (Timer*)TIMER4_BASE; +        break; +    default: +        ASSERT(0); +    } + +    switch (channel) { +    case 1: +        timer->CCER &= ~(0x1); +        break; +    case 2: +        timer->CCER &= ~(0x10); +        break; +    case 3: +        timer->CCER &= ~(0x100); +        break; +    case 4: +        timer->CCER &= ~(0x1000); +        break; +    default: +        ASSERT(0); +    } +} diff --git a/libmaple/timers.h b/libmaple/timers.h new file mode 100644 index 0000000..18b0afb --- /dev/null +++ b/libmaple/timers.h @@ -0,0 +1,145 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:38:10 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file timers.h + * + *  @brief Timer prototypes and various definitions + */ + +/* Note to self: + * The timer clock frequencies are automatically fixed by hardware. + * There are two cases: + *     1.  if the APB prescaler is 1, the timer clock frequencies are + *         set to the same frequency as that of the APB domain to which + *         the timers are connected. + *     2.  otherwise, they are set to twice (x2) the frequency of the + *         APB domain to which the timers are connected. + * See stm32 manual, 77/995 + * + * hence, 72 mhz timers + * */ + +/* Maple Timer channels: + * Timer        Maple Pin               STM32 Pin     Type + * TIM1_CH1     D6                      PA8           Advanced + * TIM1_CH2     D7                      PA9           Advanced + * TIM1_CH3     D8                      PA10          Advanced + * + * TIM2_CH1     D2                      PA0 + * TIM2_CH2     D3                      PA1 + * TIM2_CH3     D1                      PA2 + * TIM2_CH4     D0                      PA3 + * + * TIM3_CH1     D12                     PA6 + * TIM3_CH2     D11                     PA7 + * TIM3_CH3     EXT7                    PB0 + * TIM3_CH4     EXT8                    PB1 + * + * TIM4_CH1     EXT5                    PB6 + * TIM4_CH1     EXT9                    PB7 + * TIM4_CH1     EXT15                   PB8 + * TIM4_CH1     EXT4                    PB9 + * + * Not supported: + * TIM1_CH4    USBDM, not available     PA11          Advanced + * TIM1_CH1_N  EXT12                    PB13 + * TIM1_CH2_N  EXT13                    PB14 + * TIM1_CH3_N  EXT14                    PB15 + * */ + +/* I don't like the Arduino API for dealing with pin modes. + * How about... + * + * pinMode(digitalPin, PWM); + * pwmWrite(digitalPin) */ + + +#ifndef _TIMERS_H_ +#define _TIMERS_H_ +#include  <inttypes.h> + +#ifdef __cplusplus +extern "C"{ +#endif + +typedef volatile uint32_t* TimerCCR; + +#define TIMER1_BASE        0x40012C00 +#define TIMER2_BASE        0x40000000 +#define TIMER3_BASE        0x40000400 +#define TIMER4_BASE        0x40000800 + +#define ARPE               BIT(7)                // Auto-reload preload enable +#define NOT_A_TIMER        0 + +#define TIMER1_CH1_CCR     (TimerCCR)(TIMER1_BASE + 0x34) +#define TIMER1_CH2_CCR     (TimerCCR)(TIMER1_BASE + 0x38) +#define TIMER1_CH3_CCR     (TimerCCR)(TIMER1_BASE + 0x3C) +#define TIMER1_CH4_CCR     (TimerCCR)(TIMER1_BASE + 0x40) + +#define TIMER2_CH1_CCR     (TimerCCR)(TIMER2_BASE + 0x34) +#define TIMER2_CH2_CCR     (TimerCCR)(TIMER2_BASE + 0x38) +#define TIMER2_CH3_CCR     (TimerCCR)(TIMER2_BASE + 0x3C) +#define TIMER2_CH4_CCR     (TimerCCR)(TIMER2_BASE + 0x40) + +#define TIMER3_CH1_CCR     (TimerCCR)(TIMER3_BASE + 0x34) +#define TIMER3_CH2_CCR     (TimerCCR)(TIMER3_BASE + 0x38) +#define TIMER3_CH3_CCR     (TimerCCR)(TIMER3_BASE + 0x3C) +#define TIMER3_CH4_CCR     (TimerCCR)(TIMER3_BASE + 0x40) + +#define TIMER4_CH1_CCR     (TimerCCR)(TIMER4_BASE + 0x34) +#define TIMER4_CH2_CCR     (TimerCCR)(TIMER4_BASE + 0x38) +#define TIMER4_CH3_CCR     (TimerCCR)(TIMER4_BASE + 0x3C) +#define TIMER4_CH4_CCR     (TimerCCR)(TIMER4_BASE + 0x40) + + +/* Turn on timer with prescale as the divisor + * void timer_init(uint32_t timer, uint16_t prescale) + *      timer     ->  {1-4} + *      prescale  ->  {1-65535} + * */ +void timer_init(uint8_t, uint16_t); +void timers_disable(void); +void timers_disable_channel(uint8, uint8); + +/* Turn on PWM with duty_cycle on the specified channel in timer. + * This function takes in a pointer to the corresponding CCR + * register for the pin cause it saves pwmWrite() a couple of + * cycles. + * + * void timer_pwm(uint8_t channel, uint8_t duty_cycle); + *      channel    -> {TIMERx_CHn_CCR} + *      duty_cycle -> {0-65535} + * + * PRECONDITIONS: + *      pin has been set to alternate function output + *      timer has been initialized + */ +static inline void timer_pwm_write_ccr(TimerCCR CCR, uint16_t duty_cycle) { +    *CCR = duty_cycle; +} + +#ifdef __cplusplus +} // extern "C" +#endif + + +#endif + diff --git a/libmaple/usart.c b/libmaple/usart.c new file mode 100644 index 0000000..9987641 --- /dev/null +++ b/libmaple/usart.c @@ -0,0 +1,345 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:38:26 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file usart.c + * + *  @brief USART control routines + */ + +#include "libmaple.h" +#include "stm32f10x_rcc.h" +#include "usart.h" +#include "nvic.h" + +#define USART1_BASE         0x40013800 +#define USART2_BASE         0x40004400 +#define USART3_BASE         0x40004800 + +#define USART_UE            BIT(13) +#define USART_M             BIT(12) +#define USART_TE            BIT(3) +#define USART_RE            BIT(2) +#define USART_RXNEIE        BIT(5)       // read data register not empty interrupt enable +#define USART_TXE           BIT(7) +#define USART_TC            BIT(6) + +#define USART_STOP_BITS_1   BIT_MASK_SHIFT(0b0, 12) +#define USART_STOP_BITS_05  BIT_MASK_SHIFT(0b01, 12) +#define USART_STOP_BITS_2   BIT_MASK_SHIFT(0b02, 12) +#define USART_STOP_BITS_15  BIT_MASK_SHIFT(0b02, 12) + +#define USART1_CLK          72000000UL +#define USART2_CLK          36000000UL +#define USART3_CLK          36000000UL + +#define USART_RECV_BUF_SIZE 64 + +/* Ring buffer notes: + * The buffer is empty when head == tail. + * The buffer is full when the head is one byte in front of the tail + * The total buffer size must be a power of two + * Note, one byte is necessarily left free with this scheme */ +typedef struct usart_ring_buf { +    uint32 head; +    uint32 tail; +    uint8 buf[USART_RECV_BUF_SIZE]; +} usart_ring_buf; + +static usart_ring_buf ring_buf1; +static usart_ring_buf ring_buf2; +static usart_ring_buf ring_buf3; + +typedef struct usart_port { +    volatile uint32 SR;       // Status register +    volatile uint32 DR;       // Data register +    volatile uint32 BRR;      // Baud rate register +    volatile uint32 CR1;      // Control register 1 +    volatile uint32 CR2;      // Control register 2 +    volatile uint32 CR3;      // Control register 3 +    volatile uint32 GTPR;     // Guard time and prescaler register +} usart_port; + +void USART1_IRQHandler(void) { +    /* Read the data  */ +    ring_buf1.buf[ring_buf1.tail++] = (uint8_t)(((usart_port*)(USART1_BASE))->DR); +    ring_buf1.tail %= USART_RECV_BUF_SIZE; +} + +/* Don't overrun your buffer, seriously  */ +void USART2_IRQHandler(void) { +    /* Read the data  */ +    ring_buf2.buf[ring_buf2.tail++] = (uint8_t)(((usart_port*)(USART2_BASE))->DR); +    ring_buf2.tail %= USART_RECV_BUF_SIZE; +} +/* Don't overrun your buffer, seriously  */ +void USART3_IRQHandler(void) { +    /* Read the data  */ +    ring_buf3.buf[ring_buf3.tail++] = (uint8_t)(((usart_port*)(USART3_BASE))->DR); +    ring_buf3.tail %= USART_RECV_BUF_SIZE; +} + +/** + *  @brief Enable a USART in single buffer transmission mode, multibuffer + *  receiver mode. + * + *  @param usart_num USART to be initialized + *  @param baud Baud rate to be set at + *  @param recvBuf buf buffer for receiver + *  @param len size of recvBuf + * + *  @sideeffect Turns on the specified USART + */ +void usart_init(uint8 usart_num, uint32 baud) { +    ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); +    ASSERT(baud && (baud < USART_MAX_BAUD)); + +    usart_port *port; +    usart_ring_buf *ring_buf; + +    uint32 clk_speed; +    uint32 integer_part; +    uint32 fractional_part; +    uint32 tmp; + +    switch (usart_num) { +    case 1: +        port = (usart_port*)USART1_BASE; +        ring_buf = &ring_buf1; +        clk_speed = USART1_CLK; +        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); +        REG_SET(NVIC_ISER1, BIT(5)); +        break; +    case 2: +        port = (usart_port*)USART2_BASE; +        ring_buf = &ring_buf2; +        clk_speed = USART2_CLK; +        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); +        REG_SET(NVIC_ISER1, BIT(6)); +        break; +    case 3: +        port = (usart_port*)USART3_BASE; +        ring_buf = &ring_buf3; +        clk_speed = USART3_CLK; +        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); +        REG_SET(NVIC_ISER1, BIT(7)); +        break; +    default: +        /* should never get here  */ +        ASSERT(0); +    } + +    /* Initialize ring buffer  */ +    ring_buf->head = 0; +    ring_buf->tail = 0; + +    /* Set baud rate  */ +    integer_part = ((25 * clk_speed) / (4 * baud)); +    tmp = (integer_part / 100) << 4; + +    fractional_part = integer_part - (100 * (tmp >> 4)); +    tmp |= (((fractional_part * 16) + 50) / 100) & ((uint8)0x0F); + +    port->BRR = (uint16_t)tmp; + +    port->CR1 = USART_TE          |    // transmitter enable +                USART_RE          |    // receiver enable +                USART_RXNEIE;          // receive interrupt enable + + +    /* Enable the USART and set mode to 8n1 */ +    port->CR1 |= USART_UE; +} + + +/** + *  @brief Turn off a USART. + * + *  @param USART to be disabled + * + *  @sideeffect Turns off the specified USART + */ +void usart_disable(uint8 usart_num) { +    ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); +    usart_port *port; + +    switch (usart_num) { +    case 1: +        port = (usart_port*)USART1_BASE; +        break; +    case 2: +        port = (usart_port*)USART2_BASE; +        break; +    case 3: +        port = (usart_port*)USART3_BASE; +        break; +    default: +        /* should never get here  */ +        ASSERT(0); +    } + +    /* Is this usart enabled?  */ +    if (!(port->SR & USART_UE)) +        return; + +    /* TC bit must be high before disabling the usart  */ +    while ((port->SR & USART_TC) == 0) +        ; + +    /* Disable UE */ +    port->CR1 = 0; +} + + +/** + *  @brief Print a null terminated string to the specified USART + * + *  @param[in] usart_num USART to send on + *  @param[in] str String to send + */ +void usart_putstr(uint8 usart_num, const char* str) { +    ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); +    char ch; + +    while((ch = *(str++)) != '\0') { +        usart_putc(usart_num, ch); +    } +} + +/** + *  @brief Print an unsigned integer to the specified usart + * + *  @param[in] usart_num usart to send on + *  @param[in] val number to print + */ +void usart_putudec(uint8 usart_num, uint32 val) { +    ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); +    char digits[12]; +    int i; + +    i = 0; +    do { +        digits[i++] = val % 10 + '0'; +        val /= 10; +    } while (val > 0); +    while (--i >= 0) { +        usart_putc(usart_num, digits[i]); +    } + +} + + +/** + *  @brief Return one character from the receive buffer. Assumes + *  that there is data available. + * + *  @param[in] usart_num number of the usart to read from + * + *  @return character from ring buffer + * + *  @sideeffect may update the head pointer of the recv buffer + */ +uint8 usart_getc(uint8 usart_num) { +    uint8 ch; +    usart_ring_buf *rb; + +    switch (usart_num) { +    case 1: +        rb = &ring_buf1; +        break; +    case 2: +        rb = &ring_buf2; +        break; +    case 3: +        rb = &ring_buf3; +        break; +    default: +        ASSERT(0); +    } + +    /* Make sure there's actually data to be read  */ +    ASSERT(rb->head != rb->tail); + +    /* Read the data and check for wraparound  */ +    ch = rb->buf[rb->head++]; +    rb->head %= USART_RECV_BUF_SIZE; + +    return ch; +} + +uint32 usart_data_available(uint8 usart_num) { +    usart_ring_buf *rb; + +    switch (usart_num) { +    case 1: +        rb = &ring_buf1; +        break; +    case 2: +        rb = &ring_buf2; +        break; +    case 3: +        rb = &ring_buf3; +        break; +    default: +        ASSERT(0); +    } + +    return rb->tail - rb->head; +} + + + +/** + *  @brief Output a byte out the uart + * + *  @param[in] usart_num usart number to output on + *  @param[in] byte byte to send + * + */ +void usart_putc(uint8 usart_num, uint8 byte) { +    ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); +    usart_port *port; + +    switch (usart_num) { +    case 1: +        port = (usart_port*)USART1_BASE; +        break; +    case 2: +        port = (usart_port*)USART2_BASE; +        break; +    case 3: +        port = (usart_port*)USART3_BASE; +        break; +    default: +        /* Should never get here  */ +        ASSERT(0); +    } + +//    if (ch == '\n') { +//        usart_putc(usart_num, '\r'); +//    } + +    port->DR = byte; + +    /* Wait for transmission to complete  */ +    while ((port->SR & USART_TXE) == 0) +        ; +} + + diff --git a/libmaple/usart.h b/libmaple/usart.h new file mode 100644 index 0000000..b9efdd5 --- /dev/null +++ b/libmaple/usart.h @@ -0,0 +1,53 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:38:35 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file usart.h + * + *  @brief USART Definitions + */ + +#ifndef _USART_H_ +#define _USART_H_ + +#define NR_USARTS           0x3 + +#ifdef __cplusplus +extern "C"{ +#endif + +#define USART_MAX_BAUD      225000 + +void usart_init(uint8 usart_num, uint32 baud); +void usart_disable(uint8 usart_num); + +void usart_putstr(uint8 usart_num, const char*); +void usart_putudec(uint8 usart_num, uint32 val); +void usart_putc(uint8 usart_num, uint8 ch); + +uint32 usart_data_available(uint8 usart_num); +uint8 usart_getc(uint8 usart_num); + +#ifdef __cplusplus +} // extern "C" +#endif + + +#endif + diff --git a/libmaple/usb.c b/libmaple/usb.c new file mode 100644 index 0000000..8c312f8 --- /dev/null +++ b/libmaple/usb.c @@ -0,0 +1,83 @@ +#include <inttypes.h> +#include "usb.h" + +void usb_lpIRQHandler(void) +{ +  typedef void (*funcPtr)(void); +   +  const uint32_t usbIsrAddr = *(uint32_t*)(USB_ISR_ADDR); +  void (*ptrToUsbISR)(void) = (funcPtr) usbIsrAddr; +  ptrToUsbISR(); +} + +void usb_userToPMABufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes) +{ +  u32 n = (wNBytes + 1) >> 1;   /* n = (wNBytes + 1) / 2 */ +  u32 i, temp1, temp2; +  u16 *pdwVal; +  pdwVal = (u16 *)(wPMABufAddr * 2 + PMAAddr); +  for (i = n; i != 0; i--) +    { +      temp1 = (u16) * pbUsrBuf; +      pbUsrBuf++; +      temp2 = temp1 | (u16) * pbUsrBuf << 8; +      *pdwVal++ = temp2; +      pdwVal++; +      pbUsrBuf++; +    } +} + +void usb_PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes) +{ +  u32 n = (wNBytes + 1) >> 1;/* /2*/ +  u32 i; +  u32 *pdwVal; +  pdwVal = (u32 *)(wPMABufAddr * 2 + PMAAddr); +  for (i = n; i != 0; i--) +    { +      *(u16*)pbUsrBuf++ = *pdwVal++; +      pbUsrBuf++; +    } +} + +void usb_serialWriteStr(const char* outStr) { +  u8 offset=0; +  BootVectTable *bootVector = ((BootVectTable*)BOOTLOADER_VECT_TABLE); + +  while ((outStr[offset] != '\0') +	 && (offset < USB_SERIAL_BUF_SIZE)) { +    offset++; +  } + +  delay(offset*1); + +  bootVector->serial_count_in = (u32*) &offset; +  usb_userToPMABufferCopy((u8*)outStr,USB_SERIAL_ENDP_TXADDR,offset); +  _SetEPTxCount(USB_SERIAL_ENDP_TX,offset); +  _SetEPTxValid(USB_SERIAL_ENDP_TX); + +} + +void usb_serialWriteChar(unsigned char ch) { +  BootVectTable *bootVector = ((BootVectTable*)BOOTLOADER_VECT_TABLE); + +  delay(1); + +  *(bootVector->serial_count_in) = 1; +  usb_userToPMABufferCopy((u8*)(&ch),USB_SERIAL_ENDP_TXADDR,1); +  _SetEPTxCount(USB_SERIAL_ENDP_TX,1); +  _SetEPTxValid(USB_SERIAL_ENDP_TX); + +} + +uint8_t usb_serialGetRecvLen() { +  uint8_t count_out =_GetEPRxCount(USB_SERIAL_ENDP_RX);  +  return count_out; +} + +void usb_copyRecvBuffer(unsigned char* dest, uint8_t len) { +  ASSERT(len < USB_SERIAL_BUF_SIZE); +  usb_PMAToUserBufferCopy((u8*)(dest),USB_SERIAL_ENDP_RXADDR,len); +  _SetEPRxValid(USB_SERIAL_ENDP_RX); +} + diff --git a/libmaple/usb.h b/libmaple/usb.h new file mode 100644 index 0000000..3b7a971 --- /dev/null +++ b/libmaple/usb.h @@ -0,0 +1,32 @@ +#ifndef _USB_H_ +#define _USB_H_ + +#include <inttypes.h> +#include "util.h" +#include "cortexm3_macro.h" +#include "usb_regs.h" +#include "bootVect.h" + +#define USB_ISR_ADDR              (0x08000090) +#define USB_SERIAL_ENDP_TXADDR    ((uint32_t) 0xC0) +#define USB_SERIAL_ENDP_RXADDR    ((uint32_t) 0x110) +#define USB_SERIAL_ENDP_TX        ((uint16_t) 0x1) +#define USB_SERIAL_ENDP_RX        ((uint16_t) 0x3) +#define USB_SERIAL_BUF_SIZE       (0x40) + +#ifdef __cplusplus +extern "C" { +#endif + +void usb_lpIRQHandler(void);   +void usb_userToPMABufferCopy(u8  *pbUsrBuf,u16 wPMABufAddr,u16 wNBytes); +void usb_PMAToUserBufferCopy(u8  *pbUsrBuf,u16 wPMABufAddr,u16 wNBytes); +void usb_serialWriteStr(const char *outStr); +void usb_serialWriteChar(unsigned char ch); +uint8_t usb_serialGetRecvLen(); +void usb_copyRecvBuffer(unsigned char* dest, uint8_t len); + +#ifdef __cplusplus +} // extern "C" +#endif +#endif //_USB_H diff --git a/libmaple/usb_regs.h b/libmaple/usb_regs.h new file mode 100644 index 0000000..135d645 --- /dev/null +++ b/libmaple/usb_regs.h @@ -0,0 +1,555 @@ +/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
 +* File Name          : usb_regs.h
 +* Author             : MCD Application Team
 +* Version            : V2.2.1
 +* Date               : 09/22/2008
 +* Description        : Interface prototype functions to USB cell registers
 +********************************************************************************
 +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
 +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
 +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
 +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
 +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
 +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
 +*******************************************************************************/
 +
 +/* Define to prevent recursive inclusion -------------------------------------*/
 +#ifndef __USB_REGS_H
 +#define __USB_REGS_H
 +
 +/* Includes ------------------------------------------------------------------*/
 +/* Exported types ------------------------------------------------------------*/
 +#include "stm32f10x_type.h"
 +
 +typedef enum _EP_DBUF_DIR
 +{
 +  /* double buffered endpoint direction */
 +  EP_DBUF_ERR,
 +  EP_DBUF_OUT,
 +  EP_DBUF_IN
 +}EP_DBUF_DIR;
 +
 +/* endpoint buffer number */
 +enum EP_BUF_NUM
 +{
 +  EP_NOBUF,
 +  EP_BUF0,
 +  EP_BUF1
 +};
 +
 +/* Exported constants --------------------------------------------------------*/
 +#define RegBase  (0x40005C00L)  /* USB_IP Peripheral Registers base address */
 +#define PMAAddr  (0x40006000L)  /* USB_IP Packet Memory Area base address   */
 +
 +/******************************************************************************/
 +/*                         General registers                                  */
 +/******************************************************************************/
 +
 +/* Control register */
 +#define CNTR    ((volatile unsigned *)(RegBase + 0x40))
 +/* Interrupt status register */
 +#define ISTR    ((volatile unsigned *)(RegBase + 0x44))
 +/* Frame number register */
 +#define FNR     ((volatile unsigned *)(RegBase + 0x48))
 +/* Device address register */
 +#define DADDR   ((volatile unsigned *)(RegBase + 0x4C))
 +/* Buffer Table address register */
 +#define BTABLE  ((volatile unsigned *)(RegBase + 0x50))
 +/******************************************************************************/
 +/*                         Endpoint registers                                 */
 +/******************************************************************************/
 +#define EP0REG  ((volatile unsigned *)(RegBase)) /* endpoint 0 register address */
 +
 +/* endpoints enumeration */
 +#define ENDP0   ((u8)0)
 +#define ENDP1   ((u8)1)
 +#define ENDP2   ((u8)2)
 +#define ENDP3   ((u8)3)
 +#define ENDP4   ((u8)4)
 +#define ENDP5   ((u8)5)
 +#define ENDP6   ((u8)6)
 +#define ENDP7   ((u8)7)
 +/******************************************************************************/
 +/*                       ISTR interrupt events                                */
 +/******************************************************************************/
 +#define ISTR_CTR    (0x8000) /* Correct TRansfer (clear-only bit) */
 +#define ISTR_DOVR   (0x4000) /* DMA OVeR/underrun (clear-only bit) */
 +#define ISTR_ERR    (0x2000) /* ERRor (clear-only bit) */
 +#define ISTR_WKUP   (0x1000) /* WaKe UP (clear-only bit) */
 +#define ISTR_SUSP   (0x0800) /* SUSPend (clear-only bit) */
 +#define ISTR_RESET  (0x0400) /* RESET (clear-only bit) */
 +#define ISTR_SOF    (0x0200) /* Start Of Frame (clear-only bit) */
 +#define ISTR_ESOF   (0x0100) /* Expected Start Of Frame (clear-only bit) */
 +
 +
 +#define ISTR_DIR    (0x0010)  /* DIRection of transaction (read-only bit)  */
 +#define ISTR_EP_ID  (0x000F)  /* EndPoint IDentifier (read-only bit)  */
 +
 +#define CLR_CTR    (~ISTR_CTR)   /* clear Correct TRansfer bit */
 +#define CLR_DOVR   (~ISTR_DOVR)  /* clear DMA OVeR/underrun bit*/
 +#define CLR_ERR    (~ISTR_ERR)   /* clear ERRor bit */
 +#define CLR_WKUP   (~ISTR_WKUP)  /* clear WaKe UP bit     */
 +#define CLR_SUSP   (~ISTR_SUSP)  /* clear SUSPend bit     */
 +#define CLR_RESET  (~ISTR_RESET) /* clear RESET bit      */
 +#define CLR_SOF    (~ISTR_SOF)   /* clear Start Of Frame bit   */
 +#define CLR_ESOF   (~ISTR_ESOF)  /* clear Expected Start Of Frame bit */
 +
 +/******************************************************************************/
 +/*             CNTR control register bits definitions                         */
 +/******************************************************************************/
 +#define CNTR_CTRM   (0x8000) /* Correct TRansfer Mask */
 +#define CNTR_DOVRM  (0x4000) /* DMA OVeR/underrun Mask */
 +#define CNTR_ERRM   (0x2000) /* ERRor Mask */
 +#define CNTR_WKUPM  (0x1000) /* WaKe UP Mask */
 +#define CNTR_SUSPM  (0x0800) /* SUSPend Mask */
 +#define CNTR_RESETM (0x0400) /* RESET Mask   */
 +#define CNTR_SOFM   (0x0200) /* Start Of Frame Mask */
 +#define CNTR_ESOFM  (0x0100) /* Expected Start Of Frame Mask */
 +
 +
 +#define CNTR_RESUME (0x0010) /* RESUME request */
 +#define CNTR_FSUSP  (0x0008) /* Force SUSPend */
 +#define CNTR_LPMODE (0x0004) /* Low-power MODE */
 +#define CNTR_PDWN   (0x0002) /* Power DoWN */
 +#define CNTR_FRES   (0x0001) /* Force USB RESet */
 +
 +/******************************************************************************/
 +/*                FNR Frame Number Register bit definitions                   */
 +/******************************************************************************/
 +#define FNR_RXDP (0x8000) /* status of D+ data line */
 +#define FNR_RXDM (0x4000) /* status of D- data line */
 +#define FNR_LCK  (0x2000) /* LoCKed */
 +#define FNR_LSOF (0x1800) /* Lost SOF */
 +#define FNR_FN  (0x07FF) /* Frame Number */
 +/******************************************************************************/
 +/*               DADDR Device ADDRess bit definitions                         */
 +/******************************************************************************/
 +#define DADDR_EF (0x80)
 +#define DADDR_ADD (0x7F)
 +/******************************************************************************/
 +/*                            Endpoint register                               */
 +/******************************************************************************/
 +/* bit positions */
 +#define EP_CTR_RX      (0x8000) /* EndPoint Correct TRansfer RX */
 +#define EP_DTOG_RX     (0x4000) /* EndPoint Data TOGGLE RX */
 +#define EPRX_STAT      (0x3000) /* EndPoint RX STATus bit field */
 +#define EP_SETUP       (0x0800) /* EndPoint SETUP */
 +#define EP_T_FIELD     (0x0600) /* EndPoint TYPE */
 +#define EP_KIND        (0x0100) /* EndPoint KIND */
 +#define EP_CTR_TX      (0x0080) /* EndPoint Correct TRansfer TX */
 +#define EP_DTOG_TX     (0x0040) /* EndPoint Data TOGGLE TX */
 +#define EPTX_STAT      (0x0030) /* EndPoint TX STATus bit field */
 +#define EPADDR_FIELD   (0x000F) /* EndPoint ADDRess FIELD */
 +
 +/* EndPoint REGister MASK (no toggle fields) */
 +#define EPREG_MASK     (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD)
 +
 +/* EP_TYPE[1:0] EndPoint TYPE */
 +#define EP_TYPE_MASK   (0x0600) /* EndPoint TYPE Mask */
 +#define EP_BULK        (0x0000) /* EndPoint BULK */
 +#define EP_CONTROL     (0x0200) /* EndPoint CONTROL */
 +#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */
 +#define EP_INTERRUPT   (0x0600) /* EndPoint INTERRUPT */
 +#define EP_T_MASK      (~EP_T_FIELD & EPREG_MASK)
 +
 +
 +/* EP_KIND EndPoint KIND */
 +#define EPKIND_MASK    (~EP_KIND & EPREG_MASK)
 +
 +/* STAT_TX[1:0] STATus for TX transfer */
 +#define EP_TX_DIS      (0x0000) /* EndPoint TX DISabled */
 +#define EP_TX_STALL    (0x0010) /* EndPoint TX STALLed */
 +#define EP_TX_NAK      (0x0020) /* EndPoint TX NAKed */
 +#define EP_TX_VALID    (0x0030) /* EndPoint TX VALID */
 +#define EPTX_DTOG1     (0x0010) /* EndPoint TX Data TOGgle bit1 */
 +#define EPTX_DTOG2     (0x0020) /* EndPoint TX Data TOGgle bit2 */
 +#define EPTX_DTOGMASK  (EPTX_STAT|EPREG_MASK)
 +
 +/* STAT_RX[1:0] STATus for RX transfer */
 +#define EP_RX_DIS      (0x0000) /* EndPoint RX DISabled */
 +#define EP_RX_STALL    (0x1000) /* EndPoint RX STALLed */
 +#define EP_RX_NAK      (0x2000) /* EndPoint RX NAKed */
 +#define EP_RX_VALID    (0x3000) /* EndPoint RX VALID */
 +#define EPRX_DTOG1     (0x1000) /* EndPoint RX Data TOGgle bit1 */
 +#define EPRX_DTOG2     (0x2000) /* EndPoint RX Data TOGgle bit1 */
 +#define EPRX_DTOGMASK  (EPRX_STAT|EPREG_MASK)
 +/* Exported macro ------------------------------------------------------------*/
 +/* SetCNTR */
 +#define _SetCNTR(wRegValue)  (*CNTR   = (u16)wRegValue)
 +
 +/* SetISTR */
 +#define _SetISTR(wRegValue)  (*ISTR   = (u16)wRegValue)
 +
 +/* SetDADDR */
 +#define _SetDADDR(wRegValue) (*DADDR  = (u16)wRegValue)
 +
 +/* SetBTABLE */
 +#define _SetBTABLE(wRegValue)(*BTABLE = (u16)(wRegValue & 0xFFF8))
 +
 +/* GetCNTR */
 +#define _GetCNTR()   ((u16) *CNTR)
 +
 +/* GetISTR */
 +#define _GetISTR()   ((u16) *ISTR)
 +
 +/* GetFNR */
 +#define _GetFNR()    ((u16) *FNR)
 +
 +/* GetDADDR */
 +#define _GetDADDR()  ((u16) *DADDR)
 +
 +/* GetBTABLE */
 +#define _GetBTABLE() ((u16) *BTABLE)
 +
 +/* SetENDPOINT */
 +#define _SetENDPOINT(bEpNum,wRegValue)  (*(EP0REG + bEpNum)= \
 +    (u16)wRegValue)
 +
 +/* GetENDPOINT */
 +#define _GetENDPOINT(bEpNum)        ((u16)(*(EP0REG + bEpNum)))
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPType
 +* Description    : sets the type in the endpoint register(bits EP_TYPE[1:0])
 +* Input          : bEpNum: Endpoint Number. 
 +*                  wType
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPType(bEpNum,wType) (_SetENDPOINT(bEpNum,\
 +                                  ((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType)))
 +
 +/*******************************************************************************
 +* Macro Name     : GetEPType
 +* Description    : gets the type in the endpoint register(bits EP_TYPE[1:0]) 
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : Endpoint Type
 +*******************************************************************************/
 +#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD)
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPTxStatus
 +* Description    : sets the status for tx transfer (bits STAT_TX[1:0]).
 +* Input          : bEpNum: Endpoint Number. 
 +*                  wState: new state
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPTxStatus(bEpNum,wState) {\
 +    register u16 _wRegVal;       \
 +    _wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\
 +    /* toggle first bit ? */     \
 +    if((EPTX_DTOG1 & wState)!= 0)      \
 +      _wRegVal ^= EPTX_DTOG1;        \
 +    /* toggle second bit ?  */         \
 +    if((EPTX_DTOG2 & wState)!= 0)      \
 +      _wRegVal ^= EPTX_DTOG2;        \
 +    _SetENDPOINT(bEpNum, _wRegVal);    \
 +  } /* _SetEPTxStatus */
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPRxStatus
 +* Description    : sets the status for rx transfer (bits STAT_TX[1:0])
 +* Input          : bEpNum: Endpoint Number. 
 +*                  wState: new state.
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPRxStatus(bEpNum,wState) {\
 +    register u16 _wRegVal;   \
 +    \
 +    _wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\
 +    /* toggle first bit ? */  \
 +    if((EPRX_DTOG1 & wState)!= 0) \
 +      _wRegVal ^= EPRX_DTOG1;  \
 +    /* toggle second bit ? */  \
 +    if((EPRX_DTOG2 & wState)!= 0) \
 +      _wRegVal ^= EPRX_DTOG2;  \
 +    _SetENDPOINT(bEpNum, _wRegVal); \
 +  } /* _SetEPRxStatus */
 +/*******************************************************************************
 +* Macro Name     : GetEPTxStatus / GetEPRxStatus 
 +* Description    : gets the status for tx/rx transfer (bits STAT_TX[1:0]
 +*                  /STAT_RX[1:0])
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : status .
 +*******************************************************************************/
 +#define _GetEPTxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPTX_STAT)
 +
 +#define _GetEPRxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPRX_STAT)
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPTxValid / SetEPRxValid 
 +* Description    : sets directly the VALID tx/rx-status into the enpoint register
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPTxValid(bEpNum)     (_SetEPTxStatus(bEpNum, EP_TX_VALID))
 +
 +#define _SetEPRxValid(bEpNum)     (_SetEPRxStatus(bEpNum, EP_RX_VALID))
 +
 +/*******************************************************************************
 +* Macro Name     : GetTxStallStatus / GetRxStallStatus.
 +* Description    : checks stall condition in an endpoint.
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : TRUE = endpoint in stall condition.
 +*******************************************************************************/
 +#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) \
 +                                   == EP_TX_STALL)
 +#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) \
 +                                   == EP_RX_STALL)
 +
 +/*******************************************************************************
 +* Macro Name     : SetEP_KIND / ClearEP_KIND.
 +* Description    : set & clear EP_KIND bit.
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEP_KIND(bEpNum)    (_SetENDPOINT(bEpNum, \
 +                                (_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK))
 +#define _ClearEP_KIND(bEpNum)  (_SetENDPOINT(bEpNum, \
 +                                (_GetENDPOINT(bEpNum) & EPKIND_MASK)))
 +
 +/*******************************************************************************
 +* Macro Name     : Set_Status_Out / Clear_Status_Out.
 +* Description    : Sets/clears directly STATUS_OUT bit in the endpoint register.
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _Set_Status_Out(bEpNum)    _SetEP_KIND(bEpNum)
 +#define _Clear_Status_Out(bEpNum)  _ClearEP_KIND(bEpNum)
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPDoubleBuff / ClearEPDoubleBuff.
 +* Description    : Sets/clears directly EP_KIND bit in the endpoint register.
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPDoubleBuff(bEpNum)   _SetEP_KIND(bEpNum)
 +#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum)
 +
 +/*******************************************************************************
 +* Macro Name     : ClearEP_CTR_RX / ClearEP_CTR_TX.
 +* Description    : Clears bit CTR_RX / CTR_TX in the endpoint register.
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _ClearEP_CTR_RX(bEpNum)   (_SetENDPOINT(bEpNum,\
 +                                   _GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK))
 +#define _ClearEP_CTR_TX(bEpNum)   (_SetENDPOINT(bEpNum,\
 +                                   _GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK))
 +
 +/*******************************************************************************
 +* Macro Name     : ToggleDTOG_RX / ToggleDTOG_TX .
 +* Description    : Toggles DTOG_RX / DTOG_TX bit in the endpoint register.
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _ToggleDTOG_RX(bEpNum)    (_SetENDPOINT(bEpNum, \
 +                                   EP_DTOG_RX | _GetENDPOINT(bEpNum) & EPREG_MASK))
 +#define _ToggleDTOG_TX(bEpNum)    (_SetENDPOINT(bEpNum, \
 +                                   EP_DTOG_TX | _GetENDPOINT(bEpNum) & EPREG_MASK))
 +
 +/*******************************************************************************
 +* Macro Name     : ClearDTOG_RX / ClearDTOG_TX.
 +* Description    : Clears DTOG_RX / DTOG_TX bit in the endpoint register.
 +* Input          : bEpNum: Endpoint Number. 
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _ClearDTOG_RX(bEpNum)  if((_GetENDPOINT(bEpNum) & EP_DTOG_RX) != 0)\
 +    _ToggleDTOG_RX(bEpNum)
 +#define _ClearDTOG_TX(bEpNum)  if((_GetENDPOINT(bEpNum) & EP_DTOG_TX) != 0)\
 +    _ToggleDTOG_TX(bEpNum)
 +/*******************************************************************************
 +* Macro Name     : SetEPAddress.
 +* Description    : Sets address in an endpoint register.
 +* Input          : bEpNum: Endpoint Number.
 +*                  bAddr: Address. 
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPAddress(bEpNum,bAddr) _SetENDPOINT(bEpNum,\
 +    _GetENDPOINT(bEpNum) & EPREG_MASK | bAddr)
 +
 +/*******************************************************************************
 +* Macro Name     : GetEPAddress.
 +* Description    : Gets address in an endpoint register.
 +* Input          : bEpNum: Endpoint Number.
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _GetEPAddress(bEpNum) ((u8)(_GetENDPOINT(bEpNum) & EPADDR_FIELD))
 +
 +#define _pEPTxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8  )*2 + PMAAddr))
 +#define _pEPTxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+2)*2 + PMAAddr))
 +#define _pEPRxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+4)*2 + PMAAddr))
 +#define _pEPRxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+6)*2 + PMAAddr))
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPTxAddr / SetEPRxAddr.
 +* Description    : sets address of the tx/rx buffer.
 +* Input          : bEpNum: Endpoint Number.
 +*                  wAddr: address to be set (must be word aligned).
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPTxAddr(bEpNum,wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1))
 +#define _SetEPRxAddr(bEpNum,wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1))
 +
 +/*******************************************************************************
 +* Macro Name     : GetEPTxAddr / GetEPRxAddr.
 +* Description    : Gets address of the tx/rx buffer.
 +* Input          : bEpNum: Endpoint Number.
 +* Output         : None.
 +* Return         : address of the buffer.
 +*******************************************************************************/
 +#define _GetEPTxAddr(bEpNum) ((u16)*_pEPTxAddr(bEpNum))
 +#define _GetEPRxAddr(bEpNum) ((u16)*_pEPRxAddr(bEpNum))
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPCountRxReg.
 +* Description    : Sets counter of rx buffer with no. of blocks.
 +* Input          : pdwReg: pointer to counter.
 +*                  wCount: Counter.
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _BlocksOf32(dwReg,wCount,wNBlocks) {\
 +    wNBlocks = wCount >> 5;\
 +    if((wCount & 0x1f) == 0)\
 +      wNBlocks--;\
 +    *pdwReg = (u32)((wNBlocks << 10) | 0x8000);\
 +  }/* _BlocksOf32 */
 +
 +#define _BlocksOf2(dwReg,wCount,wNBlocks) {\
 +    wNBlocks = wCount >> 1;\
 +    if((wCount & 0x1) != 0)\
 +      wNBlocks++;\
 +    *pdwReg = (u32)(wNBlocks << 10);\
 +  }/* _BlocksOf2 */
 +
 +#define _SetEPCountRxReg(dwReg,wCount)  {\
 +    u16 wNBlocks;\
 +    if(wCount > 62){_BlocksOf32(dwReg,wCount,wNBlocks);}\
 +    else {_BlocksOf2(dwReg,wCount,wNBlocks);}\
 +  }/* _SetEPCountRxReg */
 +
 +
 +
 +#define _SetEPRxDblBuf0Count(bEpNum,wCount) {\
 +    u32 *pdwReg = _pEPTxCount(bEpNum); \
 +    _SetEPCountRxReg(pdwReg, wCount);\
 +  }
 +/*******************************************************************************
 +* Macro Name     : SetEPTxCount / SetEPRxCount.
 +* Description    : sets counter for the tx/rx buffer.
 +* Input          : bEpNum: endpoint number.
 +*                  wCount: Counter value.
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPTxCount(bEpNum,wCount) (*_pEPTxCount(bEpNum) = wCount)
 +#define _SetEPRxCount(bEpNum,wCount) {\
 +    u32 *pdwReg = _pEPRxCount(bEpNum); \
 +    _SetEPCountRxReg(pdwReg, wCount);\
 +  }
 +/*******************************************************************************
 +* Macro Name     : GetEPTxCount / GetEPRxCount.
 +* Description    : gets counter of the tx buffer.
 +* Input          : bEpNum: endpoint number.
 +* Output         : None.
 +* Return         : Counter value.
 +*******************************************************************************/
 +#define _GetEPTxCount(bEpNum)((u16)(*_pEPTxCount(bEpNum)) & 0x3ff)
 +#define _GetEPRxCount(bEpNum)((u16)(*_pEPRxCount(bEpNum)) & 0x3ff)
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPDblBuf0Addr / SetEPDblBuf1Addr.
 +* Description    : Sets buffer 0/1 address in a double buffer endpoint.
 +* Input          : bEpNum: endpoint number.
 +*                : wBuf0Addr: buffer 0 address.
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPDblBuf0Addr(bEpNum,wBuf0Addr) {_SetEPTxAddr(bEpNum, wBuf0Addr);}
 +#define _SetEPDblBuf1Addr(bEpNum,wBuf1Addr) {_SetEPRxAddr(bEpNum, wBuf1Addr);}
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPDblBuffAddr.
 +* Description    : Sets addresses in a double buffer endpoint.
 +* Input          : bEpNum: endpoint number.
 +*                : wBuf0Addr: buffer 0 address.
 +*                : wBuf1Addr = buffer 1 address.
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPDblBuffAddr(bEpNum,wBuf0Addr,wBuf1Addr) { \
 +    _SetEPDblBuf0Addr(bEpNum, wBuf0Addr);\
 +    _SetEPDblBuf1Addr(bEpNum, wBuf1Addr);\
 +  } /* _SetEPDblBuffAddr */
 +
 +/*******************************************************************************
 +* Macro Name     : GetEPDblBuf0Addr / GetEPDblBuf1Addr.
 +* Description    : Gets buffer 0/1 address of a double buffer endpoint.
 +* Input          : bEpNum: endpoint number.
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum))
 +#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum))
 +
 +/*******************************************************************************
 +* Macro Name     : SetEPDblBuffCount / SetEPDblBuf0Count / SetEPDblBuf1Count.
 +* Description    : Gets buffer 0/1 address of a double buffer endpoint.
 +* Input          : bEpNum: endpoint number.
 +*                : bDir: endpoint dir  EP_DBUF_OUT = OUT 
 +*                                      EP_DBUF_IN  = IN 
 +*                : wCount: Counter value    
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _SetEPDblBuf0Count(bEpNum, bDir, wCount)  { \
 +    if(bDir == EP_DBUF_OUT)\
 +      /* OUT endpoint */ \
 +    {_SetEPRxDblBuf0Count(bEpNum,wCount);} \
 +    else if(bDir == EP_DBUF_IN)\
 +      /* IN endpoint */ \
 +      *_pEPTxCount(bEpNum) = (u32)wCount;  \
 +  } /* SetEPDblBuf0Count*/
 +
 +#define _SetEPDblBuf1Count(bEpNum, bDir, wCount)  { \
 +    if(bDir == EP_DBUF_OUT)\
 +      /* OUT endpoint */ \
 +    {_SetEPRxCount(bEpNum,wCount);}\
 +    else if(bDir == EP_DBUF_IN)\
 +      /* IN endpoint */\
 +      *_pEPRxCount(bEpNum) = (u32)wCount; \
 +  } /* SetEPDblBuf1Count */
 +
 +#define _SetEPDblBuffCount(bEpNum, bDir, wCount) {\
 +    _SetEPDblBuf0Count(bEpNum, bDir, wCount); \
 +    _SetEPDblBuf1Count(bEpNum, bDir, wCount); \
 +  } /* _SetEPDblBuffCount  */
 +
 +/*******************************************************************************
 +* Macro Name     : GetEPDblBuf0Count / GetEPDblBuf1Count.
 +* Description    : Gets buffer 0/1 rx/tx counter for double buffering.
 +* Input          : bEpNum: endpoint number.
 +* Output         : None.
 +* Return         : None.
 +*******************************************************************************/
 +#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum))
 +#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum))
 +
 +#endif
 +/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
 diff --git a/libmaple/util.c b/libmaple/util.c new file mode 100644 index 0000000..d323611 --- /dev/null +++ b/libmaple/util.c @@ -0,0 +1,103 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:38:44 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file util.h + * + *  @brief Utility procedures for debugging, mostly an error LED fade and + *  messages dumped over a uart for failed asserts. + */ + +#include "libmaple.h" +#include "usart.h" +#include "gpio.h" +#include "nvic.h" +#include "adc.h" +#include "timers.h" + +#define ERROR_LED_PORT         GPIOA_BASE +#define ERROR_LED_PIN          5 +#define ERROR_USART_NUM        2 +#define ERROR_USART_BAUD       9600 +#define ERROR_TX_PIN           2 +#define ERROR_TX_PORT          GPIOA_BASE + +/* Error assert + fade */ +void _fail(const char* file, int line, const char* exp) { +    int32_t  slope   = 1; +    int32_t CC      = 0x0000; +    int32_t TOP_CNT = 0x02FF; +    int32_t i       = 0; + +    /* Turn off interrupts */ +    nvic_disable_interrupts(); + +    /* Turn off timers  */ +    timers_disable(); + +    /* Turn off ADC */ +    adc_disable(); + +    /* Turn off all usarts  */ +    usart_disable(1); +    usart_disable(2); +    usart_disable(3); + +    /* Initialize the error usart */ +    gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_MODE_AF_OUTPUT_PP); +    usart_init(ERROR_USART_NUM, ERROR_USART_BAUD); + +    /* Print failed assert message  */ +    usart_putstr(ERROR_USART_NUM, "ERROR: FAILED ASSERT("); +    usart_putstr(ERROR_USART_NUM, exp); +    usart_putstr(ERROR_USART_NUM, "): "); +    usart_putstr(ERROR_USART_NUM, file); +    usart_putstr(ERROR_USART_NUM, ": "); +    usart_putudec(ERROR_USART_NUM, line); +    usart_putc(ERROR_USART_NUM, '\n'); + +    /* Turn on the error LED  */ +    gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_MODE_OUTPUT_PP); + +    /* Turn the USB interrupt back on so the bootloader keeps on functioning  */ +    nvic_enable_interrupt(NVIC_INT_USBHP); +    nvic_enable_interrupt(NVIC_INT_USBLP); + +    /* Error fade  */ +    while (1) { +        if (CC == TOP_CNT)  { +            slope = -1; +        } else if (CC == 0) { +            slope = 1; +        } + +        if (i == TOP_CNT)  { +            CC += slope; +            i = 0; +        } + +        if (i < CC) { +            gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 1); +        } else { +            gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 0); +        } +        i++; +    } +} + diff --git a/libmaple/util.h b/libmaple/util.h new file mode 100644 index 0000000..e425cc0 --- /dev/null +++ b/libmaple/util.h @@ -0,0 +1,82 @@ +/* ***************************************************************************** + *  This program 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. + * + *  This program 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 <http://www.gnu.org/licenses/>. + * + *  Created: 12/18/09 02:39:27 + *  Copyright (c) 2009 Perry L. Hung. All rights reserved. + * + * ****************************************************************************/ + +/** + *  @file util.h + * + *  @brief Various macros and utility procedures. + */ + +/* Generally "useful" utility procedures  */ +#ifndef _UTIL_H_ +#define _UTIL_H_ +#include <inttypes.h> + +#define MAPLE_DEBUG 1 + +#define BIT(shift)                     (1 << (shift)) +#define BIT_MASK_SHIFT(mask, shift)    ((mask) << (shift)) + +/* Return bits m to n of x  */ +#define GET_BITS(x, m, n) ((((uint32_t)x) << (31 - (n))) >> ((31 - (n)) + (m))) + +/* Bit-banding macros  */ +#define BITBAND_SRAM_REF   0x20000000 +#define BITBAND_SRAM_BASE  0x22000000 +#define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + (a-BITBAND_SRAM_REF)*32 + (b*4)))  // Convert SRAM address +#define BITBAND_PERI_REF   0x40000000 +#define BITBAND_PERI_BASE  0x42000000 +#define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 + (b*4)))  // Convert PERI address + +#define COUNTFLAG *((volatile unsigned char*) (BITBAND_PERI(SYSTICK_CSR,2))) + +#define REG_SET(reg, val)               (*(volatile uint32_t*)(reg)  = (val)) +#define REG_SET_BIT(reg, bit)           (*(volatile uint32_t*)(reg) |= BIT(bit)) +#define REG_CLEAR_BIT(reg, bit)         (*(volatile uint32_t*)(reg) &= ~BIT(bit)) +#define REG_SET_MASK(reg, mask)         (*(volatile uint32_t*)(reg) |= (uint32_t)(mask)) +#define REG_CLEAR_MASK(reg, mask)       (*(volatile uint32_t*)(reg) &= (uint32_t)~(mask)) + +#define REG_GET(reg)                    *(volatile uint32_t*)(reg) + + +#ifdef __cplusplus +extern "C"{ +#endif + +void _fail(const char*, int, const char*); + +#ifdef __cplusplus +} // extern "C" +#endif + + +/* Assert for sanity checks, undefine MAPLE_DEBUG to compile + * out these checks */ +#if MAPLE_DEBUG +#define ASSERT(exp)         \ +    if (exp)              \ +        {}                  \ +    else                    \ +        _fail(__FILE__, __LINE__, #exp) +#else +#define ASSERT(exp) (void)((0)) +#endif + +#endif + | 
