Merging pull request #63 Improvements to STM32F1 I2C, CAN, RCC, and USB (f107)

Merge remote-tracking branch 'icd/master'
This commit is contained in:
Piotr Esden-Tempski
2013-01-06 17:52:43 -08:00
20 changed files with 496 additions and 42 deletions

View File

@@ -85,7 +85,8 @@ Initialize the selected CAN peripheral block.
@returns int 0 on success, 1 on initialization failure.
*/
int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
bool rflm, bool txfp, u32 sjw, u32 ts1, u32 ts2, u32 brp)
bool rflm, bool txfp, u32 sjw, u32 ts1, u32 ts2, u32 brp,
bool loopback, bool silent)
{
u32 wait_ack = 0x00000000;
u32 can_msr_inak_timeout = 0x0000FFFF;
@@ -107,6 +108,9 @@ int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
if ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK)
return 1;
/* clear can timing bits */
CAN_BTR(canport) = 0;
/* Set the automatic bus-off management. */
if (ttcm)
CAN_MCR(canport) |= CAN_MCR_TTCM;
@@ -138,8 +142,19 @@ int can_init(u32 canport, bool ttcm, bool abom, bool awum, bool nart,
else
CAN_MCR(canport) &= ~CAN_MCR_TXFP;
if (silent)
CAN_BTR(canport) |= CAN_BTR_SILM;
else
CAN_BTR(canport) &= ~CAN_BTR_SILM;
if (loopback)
CAN_BTR(canport) |= CAN_BTR_LBKM;
else
CAN_BTR(canport) &= ~CAN_BTR_LBKM;
/* Set bit timings. */
CAN_BTR(canport) = sjw | ts2 | ts1 |
CAN_BTR(canport) |= sjw | ts2 | ts1 |
(u32)(CAN_BTR_BRP_MASK & (brp - 1));
/* Request initialization "leave". */
@@ -456,3 +471,8 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
if (release)
can_fifo_release(canport, fifo);
}
bool can_available_mailbox(u32 canport)
{
return CAN_TSR(canport) & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2);
}

View File

@@ -35,3 +35,25 @@ void desig_get_unique_id(u32 result[])
result[1] = bits63_32;
result[2] = bits31_16 << 16 | bits15_0;
}
void desig_get_unique_id_as_string(char *string,
unsigned int string_len)
{
int i, len;
u8 device_id[12];
static const char chars[] = "0123456789ABCDEF";
desig_get_unique_id((u32 *)device_id);
/* Each byte produces two characters */
len = (2 * sizeof(device_id) < string_len) ?
2 * sizeof(device_id) : string_len - 1;
for (i = 0; i < len; i += 2) {
string[i] = chars[(device_id[i / 2] >> 0) & 0x0F];
string[i + 1] = chars[(device_id[i / 2] >> 4) & 0x0F];
}
string[len] = '\0';
}

View File

@@ -433,5 +433,10 @@ void dma_set_number_of_data(u32 dma, u8 channel, u16 number)
{
DMA_CNDTR(dma, channel) = number;
}
void dma_clear_flag(u32 dma, u32 flag)
{
DMA_ISR(dma) &= ~flag;
}
/**@}*/

View File

@@ -164,7 +164,7 @@ value cannot be ascertained from the hardware.
*/
void gpio_primary_remap(u8 swjdisable, u32 maps)
{
AFIO_MAPR = swjdisable | (maps & 0x1FFFFF);
AFIO_MAPR |= swjdisable | (maps & 0x1FFFFF);
}
/*-----------------------------------------------------------------------------*/
@@ -182,7 +182,7 @@ The AFIO remapping feature is used only with the STM32F10x series.
*/
void gpio_secondary_remap(u32 maps)
{
AFIO_MAPR2 = maps;
AFIO_MAPR2 |= maps;
}
/**@}*/

View File

