Made new generic STM32F103C board variant based on Maple mini. This is a work in process. It seems to work, but needs more tidying up ;-)

This commit is contained in:
Roger Clark 2015-04-14 20:18:37 +10:00
parent 544908bb14
commit 6fec429e99
23 changed files with 1779 additions and 418 deletions

View File

@ -253,7 +253,7 @@ GenericSTM32F103C.name= Generic STM32F103C
GenericSTM32F103C.upload.tool=upload_router
#GenericSTM32F103C.upload.tool=maple_upload
GenericSTM32F103C.build.core=maple
GenericSTM32F103C.build.variant=maple_mini
GenericSTM32F103C.build.variant=generic_stm32f103c
GenericSTM32F103C.upload.use_1200bps_touch=false
GenericSTM32F103C.upload.file_type=bin
GenericSTM32F103C.upload.usbID=1EAF:0003
@ -261,16 +261,11 @@ GenericSTM32F103C.upload.auto_reset=true
GenericSTM32F103C.build.mcu=cortex-m3
GenericSTM32F103C.build.f_cpu=72000000L
GenericSTM32F103C.build.board=MAPLE_MINI_GENERIC
GenericSTM32F103C.build.core=maple
GenericSTM32F103C.build.common_flags=-mthumb -march=armv7-m -D__STM32F1__
GenericSTM32F103C.build.variant=maple_mini
GenericSTM32F103C.build.variant_system_lib=libmaple.a
GenericSTM32F103C.build.density=STM32_MEDIUM_DENSITY
GenericSTM32F103C.build.error_led_port=GPIOB
GenericSTM32F103C.build.error_led_pin=1
GenericSTM32F103C.build.gcc_ver=gcc-arm-none-eabi-4.8.3-2014q1
## ==UPLOAD MODE==
## F103CB USB to Flash upload

View File

