Merge branch 'master' into generalizations

Conflicts:
	lib/lm3s/vector.c -- split out to lm3s/irq.h
	lib/stm32/f4/vector.c -- put the floating point initialization code into a function like in lpc43xx
This commit is contained in:
chrysn
2012-10-17 18:55:54 +02:00
51 changed files with 3324 additions and 151 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ ARFLAGS = rcs
OBJS = vector.o rcc.o gpio.o usart.o adc.o spi.o flash.o nvic.o \
rtc.o i2c.o dma.o systick.o exti.o scb.o ethernet.o \
usb_f103.o usb.o usb_control.o usb_standard.o can.o \
timer.o usb_f107.o desig.o crc.o assert.o
timer.o usb_f107.o desig.o crc.o assert.o dac.o iwdg.o pwr.o
VPATH += ../../usb:../:../../cm3
+201 -42
View File
@@ -44,12 +44,12 @@ conversion, which occurs after all channels have been scanned.
@section adc_api_ex Basic ADC Handling API.
Example 1: Simple single channel conversion polled. Enable the peripheral clock
and ADC, reset ADC and set the prescaler divider. Set dual mode to independent.
and ADC, reset ADC and set the prescaler divider. Set dual mode to independent
(default). Enable triggering for a software trigger.
@code
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
adc_power_on(ADC1);
adc_calibration(ADC1);
adc_off(ADC1);
rcc_peripheral_reset(&RCC_APB2RSTR, RCC_APB2RSTR_ADC1RST);
rcc_peripheral_clear_reset(&RCC_APB2RSTR, RCC_APB2RSTR_ADC1RST);
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV2);
@@ -58,6 +58,10 @@ and ADC, reset ADC and set the prescaler divider. Set dual mode to independent.
adc_set_single_conversion_mode(ADC1);
adc_set_sample_time(ADC1, ADC_CHANNEL0, ADC_SMPR1_SMP_1DOT5CYC);
adc_set_single_channel(ADC1, ADC_CHANNEL0);
adc_enable_trigger(ADC1, ADC_CR2_EXTSEL_SWSTART);
adc_power_on(ADC1);
adc_reset_calibration(ADC1);
adc_calibration(ADC1);
adc_start_conversion_regular(ADC1);
while (! adc_eoc(ADC1));
reg16 = adc_read_regular(ADC1);
@@ -102,38 +106,181 @@ LGPL License Terms @ref lgpl_license
#include <libopencm3/stm32/f1/adc.h>
void rcc_set_adc_clk(u32 prescaler)
/*-----------------------------------------------------------------------------*/
/** @brief ADC Power On
If the ADC is in power-down mode then it is powered up. The application needs
to wait a time of about 3 microseconds for stabilization before using the ADC.
If the ADC is already on this function call has no effect.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_power_on(u32 adc)
{
/* TODO */
/* FIXME: QUICK HACK to prevent compiler warnings. */
prescaler = prescaler;
}
void adc_set_mode(u32 block, /* TODO */ u8 mode)
{
/* TODO */
/* FIXME: QUICK HACK to prevent compiler warnings. */
block = block;
mode = mode;
if (!(ADC_CR2(adc) & ADC_CR2_ADON))
ADC_CR2(adc) |= ADC_CR2_ADON;
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read from a Conversion Result Register
/** @brief ADC Start a Conversion Without Trigger
This initiates a conversion by software without a trigger. The ADC needs to be
powered on before this is called, otherwise this function has no effect.
Note that this is not available in other STM32F families. To ensure code compatibility,
enable triggering and use a software trigger source @see adc_start_conversion_regular.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_start_conversion_direct(u32 adc)
{
if (ADC_CR2(adc) & ADC_CR2_ADON)
ADC_CR2(adc) |= ADC_CR2_ADON;
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Set Dual A/D Mode
The dual mode uses ADC1 as master and ADC2 in a slave arrangement. This setting
is applied to ADC1 only. Start of conversion when triggered can cause simultaneous
conversion with ADC2, or alternate conversion. Regular and injected conversions
can be configured, each one being separately simultaneous or alternate.
Fast interleaved mode starts ADC1 immediately on trigger, and ADC2 seven clock
cycles later.
Slow interleaved mode starts ADC1 immediately on trigger, and ADC2 fourteen clock
cycles later, followed by ADC1 fourteen cycles later again. This can only be used
on a single channel.
Alternate trigger mode must occur on an injected channel group, and alternates
between the ADCs on each trigger.
Note that sampling must not overlap between ADCs on the same channel.
Dual A/D converter modes possible:
@li IND: Independent mode.
@li CRSISM: Combined regular simultaneous + injected simultaneous mode.
@li CRSATM: Combined regular simultaneous + alternate trigger mode.
@li CISFIM: Combined injected simultaneous + fast interleaved mode.
@li CISSIM: Combined injected simultaneous + slow interleaved mode.
@li ISM: Injected simultaneous mode only.
@li RSM: Regular simultaneous mode only.
@li FIM: Fast interleaved mode only.
@li SIM: Slow interleaved mode only.
@li ATM: Alternate trigger mode only.
@param[in] mode Unsigned int32. Dual mode selection from @ref adc_cr1_dualmod
*/
void adc_set_dual_mode(u32 mode)
{
ADC1_CR1 |= mode;
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read the End-of-Conversion Flag
This flag is set after all channels of a regular or injected group have been
converted.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
@returns bool. End of conversion flag.
*/
bool adc_eoc(u32 adc)
{
return ((ADC_SR(adc) & ADC_SR_EOC) != 0);
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read the End-of-Conversion Flag for Injected Conversion
This flag is set after all channels of an injected group have been converted.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
@returns bool. End of conversion flag.
*/
bool adc_eoc_injected(u32 adc)
{
return ((ADC_SR(adc) & ADC_SR_JEOC) != 0);
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read from the Regular Conversion Result Register
The result read back is 12 bits, right or left aligned within the first 16 bits.
For ADC1 only, the higher 16 bits will hold the result from ADC2 if
an appropriate dual mode has been set @see adc_set_dual_mode.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
@returns Unsigned int32 conversion result.
*/
u32 adc_read_regular(u32 adc)
{
return ADC_DR(adc);
}
/*-----------------------------------------------------------------------------*/
/** @brief ADC Read from an Injected Conversion Result Register
The result read back from the selected injected result register (one of four) is
12 bits, right or left aligned within the first 16 bits. The result can have a
negative value if the injected channel offset has been set @see adc_set_injected_offset.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
@param[in] reg Unsigned int8. Register number (1 ... 4).
@returns Unsigned int32 conversion result.
*/
void adc_read(u32 block, u32 channel)
u32 adc_read_injected(u32 adc, u8 reg)
{
/* TODO */
switch (reg) {
case 1:
return ADC_JDR1(adc);
case 2:
return ADC_JDR2(adc);
case 3:
return ADC_JDR3(adc);
case 4:
return ADC_JDR4(adc);
}
return 0;
}
/* FIXME: QUICK HACK to prevent compiler warnings. */
block = block;
channel = channel;
/*-----------------------------------------------------------------------------*/
/** @brief ADC Set the Injected Channel Data Offset
This value is subtracted from the injected channel results after conversion
is complete, and can result in negative results. A separate value can be specified
for each injected data register.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
@param[in] reg Unsigned int8. Register number (1 ... 4).
@param[in] offset Unsigned int32.
*/
void adc_set_injected_offset(u32 adc, u8 reg, u32 offset)
{
switch (reg) {
case 1:
ADC_JOFR1(adc) = offset;
break;
case 2:
ADC_JOFR2(adc) = offset;
break;
case 3:
ADC_JOFR3(adc) = offset;
break;
case 4:
ADC_JOFR4(adc) = offset;
break;
}
}
/*-----------------------------------------------------------------------------*/
@@ -203,9 +350,11 @@ of the subgroup at the beginning of the whole group.
@param[in] length Unsigned int8. Number of channels in the group @ref adc_cr1_discnum
*/
void adc_enable_discontinous_mode_regular(u32 adc)
void adc_enable_discontinuous_mode_regular(u32 adc, u8 length)
{
ADC_CR1(adc) |= ADC_CR1_DISCEN;
if ( (length-1) > 7 ) return;
ADC_CR1(adc) |= ADC_CR1_DISCEN;
ADC_CR2(adc) |= ((length-1) << ADC_CR1_DISCNUM_SHIFT);
}
/*-----------------------------------------------------------------------------*/
@@ -214,7 +363,7 @@ void adc_enable_discontinous_mode_regular(u32 adc)
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_disable_discontinous_mode_regular(u32 adc)
void adc_disable_discontinuous_mode_regular(u32 adc)
{
ADC_CR1(adc) &= ~ADC_CR1_DISCEN;
}
@@ -229,7 +378,7 @@ entire group has been converted.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_enable_discontinous_mode_injected(u32 adc)
void adc_enable_discontinuous_mode_injected(u32 adc)
{
ADC_CR1(adc) |= ADC_CR1_JDISCEN;
}
@@ -240,7 +389,7 @@ void adc_enable_discontinous_mode_injected(u32 adc)
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_disable_discontinous_mode_injected(u32 adc)
void adc_disable_discontinuous_mode_injected(u32 adc)
{
ADC_CR1(adc) &= ~ADC_CR1_JDISCEN;
}
@@ -257,6 +406,7 @@ channels is disabled as required.
void adc_enable_automatic_injected_group_conversion(u32 adc)
{
adc_disable_external_trigger_injected(adc);
ADC_CR1(adc) |= ADC_CR1_JAUTO;
}
@@ -288,7 +438,7 @@ disabled.
void adc_enable_analog_watchdog_on_all_channels(u32 adc)
{
ADC_CR1(adc) |= ADC_CR1_AWDSGL;
ADC_CR1(adc) &= ~ADC_CR1_AWDSGL;
}
/*-----------------------------------------------------------------------------*/
@@ -315,7 +465,7 @@ void adc_enable_analog_watchdog_on_selected_channel(u32 adc, u8 channel)
if (channel < 18)
reg32 |= channel;
ADC_CR1(adc) = reg32;
ADC_CR1(adc) &= ~ADC_CR1_AWDSGL;
ADC_CR1(adc) |= ADC_CR1_AWDSGL;
}
/*-----------------------------------------------------------------------------*/
@@ -350,7 +500,7 @@ void adc_disable_scan_mode(u32 adc)
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_enable_jeoc_interrupt(u32 adc)
void adc_enable_eoc_interrupt_injected(u32 adc)
{
ADC_CR1(adc) |= ADC_CR1_JEOCIE;
}
@@ -361,7 +511,7 @@ void adc_enable_jeoc_interrupt(u32 adc)
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_disable_jeoc_interrupt(u32 adc)
void adc_disable_eoc_interrupt_injected(u32 adc)
{
ADC_CR1(adc) &= ~ADC_CR1_JEOCIE;
}
@@ -519,8 +669,7 @@ void adc_enable_external_trigger_regular(u32 adc, u32 trigger)
u32 reg32;
reg32 = (ADC_CR2(adc) & ~(ADC_CR2_EXTSEL_MASK));
if (trigger < 8)
reg32 |= (trigger);
reg32 |= (trigger);
ADC_CR2(adc) = reg32;
ADC_CR2(adc) |= ADC_CR2_EXTTRIG;
}
@@ -565,14 +714,12 @@ For ADC3
@param[in] trigger Unsigned int8. Trigger identifier @ref adc_trigger_injected_12
for ADC1 and ADC2, or @ref adc_trigger_injected_3 for ADC3
*/
void adc_enable_external_trigger_injected(u32 adc, u32 trigger)
{
u32 reg32;
reg32 = (ADC_CR2(adc) & ~(ADC_CR2_JEXTSEL_MASK)); /* Clear bits [12:14]. */
if (trigger < 8)
reg32 |= (trigger);
reg32 |= (trigger);
ADC_CR2(adc) = reg32;
ADC_CR2(adc) |= ADC_CR2_JEXTTRIG;
}
@@ -681,7 +828,7 @@ group immediately following completion of the previous channel group conversion.
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
void adc_set_continous_conversion_mode(u32 adc)
void adc_set_continuous_conversion_mode(u32 adc)
{
ADC_CR2(adc) |= ADC_CR2_CONT;
}
@@ -707,7 +854,7 @@ If the ADC is in power-down mode then it is powered up. The application needs
to wait a time of about 3 microseconds for stabilization before using the ADC.
If the ADC is already on this function call will initiate a conversion.
@todo fix this.
@deprecated to be removed in a later release
@param[in] adc Unsigned int32. ADC block register address base @ref adc_reg_base
*/
@@ -740,7 +887,7 @@ The sampling time can be selected in ADC clock cycles from 1.5 to 239.5.
@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg
*/
void adc_set_conversion_time(u32 adc, u8 channel, u8 time)
void adc_set_sample_time(u32 adc, u8 channel, u8 time)
{
u32 reg32;
@@ -767,7 +914,7 @@ all channels.
@param[in] time Unsigned int8. Sampling time selection from @ref adc_sample_rg
*/
void adc_set_conversion_time_on_all_channels(u32 adc, u8 time)
void adc_set_sample_time_on_all_channels(u32 adc, u8 time)
{
u8 i;
u32 reg32 = 0;
@@ -871,12 +1018,24 @@ void adc_set_injected_sequence(u32 adc, u8 length, u8 channel[])
return;
for (i = 1; i <= length; i++)
reg32 |= (channel[i - 1] << ((i - 1) * 5));
reg32 |= (channel[4 - i] << ((4 - i) * 5));
reg32 |= ((length - 1) << ADC_JSQR_JL_LSB);
ADC_JSQR(adc) = reg32;
}
/*-----------------------------------------------------------------------------*/
/* Aliases */
#ifdef __GNUC__
void adc_set_continous_conversion_mode(u32 adc) __attribute__ ((alias("adc_set_continuous_conversion_mode")));
void adc_set_conversion_time(u32 adc, u8 channel, u8 time) __attribute__ ((alias ("adc_set_sample_time")));
void adc_set_conversion_time_on_all_channels(u32 adc, u8 time) __attribute__ ((alias ("adc_set_sample_time_on_all_channels")));
void adc_enable_jeoc_interrupt(u32 adc) __attribute__ ((alias ("adc_enable_eoc_interrupt_injected")));
void adc_disable_jeoc_interrupt(u32 adc) __attribute__ ((alias ("adc_disable_eoc_interrupt_injected")));
#endif
/**@}*/
+5 -5
View File
@@ -157,7 +157,7 @@ The wakeup pin is used for waking the processor from standby mode.
void pwr_enable_wakeup_pin(void)
{
PWR_CSR |= PWR_CR_EWUP;
PWR_CSR |= PWR_CSR_EWUP;
}
/*---------------------------------------------------------------------------*/
@@ -168,7 +168,7 @@ The wakeup pin is used for general purpose I/O.
void pwr_disable_wakeup_pin(void)
{
PWR_CSR &= ~PWR_CR_EWUP;
PWR_CSR &= ~PWR_CSR_EWUP;
}
/*---------------------------------------------------------------------------*/
@@ -183,7 +183,7 @@ threshold.
bool pwr_voltage_high(void)
{
return (PWR_CSR & PWR_CR_PVDO);
return (PWR_CSR & PWR_CSR_PVDO);
}
/*---------------------------------------------------------------------------*/
@@ -197,7 +197,7 @@ cleared by software (see @ref pwr_clear_standby_flag).
bool pwr_get_standby_flag(void)
{
return (PWR_CSR & PWR_CR_SBF);
return (PWR_CSR & PWR_CSR_SBF);
}
/*---------------------------------------------------------------------------*/
@@ -211,7 +211,7 @@ cleared by software (see @ref pwr_clear_wakeup_flag).
bool pwr_get_wakeup_flag(void)
{
return (PWR_CSR & PWR_CR_WUF);
return (PWR_CSR & PWR_CSR_WUF);
}
/**@}*/
+39
View File
@@ -198,6 +198,31 @@ void timer_disable_irq(u32 timer_peripheral, u32 irq)
TIM_DIER(timer_peripheral) &= ~irq;
}
/*---------------------------------------------------------------------------*/
/** @brief Return Interrupt Source.
Returns true if the specified interrupt flag (UIF, TIF or CCxIF, with BIF or COMIF
for advanced timers) was set and the interrupt was enabled. If the specified flag
is not an interrupt flag, the function returns false.
@todo Timers 6-7, 9-14 have fewer interrupts, but invalid flags are not caught here.
@param[in] timer_peripheral Unsigned int32. Timer register address base @ref tim_reg_base
@param[in] flag Unsigned int32. Status register flag @ref tim_sr_values.
@returns boolean: flag set.
*/
bool timer_interrupt_source(u32 timer_peripheral, u32 flag)
{
/* flag not set or interrupt disabled or not an interrupt source */
if (((TIM_SR(timer_peripheral) & TIM_DIER(timer_peripheral) & flag) == 0) ||
(flag > TIM_SR_BIF)) return false;
/* Only an interrupt source for advanced timers */
if ((flag == TIM_SR_BIF) || (flag == TIM_SR_COMIF))
return ((timer_peripheral == TIM1) || (timer_peripheral == TIM8));
return true;
}
/*---------------------------------------------------------------------------*/
/** @brief Read a Status Flag.
@@ -1671,6 +1696,20 @@ u32 timer_get_counter(u32 timer_peripheral)
return TIM_CNT(timer_peripheral);
}
/*---------------------------------------------------------------------------*/
/** @brief Set Counter
Set the value of a timer's counter register contents.
@param[in] timer_peripheral Unsigned int32. Timer register address base
@param[in] Unsigned int32. Counter value.
*/
void timer_set_counter(u32 timer_peripheral, u32 count)
{
TIM_CNT(timer_peripheral) = count;
}
/*---------------------------------------------------------------------------*/
/** @brief Set Input Capture Filter Parameters