@@ -71,6 +71,12 @@ void rcc_osc_ready_int_clear(osc_t osc)
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYC;
break;
case PLL2:
RCC_CIR |= RCC_CIR_PLL2RDYC;
break;
case PLL3:
RCC_CIR |= RCC_CIR_PLL3RDYC;
break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYC;
break;
@@ -98,6 +104,12 @@ void rcc_osc_ready_int_enable(osc_t osc)
case PLL:
RCC_CIR |= RCC_CIR_PLLRDYIE;
break;
case PLL2:
RCC_CIR |= RCC_CIR_PLL2RDYIE;
break;
case PLL3:
RCC_CIR |= RCC_CIR_PLL3RDYIE;
break;
case HSE:
RCC_CIR |= RCC_CIR_HSERDYIE;
break;
@@ -125,6 +137,12 @@ void rcc_osc_ready_int_disable(osc_t osc)
case PLL:
RCC_CIR &= ~RCC_CIR_PLLRDYIE;
break;
case PLL2:
RCC_CIR &= ~RCC_CIR_PLL2RDYIE;
break;
case PLL3:
RCC_CIR &= ~RCC_CIR_PLL3RDYIE;
break;
case HSE:
RCC_CIR &= ~RCC_CIR_HSERDYIE;
break;
@@ -153,6 +171,12 @@ int rcc_osc_ready_int_flag(osc_t osc)
case PLL:
return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
break;
case PLL2:
return ((RCC_CIR & RCC_CIR_PLL2RDYF) != 0);
break;
case PLL3:
return ((RCC_CIR & RCC_CIR_PLL3RDYF) != 0);
break;
case HSE:
return ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
break;
@@ -203,6 +227,12 @@ void rcc_wait_for_osc_ready(osc_t osc)
case PLL:
while ((RCC_CR & RCC_CR_PLLRDY) == 0);
break;
case PLL2:
while ((RCC_CR & RCC_CR_PLL2RDY) == 0);
break;
case PLL3:
while ((RCC_CR & RCC_CR_PLL3RDY) == 0);
break;
case HSE:
while ((RCC_CR & RCC_CR_HSERDY) == 0);
break;
@@ -238,6 +268,12 @@ void rcc_osc_on(osc_t osc)
case PLL:
RCC_CR |= RCC_CR_PLLON;
break;
case PLL2:
RCC_CR |= RCC_CR_PLL2ON;
break;
case PLL3:
RCC_CR |= RCC_CR_PLL3ON;
break;
case HSE:
RCC_CR |= RCC_CR_HSEON;
break;
@@ -273,6 +309,12 @@ void rcc_osc_off(osc_t osc)
case PLL:
RCC_CR &= ~RCC_CR_PLLON;
break;
case PLL2:
RCC_CR &= ~RCC_CR_PLL2ON;
break;
case PLL3:
RCC_CR &= ~RCC_CR_PLL3ON;
break;
case HSE:
RCC_CR &= ~RCC_CR_HSEON;
break;
@@ -331,6 +373,8 @@ void rcc_osc_bypass_enable(osc_t osc)
RCC_BDCR |= RCC_BDCR_LSEBYP;
break;
case PLL:
case PLL2:
case PLL3:
case HSI:
case LSI:
/* Do nothing, only HSE/LSE allowed here. */
@@ -361,6 +405,8 @@ void rcc_osc_bypass_disable(osc_t osc)
RCC_BDCR &= ~RCC_BDCR_LSEBYP;
break;
case PLL:
case PLL2:
case PLL3:
case HSI:
case LSI:
/* Do nothing, only HSE/LSE allowed here. */
@@ -484,6 +530,40 @@ void rcc_set_pll_multiplication_factor(u32 mul)
RCC_CFGR = (reg32 | (mul << 18));
}
/*-----------------------------------------------------------------------------*/
/** @brief RCC Set the PLL2 Multiplication Factor.
@note This only has effect when the PLL is disabled.
@param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf
*/
void rcc_set_pll2_multiplication_factor(u32 mul)
{
u32 reg32;
reg32 = RCC_CFGR2;
reg32 &= ~((1 << 11) | (1 << 10) | (1 << 9) | (1 << 8));
RCC_CFGR2 = (reg32 | (mul << 8));
}
/*-----------------------------------------------------------------------------*/
/** @brief RCC Set the PLL3 Multiplication Factor.
@note This only has effect when the PLL is disabled.
@param[in] mul Unsigned int32. PLL multiplication factor @ref rcc_cfgr_pmf
*/
void rcc_set_pll3_multiplication_factor(u32 mul)
{
u32 reg32;
reg32 = RCC_CFGR2;
reg32 &= ~((1 << 15) | (1 << 14) | (1 << 13) | (1 << 12));
RCC_CFGR2 = (reg32 | (mul << 12));
}
/*-----------------------------------------------------------------------------*/
/** @brief RCC Set the PLL Clock Source.
@@ -602,6 +682,36 @@ void rcc_set_usbpre(u32 usbpre)
RCC_CFGR = (reg32 | (usbpre << 22));
}
void rcc_set_prediv1(u32 prediv)
{
u32 reg32;
reg32 = RCC_CFGR2;
reg32 &= ~(1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
RCC_CFGR2 |= (reg32 | prediv);
}
void rcc_set_prediv2(u32 prediv)
{
u32 reg32;
reg32 = RCC_CFGR2;
reg32 &= ~(1 << 7) | (1 << 6) | (1 << 5) | (1 << 4);
RCC_CFGR2 |= (reg32 | (prediv << 4));
}
void rcc_set_prediv1_source(u32 rccsrc)
{
RCC_CFGR2 &= ~(1 << 16);
RCC_CFGR2 |= (rccsrc << 16);
}
void rcc_set_mco(u32 mcosrc)
{
u32 reg32;
reg32 = RCC_CFGR;
reg32 &= ~((1 << 27) | (1 << 26) | (1 << 25) | (1 << 24));
RCC_CFGR |= (reg32 | (mcosrc << 24));
}
/*-----------------------------------------------------------------------------*/
/** @brief RCC Get the System Clock Source.
@@ -1030,6 +1140,63 @@ void rcc_clock_setup_in_hse_16mhz_out_72mhz(void)
rcc_ppre2_frequency = 72000000;
}
/*-----------------------------------------------------------------------------*/
/** @brief RCC Set System Clock PLL at 72MHz from HSE at 25MHz
*/
void rcc_clock_setup_in_hse_25mhz_out_72mhz(void)
{
/* Enable external high-speed oscillator 25MHz. */
rcc_osc_on(HSE);
rcc_wait_for_osc_ready(HSE);
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
/*
* Sysclk runs with 72MHz -> 2 waitstates.
* 0WS from 0-24MHz
* 1WS from 24-48MHz
* 2WS from 48-72MHz
*/
flash_set_ws(FLASH_LATENCY_2WS);
/*
* Set prescalers for AHB, ADC, ABP1, ABP2.
* Do this before touching the PLL (TODO: why?).
*/
rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 72MHz Max. 72MHz */
rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV6); /* Set. 12MHz Max. 14MHz */
rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 36MHz Max. 36MHz */
rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 72MHz Max. 72MHz */
/* Set pll2 prediv and multiplier */
rcc_set_prediv2(RCC_CFGR2_PREDIV2_DIV5);
rcc_set_pll2_multiplication_factor(RCC_CFGR2_PLL2MUL_PLL2_CLK_MUL8);
/* Enable PLL2 oscillator and wait for it to stabilize */
rcc_osc_on(PLL2);
rcc_wait_for_osc_ready(PLL2);
/* Set pll1 prediv/multiplier, prediv1 src, and usb predivider */
rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
rcc_set_prediv1_source(RCC_CFGR2_PREDIV1SRC_PLL2_CLK);
rcc_set_prediv1(RCC_CFGR2_PREDIV_DIV5);
rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL9);
rcc_set_pll_source(RCC_CFGR_PLLSRC_PREDIV1_CLK);
rcc_set_usbpre(RCC_CFGR_USBPRE_PLL_VCO_CLK_DIV3);
/* enable PLL1 and wait for it to stabilize */
rcc_osc_on(PLL);
rcc_wait_for_osc_ready(PLL);
/* Select PLL as SYSCLK source. */
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
/* Set the peripheral clock frequencies used */
rcc_ppre1_frequency = 36000000;
rcc_ppre2_frequency = 72000000;
}
/*-----------------------------------------------------------------------------*/
/** @brief RCC Reset the backup domain

View File

@@ -67,6 +67,8 @@ void rtc_awake_from_off(osc_t clock_source)
RCC_BDCR |= (1 << 9) | (1 << 8);
break;
case PLL:
case PLL2:
case PLL3:
case HSI:
/* Unusable clock source, here to prevent warnings. */
/* Turn off clock sources to RTC. */