@ -1,412 +1,412 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2011 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @file libmaple/timer.c
* @author Marti Bolivar <mbolivar@leaflabs.com>
* @brief Portable timer routines.
*/
#include <libmaple/timer.h>
#include <libmaple/stm32.h>
#include "timer_private.h"
static void disable_channel(timer_dev *dev, uint8 channel);
static void pwm_mode(timer_dev *dev, uint8 channel);
static void output_compare_mode(timer_dev *dev, uint8 channel);
static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid);
/*
* Devices
*
* Defer to the timer_private API for declaring these.
*/
#if STM32_HAVE_TIMER(1)
static timer_dev timer1 = ADVANCED_TIMER(1);
/** Timer 1 device (advanced) */
timer_dev *TIMER1 = &timer1;
#endif
#if STM32_HAVE_TIMER(2)
static timer_dev timer2 = GENERAL_TIMER(2);
/** Timer 2 device (general-purpose) */
timer_dev *TIMER2 = &timer2;
#endif
#if STM32_HAVE_TIMER(3)
static timer_dev timer3 = GENERAL_TIMER(3);
/** Timer 3 device (general-purpose) */
timer_dev *TIMER3 = &timer3;
#endif
#if STM32_HAVE_TIMER(4)
static timer_dev timer4 = GENERAL_TIMER(4);
/** Timer 4 device (general-purpose) */
timer_dev *TIMER4 = &timer4;
#endif
#if STM32_HAVE_TIMER(5)
static timer_dev timer5 = GENERAL_TIMER(5);
/** Timer 5 device (general-purpose) */
timer_dev *TIMER5 = &timer5;
#endif
#if STM32_HAVE_TIMER(6)
static timer_dev timer6 = BASIC_TIMER(6);
/** Timer 6 device (basic) */
timer_dev *TIMER6 = &timer6;
#endif
#if STM32_HAVE_TIMER(7)
static timer_dev timer7 = BASIC_TIMER(7);
/** Timer 7 device (basic) */
timer_dev *TIMER7 = &timer7;
#endif
#if STM32_HAVE_TIMER(8)
static timer_dev timer8 = ADVANCED_TIMER(8);
/** Timer 8 device (advanced) */
timer_dev *TIMER8 = &timer8;
#endif
#if STM32_HAVE_TIMER(9)
static timer_dev timer9 = RESTRICTED_GENERAL_TIMER(9, TIMER_DIER_TIE_BIT);
/** Timer 9 device (general-purpose) */
timer_dev *TIMER9 = &timer9;
#endif
#if STM32_HAVE_TIMER(10)
static timer_dev timer10 = RESTRICTED_GENERAL_TIMER(10, TIMER_DIER_CC1IE_BIT);
/** Timer 10 device (general-purpose) */
timer_dev *TIMER10 = &timer10;
#endif
#if STM32_HAVE_TIMER(11)
static timer_dev timer11 = RESTRICTED_GENERAL_TIMER(11, TIMER_DIER_CC1IE_BIT);
/** Timer 11 device (general-purpose) */
timer_dev *TIMER11 = &timer11;
#endif
#if STM32_HAVE_TIMER(12)
static timer_dev timer12 = RESTRICTED_GENERAL_TIMER(12, TIMER_DIER_TIE_BIT);
/** Timer 12 device (general-purpose) */
timer_dev *TIMER12 = &timer12;
#endif
#if STM32_HAVE_TIMER(13)
static timer_dev timer13 = RESTRICTED_GENERAL_TIMER(13, TIMER_DIER_CC1IE_BIT);
/** Timer 13 device (general-purpose) */
timer_dev *TIMER13 = &timer13;
#endif
#if STM32_HAVE_TIMER(14)
static timer_dev timer14 = RESTRICTED_GENERAL_TIMER(14, TIMER_DIER_CC1IE_BIT);
/** Timer 14 device (general-purpose) */
timer_dev *TIMER14 = &timer14;
#endif
/*
* Routines
*/
/**
* @brief Call a function on timer devices.
* @param fn Function to call on each timer device.
*/
void timer_foreach(void (*fn)(timer_dev*)) {
#if STM32_HAVE_TIMER(1)
fn(TIMER1);
#endif
#if STM32_HAVE_TIMER(2)
fn(TIMER2);
#endif
#if STM32_HAVE_TIMER(3)
fn(TIMER3);
#endif
#if STM32_HAVE_TIMER(4)
fn(TIMER4);
#endif
#if STM32_HAVE_TIMER(5)
fn(TIMER5);
#endif
#if STM32_HAVE_TIMER(6)
fn(TIMER6);
#endif
#if STM32_HAVE_TIMER(7)
fn(TIMER7);
#endif
#if STM32_HAVE_TIMER(8)
fn(TIMER8);
#endif
#if STM32_HAVE_TIMER(9)
fn(TIMER9);
#endif
#if STM32_HAVE_TIMER(10)
fn(TIMER10);
#endif
#if STM32_HAVE_TIMER(11)
fn(TIMER11);
#endif
#if STM32_HAVE_TIMER(12)
fn(TIMER12);
#endif
#if STM32_HAVE_TIMER(13)
fn(TIMER13);
#endif
#if STM32_HAVE_TIMER(14)
fn(TIMER14);
#endif
}
/**
* Initialize a timer, and reset its register map.
* @param dev Timer to initialize
*/
void timer_init(timer_dev *dev) {
rcc_clk_enable(dev->clk_id);
rcc_reset_dev(dev->clk_id);
}
/**
* @brief Disable a timer.
*
* The timer will stop counting, all DMA requests and interrupts will
* be disabled, and no state changes will be output.
*
* @param dev Timer to disable.
*/
void timer_disable(timer_dev *dev) {
(dev->regs).bas->CR1 = 0;
(dev->regs).bas->DIER = 0;
switch (dev->type) {
case TIMER_ADVANCED: /* fall-through */
case TIMER_GENERAL:
(dev->regs).gen->CCER = 0;
break;
case TIMER_BASIC:
break;
}
}
/**
* Sets the mode of an individual timer channel.
*
* Note that not all timers can be configured in every mode. For
* example, basic timers cannot be configured to output compare mode.
* Be sure to use a timer which is appropriate for the mode you want.
*
* @param dev Timer whose channel mode to set
* @param channel Relevant channel
* @param mode New timer mode for channel
*/
void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode) {
ASSERT_FAULT(channel > 0 && channel <= 4);
/* TODO decide about the basic timers */
ASSERT(dev->type != TIMER_BASIC);
if (dev->type == TIMER_BASIC)
return;
switch (mode) {
case TIMER_DISABLED:
disable_channel(dev, channel);
break;
case TIMER_PWM:
pwm_mode(dev, channel);
break;
case TIMER_OUTPUT_COMPARE:
output_compare_mode(dev, channel);
break;
}
}
/**
* @brief Determine whether a timer has a particular capture/compare channel.
*
* Different timers have different numbers of capture/compare channels
* (and some have none at all). Use this function to test whether a
* given timer/channel combination will work.
*
* @param dev Timer device
* @param channel Capture/compare channel, from 1 to 4
* @return Nonzero if dev has channel, zero otherwise.
*/
int timer_has_cc_channel(timer_dev *dev, uint8 channel) {
/* On all currently supported series: advanced and "full-featured"
* general purpose timers have all four channels. Of the
* restricted general timers, timers 9 and 12 have channels 1 and
* 2; the others have channel 1 only. Basic timers have none. */
rcc_clk_id id = dev->clk_id;
ASSERT((1 <= channel) && (channel <= 4));
if (id <= RCC_TIMER5 || id == RCC_TIMER8) {
return 1; /* 1 and 8 are advanced, 2-5 are "full" general */
} else if (id <= RCC_TIMER7) {
return 0; /* 6 and 7 are basic */
}
/* The rest are restricted general. */
return (((id == RCC_TIMER9 || id == RCC_TIMER12) && channel <= 2) ||
channel == 1);
}
/**
* @brief Attach a timer interrupt.
* @param dev Timer device
* @param interrupt Interrupt number to attach to; this may be any
* timer_interrupt_id or timer_channel value appropriate
* for the timer.
* @param handler Handler to attach to the given interrupt.
* @see timer_interrupt_id
* @see timer_channel
*/
void timer_attach_interrupt(timer_dev *dev,
uint8 interrupt,
voidFuncPtr handler) {
dev->handlers[interrupt] = handler;
timer_enable_irq(dev, interrupt);
enable_irq(dev, interrupt);
}
/**
* @brief Detach a timer interrupt.
* @param dev Timer device
* @param interrupt Interrupt number to detach; this may be any
* timer_interrupt_id or timer_channel value appropriate
* for the timer.
* @see timer_interrupt_id
* @see timer_channel
*/
void timer_detach_interrupt(timer_dev *dev, uint8 interrupt) {
timer_disable_irq(dev, interrupt);
dev->handlers[interrupt] = NULL;
}
/*
* Utilities
*/
static void disable_channel(timer_dev *dev, uint8 channel) {
timer_detach_interrupt(dev, channel);
timer_cc_disable(dev, channel);
}
static void pwm_mode(timer_dev *dev, uint8 channel) {
timer_disable_irq(dev, channel);
timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE);
timer_cc_enable(dev, channel);
}
static void output_compare_mode(timer_dev *dev, uint8 channel) {
timer_oc_set_mode(dev, channel, TIMER_OC_MODE_ACTIVE_ON_MATCH, 0);
timer_cc_enable(dev, channel);
}
static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id);
static void enable_bas_gen_irq(timer_dev *dev);
static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid) {
if (dev->type == TIMER_ADVANCED) {
enable_adv_irq(dev, iid);
} else {
enable_bas_gen_irq(dev);
}
}
/* Advanced control timers have several IRQ lines corresponding to
* different timer interrupts.
*
* Note: This function assumes that the only advanced timers are TIM1
* and TIM8, and needs the obvious changes if that assumption is
* violated by a later STM32 series. */
static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id) {
uint8 is_tim1 = dev->clk_id == RCC_TIMER1;
nvic_irq_num irq_num;
switch (id) {
case TIMER_UPDATE_INTERRUPT:
irq_num = (is_tim1 ?
NVIC_TIMER1_UP_TIMER10 :
NVIC_TIMER8_UP_TIMER13);
break;
case TIMER_CC1_INTERRUPT: /* Fall through */
case TIMER_CC2_INTERRUPT: /* ... */
case TIMER_CC3_INTERRUPT: /* ... */
case TIMER_CC4_INTERRUPT:
irq_num = is_tim1 ? NVIC_TIMER1_CC : NVIC_TIMER8_CC;
break;
case TIMER_COM_INTERRUPT: /* Fall through */
case TIMER_TRG_INTERRUPT:
irq_num = (is_tim1 ?
NVIC_TIMER1_TRG_COM_TIMER11 :
NVIC_TIMER8_TRG_COM_TIMER14);
break;
case TIMER_BREAK_INTERRUPT:
irq_num = (is_tim1 ?
NVIC_TIMER1_BRK_TIMER9 :
NVIC_TIMER8_BRK_TIMER12);
break;
default:
/* Can't happen, but placate the compiler */
ASSERT(0);
return;
}
nvic_irq_enable(irq_num);
}
/* Basic and general purpose timers have a single IRQ line, which is
* shared by all interrupts supported by a particular timer. */
static void enable_bas_gen_irq(timer_dev *dev) {
nvic_irq_num irq_num;
switch (dev->clk_id) {
case RCC_TIMER2:
irq_num = NVIC_TIMER2;
break;
case RCC_TIMER3:
irq_num = NVIC_TIMER3;
break;
case RCC_TIMER4:
irq_num = NVIC_TIMER4;
break;
case RCC_TIMER5:
irq_num = NVIC_TIMER5;
break;
case RCC_TIMER6:
irq_num = NVIC_TIMER6;
break;
case RCC_TIMER7:
irq_num = NVIC_TIMER7;
break;
case RCC_TIMER9:
irq_num = NVIC_TIMER1_BRK_TIMER9;
break;
case RCC_TIMER10:
irq_num = NVIC_TIMER1_UP_TIMER10;
break;
case RCC_TIMER11:
irq_num = NVIC_TIMER1_TRG_COM_TIMER11;
break;
case RCC_TIMER12:
irq_num = NVIC_TIMER8_BRK_TIMER12;
break;
case RCC_TIMER13:
irq_num = NVIC_TIMER8_UP_TIMER13;
break;
case RCC_TIMER14:
irq_num = NVIC_TIMER8_TRG_COM_TIMER14;
break;
default:
ASSERT_FAULT(0);
return;
}
nvic_irq_enable(irq_num);
}
/******************************************************************************
* The MIT License
*
* Copyright (c) 2011 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @file libmaple/timer.c
* @author Marti Bolivar <mbolivar@leaflabs.com>
* @brief Portable timer routines.
*/
#include <libmaple/timer.h>
#include <libmaple/stm32.h>
#include "timer_private.h"
static void disable_channel(timer_dev *dev, uint8 channel);
static void pwm_mode(timer_dev *dev, uint8 channel);
static void output_compare_mode(timer_dev *dev, uint8 channel);
static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid);
/*
* Devices
*
* Defer to the timer_private API for declaring these.
*/
#if STM32_HAVE_TIMER(1)
static timer_dev timer1 = ADVANCED_TIMER(1);
/** Timer 1 device (advanced) */
timer_dev *TIMER1 = &timer1;
#endif
#if STM32_HAVE_TIMER(2)
static timer_dev timer2 = GENERAL_TIMER(2);
/** Timer 2 device (general-purpose) */
timer_dev *TIMER2 = &timer2;
#endif
#if STM32_HAVE_TIMER(3)
static timer_dev timer3 = GENERAL_TIMER(3);
/** Timer 3 device (general-purpose) */
timer_dev *TIMER3 = &timer3;
#endif
#if STM32_HAVE_TIMER(4)
static timer_dev timer4 = GENERAL_TIMER(4);
/** Timer 4 device (general-purpose) */
timer_dev *TIMER4 = &timer4;
#endif
#if STM32_HAVE_TIMER(5)
static timer_dev timer5 = GENERAL_TIMER(5);
/** Timer 5 device (general-purpose) */
timer_dev *TIMER5 = &timer5;
#endif
#if STM32_HAVE_TIMER(6)
static timer_dev timer6 = BASIC_TIMER(6);
/** Timer 6 device (basic) */
timer_dev *TIMER6 = &timer6;
#endif
#if STM32_HAVE_TIMER(7)
static timer_dev timer7 = BASIC_TIMER(7);
/** Timer 7 device (basic) */
timer_dev *TIMER7 = &timer7;
#endif
#if STM32_HAVE_TIMER(8)
static timer_dev timer8 = ADVANCED_TIMER(8);
/** Timer 8 device (advanced) */
timer_dev *TIMER8 = &timer8;
#endif
#if STM32_HAVE_TIMER(9)
static timer_dev timer9 = RESTRICTED_GENERAL_TIMER(9, TIMER_DIER_TIE_BIT);
/** Timer 9 device (general-purpose) */
timer_dev *TIMER9 = &timer9;
#endif
#if STM32_HAVE_TIMER(10)
static timer_dev timer10 = RESTRICTED_GENERAL_TIMER(10, TIMER_DIER_CC1IE_BIT);
/** Timer 10 device (general-purpose) */
timer_dev *TIMER10 = &timer10;
#endif
#if STM32_HAVE_TIMER(11)
static timer_dev timer11 = RESTRICTED_GENERAL_TIMER(11, TIMER_DIER_CC1IE_BIT);
/** Timer 11 device (general-purpose) */
timer_dev *TIMER11 = &timer11;
#endif
#if STM32_HAVE_TIMER(12)
static timer_dev timer12 = RESTRICTED_GENERAL_TIMER(12, TIMER_DIER_TIE_BIT);
/** Timer 12 device (general-purpose) */
timer_dev *TIMER12 = &timer12;
#endif
#if STM32_HAVE_TIMER(13)
static timer_dev timer13 = RESTRICTED_GENERAL_TIMER(13, TIMER_DIER_CC1IE_BIT);
/** Timer 13 device (general-purpose) */
timer_dev *TIMER13 = &timer13;
#endif
#if STM32_HAVE_TIMER(14)
static timer_dev timer14 = RESTRICTED_GENERAL_TIMER(14, TIMER_DIER_CC1IE_BIT);
/** Timer 14 device (general-purpose) */
timer_dev *TIMER14 = &timer14;
#endif
/*
* Routines
*/
/**
* @brief Call a function on timer devices.
* @param fn Function to call on each timer device.
*/
void timer_foreach(void (*fn)(timer_dev*)) {
#if STM32_HAVE_TIMER(1)
fn(TIMER1);
#endif
#if STM32_HAVE_TIMER(2)
fn(TIMER2);
#endif
#if STM32_HAVE_TIMER(3)
fn(TIMER3);
#endif
#if STM32_HAVE_TIMER(4)
fn(TIMER4);
#endif
#if STM32_HAVE_TIMER(5)
fn(TIMER5);
#endif
#if STM32_HAVE_TIMER(6)
fn(TIMER6);
#endif
#if STM32_HAVE_TIMER(7)
fn(TIMER7);
#endif
#if STM32_HAVE_TIMER(8)
fn(TIMER8);
#endif
#if STM32_HAVE_TIMER(9)
fn(TIMER9);
#endif
#if STM32_HAVE_TIMER(10)
fn(TIMER10);
#endif
#if STM32_HAVE_TIMER(11)
fn(TIMER11);
#endif
#if STM32_HAVE_TIMER(12)
fn(TIMER12);
#endif
#if STM32_HAVE_TIMER(13)
fn(TIMER13);
#endif
#if STM32_HAVE_TIMER(14)
fn(TIMER14);
#endif
}
/**
* Initialize a timer, and reset its register map.
* @param dev Timer to initialize
*/
void timer_init(timer_dev *dev) {
rcc_clk_enable(dev->clk_id);
rcc_reset_dev(dev->clk_id);
}
/**
* @brief Disable a timer.
*
* The timer will stop counting, all DMA requests and interrupts will
* be disabled, and no state changes will be output.
*
* @param dev Timer to disable.
*/
void timer_disable(timer_dev *dev) {
(dev->regs).bas->CR1 = 0;
(dev->regs).bas->DIER = 0;
switch (dev->type) {
case TIMER_ADVANCED: /* fall-through */
case TIMER_GENERAL:
(dev->regs).gen->CCER = 0;
break;
case TIMER_BASIC:
break;
}
}
/**
* Sets the mode of an individual timer channel.
*
* Note that not all timers can be configured in every mode. For
* example, basic timers cannot be configured to output compare mode.
* Be sure to use a timer which is appropriate for the mode you want.
*
* @param dev Timer whose channel mode to set
* @param channel Relevant channel
* @param mode New timer mode for channel
*/
void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode) {
ASSERT_FAULT(channel > 0 && channel <= 4);
/* TODO decide about the basic timers */
ASSERT(dev->type != TIMER_BASIC);
if (dev->type == TIMER_BASIC)
return;
switch (mode) {
case TIMER_DISABLED:
disable_channel(dev, channel);
break;
case TIMER_PWM:
pwm_mode(dev, channel);
break;
case TIMER_OUTPUT_COMPARE:
output_compare_mode(dev, channel);
break;
}
}
/**
* @brief Determine whether a timer has a particular capture/compare channel.
*
* Different timers have different numbers of capture/compare channels
* (and some have none at all). Use this function to test whether a
* given timer/channel combination will work.
*
* @param dev Timer device
* @param channel Capture/compare channel, from 1 to 4
* @return Nonzero if dev has channel, zero otherwise.
*/
int timer_has_cc_channel(timer_dev *dev, uint8 channel) {
/* On all currently supported series: advanced and "full-featured"
* general purpose timers have all four channels. Of the
* restricted general timers, timers 9 and 12 have channels 1 and
* 2; the others have channel 1 only. Basic timers have none. */
rcc_clk_id id = dev->clk_id;
ASSERT((1 <= channel) && (channel <= 4));
if (id <= RCC_TIMER5 || id == RCC_TIMER8) {
return 1; /* 1 and 8 are advanced, 2-5 are "full" general */
} else if (id <= RCC_TIMER7) {
return 0; /* 6 and 7 are basic */
}
/* The rest are restricted general. */
return (((id == RCC_TIMER9 || id == RCC_TIMER12) && channel <= 2) ||
channel == 1);
}
/**
* @brief Attach a timer interrupt.
* @param dev Timer device
* @param interrupt Interrupt number to attach to; this may be any
* timer_interrupt_id or timer_channel value appropriate
* for the timer.
* @param handler Handler to attach to the given interrupt.
* @see timer_interrupt_id
* @see timer_channel
*/
void timer_attach_interrupt(timer_dev *dev,
uint8 interrupt,
voidFuncPtr handler) {
dev->handlers[interrupt] = handler;
timer_enable_irq(dev, interrupt);
enable_irq(dev, interrupt);
}
/**
* @brief Detach a timer interrupt.
* @param dev Timer device
* @param interrupt Interrupt number to detach; this may be any
* timer_interrupt_id or timer_channel value appropriate
* for the timer.
* @see timer_interrupt_id
* @see timer_channel
*/
void timer_detach_interrupt(timer_dev *dev, uint8 interrupt) {
timer_disable_irq(dev, interrupt);
dev->handlers[interrupt] = NULL;
}
/*
* Utilities
*/
static void disable_channel(timer_dev *dev, uint8 channel) {
timer_detach_interrupt(dev, channel);
timer_cc_disable(dev, channel);
}
static void pwm_mode(timer_dev *dev, uint8 channel) {
timer_disable_irq(dev, channel);
timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE);
timer_cc_enable(dev, channel);
}
static void output_compare_mode(timer_dev *dev, uint8 channel) {
timer_oc_set_mode(dev, channel, TIMER_OC_MODE_ACTIVE_ON_MATCH, 0);
timer_cc_enable(dev, channel);
}
static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id);
static void enable_bas_gen_irq(timer_dev *dev);
static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid) {
if (dev->type == TIMER_ADVANCED) {
enable_adv_irq(dev, iid);
} else {
enable_bas_gen_irq(dev);
}
}
/* Advanced control timers have several IRQ lines corresponding to
* different timer interrupts.
*
* Note: This function assumes that the only advanced timers are TIM1
* and TIM8, and needs the obvious changes if that assumption is
* violated by a later STM32 series. */
static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id) {
uint8 is_tim1 = dev->clk_id == RCC_TIMER1;
nvic_irq_num irq_num;
switch (id) {
case TIMER_UPDATE_INTERRUPT:
irq_num = (is_tim1 ?
NVIC_TIMER1_UP_TIMER10 :
NVIC_TIMER8_UP_TIMER13);
break;
case TIMER_CC1_INTERRUPT: /* Fall through */
case TIMER_CC2_INTERRUPT: /* ... */
case TIMER_CC3_INTERRUPT: /* ... */
case TIMER_CC4_INTERRUPT:
irq_num = is_tim1 ? NVIC_TIMER1_CC : NVIC_TIMER8_CC;
break;
case TIMER_COM_INTERRUPT: /* Fall through */
case TIMER_TRG_INTERRUPT:
irq_num = (is_tim1 ?
NVIC_TIMER1_TRG_COM_TIMER11 :
NVIC_TIMER8_TRG_COM_TIMER14);
break;
case TIMER_BREAK_INTERRUPT:
irq_num = (is_tim1 ?
NVIC_TIMER1_BRK_TIMER9 :
NVIC_TIMER8_BRK_TIMER12);
break;
default:
/* Can't happen, but placate the compiler */
ASSERT(0);
return;
}
nvic_irq_enable(irq_num);
}
/* Basic and general purpose timers have a single IRQ line, which is
* shared by all interrupts supported by a particular timer. */
static void enable_bas_gen_irq(timer_dev *dev) {
nvic_irq_num irq_num;
switch (dev->clk_id) {
case RCC_TIMER2:
irq_num = NVIC_TIMER2;
break;
case RCC_TIMER3:
irq_num = NVIC_TIMER3;
break;
case RCC_TIMER4:
irq_num = NVIC_TIMER4;
break;
case RCC_TIMER5:
irq_num = NVIC_TIMER5;
break;
case RCC_TIMER6:
irq_num = NVIC_TIMER6;
break;
case RCC_TIMER7:
irq_num = NVIC_TIMER7;
break;
case RCC_TIMER9:
irq_num = NVIC_TIMER1_BRK_TIMER9;
break;
case RCC_TIMER10:
irq_num = NVIC_TIMER1_UP_TIMER10;
break;
case RCC_TIMER11:
irq_num = NVIC_TIMER1_TRG_COM_TIMER11;
break;
case RCC_TIMER12:
irq_num = NVIC_TIMER8_BRK_TIMER12;
break;
case RCC_TIMER13:
irq_num = NVIC_TIMER8_UP_TIMER13;
break;
case RCC_TIMER14:
irq_num = NVIC_TIMER8_TRG_COM_TIMER14;
break;
default:
ASSERT_FAULT(0);
return;
}
nvic_irq_enable(irq_num);
}

