Merge pull request #331 from bcostm/master

[NUCLEO_xxx] Update xxx_free() functions + typo
pull/334/head
Bogdan Marinescu 2014-05-27 09:57:57 +01:00
commit 1cdfe81b13
23 changed files with 527 additions and 445 deletions

View File

@ -46,7 +46,7 @@ typedef enum {
} DACName;
typedef enum {
UART_1 = (int)USART1_BASE,
UART_1 = (int)USART1_BASE,
UART_2 = (int)USART2_BASE
} UARTName;

View File

@ -57,15 +57,15 @@ static const PinMap PinMap_ADC[] = {
int adc_inited = 0;
void analogin_init(analogin_t *obj, PinName pin) {
ADC_TypeDef *adc;
ADC_InitTypeDef ADC_InitStructure;
// Get the peripheral name (ADC_1, ADC_2...) from the pin and assign it to the object
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
if (obj->adc == (ADCName)NC) {
error("ADC pin mapping failed");
error("ADC pin mapping failed");
}
// Configure GPIO
@ -80,13 +80,13 @@ void analogin_init(analogin_t *obj, PinName pin) {
// Get ADC registers structure address
adc = (ADC_TypeDef *)(obj->adc);
// Enable ADC clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// Configure ADC
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_TRGO;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
@ -102,81 +102,81 @@ void analogin_init(analogin_t *obj, PinName pin) {
}
static inline uint16_t adc_read(analogin_t *obj) {
// Get ADC registers structure address
ADC_TypeDef *adc = (ADC_TypeDef *)(obj->adc);
adc->CHSELR = 0; // Clear all channels first
// Configure ADC channel
switch (obj->pin) {
case PA_0:
ADC_ChannelConfig(adc, ADC_Channel_0, ADC_SampleTime_7_5Cycles);
break;
case PA_1:
ADC_ChannelConfig(adc, ADC_Channel_1, ADC_SampleTime_7_5Cycles);
break;
case PA_2:
ADC_ChannelConfig(adc, ADC_Channel_2, ADC_SampleTime_7_5Cycles);
break;
case PA_3:
ADC_ChannelConfig(adc, ADC_Channel_3, ADC_SampleTime_7_5Cycles);
break;
case PA_4:
ADC_ChannelConfig(adc, ADC_Channel_4, ADC_SampleTime_7_5Cycles);
break;
case PA_5:
ADC_ChannelConfig(adc, ADC_Channel_5, ADC_SampleTime_7_5Cycles);
break;
case PA_6:
ADC_ChannelConfig(adc, ADC_Channel_6, ADC_SampleTime_7_5Cycles);
break;
case PA_7:
ADC_ChannelConfig(adc, ADC_Channel_7, ADC_SampleTime_7_5Cycles);
break;
case PB_0:
ADC_ChannelConfig(adc, ADC_Channel_8, ADC_SampleTime_7_5Cycles);
break;
case PB_1:
ADC_ChannelConfig(adc, ADC_Channel_9, ADC_SampleTime_7_5Cycles);
break;
case PC_0:
ADC_ChannelConfig(adc, ADC_Channel_10, ADC_SampleTime_7_5Cycles);
break;
case PC_1:
ADC_ChannelConfig(adc, ADC_Channel_11, ADC_SampleTime_7_5Cycles);
break;
case PC_2:
ADC_ChannelConfig(adc, ADC_Channel_12, ADC_SampleTime_7_5Cycles);
break;
case PC_3:
ADC_ChannelConfig(adc, ADC_Channel_13, ADC_SampleTime_7_5Cycles);
break;
case PC_4:
ADC_ChannelConfig(adc, ADC_Channel_14, ADC_SampleTime_7_5Cycles);
break;
case PC_5:
ADC_ChannelConfig(adc, ADC_Channel_15, ADC_SampleTime_7_5Cycles);
break;
default:
return 0;
}
// Get ADC registers structure address
ADC_TypeDef *adc = (ADC_TypeDef *)(obj->adc);
while(!ADC_GetFlagStatus(adc, ADC_FLAG_ADRDY)); // Wait ADC ready
adc->CHSELR = 0; // Clear all channels first
ADC_StartOfConversion(adc); // Start conversion
while(ADC_GetFlagStatus(adc, ADC_FLAG_EOC) == RESET); // Wait end of conversion
return(ADC_GetConversionValue(adc)); // Get conversion value
// Configure ADC channel
switch (obj->pin) {
case PA_0:
ADC_ChannelConfig(adc, ADC_Channel_0, ADC_SampleTime_7_5Cycles);
break;
case PA_1:
ADC_ChannelConfig(adc, ADC_Channel_1, ADC_SampleTime_7_5Cycles);
break;
case PA_2:
ADC_ChannelConfig(adc, ADC_Channel_2, ADC_SampleTime_7_5Cycles);
break;
case PA_3:
ADC_ChannelConfig(adc, ADC_Channel_3, ADC_SampleTime_7_5Cycles);
break;
case PA_4:
ADC_ChannelConfig(adc, ADC_Channel_4, ADC_SampleTime_7_5Cycles);
break;
case PA_5:
ADC_ChannelConfig(adc, ADC_Channel_5, ADC_SampleTime_7_5Cycles);
break;
case PA_6:
ADC_ChannelConfig(adc, ADC_Channel_6, ADC_SampleTime_7_5Cycles);
break;
case PA_7:
ADC_ChannelConfig(adc, ADC_Channel_7, ADC_SampleTime_7_5Cycles);
break;
case PB_0:
ADC_ChannelConfig(adc, ADC_Channel_8, ADC_SampleTime_7_5Cycles);
break;
case PB_1:
ADC_ChannelConfig(adc, ADC_Channel_9, ADC_SampleTime_7_5Cycles);
break;
case PC_0:
ADC_ChannelConfig(adc, ADC_Channel_10, ADC_SampleTime_7_5Cycles);
break;
case PC_1:
ADC_ChannelConfig(adc, ADC_Channel_11, ADC_SampleTime_7_5Cycles);
break;
case PC_2:
ADC_ChannelConfig(adc, ADC_Channel_12, ADC_SampleTime_7_5Cycles);
break;
case PC_3:
ADC_ChannelConfig(adc, ADC_Channel_13, ADC_SampleTime_7_5Cycles);
break;
case PC_4:
ADC_ChannelConfig(adc, ADC_Channel_14, ADC_SampleTime_7_5Cycles);
break;
case PC_5:
ADC_ChannelConfig(adc, ADC_Channel_15, ADC_SampleTime_7_5Cycles);
break;
default:
return 0;
}
while (!ADC_GetFlagStatus(adc, ADC_FLAG_ADRDY)); // Wait ADC ready
ADC_StartOfConversion(adc); // Start conversion
while (ADC_GetFlagStatus(adc, ADC_FLAG_EOC) == RESET); // Wait end of conversion
return (ADC_GetConversionValue(adc)); // Get conversion value
}
uint16_t analogin_read_u16(analogin_t *obj) {
return(adc_read(obj));
return (adc_read(obj));
}
float analogin_read(analogin_t *obj) {
uint16_t value = adc_read(obj);
return (float)value * (1.0f / (float)0xFFF); // 12 bits range
uint16_t value = adc_read(obj);
return (float)value * (1.0f / (float)0xFFF); // 12 bits range
}
#endif

View File

@ -33,7 +33,7 @@
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
uint32_t gpio_set(PinName pin) {
uint32_t gpio_set(PinName pin) {
if (pin == NC) return 0;
pin_function(pin, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
@ -45,11 +45,11 @@ void gpio_init(gpio_t *obj, PinName pin) {
if (pin == NC) return;
uint32_t port_index = STM_PORT(pin);
// Enable GPIO clock
uint32_t gpio_add = Set_GPIO_Clock(port_index);
GPIO_TypeDef *gpio = (GPIO_TypeDef *)gpio_add;
// Fill GPIO object structure for future use
obj->pin = pin;
obj->mask = gpio_set(pin);
@ -65,8 +65,7 @@ void gpio_mode(gpio_t *obj, PinMode mode) {
void gpio_dir(gpio_t *obj, PinDirection direction) {
if (direction == PIN_OUTPUT) {
pin_function(obj->pin, STM_PIN_DATA(GPIO_Mode_OUT, GPIO_OType_PP, GPIO_PuPd_NOPULL, 0xFF));
}
else { // PIN_INPUT
} else { // PIN_INPUT
pin_function(obj->pin, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
}
}

View File

@ -53,26 +53,30 @@ static void handle_interrupt_in(uint32_t irq_index) {
uint32_t pin = (uint32_t)(1 << channel_pin[irq_index]);
// Clear interrupt flag
if (EXTI_GetITStatus(pin) != RESET)
{
if (EXTI_GetITStatus(pin) != RESET) {
EXTI_ClearITPendingBit(pin);
}
if (channel_ids[irq_index] == 0) return;
// Check which edge has generated the irq
if ((gpio->IDR & pin) == 0) {
irq_handler(channel_ids[irq_index], IRQ_FALL);
}
else {
} else {
irq_handler(channel_ids[irq_index], IRQ_RISE);
}
}
// The irq_index is passed to the function
static void gpio_irq0(void) {handle_interrupt_in(0);}
static void gpio_irq1(void) {handle_interrupt_in(1);}
static void gpio_irq2(void) {handle_interrupt_in(2);}
static void gpio_irq0(void) {
handle_interrupt_in(0);
}
static void gpio_irq1(void) {
handle_interrupt_in(1);
}
static void gpio_irq2(void) {
handle_interrupt_in(2);
}
extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
@ -91,18 +95,15 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
irq_n = EXTI0_1_IRQn;
vector = (uint32_t)&gpio_irq0;
irq_index = 0;
}
else if ((pin_index == 2) || (pin_index == 3)) {
} else if ((pin_index == 2) || (pin_index == 3)) {
irq_n = EXTI2_3_IRQn;
vector = (uint32_t)&gpio_irq1;
irq_index = 1;
}
else if ((pin_index > 3) && (pin_index < 16)) {
} else if ((pin_index > 3) && (pin_index < 16)) {
irq_n = EXTI4_15_IRQn;
vector = (uint32_t)&gpio_irq2;
irq_index = 2;
}
else {
} else {
error("InterruptIn error: pin not supported.\n");
return -1;
}
@ -112,25 +113,25 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
// Enable SYSCFG clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
// Connect EXTI line to pin
SYSCFG_EXTILineConfig(port_index, pin_index);
// Configure EXTI line
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = (uint32_t)(1 << pin_index);
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// Enable and set EXTI interrupt to the lowest priority
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = irq_n;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_SetVector(irq_n, vector);
NVIC_EnableIRQ(irq_n);
@ -141,9 +142,9 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
channel_ids[irq_index] = id;
channel_gpio[irq_index] = gpio_add;
channel_pin[irq_index] = pin_index;
irq_handler = handler;
irq_handler = handler;
return 0;
}
@ -154,47 +155,44 @@ void gpio_irq_free(gpio_irq_t *obj) {
// Disable EXTI line
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_StructInit(&EXTI_InitStructure);
EXTI_Init(&EXTI_InitStructure);
EXTI_Init(&EXTI_InitStructure);
obj->event = EDGE_NONE;
}
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
EXTI_InitTypeDef EXTI_InitStructure;
uint32_t pin_index = channel_pin[obj->irq_index];
EXTI_InitStructure.EXTI_Line = (uint32_t)(1 << pin_index);
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
if (event == IRQ_RISE) {
if ((obj->event == EDGE_FALL) || (obj->event == EDGE_BOTH)) {
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
obj->event = EDGE_BOTH;
}
else { // NONE or RISE
} else { // NONE or RISE
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
obj->event = EDGE_RISE;
}
}
if (event == IRQ_FALL) {
if ((obj->event == EDGE_RISE) || (obj->event == EDGE_BOTH)) {
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
obj->event = EDGE_BOTH;
}
else { // NONE or FALL
} else { // NONE or FALL
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
obj->event = EDGE_FALL;
}
}
if (enable) {
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
}
else {
} else {
EXTI_InitStructure.EXTI_LineCmd = DISABLE;
}
EXTI_Init(&EXTI_InitStructure);
}

View File

@ -50,8 +50,7 @@ typedef struct {
static inline void gpio_write(gpio_t *obj, int value) {
if (value) {
*obj->reg_set = obj->mask;
}
else {
} else {
*obj->reg_clr = obj->mask;
}
}

View File

@ -36,8 +36,8 @@
#include "error.h"
/* Timeout values for flags and events waiting loops. These timeouts are
not based on accurate values, they just guarantee that the application will
not remain stuck if the I2C communication is corrupted. */
not based on accurate values, they just guarantee that the application will
not remain stuck if the I2C communication is corrupted. */
#define FLAG_TIMEOUT ((int)0x1000)
#define LONG_TIMEOUT ((int)0x8000)
@ -55,19 +55,19 @@ static const PinMap PinMap_I2C_SCL[] = {
{NC, NC, 0}
};
void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
// Determine the I2C to use
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
obj->i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
if (obj->i2c == (I2CName)NC) {
error("I2C pin mapping failed");
}
// Enable I2C clock
if (obj->i2c == I2C_1) {
if (obj->i2c == I2C_1) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
}
@ -80,12 +80,12 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
pin_mode(scl, OpenDrain);
pinmap_pinout(sda, PinMap_I2C_SDA);
pin_mode(sda, OpenDrain);
// Reset to clear pending flags if any
i2c_reset(obj);
// I2C configuration
i2c_frequency(obj, 100000); // 100 kHz per default
i2c_frequency(obj, 100000); // 100 kHz per default
}
void i2c_frequency(i2c_t *obj, int hz) {
@ -97,7 +97,7 @@ void i2c_frequency(i2c_t *obj, int hz) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // Enable SYSCFG clock
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C1, DISABLE);
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, DISABLE);
/*
Values calculated with I2C_Timing_Configuration_V1.0.1.xls file (see AN4235)
* Standard mode (up to 100 kHz)
@ -111,30 +111,30 @@ void i2c_frequency(i2c_t *obj, int hz) {
- Fall time = 10ns
*/
switch (hz) {
case 100000:
tim = 0x10805E89; // Standard mode
break;
case 200000:
tim = 0x00905E82; // Fast Mode
break;
case 400000:
tim = 0x00901850; // Fast Mode
break;
case 1000000:
tim = 0x00700818; // Fast Mode Plus
// Enable the Fast Mode Plus capability
if (obj->i2c == I2C_1) {
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C1, ENABLE);
}
if (obj->i2c == I2C_2) {
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, ENABLE);
}
break;
default:
error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
break;
case 100000:
tim = 0x10805E89; // Standard mode
break;
case 200000:
tim = 0x00905E82; // Fast Mode
break;
case 400000:
tim = 0x00901850; // Fast Mode
break;
case 1000000:
tim = 0x00700818; // Fast Mode Plus
// Enable the Fast Mode Plus capability
if (obj->i2c == I2C_1) {
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C1, ENABLE);
}
if (obj->i2c == I2C_2) {
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, ENABLE);
}
break;
default:
error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
break;
}
// I2C configuration
I2C_DeInit(i2c);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
@ -145,7 +145,7 @@ void i2c_frequency(i2c_t *obj, int hz) {
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_Timing = tim;
I2C_Init(i2c, &I2C_InitStructure);
I2C_Cmd(i2c, ENABLE);
}
@ -169,9 +169,9 @@ inline int i2c_start(i2c_t *obj) {
inline int i2c_stop(i2c_t *obj) {
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
I2C_GenerateSTOP(i2c, ENABLE);
return 0;
}
@ -180,25 +180,25 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
int count;
int timeout;
int value;
if (length == 0) return 0;
// Configure slave address, nbytes, reload, end mode and start or stop generation
I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
// Read all bytes
for (count = 0; count < length; count++) {
value = i2c_byte_read(obj, 0);
data[count] = (char)value;
}
timeout = FLAG_TIMEOUT;
while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
while (!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
timeout--;
if (timeout == 0) return 0;
}
if(stop) i2c_stop(obj);
if (stop) i2c_stop(obj);
return length;
}
@ -207,25 +207,25 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
int timeout;
int count;
if (length == 0) return 0;
// Configure slave address, nbytes, reload, end mode and start generation
I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
// Write all bytes
for (count = 0; count < length; count++) {
i2c_byte_write(obj, data[count]);
}
}
timeout = FLAG_TIMEOUT;
while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
while (!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
timeout--;
if (timeout == 0) return 0;
}
if(stop) i2c_stop(obj);
if (stop) i2c_stop(obj);
return count;
}
@ -233,9 +233,9 @@ int i2c_byte_read(i2c_t *obj, int last) {
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
uint8_t data;
int timeout;
// Wait until the byte is received
timeout = FLAG_TIMEOUT;
timeout = FLAG_TIMEOUT;
while (I2C_GetFlagStatus(i2c, I2C_ISR_RXNE) == RESET) {
timeout--;
if (timeout == 0) {
@ -244,7 +244,7 @@ int i2c_byte_read(i2c_t *obj, int last) {
}
data = I2C_ReceiveData(i2c);
return (int)data;
}
@ -260,20 +260,20 @@ int i2c_byte_write(i2c_t *obj, int data) {
return 0;
}
}
I2C_SendData(i2c, (uint8_t)data);
return 1;
}
void i2c_reset(i2c_t *obj) {
if (obj->i2c == I2C_1) {
if (obj->i2c == I2C_1) {
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
}
if (obj->i2c == I2C_2) {
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);
}
}
@ -282,10 +282,10 @@ void i2c_reset(i2c_t *obj) {
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
uint16_t tmpreg;
// reset own address enable
i2c->OAR1 &=~ I2C_OAR1_OA1EN;
i2c->OAR1 &= ~ I2C_OAR1_OA1EN;
// Get the old register value
tmpreg = i2c->OAR1;
// Reset address bits
@ -309,16 +309,15 @@ void i2c_slave_mode(i2c_t *obj, int enable_slave) {
int i2c_slave_receive(i2c_t *obj) {
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
int event = NoData;
if(I2C_GetFlagStatus(i2c, I2C_ISR_BUSY) == SET) {
if(I2C_GetFlagStatus(i2c, I2C_ISR_ADDR) == SET) {
// Check direction
if (I2C_GetFlagStatus(i2c, I2C_ISR_BUSY) == SET) {
if (I2C_GetFlagStatus(i2c, I2C_ISR_ADDR) == SET) {
// Check direction
if (I2C_GetFlagStatus(i2c, I2C_ISR_DIR) == SET) {
event = ReadAddressed;
}
else event = WriteAddressed;
// Clear adress match flag to generate an acknowledge
i2c->ICR |= I2C_ICR_ADDRCF;
event = ReadAddressed;
} else event = WriteAddressed;
// Clear adress match flag to generate an acknowledge
i2c->ICR |= I2C_ICR_ADDRCF;
}
}
return event;
@ -326,23 +325,23 @@ int i2c_slave_receive(i2c_t *obj) {
int i2c_slave_read(i2c_t *obj, char *data, int length) {
int count = 0;
// Read all bytes
for (count = 0; count < length; count++) {
data[count] = i2c_byte_read(obj, 0);
}
return count;
}
int i2c_slave_write(i2c_t *obj, const char *data, int length) {
int count = 0;
// Write all bytes
for (count = 0; count < length; count++) {
i2c_byte_write(obj, data[count]);
}
return count;
}

View File

@ -48,7 +48,7 @@ struct gpio_irq_s {
struct port_s {
PortName port;
uint32_t mask;
PinDirection direction;
PinDirection direction;
__IO uint16_t *reg_in;
__IO uint16_t *reg_out;
};
@ -58,18 +58,15 @@ struct analogin_s {
PinName pin;
};
struct dac_s {
DACName dac;
PinName channel;
};
struct serial_s {
UARTName uart;
int index; // Used by irq
uint32_t baudrate;
uint32_t databits;
uint32_t stopbits;
uint32_t parity;
uint32_t parity;
PinName pin_tx;
PinName pin_rx;
};
struct spi_s {
@ -80,6 +77,10 @@ struct spi_s {
uint32_t mode;
uint32_t nss;
uint32_t br_presc;
PinName pin_miso;
PinName pin_mosi;
PinName pin_sclk;
PinName pin_ssel;
};
struct i2c_s {

View File

@ -86,7 +86,7 @@ void pin_function(PinName pin, int data) {
if (afnum != 0xFF) {
GPIO_PinAFConfig(gpio, (uint16_t)pin_index, afnum);
}
// Configure GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = (uint16_t)(1 << pin_index);
@ -95,7 +95,7 @@ void pin_function(PinName pin, int data) {
GPIO_InitStructure.GPIO_OType = (GPIOOType_TypeDef)otype;
GPIO_InitStructure.GPIO_PuPd = (GPIOPuPd_TypeDef)pupd;
GPIO_Init(gpio, &GPIO_InitStructure);
// *** TODO ***
// Disconnect JTAG-DP + SW-DP signals.
// Warning: Need to reconnect under reset
@ -104,7 +104,7 @@ void pin_function(PinName pin, int data) {
//}
//if ((pin == PA_15) || (pin == PB_3) || (pin == PB_4)) {
//
//}
//}
}
/**
@ -125,5 +125,5 @@ void pin_mode(PinName pin, PinMode mode) {
if (pupd > 2) pupd = 0; // Open-drain = No pull-up/No pull-down
gpio->PUPDR &= (uint32_t)(~(GPIO_PUPDR_PUPDR0 << (pin_index * 2)));
gpio->PUPDR |= (uint32_t)(pupd << (pin_index * 2));
}

View File

@ -40,7 +40,7 @@ extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
// high nibble = port number (0=A, 1=B, 2=C, 3=D, 4=E, 5=F, ...)
// low nibble = pin number
PinName port_pin(PortName port, int pin_n) {
return (PinName)(pin_n + (port << 4));
return (PinName)(pin_n + (port << 4));
}
void port_init(port_t *obj, PortName port, int mask, PinDirection dir) {
@ -53,9 +53,9 @@ void port_init(port_t *obj, PortName port, int mask, PinDirection dir) {
// Fill PORT object structure for future use
obj->port = port;
obj->mask = mask;
obj->direction = dir;
obj->direction = dir;
obj->reg_in = &gpio->IDR;
obj->reg_out = &gpio->ODR;
obj->reg_out = &gpio->ODR;
port_dir(obj, dir);
}
@ -67,16 +67,15 @@ void port_dir(port_t *obj, PinDirection dir) {
if (obj->mask & (1 << i)) { // If the pin is used
if (dir == PIN_OUTPUT) {
pin_function(port_pin(obj->port, i), STM_PIN_DATA(GPIO_Mode_OUT, GPIO_OType_PP, GPIO_PuPd_NOPULL, 0xFF));
}
else { // PIN_INPUT
} else { // PIN_INPUT
pin_function(port_pin(obj->port, i), STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
}
}
}
}
}
void port_mode(port_t *obj, PinMode mode) {
uint32_t i;
uint32_t i;
for (i = 0; i < 16; i++) { // Process all pins
if (obj->mask & (1 << i)) { // If the pin is used
pin_mode(port_pin(obj->port, i), mode);
@ -91,8 +90,7 @@ void port_write(port_t *obj, int value) {
int port_read(port_t *obj) {
if (obj->direction == PIN_OUTPUT) {
return (*obj->reg_out & obj->mask);
}
else { // PIN_INPUT
} else { // PIN_INPUT
return (*obj->reg_in & obj->mask);
}
}

View File

@ -62,14 +62,14 @@ static const PinMap PinMap_PWM[] = {
{NC, NC, 0}
};
void pwmout_init(pwmout_t* obj, PinName pin) {
void pwmout_init(pwmout_t* obj, PinName pin) {
// Get the peripheral name from the pin and assign it to the object
obj->pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
if (obj->pwm == (PWMName)NC) {
error("PWM pinout mapping failed");
}
// Enable TIM clock
if (obj->pwm == TIM_3) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
if (obj->pwm == TIM_14) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
@ -79,32 +79,31 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
// Configure GPIO
pinmap_pinout(pin, PinMap_PWM);
//pin_mode(pin, PullUp);
obj->pin = pin;
obj->period = 0;
obj->pulse = 0;
pwmout_period_us(obj, 20000); // 20 ms per default
}
void pwmout_free(pwmout_t* obj) {
TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm);
TIM_DeInit(tim);
// Configure GPIOs
pin_function(obj->pin, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
}
void pwmout_write(pwmout_t* obj, float value) {
TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm);
TIM_OCInitTypeDef TIM_OCInitStructure;
if (value < 0.0) {
value = 0.0;
} else if (value > 1.0) {
value = 1.0;
}
obj->pulse = (uint32_t)((float)obj->period * value);
// Configure channels
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_Pulse = obj->pulse;
@ -141,7 +140,7 @@ void pwmout_write(pwmout_t* obj, float value) {
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OC2PreloadConfig(tim, TIM_OCPreload_Enable);
TIM_OC2Init(tim, &TIM_OCInitStructure);
break;
break;
// Channels 3
case PB_0:
case PC_8:
@ -149,7 +148,7 @@ void pwmout_write(pwmout_t* obj, float value) {
TIM_OC3PreloadConfig(tim, TIM_OCPreload_Enable);
TIM_OC3Init(tim, &TIM_OCInitStructure);
break;
// Channels 4
// Channels 4
// case PB_1:
case PC_9:
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
@ -157,11 +156,11 @@ void pwmout_write(pwmout_t* obj, float value) {
TIM_OC4Init(tim, &TIM_OCInitStructure);
break;
default:
return;
}
TIM_CtrlPWMOutputs(tim, ENABLE);
return;
}
TIM_CtrlPWMOutputs(tim, ENABLE);
}
float pwmout_read(pwmout_t* obj) {
@ -185,10 +184,10 @@ void pwmout_period_us(pwmout_t* obj, int us) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
float dc = pwmout_read(obj);
TIM_Cmd(tim, DISABLE);
TIM_Cmd(tim, DISABLE);
obj->period = us;
TIM_TimeBaseStructure.TIM_Period = obj->period - 1;
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
@ -197,7 +196,7 @@ void pwmout_period_us(pwmout_t* obj, int us) {
// Set duty cycle again
pwmout_write(obj, dc);
TIM_ARRPreloadConfig(tim, ENABLE);
TIM_Cmd(tim, ENABLE);

View File

@ -49,7 +49,7 @@ void rtc_init(void) {
// Reset back up registers
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);
// Enable LSE clock
RCC_LSEConfig(RCC_LSE_ON);
@ -58,40 +58,48 @@ void rtc_init(void) {
LSEStatus = RCC_GetFlagStatus(RCC_FLAG_LSERDY);
wait_ms(1);
StartUpCounter++;
} while((LSEStatus == 0) && (StartUpCounter <= LSE_STARTUP_TIMEOUT));
} while ((LSEStatus == 0) && (StartUpCounter <= LSE_STARTUP_TIMEOUT));
if (StartUpCounter > LSE_STARTUP_TIMEOUT) {
// The LSE has not started, use LSI instead.
// The RTC Clock may vary due to LSI frequency dispersion.
RCC_LSEConfig(RCC_LSE_OFF);
// The RTC Clock may vary due to LSI frequency dispersion.
RCC_LSEConfig(RCC_LSE_OFF);
RCC_LSICmd(ENABLE); // Enable LSI
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {} // Wait until ready
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); // Select the RTC Clock Source
rtc_freq = 40000; // [TODO] To be measured precisely using a timer input capture
}
else {
rtc_freq = 40000; // [TODO] To be measured precisely using a timer input capture
} else {
// The LSE has correctly started
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // Select the RTC Clock Source
rtc_freq = LSE_VALUE;
}
RCC_RTCCLKCmd(ENABLE); // Enable RTC Clock
RCC_RTCCLKCmd(ENABLE); // Enable RTC Clock
RTC_WaitForSynchro(); // Wait for RTC registers synchronization
RTC_InitTypeDef RTC_InitStructure;
RTC_InitStructure.RTC_AsynchPrediv = 127;
RTC_InitStructure.RTC_SynchPrediv = (rtc_freq / 128) - 1;
RTC_InitStructure.RTC_SynchPrediv = (rtc_freq / 128) - 1;
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
PWR_BackupAccessCmd(DISABLE); // Disable access to Backup domain
rtc_inited = 1;
}
void rtc_free(void) {
RCC_DeInit(); // Resets the RCC clock configuration to the default reset state
// Reset RTC
PWR_BackupAccessCmd(ENABLE); // Enable access to Backup Domain
RTC_DeInit();
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);
// Disable RTC, LSE and LSI clocks
RCC_RTCCLKCmd(DISABLE);
RCC_LSEConfig(RCC_LSE_OFF);
RCC_LSICmd(DISABLE);
rtc_inited = 0;
}
@ -120,11 +128,11 @@ time_t rtc_read(void) {
RTC_DateTypeDef dateStruct;
RTC_TimeTypeDef timeStruct;
struct tm timeinfo;
// Read actual date and time
RTC_GetTime(RTC_Format_BIN, &timeStruct);
RTC_GetDate(RTC_Format_BIN, &dateStruct);
// Setup a tm structure based on the RTC
timeinfo.tm_wday = dateStruct.RTC_WeekDay;
timeinfo.tm_mon = dateStruct.RTC_Month - 1;
@ -133,11 +141,11 @@ time_t rtc_read(void) {
timeinfo.tm_hour = timeStruct.RTC_Hours;
timeinfo.tm_min = timeStruct.RTC_Minutes;
timeinfo.tm_sec = timeStruct.RTC_Seconds;
// Convert to timestamp
time_t t = mktime(&timeinfo);
return t;
return t;
}
void rtc_write(time_t t) {
@ -146,7 +154,7 @@ void rtc_write(time_t t) {
// Convert the time into a tm
struct tm *timeinfo = localtime(&t);
// Fill RTC structures
dateStruct.RTC_WeekDay = timeinfo->tm_wday;
dateStruct.RTC_Month = timeinfo->tm_mon + 1;
@ -156,11 +164,11 @@ void rtc_write(time_t t) {
timeStruct.RTC_Minutes = timeinfo->tm_min;
timeStruct.RTC_Seconds = timeinfo->tm_sec;
timeStruct.RTC_H12 = RTC_HourFormat_24;
// Change the RTC current date/time
PWR_BackupAccessCmd(ENABLE); // Enable access to RTC
PWR_BackupAccessCmd(ENABLE); // Enable access to RTC
RTC_SetDate(RTC_Format_BIN, &dateStruct);
RTC_SetTime(RTC_Format_BIN, &timeStruct);
RTC_SetTime(RTC_Format_BIN, &timeStruct);
PWR_BackupAccessCmd(DISABLE); // Disable access to RTC
}

View File

@ -44,7 +44,7 @@ static const PinMap PinMap_UART_TX[] = {
};
static const PinMap PinMap_UART_RX[] = {
{PA_3, UART_2, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},
{PA_3, UART_2, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},
{PA_10, UART_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},
{PA_15, UART_2, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_1)},
{PB_7, UART_1, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_0)},
@ -63,7 +63,7 @@ serial_t stdio_uart;
static void init_usart(serial_t *obj) {
USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
USART_InitTypeDef USART_InitStructure;
USART_Cmd(usart, DISABLE);
USART_InitStructure.USART_BaudRate = obj->baudrate;
@ -73,15 +73,15 @@ static void init_usart(serial_t *obj) {
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(usart, &USART_InitStructure);
USART_Cmd(usart, ENABLE);
}
void serial_init(serial_t *obj, PinName tx, PinName rx) {
void serial_init(serial_t *obj, PinName tx, PinName rx) {
// Determine the UART to use (UART_1, UART_2, ...)
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
// Get the peripheral name (UART_1, UART_2, ...) from the pin and assign it to the object
obj->uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
@ -91,12 +91,14 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
// Enable USART clock
if (obj->uart == UART_1) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
obj->index = 0;
}
if (obj->uart == UART_2) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
obj->index = 1;
}
// Configure the UART pins
pinmap_pinout(tx, PinMap_UART_TX);
pinmap_pinout(rx, PinMap_UART_RX);
@ -107,23 +109,38 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
obj->baudrate = 9600;
obj->databits = USART_WordLength_8b;
obj->stopbits = USART_StopBits_1;
obj->parity = USART_Parity_No;
obj->parity = USART_Parity_No;
obj->pin_tx = tx;
obj->pin_rx = rx;
init_usart(obj);
// The index is used by irq
if (obj->uart == UART_1) obj->index = 0;
if (obj->uart == UART_2) obj->index = 1;
// For stdio management
if (obj->uart == STDIO_UART) {
stdio_uart_inited = 1;
memcpy(&stdio_uart, obj, sizeof(serial_t));
}
}
void serial_free(serial_t *obj) {
// Reset UART and disable clock
if (obj->uart == UART_1) {
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, DISABLE);
}
if (obj->uart == UART_2) {
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
}
// Configure GPIOs
pin_function(obj->pin_tx, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
pin_function(obj->pin_rx, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
serial_irq_ids[obj->index] = 0;
}
@ -135,29 +152,27 @@ void serial_baud(serial_t *obj, int baudrate) {
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
if (data_bits == 8) {
obj->databits = USART_WordLength_8b;
}
else {
} else {
obj->databits = USART_WordLength_9b;
}
switch (parity) {
case ParityOdd:
case ParityForced0:
obj->parity = USART_Parity_Odd;
break;
case ParityEven:
case ParityForced1:
obj->parity = USART_Parity_Even;
break;
default: // ParityNone
obj->parity = USART_Parity_No;
break;
case ParityOdd:
case ParityForced0:
obj->parity = USART_Parity_Odd;
break;
case ParityEven:
case ParityForced1:
obj->parity = USART_Parity_Even;
break;
default: // ParityNone
obj->parity = USART_Parity_No;
break;
}
if (stop_bits == 2) {
obj->stopbits = USART_StopBits_2;
}
else {
} else {
obj->stopbits = USART_StopBits_1;
}
@ -182,8 +197,12 @@ static void uart_irq(USART_TypeDef* usart, int id) {
}
}
static void uart1_irq(void) {uart_irq((USART_TypeDef*)UART_1, 0);}
static void uart2_irq(void) {uart_irq((USART_TypeDef*)UART_2, 1);}
static void uart1_irq(void) {
uart_irq((USART_TypeDef*)UART_1, 0);
}
static void uart2_irq(void) {
uart_irq((USART_TypeDef*)UART_2, 1);
}
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
irq_handler = handler;
@ -196,45 +215,43 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
USART_TypeDef *usart = (USART_TypeDef *)(obj->uart);
if (obj->uart == UART_1) {
irq_n = USART1_IRQn;
vector = (uint32_t)&uart1_irq;
irq_n = USART1_IRQn;
vector = (uint32_t)&uart1_irq;
}
if (obj->uart == UART_2) {
irq_n = USART2_IRQn;
vector = (uint32_t)&uart2_irq;
irq_n = USART2_IRQn;
vector = (uint32_t)&uart2_irq;
}
if (enable) {
if (irq == RxIrq) {
USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
}
else { // TxIrq
} else { // TxIrq
USART_ITConfig(usart, USART_IT_TC, ENABLE);
}
}
NVIC_SetVector(irq_n, vector);
NVIC_EnableIRQ(irq_n);
} else { // disable
int all_disabled = 0;
if (irq == RxIrq) {
USART_ITConfig(usart, USART_IT_RXNE, DISABLE);
// Check if TxIrq is disabled too
if ((usart->CR1 & USART_CR1_TXEIE) == 0) all_disabled = 1;
}
else { // TxIrq
} else { // TxIrq
USART_ITConfig(usart, USART_IT_TXE, DISABLE);
// Check if RxIrq is disabled too
if ((usart->CR1 & USART_CR1_RXNEIE) == 0) all_disabled = 1;
if ((usart->CR1 & USART_CR1_RXNEIE) == 0) all_disabled = 1;
}
if (all_disabled) NVIC_DisableIRQ(irq_n);
}
}
}
/******************************************************************************

View File

@ -33,28 +33,26 @@
#include "cmsis.h"
void sleep(void)
{
void sleep(void) {
// Disable us_ticker update interrupt
TIM_ITConfig(TIM1, TIM_IT_Update, DISABLE);
SCB->SCR = 0; // Normal sleep mode for ARM core
__WFI();
// Re-enable us_ticker update interrupt
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
}
// MCU STOP mode
// Wake-up with external interrupt
void deepsleep(void)
{
void deepsleep(void) {
// Enable PWR clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
// Request to enter STOP mode with regulator in low power mode
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
// After wake-up from STOP reconfigure the PLL
SetSysClock();
}

View File

@ -72,11 +72,11 @@ static void init_spi(spi_t *obj) {
SPI_Cmd(spi, DISABLE);
SPI_InitStructure.SPI_Mode = obj->mode;
SPI_InitStructure.SPI_NSS = obj->nss;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_NSS = obj->nss;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = obj->bits;
SPI_InitStructure.SPI_CPOL = obj->cpol;
SPI_InitStructure.SPI_CPHA = obj->cpha;
SPI_InitStructure.SPI_CPHA = obj->cpha;
SPI_InitStructure.SPI_BaudRatePrescaler = obj->br_presc;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
@ -93,40 +93,44 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
obj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl);
if (obj->spi == (SPIName)NC) {
error("SPI pinout mapping failed");
}
// Enable SPI clock
if (obj->spi == SPI_1) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
}
if (obj->spi == SPI_2) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
}
// Configure the SPI pins
pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO);
pinmap_pinout(sclk, PinMap_SPI_SCLK);
// Save new values
obj->bits = SPI_DataSize_8b;
obj->cpol = SPI_CPOL_Low;
obj->cpha = SPI_CPHA_1Edge;
obj->br_presc = SPI_BaudRatePrescaler_8; // 1 MHz
obj->pin_miso = miso;
obj->pin_mosi = mosi;
obj->pin_sclk = sclk;
obj->pin_ssel = ssel;
if (ssel == NC) { // Master
obj->mode = SPI_Mode_Master;
obj->nss = SPI_NSS_Soft;
}
else { // Slave
} else { // Slave
pinmap_pinout(ssel, PinMap_SPI_SSEL);
obj->mode = SPI_Mode_Slave;
obj->nss = SPI_NSS_Hard;
@ -136,47 +140,61 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
}
void spi_free(spi_t *obj) {
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
SPI_I2S_DeInit(spi);
// Reset SPI and disable clock
if (obj->spi == SPI_1) {
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, DISABLE);
}
if (obj->spi == SPI_2) {
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, DISABLE);
}
// Configure GPIOs
pin_function(obj->pin_miso, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
pin_function(obj->pin_mosi, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
pin_function(obj->pin_sclk, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
pin_function(obj->pin_ssel, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
}
void spi_format(spi_t *obj, int bits, int mode, int slave) {
void spi_format(spi_t *obj, int bits, int mode, int slave) {
// Save new values
if (bits == 8) {
obj->bits = SPI_DataSize_8b;
}
else {
} else {
obj->bits = SPI_DataSize_16b;
}
switch (mode) {
case 0:
obj->cpol = SPI_CPOL_Low;
obj->cpha = SPI_CPHA_1Edge;
break;
obj->cpol = SPI_CPOL_Low;
obj->cpha = SPI_CPHA_1Edge;
break;
case 1:
obj->cpol = SPI_CPOL_Low;
obj->cpha = SPI_CPHA_2Edge;
break;
obj->cpol = SPI_CPOL_Low;
obj->cpha = SPI_CPHA_2Edge;
break;
case 2:
obj->cpol = SPI_CPOL_High;
obj->cpha = SPI_CPHA_1Edge;
break;
obj->cpol = SPI_CPOL_High;
obj->cpha = SPI_CPHA_1Edge;
break;
default:
obj->cpol = SPI_CPOL_High;
obj->cpha = SPI_CPHA_2Edge;
break;
obj->cpol = SPI_CPOL_High;
obj->cpha = SPI_CPHA_2Edge;
break;
}
if (slave == 0) {
obj->mode = SPI_Mode_Master;
obj->nss = SPI_NSS_Soft;
}
else {
} else {
obj->mode = SPI_Mode_Slave;
obj->nss = SPI_NSS_Hard;
obj->nss = SPI_NSS_Hard;
}
init_spi(obj);
}
@ -184,26 +202,19 @@ void spi_frequency(spi_t *obj, int hz) {
// Note: The frequencies are obtained with SPI clock = 48 MHz (APB1 & APB2 clocks)
if (hz < 300000) {
obj->br_presc = SPI_BaudRatePrescaler_256; // 188 kHz
}
else if ((hz >= 300000) && (hz < 700000)) {
} else if ((hz >= 300000) && (hz < 700000)) {
obj->br_presc = SPI_BaudRatePrescaler_128; // 375 kHz
}
else if ((hz >= 700000) && (hz < 1000000)) {
} else if ((hz >= 700000) && (hz < 1000000)) {
obj->br_presc = SPI_BaudRatePrescaler_64; // 750 kHz
}
else if ((hz >= 1000000) && (hz < 3000000)) {
} else if ((hz >= 1000000) && (hz < 3000000)) {
obj->br_presc = SPI_BaudRatePrescaler_32; // 1.5 MHz
}
else if ((hz >= 3000000) && (hz < 6000000)) {
} else if ((hz >= 3000000) && (hz < 6000000)) {
obj->br_presc = SPI_BaudRatePrescaler_16; // 3 MHz
}
else if ((hz >= 6000000) && (hz < 12000000)) {
} else if ((hz >= 6000000) && (hz < 12000000)) {
obj->br_presc = SPI_BaudRatePrescaler_8; // 6 MHz
}
else if ((hz >= 12000000) && (hz < 24000000)) {
} else if ((hz >= 12000000) && (hz < 24000000)) {
obj->br_presc = SPI_BaudRatePrescaler_4; // 12 MHz
}
else { // >= 24000000
} else { // >= 24000000
obj->br_presc = SPI_BaudRatePrescaler_2; // 24 MHz
}
init_spi(obj);
@ -214,7 +225,7 @@ static inline int ssp_readable(spi_t *obj) {
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
// Check if data is received
status = ((SPI_I2S_GetFlagStatus(spi, SPI_I2S_FLAG_RXNE) != RESET) ? 1 : 0);
return status;
return status;
}
static inline int ssp_writeable(spi_t *obj) {
@ -226,23 +237,21 @@ static inline int ssp_writeable(spi_t *obj) {
}
static inline void ssp_write(spi_t *obj, int value) {
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
while (!ssp_writeable(obj));
if (obj->bits == SPI_DataSize_8b) {
SPI_SendData8(spi, (uint8_t)value);
}
else { // 16-bit
} else { // 16-bit
SPI_I2S_SendData16(spi, (uint16_t)value);
}
}
static inline int ssp_read(spi_t *obj) {
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
while (!ssp_readable(obj));
if (obj->bits == SPI_DataSize_8b) {
return (int)SPI_ReceiveData8(spi);
}
else { // 16-bit
} else { // 16-bit
return (int)SPI_I2S_ReceiveData16(spi);
}
}
@ -267,19 +276,17 @@ int spi_slave_read(spi_t *obj) {
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
if (obj->bits == SPI_DataSize_8b) {
return (int)SPI_ReceiveData8(spi);
}
else { // 16-bit
} else { // 16-bit
return (int)SPI_I2S_ReceiveData16(spi);
}
}
void spi_slave_write(spi_t *obj, int value) {
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
while (!ssp_writeable(obj));
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
while (!ssp_writeable(obj));
if (obj->bits == SPI_DataSize_8b) {
SPI_SendData8(spi, (uint8_t)value);
}
else { // 16-bit
} else { // 16-bit
SPI_I2S_SendData16(spi, (uint16_t)value);
}
}

View File

@ -58,7 +58,7 @@ static void tim_update_irq_handler(void) {
// Used by interrupt system
static void tim_oc_irq_handler(void) {
uint16_t cval = TIM_MST->CNT;
// Clear interrupt flag
if (TIM_GetITStatus(TIM_MST, TIM_IT_CC1) == SET) {
TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1);
@ -67,14 +67,12 @@ static void tim_oc_irq_handler(void) {
if (oc_rem_part > 0) {
set_compare(oc_rem_part); // Finish the remaining time left
oc_rem_part = 0;
}
else {
} else {
if (oc_int_part > 0) {
set_compare(0xFFFF);
oc_rem_part = cval; // To finish the counter loop the next time
oc_int_part--;
}
else {
} else {
us_ticker_irq_handler();
}
}
@ -82,13 +80,13 @@ static void tim_oc_irq_handler(void) {
void us_ticker_init(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
if (us_ticker_inited) return;
us_ticker_inited = 1;
// Enable Timer clock
TIM_MST_RCC;
// Configure time base
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
@ -96,18 +94,18 @@ void us_ticker_init(void) {
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM_MST, &TIM_TimeBaseStructure);
// Configure interrupts
TIM_ITConfig(TIM_MST, TIM_IT_Update, ENABLE);
// Update interrupt used for 32-bit counter
NVIC_SetVector(TIM_MST_UP_IRQ, (uint32_t)tim_update_irq_handler);
NVIC_EnableIRQ(TIM_MST_UP_IRQ);
// Output compare interrupt used for timeout feature
NVIC_SetVector(TIM_MST_OC_IRQ, (uint32_t)tim_oc_irq_handler);
NVIC_EnableIRQ(TIM_MST_OC_IRQ);
// Enable timer
TIM_Cmd(TIM_MST, ENABLE);
}
@ -139,8 +137,7 @@ void us_ticker_set_interrupt(unsigned int timestamp) {
if (delta <= 0) { // This event was in the past
us_ticker_irq_handler();
}
else {
} else {
oc_int_part = (uint32_t)(delta >> 16);
oc_rem_part = (uint16_t)(delta & 0xFFFF);
if (oc_rem_part <= (0xFFFF - cval)) {

View File

@ -57,7 +57,7 @@ void analogout_init(dac_t *obj, PinName pin) {
pinmap_pinout(pin, PinMap_DAC);
// Save the channel for future use
obj->channel = pin;
obj->pin = pin;
// Enable DAC clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
@ -76,7 +76,7 @@ void analogout_free(dac_t *obj) {
DAC_DeInit(dac);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, DISABLE);
// Configure GPIO
pin_function(obj->channel, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
pin_function(obj->pin, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
}
static inline void dac_write(dac_t *obj, uint16_t value) {

View File

@ -124,13 +124,13 @@ void i2c_frequency(i2c_t *obj, int hz) {
switch (hz) {
case 100000:
tim = 0x60302730; // Standard mode
break;
break;
case 200000:
tim = 0x00C07AB3; // Fast Mode
break;
break;
case 400000:
tim = 0x00C0216C; // Fast Mode
break;
break;
case 1000000:
tim = 0x00900B22; // Fast Mode Plus
// Enable the Fast Mode Plus capability
@ -140,13 +140,12 @@ void i2c_frequency(i2c_t *obj, int hz) {
if (obj->i2c == I2C_2) {
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, ENABLE);
}
break;
break;
default:
error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
break;
break;
}
}
else if (SystemCoreClock == 72000000) {
} else if (SystemCoreClock == 72000000) {
switch (hz) {
case 100000:
tim = 0x10C08DCF; // Standard mode
@ -171,8 +170,7 @@ void i2c_frequency(i2c_t *obj, int hz) {
error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
break;
}
}
else {
} else {
error("System clock setting is not supported.");
}
@ -235,12 +233,12 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
}
timeout = FLAG_TIMEOUT;
while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
while (!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
timeout--;
if (timeout == 0) return 0;
}
if(stop) i2c_stop(obj);
if (stop) i2c_stop(obj);
return length;
}
@ -262,12 +260,12 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
}
timeout = FLAG_TIMEOUT;
while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
while (!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
timeout--;
if (timeout == 0) return 0;
}
if(stop) i2c_stop(obj);
if (stop) i2c_stop(obj);
return count;
}
@ -331,8 +329,8 @@ void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
uint16_t tmpreg;
// reset own address enable
i2c->OAR1 &=~ I2C_OAR1_OA1EN;
i2c->OAR1 &= ~ I2C_OAR1_OA1EN;
// Get the old register value
tmpreg = i2c->OAR1;
// Reset address bits
@ -356,16 +354,15 @@ void i2c_slave_mode(i2c_t *obj, int enable_slave) {
int i2c_slave_receive(i2c_t *obj) {
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
int event = NoData;
if(I2C_GetFlagStatus(i2c, I2C_ISR_BUSY) == SET) {
if(I2C_GetFlagStatus(i2c, I2C_ISR_ADDR) == SET) {
// Check direction
if (I2C_GetFlagStatus(i2c, I2C_ISR_BUSY) == SET) {
if (I2C_GetFlagStatus(i2c, I2C_ISR_ADDR) == SET) {
// Check direction
if (I2C_GetFlagStatus(i2c, I2C_ISR_DIR) == SET) {
event = ReadAddressed;
}
else event = WriteAddressed;
// Clear adress match flag to generate an acknowledge
i2c->ICR |= I2C_ICR_ADDRCF;
} else event = WriteAddressed;
// Clear adress match flag to generate an acknowledge
i2c->ICR |= I2C_ICR_ADDRCF;
}
}
return event;

View File

@ -60,7 +60,7 @@ struct analogin_s {
struct dac_s {
DACName dac;
PinName channel;
PinName pin;
};
struct serial_s {
@ -70,6 +70,8 @@ struct serial_s {
uint32_t databits;
uint32_t stopbits;
uint32_t parity;
PinName pin_tx;
PinName pin_rx;
};
struct spi_s {
@ -80,10 +82,14 @@ struct spi_s {
uint32_t mode;
uint32_t nss;
uint32_t br_presc;
PinName pin_miso;
PinName pin_mosi;
PinName pin_sclk;
PinName pin_ssel;
};
struct i2c_s {
I2CName i2c;
I2CName i2c;
};
struct pwmout_s {

View File

@ -112,8 +112,8 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
}
void pwmout_free(pwmout_t* obj) {
TIM_TypeDef *tim = (TIM_TypeDef *)(obj->pwm);
TIM_DeInit(tim);
// Configure GPIO
pin_function(obj->pin, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
}
void pwmout_write(pwmout_t* obj, float value) {

View File

@ -49,7 +49,7 @@ void rtc_init(void) {
// Reset back up registers
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);
// Enable LSE clock
RCC_LSEConfig(RCC_LSE_ON);
@ -58,40 +58,48 @@ void rtc_init(void) {
LSEStatus = RCC_GetFlagStatus(RCC_FLAG_LSERDY);
wait_ms(1);
StartUpCounter++;
} while((LSEStatus == 0) && (StartUpCounter <= LSE_STARTUP_TIMEOUT));
} while ((LSEStatus == 0) && (StartUpCounter <= LSE_STARTUP_TIMEOUT));
if (StartUpCounter > LSE_STARTUP_TIMEOUT) {
// The LSE has not started, use LSI instead.
// The RTC Clock may vary due to LSI frequency dispersion.
RCC_LSEConfig(RCC_LSE_OFF);
// The RTC Clock may vary due to LSI frequency dispersion.
RCC_LSEConfig(RCC_LSE_OFF);
RCC_LSICmd(ENABLE); // Enable LSI
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {} // Wait until ready
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); // Select the RTC Clock Source
rtc_freq = 40000; // [TODO] To be measured precisely using a timer input capture
}
else {
rtc_freq = 40000; // [TODO] To be measured precisely using a timer input capture
} else {
// The LSE has correctly started
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // Select the RTC Clock Source
rtc_freq = LSE_VALUE;
}
RCC_RTCCLKCmd(ENABLE); // Enable RTC Clock
RCC_RTCCLKCmd(ENABLE); // Enable RTC Clock
RTC_WaitForSynchro(); // Wait for RTC registers synchronization
RTC_InitTypeDef RTC_InitStructure;
RTC_InitStructure.RTC_AsynchPrediv = 127;
RTC_InitStructure.RTC_SynchPrediv = (rtc_freq / 128) - 1;
RTC_InitStructure.RTC_SynchPrediv = (rtc_freq / 128) - 1;
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
PWR_BackupAccessCmd(DISABLE); // Disable access to Backup domain
rtc_inited = 1;
}
void rtc_free(void) {
RCC_DeInit(); // Resets the RCC clock configuration to the default reset state
// Reset RTC
PWR_BackupAccessCmd(ENABLE); // Enable access to Backup Domain
RTC_DeInit();
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);
// Disable RTC, LSE and LSI clocks
RCC_RTCCLKCmd(DISABLE);
RCC_LSEConfig(RCC_LSE_OFF);
RCC_LSICmd(DISABLE);
rtc_inited = 0;
}

View File

@ -103,12 +103,15 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
// Enable USART clock
if (obj->uart == UART_1) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
obj->index = 0;
}
if (obj->uart == UART_2) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
obj->index = 1;
}
if (obj->uart == UART_3) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
obj->index = 2;
}
// Configure the UART pins
@ -123,12 +126,10 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
obj->stopbits = USART_StopBits_1;
obj->parity = USART_Parity_No;
init_usart(obj);
obj->pin_tx = tx;
obj->pin_rx = rx;
// The index is used by irq
if (obj->uart == UART_1) obj->index = 0;
if (obj->uart == UART_2) obj->index = 1;
if (obj->uart == UART_3) obj->index = 2;
init_usart(obj);
// For stdio management
if (obj->uart == STDIO_UART) {
@ -139,6 +140,27 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
}
void serial_free(serial_t *obj) {
// Reset UART and disable clock
if (obj->uart == UART_1) {
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, DISABLE);
}
if (obj->uart == UART_2) {
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
}
if (obj->uart == UART_3) {
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, DISABLE);
}
// Configure GPIOs
pin_function(obj->pin_tx, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
pin_function(obj->pin_rx, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
serial_irq_ids[obj->index] = 0;
}

View File

@ -125,6 +125,11 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
obj->cpha = SPI_CPHA_1Edge;
obj->br_presc = SPI_BaudRatePrescaler_256;
obj->pin_miso = miso;
obj->pin_mosi = mosi;
obj->pin_sclk = sclk;
obj->pin_ssel = ssel;
if (ssel == NC) { // Master
obj->mode = SPI_Mode_Master;
obj->nss = SPI_NSS_Soft;
@ -138,8 +143,23 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
}
void spi_free(spi_t *obj) {
SPI_TypeDef *spi = (SPI_TypeDef *)(obj->spi);
SPI_I2S_DeInit(spi);
// Reset SPI and disable clock
if (obj->spi == SPI_2) {
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, DISABLE);
}
if (obj->spi == SPI_3) {
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, DISABLE);
}
// Configure GPIOs
pin_function(obj->pin_miso, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
pin_function(obj->pin_mosi, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
pin_function(obj->pin_sclk, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
pin_function(obj->pin_ssel, STM_PIN_DATA(GPIO_Mode_IN, 0, GPIO_PuPd_NOPULL, 0xFF));
}
void spi_format(spi_t *obj, int bits, int mode, int slave) {

View File

@ -90,7 +90,16 @@ void rtc_init(void) {
}
void rtc_free(void) {
RCC_DeInit(); // Resets the RCC clock configuration to the default reset state
// Reset RTC
PWR_RTCAccessCmd(ENABLE); // Enable access to Backup Domain
RTC_DeInit();
RCC_RTCResetCmd(ENABLE);
RCC_RTCResetCmd(DISABLE);
// Disable RTC, LSE and LSI clocks
RCC_RTCCLKCmd(DISABLE);
RCC_LSEConfig(RCC_LSE_OFF);
RCC_LSICmd(DISABLE);
rtc_inited = 0;
}