View File

@@ -124,6 +124,18 @@ void i2c_send_stop(u32 i2c)
I2C_CR1(i2c) |= I2C_CR1_STOP;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Clear Stop Flag.
Clear the "Send Stop" flag in the I2C config register
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_clear_stop(u32 i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_STOP;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set the 7 bit Slave Address for the Peripheral.
@@ -269,5 +281,135 @@ void i2c_send_data(u32 i2c, u8 data)
I2C_DR(i2c) = data;
}
/**@}*/
/*-----------------------------------------------------------------------------*/
/** @brief I2C Get Data.
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
uint8_t i2c_get_data(u32 i2c)
{
return I2C_DR(i2c) & 0xff;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Enable Interrupt
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] interrupt Unsigned int32. Interrupt to enable.
*/
void i2c_enable_interrupt(u32 i2c, u32 interrupt)
{
I2C_CR2(i2c) |= interrupt;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Disable Interrupt
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] interrupt Unsigned int32. Interrupt to disable.
*/
void i2c_disable_interrupt(u32 i2c, u32 interrupt)
{
I2C_CR2(i2c) &= ~interrupt;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Enable ACK
Enables acking of own 7/10 bit address
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_enable_ack(u32 i2c)
{
I2C_CR1(i2c) |= I2C_CR1_ACK;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Disable ACK
Disables acking of own 7/10 bit address
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_disable_ack(u32 i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_ACK;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C NACK Next Byte
Causes the I2C controller to NACK the reception of the next byte
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_nack_next(u32 i2c)
{
I2C_CR1(i2c) |= I2C_CR1_POS;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C NACK Next Byte
Causes the I2C controller to NACK the reception of the current byte
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_nack_current(u32 i2c)
{
I2C_CR1(i2c) &= ~I2C_CR1_POS;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set clock duty cycle
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
@param[in] dutycycle Unsigned int32. I2C duty cycle @ref i2c_duty_cycle.
*/
void i2c_set_dutycycle(u32 i2c, u32 dutycycle)
{
if (dutycycle == I2C_CCR_DUTY_DIV2)
I2C_CCR(i2c) &= ~I2C_CCR_DUTY;
else
I2C_CCR(i2c) |= I2C_CCR_DUTY;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Enable DMA
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_enable_dma(u32 i2c)
{
I2C_CR2(i2c) |= I2C_CR2_DMAEN;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Disable DMA
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_disable_dma(u32 i2c)
{
I2C_CR2(i2c) &= ~I2C_CR2_DMAEN;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Set DMA last transfer
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_set_dma_last_transfer(u32 i2c)
{
I2C_CR2(i2c) |= I2C_CR2_LAST;
}
/*-----------------------------------------------------------------------------*/
/** @brief I2C Clear DMA last transfer
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_clear_dma_last_transfer(u32 i2c)
{
I2C_CR2(i2c) &= ~I2C_CR2_LAST;
}
/**@}*/