View File

@ -0,0 +1,115 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2011 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @file wirish/boards/maple_mini/board.cpp
* @author Marti Bolivar <mbolivar@leaflabs.com>
* @brief Maple Mini board file.
*/
#include <board/board.h>
#include <libmaple/gpio.h>
#include <libmaple/timer.h>
#include <wirish_debug.h>
#include <wirish_types.h>
/* Since we want the Serial Wire/JTAG pins as GPIOs, disable both SW
* and JTAG debug support, unless configured otherwise. */
void boardInit(void) {
#ifndef CONFIG_MAPLE_MINI_NO_DISABLE_DEBUG
disableDebugPorts();
#endif
}
extern const stm32_pin_info PIN_MAP[BOARD_NR_GPIO_PINS] = {
/* Top header */
{GPIOA, TIMER2, ADC1, 0, 1, 0}, /* D11/PA0 */
{GPIOA, TIMER2, ADC1, 1, 2, 1}, /* D10/PA1 */
{GPIOA, TIMER2, ADC1, 2, 3, 2}, /* D9/PA2 */
{GPIOA, TIMER2, ADC1, 3, 4, 3}, /* D8/PA3 */
{GPIOA, NULL, ADC1, 4, 0, 4}, /* D7/PA4 */
{GPIOA, NULL, ADC1, 5, 0, 5}, /* D6/PA5 */
{GPIOA, TIMER3, ADC1, 6, 1, 6}, /* D5/PA6 */
{GPIOA, TIMER3, ADC1, 7, 2, 7}, /* D4/PA7 */
{GPIOA, TIMER1, NULL, 8, 1, ADCx}, /* D27/PA8 */
{GPIOA, TIMER1, NULL, 9, 2, ADCx}, /* D26/PA9 */
{GPIOA, TIMER1, NULL, 10, 3, ADCx}, /* D25/PA10 */
{GPIOA, TIMER1, NULL, 11, 4, ADCx}, /* D24/PA11 */
{GPIOA, NULL, NULL, 12, 0, ADCx}, /* D23/PA12 */
{GPIOA, NULL, NULL, 13, 0, ADCx}, /* D22/PA13 */
{GPIOA, NULL, NULL, 14, 0, ADCx}, /* D21/PA14 */
{GPIOA, NULL, NULL, 15, 0, ADCx}, /* D20/PA15 */
{GPIOB, TIMER3, ADC1, 0, 3, 8}, /* D3/PB0 */
{GPIOB, NULL, NULL, 11, 0, ADCx}, /* D0/PB11 */
{GPIOB, NULL, NULL, 10, 0, ADCx}, /* D1/PB10 */
{GPIOB, NULL, NULL, 2, 0, ADCx}, /* D2/PB2 */
{GPIOC, NULL, NULL, 15, 0, ADCx}, /* D12/PC15 */
{GPIOC, NULL, NULL, 14, 0, ADCx}, /* D13/PC14 */
{GPIOC, NULL, NULL, 13, 0, ADCx}, /* D14/PC13 */
/* Bottom header */
{GPIOB, TIMER4, NULL, 7, 2, ADCx}, /* D15/PB7 */
{GPIOB, TIMER4, NULL, 6, 1, ADCx}, /* D16/PB6 */
{GPIOB, NULL, NULL, 5, 0, ADCx}, /* D17/PB5 */
{GPIOB, NULL, NULL, 4, 0, ADCx}, /* D18/PB4 */
{GPIOB, NULL, NULL, 3, 0, ADCx}, /* D19/PB3 */
{GPIOB, NULL, NULL, 15, 0, ADCx}, /* D28/PB15 */
{GPIOB, NULL, NULL, 14, 0, ADCx}, /* D29/PB14 */
{GPIOB, NULL, NULL, 13, 0, ADCx}, /* D30/PB13 */
{GPIOB, NULL, NULL, 12, 0, ADCx}, /* D31/PB12 */
{GPIOB, TIMER4, NULL, 8, 3, ADCx}, /* D32/PB8 */
{GPIOB, TIMER3, ADC1, 1, 4, 9}, /* D33/PB1 */
{GPIOB, NULL, NULL, 9, 0, ADCx}, /* PB9 */
};
extern const uint8 boardPWMPins[BOARD_NR_PWM_PINS] __FLASH__ = {
PB0, PA7, PA6, PA3, PA2, PA1, PA0, PB7, PB6, PA10, PA9, PA8
};
/*
old maple mini mapping enum
PB11, PB10, PB2, PB0, PA7, PA6, PA5, PA4, PA3, PA2, PA1, PA0, PC15, PC14,
PC13, PB7, PB6, PB5, PB4, PB3, PA15, PA14, PA13, PA12, PA11, PA10, PA9,
PA8, PB15, PB14, PB13, PB12, PB8, PB1
*/
extern const uint8 boardADCPins[BOARD_NR_ADC_PINS] __FLASH__ = {
PB0, PA7, PA6 , PA5 , PA4 , PA3 , PA2 , PA1 , PA0
};
#define USB_DP PA12
#define USB_DM PA11
extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
BOARD_LED_PIN, BOARD_BUTTON_PIN, USB_DP, USB_DM
};

View File

@ -0,0 +1,86 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2011 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @file wirish/boards/maple_mini/include/board/board.h
* @author Marti Bolivar <mbolivar@leaflabs.com>
* @brief Maple Mini board header.
*
* See wirish/boards/maple/include/board/board.h for more information
* on these definitions.
*/
#ifndef _BOARD_GENERIC_STM32F103C_H_
#define _BOARD_GENERIC_STM32F103C_H_
#define CYCLES_PER_MICROSECOND 72
#define SYSTICK_RELOAD_VAL 71999 /* takes a cycle to reload */
#define BOARD_BUTTON_PIN 32
#define BOARD_LED_PIN 33
#define BOARD_NR_USARTS 3
#define BOARD_USART1_TX_PIN PA9
#define BOARD_USART1_RX_PIN PA10
#define BOARD_USART2_TX_PIN PA2
#define BOARD_USART2_RX_PIN PA3
#define BOARD_USART3_TX_PIN PB10
#define BOARD_USART3_RX_PIN PB11
#define BOARD_NR_SPI 2
#define BOARD_SPI1_NSS_PIN PA4
#define BOARD_SPI1_MOSI_PIN PA7
#define BOARD_SPI1_MISO_PIN PA6
#define BOARD_SPI1_SCK_PIN PA5
#define BOARD_SPI2_NSS_PIN PB12
#define BOARD_SPI2_MOSI_PIN PB15
#define BOARD_SPI2_MISO_PIN PB14
#define BOARD_SPI2_SCK_PIN PB13
#define BOARD_NR_GPIO_PINS 35
#define BOARD_NR_PWM_PINS 12
#define BOARD_NR_ADC_PINS 9
#define BOARD_NR_USED_PINS 4
#define BOARD_JTMS_SWDIO_PIN 22
#define BOARD_JTCK_SWCLK_PIN 21
#define BOARD_JTDI_PIN 20
#define BOARD_JTDO_PIN 19
#define BOARD_NJTRST_PIN 18
#define BOARD_USB_DISC_DEV GPIOB
#define BOARD_USB_DISC_BIT 10
enum {
PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9,PA10,PA11,PA12,PA13,PA14,PA15,
PB0,PB11, PB10, PB2, PC15, PC14,
PC13, PB7, PB6, PB5, PB4, PB3, PB15, PB14, PB13, PB12, PB8, PB1, PB9
};
#endif

View File

@ -0,0 +1,220 @@
/*
* Linker script for libmaple.
*
* Original author "lanchon" from ST forums, with modifications by LeafLabs.
*/
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
/*
* Configure other libraries we want in the link.
*
* libgcc, libc, and libm are common across supported toolchains.
* However, some toolchains require additional archives which aren't
* present everywhere (e.g. ARM's gcc-arm-embedded releases).
*
* To hack around this, we let the build system specify additional
* archives by putting the right extra_libs.inc (in a directory under
* toolchains/) in our search path.
*/
GROUP(libgcc.a libc.a libm.a)
INCLUDE extra_libs.inc
/*
* These force the linker to search for vector table symbols.
*
* These symbols vary by STM32 family (and also within families).
* It's up to the build system to configure the link's search path
* properly for the target MCU.
*/
INCLUDE vector_symbols.inc
/* STM32 vector table. */
EXTERN(__stm32_vector_table)
/* C runtime initialization function. */
EXTERN(start_c)
/* main entry point */
EXTERN(main)
/* Initial stack pointer value. */
EXTERN(__msp_init)
PROVIDE(__msp_init = ORIGIN(ram) + LENGTH(ram));
/* Reset vector and chip reset entry point */
EXTERN(__start__)
ENTRY(__start__)
PROVIDE(__exc_reset = __start__);
/* Heap boundaries, for libmaple */
EXTERN(_lm_heap_start);
EXTERN(_lm_heap_end);
SECTIONS
{
.text :
{
__text_start__ = .;
/*
* STM32 vector table. Leave this here. Yes, really.
*/
*(.stm32.interrupt_vector)
/*
* Program code and vague linking
*/
*(.text .text.* .gnu.linkonce.t.*)
*(.plt)
*(.gnu.warning)
*(.glue_7t) *(.glue_7) *(.vfp11_veneer)
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.gcc_except_table)
*(.eh_frame_hdr)
*(.eh_frame)
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
} > REGION_TEXT
/*
* End of text
*/
.text.align :
{
. = ALIGN(8);
__text_end__ = .;
} > REGION_TEXT
/*
* .ARM.exidx exception unwinding; mandated by ARM's C++ ABI
*/
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > REGION_RODATA
__exidx_end = .;
/*
* .data
*/
.data :
{
__data_start__ = .;
LONG(0)
. = ALIGN(8);
*(.got.plt) *(.got)
*(.data .data.* .gnu.linkonce.d.*)
. = ALIGN(8);
__data_end__ = .;
} > REGION_DATA AT> REGION_RODATA
/*
* Read-only data
*/
.rodata :
{
*(.rodata .rodata.* .gnu.linkonce.r.*)
/* .USER_FLASH: We allow users to allocate into Flash here */
*(.USER_FLASH)
/* ROM image configuration; for C startup */
. = ALIGN(4);
_lm_rom_img_cfgp = .;
LONG(LOADADDR(.data));
/*
* Heap: Linker scripts may choose a custom heap by overriding
* _lm_heap_start and _lm_heap_end. Otherwise, the heap is in
* internal SRAM, beginning after .bss, and growing towards
* the stack.
*
* I'm shoving these here naively; there's probably a cleaner way
* to go about this. [mbolivar]
*/
_lm_heap_start = DEFINED(_lm_heap_start) ? _lm_heap_start : _end;
_lm_heap_end = DEFINED(_lm_heap_end) ? _lm_heap_end : __msp_init;
} > REGION_RODATA
/*
* .bss
*/
.bss :
{
. = ALIGN(8);
__bss_start__ = .;
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
__bss_end__ = .;
_end = __bss_end__;
} > REGION_BSS
/*
* Debugging sections
*/
.stab 0 (NOLOAD) : { *(.stab) }
.stabstr 0 (NOLOAD) : { *(.stabstr) }
/* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to the beginning
* of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) }
}

View File

@ -0,0 +1,7 @@
/*
* Extra archives needed by ARM's GCC ARM Embedded arm-none-eabi-
* releases (https://launchpad.net/gcc-arm-embedded/).
*/
/* This is for the provided newlib. */
GROUP(libnosys.a)

View File

@ -0,0 +1,26 @@
/*
* libmaple linker script for "Flash" builds.
*
* A Flash build puts .text (and .rodata) in Flash, and
* .data/.bss/heap (of course) in SRAM, but offsets the sections by
* enough space to store the Maple bootloader, which lives in low
* Flash and uses low memory.
*/
/*
* This pulls in the appropriate MEMORY declaration from the right
* subdirectory of stm32/mem/ (the environment must call ld with the
* right include directory flags to make this happen). Boards can also
* use this file to use any of libmaple's memory-related hooks (like
* where the heap should live).
*/
INCLUDE mem-flash.inc
/* Provide memory region aliases for common.inc */
REGION_ALIAS("REGION_TEXT", rom);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("REGION_RODATA", rom);
/* Let common.inc handle the real work. */
INCLUDE common.inc

View File

@ -0,0 +1,33 @@
/*
* libmaple linker script for "Flash" builds.
*
* A Flash build puts .text (and .rodata) in Flash, and
* .data/.bss/heap (of course) in SRAM, but offsets the sections by
* enough space to store the Maple bootloader, which lives in low
* Flash and uses low memory.
*/
/*
* This pulls in the appropriate MEMORY declaration from the right
* subdirectory of stm32/mem/ (the environment must call ld with the
* right include directory flags to make this happen). Boards can also
* use this file to use any of libmaple's memory-related hooks (like
* where the heap should live).
*/
/*INCLUDE mem-flash.inc*/
MEMORY
{
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
rom (rx) : ORIGIN = 0x08000000, LENGTH = 44K
}
/* Provide memory region aliases for common.inc */
REGION_ALIAS("REGION_TEXT", rom);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("REGION_RODATA", rom);
/* Let common.inc handle the real work. */
INCLUDE common.inc

View File

@ -0,0 +1,31 @@
/*
* libmaple linker script for "JTAG" builds.
*
* A "JTAG" build puts .text (and .rodata) in Flash, and
* .data/.bss/heap (of course) in SRAM, but links starting at the
* Flash and SRAM starting addresses (0x08000000 and 0x20000000
* respectively). This will wipe out a Maple bootloader if there's one
* on the board, so only use this if you know what you're doing.
*
* Of course, a "JTAG" build is perfectly usable for upload over SWD,
* the system memory bootloader, etc. The name is just a historical
* artifact.
*/
/*
* This pulls in the appropriate MEMORY declaration from the right
* subdirectory of stm32/mem/ (the environment must call ld with the
* right include directory flags to make this happen). Boards can also
* use this file to use any of libmaple's memory-related hooks (like
* where the heap should live).
*/
INCLUDE mem-jtag.inc
/* Provide memory region aliases for common.inc */
REGION_ALIAS("REGION_TEXT", rom);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("REGION_RODATA", rom);
/* Let common.inc handle the real work. */
INCLUDE common.inc

View File

@ -0,0 +1,36 @@
/*
* libmaple linker script for "JTAG" builds.
*
* A "JTAG" build puts .text (and .rodata) in Flash, and
* .data/.bss/heap (of course) in SRAM, but links starting at the
* Flash and SRAM starting addresses (0x08000000 and 0x20000000
* respectively). This will wipe out a Maple bootloader if there's one
* on the board, so only use this if you know what you're doing.
*
* Of course, a "JTAG" build is perfectly usable for upload over SWD,
* the system memory bootloader, etc. The name is just a historical
* artifact.
*/
/*
* This pulls in the appropriate MEMORY declaration from the right
* subdirectory of stm32/mem/ (the environment must call ld with the
* right include directory flags to make this happen). Boards can also
* use this file to use any of libmaple's memory-related hooks (like
* where the heap should live).
*/
MEMORY
{
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K
}
/* Provide memory region aliases for common.inc */
REGION_ALIAS("REGION_TEXT", rom);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("REGION_RODATA", rom);
/* Let common.inc handle the real work. */
INCLUDE common.inc

View File

@ -0,0 +1,5 @@
MEMORY
{
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
rom (rx) : ORIGIN = 0x08005000, LENGTH = 108K
}

View File

@ -0,0 +1,5 @@
MEMORY
{
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
}

View File

@ -0,0 +1,5 @@
MEMORY
{
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K
}

View File

@ -0,0 +1,25 @@
/*
* libmaple linker script for RAM builds.
*
* A Flash build puts .text, .rodata, and .data/.bss/heap (of course)
* in SRAM, but offsets the sections by enough space to store the
* Maple bootloader, which uses low memory.
*/
/*
* This pulls in the appropriate MEMORY declaration from the right
* subdirectory of stm32/mem/ (the environment must call ld with the
* right include directory flags to make this happen). Boards can also
* use this file to use any of libmaple's memory-related hooks (like
* where the heap should live).
*/
INCLUDE mem-ram.inc
/* Provide memory region aliases for common.inc */
REGION_ALIAS("REGION_TEXT", ram);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("REGION_RODATA", ram);
/* Let common.inc handle the real work. */
INCLUDE common.inc

View File

@ -0,0 +1,31 @@
/*
* libmaple linker script for RAM builds.
*
* A Flash build puts .text, .rodata, and .data/.bss/heap (of course)
* in SRAM, but offsets the sections by enough space to store the
* Maple bootloader, which uses low memory.
*/
/*
* This pulls in the appropriate MEMORY declaration from the right
* subdirectory of stm32/mem/ (the environment must call ld with the
* right include directory flags to make this happen). Boards can also
* use this file to use any of libmaple's memory-related hooks (like
* where the heap should live).
*/
/*INCLUDE mem-ram.inc*/
MEMORY
{
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
rom (rx) : ORIGIN = 0x08005000, LENGTH = 0
}
/* Provide memory region aliases for common.inc */
REGION_ALIAS("REGION_TEXT", ram);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("REGION_RODATA", ram);
/* Let common.inc handle the real work. */
INCLUDE common.inc

View File

@ -0,0 +1,78 @@
EXTERN(__msp_init)
EXTERN(__exc_reset)
EXTERN(__exc_nmi)
EXTERN(__exc_hardfault)
EXTERN(__exc_memmanage)
EXTERN(__exc_busfault)
EXTERN(__exc_usagefault)
EXTERN(__stm32reservedexception7)
EXTERN(__stm32reservedexception8)
EXTERN(__stm32reservedexception9)
EXTERN(__stm32reservedexception10)
EXTERN(__exc_svc)
EXTERN(__exc_debug_monitor)
EXTERN(__stm32reservedexception13)
EXTERN(__exc_pendsv)
EXTERN(__exc_systick)
EXTERN(__irq_wwdg)
EXTERN(__irq_pvd)
EXTERN(__irq_tamper)
EXTERN(__irq_rtc)
EXTERN(__irq_flash)
EXTERN(__irq_rcc)
EXTERN(__irq_exti0)
EXTERN(__irq_exti1)
EXTERN(__irq_exti2)
EXTERN(__irq_exti3)
EXTERN(__irq_exti4)
EXTERN(__irq_dma1_channel1)
EXTERN(__irq_dma1_channel2)
EXTERN(__irq_dma1_channel3)
EXTERN(__irq_dma1_channel4)
EXTERN(__irq_dma1_channel5)
EXTERN(__irq_dma1_channel6)
EXTERN(__irq_dma1_channel7)
EXTERN(__irq_adc)
EXTERN(__irq_usb_hp_can_tx)
EXTERN(__irq_usb_lp_can_rx0)
EXTERN(__irq_can_rx1)
EXTERN(__irq_can_sce)
EXTERN(__irq_exti9_5)
EXTERN(__irq_tim1_brk)
EXTERN(__irq_tim1_up)
EXTERN(__irq_tim1_trg_com)
EXTERN(__irq_tim1_cc)
EXTERN(__irq_tim2)
EXTERN(__irq_tim3)
EXTERN(__irq_tim4)
EXTERN(__irq_i2c1_ev)
EXTERN(__irq_i2c1_er)
EXTERN(__irq_i2c2_ev)
EXTERN(__irq_i2c2_er)
EXTERN(__irq_spi1)
EXTERN(__irq_spi2)
EXTERN(__irq_usart1)
EXTERN(__irq_usart2)
EXTERN(__irq_usart3)
EXTERN(__irq_exti15_10)
EXTERN(__irq_rtcalarm)
EXTERN(__irq_usbwakeup)
EXTERN(__irq_tim8_brk)
EXTERN(__irq_tim8_up)
EXTERN(__irq_tim8_trg_com)
EXTERN(__irq_tim8_cc)
EXTERN(__irq_adc3)
EXTERN(__irq_fsmc)
EXTERN(__irq_sdio)
EXTERN(__irq_tim5)
EXTERN(__irq_spi3)
EXTERN(__irq_uart4)
EXTERN(__irq_uart5)
EXTERN(__irq_tim6)
EXTERN(__irq_tim7)
EXTERN(__irq_dma2_channel1)
EXTERN(__irq_dma2_channel2)
EXTERN(__irq_dma2_channel3)
EXTERN(__irq_dma2_channel4_5)

View File

@ -0,0 +1,6 @@
// API compatibility
#include "variant.h"

View File

@ -0,0 +1,14 @@
#ifndef _VARIANT_ARDUINO_STM32_
#define _VARIANT_ARDUINO_STM32_
#define digitalPinToPort(P) ( PIN_MAP[P].gpio_device )
#define digitalPinToBitMask(P) ( BIT(PIN_MAP[P].gpio_bit) )
#define portOutputRegister(port) ( &(port->regs->ODR) )
#define portInputRegister(port) ( &(port->regs->IDR) )
#define portSetRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->BSRR) )
#define portClearRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->BRR) )
#define portConfigRegister(pin) ( &(PIN_MAP[pin].gpio_device->regs->CRL) )
#endif /* _VARIANT_ARDUINO_STM32_ */

View File

@ -0,0 +1,223 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2010 Perry Hung.
* Copyright (c) 2011, 2012 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @file wirish/boards.cpp
* @brief init() and board routines.
*
* This file is mostly interesting for the init() function, which
* configures Flash, the core clocks, and a variety of other available
* peripherals on the board so the rest of Wirish doesn't have to turn
* things on before using them.
*
* Prior to returning, init() calls boardInit(), which allows boards
* to perform any initialization they need to. This file includes a
* weak no-op definition of boardInit(), so boards that don't need any
* special initialization don't have to define their own.
*
* How init() works is chip-specific. See the boards_setup.cpp files
* under e.g. wirish/stm32f1/, wirish/stmf32f2 for the details, but be
* advised: their contents are unstable, and can/will change without
* notice.
*/
#include <boards.h>
#include <libmaple/libmaple_types.h>
#include <libmaple/flash.h>
#include <libmaple/nvic.h>
#include <libmaple/systick.h>
#include "boards_private.h"
static void setup_flash(void);
static void setup_clocks(void);
static void setup_nvic(void);
static void setup_adcs(void);
static void setup_timers(void);
/*
* Exported functions
*/
void init(void) {
setup_flash();
setup_clocks();
setup_nvic();
systick_init(SYSTICK_RELOAD_VAL);
wirish::priv::board_setup_gpio();
setup_adcs();
setup_timers();
wirish::priv::board_setup_usb();
wirish::priv::series_init();
boardInit();
}
/* Provide a default no-op boardInit(). */
__weak void boardInit(void) {
}
/* You could farm this out to the files in boards/ if e.g. it takes
* too long to test on boards with lots of pins. */
bool boardUsesPin(uint8 pin) {
for (int i = 0; i < BOARD_NR_USED_PINS; i++) {
if (pin == boardUsedPins[i]) {
return true;
}
}
return false;
}
/*
* Auxiliary routines
*/
static void setup_flash(void) {
// Turn on as many Flash "go faster" features as
// possible. flash_enable_features() just ignores any flags it
// can't support.
flash_enable_features(FLASH_PREFETCH | FLASH_ICACHE | FLASH_DCACHE);
// Configure the wait states, assuming we're operating at "close
// enough" to 3.3V.
flash_set_latency(FLASH_SAFE_WAIT_STATES);
}
static void setup_clocks(void) {
// Turn on HSI. We'll switch to and run off of this while we're
// setting up the main PLL.
rcc_turn_on_clk(RCC_CLK_HSI);
// Turn off and reset the clock subsystems we'll be using, as well
// as the clock security subsystem (CSS). Note that resetting CFGR
// to its default value of 0 implies a switch to HSI for SYSCLK.
RCC_BASE->CFGR = 0x00000000;
rcc_disable_css();
rcc_turn_off_clk(RCC_CLK_PLL);
rcc_turn_off_clk(RCC_CLK_HSE);
wirish::priv::board_reset_pll();
// Clear clock readiness interrupt flags and turn off clock
// readiness interrupts.
RCC_BASE->CIR = 0x00000000;
// Enable HSE, and wait until it's ready.
rcc_turn_on_clk(RCC_CLK_HSE);
while (!rcc_is_clk_ready(RCC_CLK_HSE))
;
// Configure AHBx, APBx, etc. prescalers and the main PLL.
wirish::priv::board_setup_clock_prescalers();
rcc_configure_pll(&wirish::priv::w_board_pll_cfg);
// Enable the PLL, and wait until it's ready.
rcc_turn_on_clk(RCC_CLK_PLL);
while(!rcc_is_clk_ready(RCC_CLK_PLL))
;
// Finally, switch to the now-ready PLL as the main clock source.
rcc_switch_sysclk(RCC_CLKSRC_PLL);
}
/*
* These addresses are where usercode starts when a bootloader is
* present. If no bootloader is present, the user NVIC usually starts
* at the Flash base address, 0x08000000.
*/
#if defined(BOOTLOADER_maple)
#define USER_ADDR_ROM 0x08005000
#else
#if defined(BOOTLOADER_robotis)
#define USER_ADDR_ROM 0x08003000
#else
#define USER_ADDR_ROM 0x08000000
#endif
#endif
#define USER_ADDR_RAM 0x20000C00
extern char __text_start__;
static void setup_nvic(void) {
#ifdef VECT_TAB_FLASH
nvic_init(USER_ADDR_ROM, 0);
#elif defined VECT_TAB_RAM
nvic_init(USER_ADDR_RAM, 0);
#elif defined VECT_TAB_BASE
nvic_init((uint32)0x08000000, 0);
#elif defined VECT_TAB_ADDR
// A numerically supplied value
nvic_init((uint32)VECT_TAB_ADDR, 0);
#else
// Use the __text_start__ value from the linker script; this
// should be the start of the vector table.
nvic_init((uint32)&__text_start__, 0);
#endif
}
static void adc_default_config(const adc_dev *dev) {
adc_enable_single_swstart(dev);
adc_set_sample_rate(dev, wirish::priv::w_adc_smp);
}
static void setup_adcs(void) {
adc_set_prescaler(wirish::priv::w_adc_pre);
adc_foreach(adc_default_config);
}
static void timer_default_config(timer_dev *dev) {
timer_adv_reg_map *regs = (dev->regs).adv;
const uint16 full_overflow = 0xFFFF;
const uint16 half_duty = 0x8FFF;
timer_init(dev);
timer_pause(dev);
regs->CR1 = TIMER_CR1_ARPE;
regs->PSC = 1;
regs->SR = 0;
regs->DIER = 0;
regs->EGR = TIMER_EGR_UG;
switch (dev->type) {
case TIMER_ADVANCED:
regs->BDTR = TIMER_BDTR_MOE | TIMER_BDTR_LOCK_OFF;
// fall-through
case TIMER_GENERAL:
timer_set_reload(dev, full_overflow);
for (uint8 channel = 1; channel <= 4; channel++) {
if (timer_has_cc_channel(dev, channel)) {
timer_set_compare(dev, channel, half_duty);
timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1,
TIMER_OC_PE);
}
}
// fall-through
case TIMER_BASIC:
break;
}
timer_generate_update(dev);
timer_resume(dev);
}
static void setup_timers(void) {
timer_foreach(timer_default_config);
}

View File

@ -0,0 +1,92 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2012 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @file wirish/stm32f1/boards_setup.cpp
* @author Marti Bolivar <mbolivar@leaflabs.com>
* @brief STM32F1 chip setup.
*
* This file controls how init() behaves on the STM32F1. Be very
* careful when changing anything here. Many of these values depend
* upon each other.
*/
#include "boards_private.h"
#include <libmaple/gpio.h>
#include <libmaple/timer.h>
#include <boards.h>
#include <usb_serial.h>
// Allow boards to provide a PLL multiplier. This is useful for
// e.g. STM32F100 value line MCUs, which use slower multipliers.
// (We're leaving the default to RCC_PLLMUL_9 for now, since that
// works for F103 performance line MCUs, which is all that LeafLabs
// currently officially supports).
#ifndef BOARD_RCC_PLLMUL
#define BOARD_RCC_PLLMUL RCC_PLLMUL_9
#endif
namespace wirish {
namespace priv {
static stm32f1_rcc_pll_data pll_data = {BOARD_RCC_PLLMUL};
__weak rcc_pll_cfg w_board_pll_cfg = {RCC_PLLSRC_HSE, &pll_data};
__weak adc_prescaler w_adc_pre = ADC_PRE_PCLK2_DIV_6;
__weak adc_smp_rate w_adc_smp = ADC_SMPR_55_5;
__weak void board_reset_pll(void) {
// TODO
}
__weak void board_setup_clock_prescalers(void) {
rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1);
rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2);
rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1);
}
__weak void board_setup_gpio(void) {
gpio_init_all();
}
__weak void board_setup_usb(void) {
#if BOARD_HAVE_SERIALUSB
#ifdef BOOTLOADER_maple
// SerialUSB.begin();
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
#endif
#endif
}
__weak void series_init(void) {
// Initialize AFIO here, too, so peripheral remaps and external
// interrupts work out of the box.
afio_init();
}
}
}

View File

@ -0,0 +1,57 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2011 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/*
* This file is a modified version of a file obtained from
* CodeSourcery Inc. (now part of Mentor Graphics Corp.), in which the
* following text appeared:
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
.text
.code 16
.thumb_func
.globl __start__
.type __start__, %function
__start__:
.fnstart
ldr r1,=__msp_init
mov sp,r1
ldr r1,=start_c
bx r1
.pool
.cantunwind
.fnend

View File

@ -0,0 +1,95 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2011 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/*
* This file is a modified version of a file obtained from
* CodeSourcery Inc. (now part of Mentor Graphics Corp.), in which the
* following text appeared:
*
* Copyright (c) 2006, 2007 CodeSourcery Inc
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
#include <stddef.h>
extern void __libc_init_array(void);
extern int main(int, char**, char**);
extern void exit(int) __attribute__((noreturn, weak));
/* The linker must ensure that these are at least 4-byte aligned. */
extern char __data_start__, __data_end__;
extern char __bss_start__, __bss_end__;
struct rom_img_cfg {
int *img_start;
};
extern char _lm_rom_img_cfgp;
void __attribute__((noreturn)) start_c(void) {
struct rom_img_cfg *img_cfg = (struct rom_img_cfg*)&_lm_rom_img_cfgp;
int *src = img_cfg->img_start;
int *dst = (int*)&__data_start__;
int exit_code;
/* Initialize .data, if necessary. */
if (src != dst) {
int *end = (int*)&__data_end__;
while (dst < end) {
*dst++ = *src++;
}
}
/* Zero .bss. */
dst = (int*)&__bss_start__;
while (dst < (int*)&__bss_end__) {
*dst++ = 0;
}
/* Run initializers. */
__libc_init_array();
/* Jump to main. */
exit_code = main(0, 0, 0);
if (exit) {
exit(exit_code);
}
/* If exit is NULL, make sure we don't return. */
for (;;)
continue;
}

View File

@ -0,0 +1,176 @@
/******************************************************************************
* The MIT License
*
* Copyright (c) 2010 Perry Hung.
* Copyright (c) 2011, 2012 LeafLabs, LLC.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*****************************************************************************/
/**
* @file wirish/syscalls.c
* @brief newlib stubs
*
* Low level system routines used by newlib for basic I/O and memory
* allocation. You can override most of these.
*/
#include <libmaple/libmaple.h>
#include <sys/stat.h>
#include <errno.h>
#include <stddef.h>
/* If CONFIG_HEAP_START (or CONFIG_HEAP_END) isn't defined, then
* assume _lm_heap_start (resp. _lm_heap_end) is appropriately set by
* the linker */
#ifndef CONFIG_HEAP_START
extern char _lm_heap_start;
#define CONFIG_HEAP_START ((void *)&_lm_heap_start)
#endif
#ifndef CONFIG_HEAP_END
extern char _lm_heap_end;
#define CONFIG_HEAP_END ((void *)&_lm_heap_end)
#endif
/*
* _sbrk -- Increment the program break.
*
* Get incr bytes more RAM (for use by the heap). malloc() and
* friends call this function behind the scenes.
*/
void *_sbrk(int incr) {
static void * pbreak = NULL; /* current program break */
void * ret;
if (pbreak == NULL) {
pbreak = CONFIG_HEAP_START;
}
if ((CONFIG_HEAP_END - pbreak < incr) ||
(pbreak - CONFIG_HEAP_START < -incr)) {
errno = ENOMEM;
return (void *)-1;
}
ret = pbreak;
pbreak += incr;
return ret;
}
__weak int _open(const char *path, int flags, ...) {
return 1;
}
__weak int _close(int fd) {
return 0;
}
__weak int _fstat(int fd, struct stat *st) {
st->st_mode = S_IFCHR;
return 0;
}
__weak int _isatty(int fd) {
return 1;
}
__weak int isatty(int fd) {
return 1;
}
__weak int _lseek(int fd, off_t pos, int whence) {
return -1;
}
__weak unsigned char getch(void) {
return 0;
}
__weak int _read(int fd, char *buf, size_t cnt) {
*buf = getch();
return 1;
}
__weak void putch(unsigned char c) {
}
__weak 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;
}
__weak int _write(int fd, const char *buf, size_t cnt) {
int i;
for (i = 0; i < cnt; i++)
putch(buf[i]);
return cnt;
}
/* Override fgets() in newlib with a version that does line editing */
__weak char *fgets(char *s, int bufsize, void *f) {
cgets(s, bufsize);
return s;
}
__weak void _exit(int exitcode) {
while (1)
;
}