mirror of https://github.com/ARMmbed/mbed-os.git
[NUCLEO_F103RB] Change ticker to use one timer...
and add another pwm output.pull/158/head
parent
0110c3eec4
commit
b275fc579a
|
@ -62,13 +62,10 @@ typedef enum {
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PWM_2 = (int)TIM2_BASE,
|
PWM_2 = (int)TIM2_BASE,
|
||||||
PWM_3 = (int)TIM3_BASE
|
PWM_3 = (int)TIM3_BASE,
|
||||||
|
PWM_4 = (int)TIM4_BASE
|
||||||
} PWMName;
|
} PWMName;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CAN_1 = (int)CAN1_BASE
|
|
||||||
} CANName;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,21 +33,13 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
// Only TIM2 and TIM3 can be used (TIM1 and TIM4 are used by the us_ticker)
|
|
||||||
static const PinMap PinMap_PWM[] = {
|
static const PinMap PinMap_PWM[] = {
|
||||||
// TIM2 default
|
|
||||||
//{PA_2, PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM2_CH3 - ARDUINO D1
|
|
||||||
//{PA_3, PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM2_CH4 - ARDUINO D0
|
|
||||||
// TIM2 full remap
|
// TIM2 full remap
|
||||||
{PB_3, PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 5)}, // TIM2fr_CH2 - ARDUINO D3
|
{PB_3, PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 5)}, // TIM2fr_CH2 - ARDUINO D3
|
||||||
//{PB_10, PWM_2, STM_PIN_DATA(GPIO_Mode_AF_PP, 5)}, // TIM2fr_CH3 - ARDUINO D6
|
|
||||||
// TIM3 default
|
|
||||||
//{PA_6, PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM3_CH1 - ARDUINO D12
|
|
||||||
//{PA_7, PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM3_CH2 - ARDUINO D11
|
|
||||||
// TIM3 full remap
|
|
||||||
//{PC_7, PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 6)}, // TIM3fr_CH2 - ARDUINO D9
|
|
||||||
// TIM3 partial remap
|
// TIM3 partial remap
|
||||||
{PB_4, PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 7)}, // TIM3pr_CH1 - ARDUINO D5
|
{PB_4, PWM_3, STM_PIN_DATA(GPIO_Mode_AF_PP, 7)}, // TIM3pr_CH1 - ARDUINO D5
|
||||||
|
// TIM4 default
|
||||||
|
{PB_6, PWM_4, STM_PIN_DATA(GPIO_Mode_AF_PP, 0)}, // TIM4_CH1 - ARDUINO D10
|
||||||
{NC, NC, 0}
|
{NC, NC, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,7 +54,8 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
|
||||||
// Enable TIM clock
|
// Enable TIM clock
|
||||||
if (obj->pwm == PWM_2) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
if (obj->pwm == PWM_2) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||||
if (obj->pwm == PWM_3) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
if (obj->pwm == PWM_3) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
||||||
|
if (obj->pwm == PWM_4) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
|
||||||
|
|
||||||
// Configure GPIO
|
// Configure GPIO
|
||||||
pinmap_pinout(pin, PinMap_PWM);
|
pinmap_pinout(pin, PinMap_PWM);
|
||||||
|
|
||||||
|
@ -87,10 +80,7 @@ void pwmout_write(pwmout_t* obj, float value) {
|
||||||
} else if (value > 1.0) {
|
} else if (value > 1.0) {
|
||||||
value = 1.0;
|
value = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//while(TIM_GetFlagStatus(tim, TIM_FLAG_Update) == RESET);
|
|
||||||
//TIM_ClearFlag(tim, TIM_FLAG_Update);
|
|
||||||
|
|
||||||
obj->pulse = (uint32_t)((float)obj->period * value);
|
obj->pulse = (uint32_t)((float)obj->period * value);
|
||||||
|
|
||||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||||
|
@ -99,7 +89,7 @@ void pwmout_write(pwmout_t* obj, float value) {
|
||||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||||
|
|
||||||
// Configure channel 1
|
// Configure channel 1
|
||||||
if (obj->pin == PB_4) {
|
if ((obj->pin == PB_4) || (obj->pin == PB_6)) {
|
||||||
TIM_OC1PreloadConfig(tim, TIM_OCPreload_Enable);
|
TIM_OC1PreloadConfig(tim, TIM_OCPreload_Enable);
|
||||||
TIM_OC1Init(tim, &TIM_OCInitStructure);
|
TIM_OC1Init(tim, &TIM_OCInitStructure);
|
||||||
}
|
}
|
||||||
|
@ -109,18 +99,6 @@ void pwmout_write(pwmout_t* obj, float value) {
|
||||||
TIM_OC2PreloadConfig(tim, TIM_OCPreload_Enable);
|
TIM_OC2PreloadConfig(tim, TIM_OCPreload_Enable);
|
||||||
TIM_OC2Init(tim, &TIM_OCInitStructure);
|
TIM_OC2Init(tim, &TIM_OCInitStructure);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure channel 3
|
|
||||||
//if (obj->pin == PB_10) {
|
|
||||||
// TIM_OC3PreloadConfig(tim, TIM_OCPreload_Enable);
|
|
||||||
// TIM_OC3Init(tim, &TIM_OCInitStructure);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Configure channel 4
|
|
||||||
//if (obj->pin == PA_3) {
|
|
||||||
// TIM_OC4PreloadConfig(tim, TIM_OCPreload_Enable);
|
|
||||||
// TIM_OC4Init(tim, &TIM_OCInitStructure);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float pwmout_read(pwmout_t* obj) {
|
float pwmout_read(pwmout_t* obj) {
|
||||||
|
|
|
@ -29,60 +29,77 @@
|
||||||
#include "us_ticker_api.h"
|
#include "us_ticker_api.h"
|
||||||
#include "PeripheralNames.h"
|
#include "PeripheralNames.h"
|
||||||
|
|
||||||
// Timers selection:
|
// Timer selection:
|
||||||
// The Master timer clocks the Slave timer
|
#define TIM_MST TIM1
|
||||||
|
#define TIM_MST_UP_IRQ TIM1_UP_IRQn
|
||||||
|
#define TIM_MST_OC_IRQ TIM1_CC_IRQn
|
||||||
|
#define TIM_MST_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE)
|
||||||
|
|
||||||
#define TIM_MST TIM1
|
static int us_ticker_inited = 0;
|
||||||
#define TIM_MST_IRQ TIM1_CC_IRQn
|
static uint32_t SlaveCounter = 0;
|
||||||
#define TIM_MST_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE)
|
static uint32_t us_ticker_int_counter = 0;
|
||||||
|
static uint16_t us_ticker_int_remainder = 0;
|
||||||
|
|
||||||
#define TIM_SLV TIM4
|
// Used to increment the slave counter
|
||||||
#define TIM_SLV_IRQ TIM4_IRQn
|
static void tim_update_irq_handler(void) {
|
||||||
#define TIM_SLV_RCC RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE)
|
SlaveCounter++;
|
||||||
|
if (TIM_GetITStatus(TIM_MST, TIM_IT_Update) == SET) {
|
||||||
|
TIM_ClearITPendingBit(TIM_MST, TIM_IT_Update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define MST_SLV_ITR TIM_TS_ITR0
|
// Used by interrupt system
|
||||||
|
static void tim_oc_irq_handler(void) {
|
||||||
int us_ticker_inited = 0;
|
// Clear interrupt flag
|
||||||
|
if (TIM_GetITStatus(TIM_MST, TIM_IT_CC1) == SET) {
|
||||||
void us_ticker_init(void) {
|
TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1);
|
||||||
|
}
|
||||||
|
|
||||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
if (us_ticker_int_counter > 0) {
|
||||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
TIM_SetCompare1(TIM_MST, 0xFFFF);
|
||||||
|
us_ticker_int_counter--;
|
||||||
|
} else {
|
||||||
|
if (us_ticker_int_remainder > 0) {
|
||||||
|
TIM_SetCompare1(TIM_MST, us_ticker_int_remainder);
|
||||||
|
us_ticker_int_remainder = 0;
|
||||||
|
} else {
|
||||||
|
// This function is going to disable the interrupts if there are
|
||||||
|
// no other events in the queue
|
||||||
|
us_ticker_irq_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void us_ticker_init(void) {
|
||||||
|
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||||
|
|
||||||
if (us_ticker_inited) return;
|
if (us_ticker_inited) return;
|
||||||
us_ticker_inited = 1;
|
us_ticker_inited = 1;
|
||||||
|
|
||||||
// Enable Timers clock
|
// Enable Timer clock
|
||||||
TIM_MST_RCC;
|
TIM_MST_RCC;
|
||||||
TIM_SLV_RCC;
|
|
||||||
|
|
||||||
// Master and Slave timers time base configuration
|
// Configure time base
|
||||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||||
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
|
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
|
||||||
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
|
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
|
||||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||||
TIM_TimeBaseInit(TIM_MST, &TIM_TimeBaseStructure);
|
TIM_TimeBaseInit(TIM_MST, &TIM_TimeBaseStructure);
|
||||||
TIM_TimeBaseStructure.TIM_Prescaler = 0;
|
|
||||||
TIM_TimeBaseInit(TIM_SLV, &TIM_TimeBaseStructure);
|
|
||||||
|
|
||||||
// Master timer configuration
|
|
||||||
TIM_OCStructInit(&TIM_OCInitStructure);
|
|
||||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
|
|
||||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
|
||||||
TIM_OCInitStructure.TIM_Pulse = 0;
|
|
||||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
|
||||||
TIM_OC1Init(TIM_MST, &TIM_OCInitStructure);
|
|
||||||
TIM_SelectMasterSlaveMode(TIM_MST, TIM_MasterSlaveMode_Enable);
|
|
||||||
TIM_SelectOutputTrigger(TIM_MST, TIM_TRGOSource_Update);
|
|
||||||
|
|
||||||
// Slave timer configuration
|
// Configure interrupts
|
||||||
TIM_SelectSlaveMode(TIM_SLV, TIM_SlaveMode_External1);
|
TIM_ITConfig(TIM_MST, TIM_IT_Update, ENABLE);
|
||||||
// The connection between Master and Slave is done here
|
TIM_ITConfig(TIM_MST, TIM_IT_CC1, ENABLE);
|
||||||
TIM_SelectInputTrigger(TIM_SLV, MST_SLV_ITR);
|
|
||||||
|
// For 32-bit counter
|
||||||
|
NVIC_SetVector(TIM_MST_UP_IRQ, (uint32_t)tim_update_irq_handler);
|
||||||
|
NVIC_EnableIRQ(TIM_MST_UP_IRQ);
|
||||||
|
|
||||||
|
// For ouput compare
|
||||||
|
NVIC_SetVector(TIM_MST_OC_IRQ, (uint32_t)tim_oc_irq_handler);
|
||||||
|
NVIC_EnableIRQ(TIM_MST_OC_IRQ);
|
||||||
|
|
||||||
// Enable timers
|
// Enable timer
|
||||||
TIM_Cmd(TIM_SLV, ENABLE);
|
|
||||||
TIM_Cmd(TIM_MST, ENABLE);
|
TIM_Cmd(TIM_MST, ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,10 +111,10 @@ uint32_t us_ticker_read() {
|
||||||
// previous (incorrect) value of Slave and the new value of Master, which would return a
|
// previous (incorrect) value of Slave and the new value of Master, which would return a
|
||||||
// value in the past. Avoid this by computing consecutive values of the timer until they
|
// value in the past. Avoid this by computing consecutive values of the timer until they
|
||||||
// are properly ordered.
|
// are properly ordered.
|
||||||
counter = (uint32_t)((uint32_t)TIM_GetCounter(TIM_SLV) << 16);
|
counter = (uint32_t)(SlaveCounter << 16);
|
||||||
counter += (uint32_t)TIM_GetCounter(TIM_MST);
|
counter += (uint32_t)TIM_GetCounter(TIM_MST);
|
||||||
while (1) {
|
while (1) {
|
||||||
counter2 = (uint32_t)((uint32_t)TIM_GetCounter(TIM_SLV) << 16);
|
counter2 = (uint32_t)(SlaveCounter << 16);
|
||||||
counter2 += (uint32_t)TIM_GetCounter(TIM_MST);
|
counter2 += (uint32_t)TIM_GetCounter(TIM_MST);
|
||||||
if (counter2 > counter) {
|
if (counter2 > counter) {
|
||||||
break;
|
break;
|
||||||
|
@ -108,26 +125,31 @@ uint32_t us_ticker_read() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_set_interrupt(unsigned int timestamp) {
|
void us_ticker_set_interrupt(unsigned int timestamp) {
|
||||||
if (timestamp > 0xFFFF) {
|
int delta = (int)(timestamp - us_ticker_read());
|
||||||
TIM_SetCompare1(TIM_SLV, (uint16_t)((timestamp >> 16) & 0xFFFF));
|
|
||||||
TIM_ITConfig(TIM_SLV, TIM_IT_CC1, ENABLE);
|
if (delta <= 0) { // This event was in the past
|
||||||
NVIC_SetVector(TIM_SLV_IRQ, (uint32_t)us_ticker_irq_handler);
|
us_ticker_irq_handler();
|
||||||
NVIC_EnableIRQ(TIM_SLV_IRQ);
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TIM_SetCompare1(TIM_MST, (uint16_t)timestamp);
|
us_ticker_int_counter = (uint32_t)(delta >> 16);
|
||||||
TIM_ITConfig(TIM_MST, TIM_IT_CC1, ENABLE);
|
us_ticker_int_remainder = (uint16_t)(delta & 0xFFFF);
|
||||||
NVIC_SetVector(TIM_MST_IRQ, (uint32_t)us_ticker_irq_handler);
|
if (us_ticker_int_counter > 0) { // means delta > 0xFFFF
|
||||||
NVIC_EnableIRQ(TIM_MST_IRQ);
|
TIM_SetCompare1(TIM_MST, 0xFFFF);
|
||||||
|
us_ticker_int_counter--;
|
||||||
|
} else {
|
||||||
|
TIM_SetCompare1(TIM_MST, us_ticker_int_remainder);
|
||||||
|
us_ticker_int_remainder = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_disable_interrupt(void) {
|
void us_ticker_disable_interrupt(void) {
|
||||||
TIM_ITConfig(TIM_MST, TIM_IT_CC1, DISABLE);
|
TIM_ITConfig(TIM_MST, TIM_IT_CC1, DISABLE);
|
||||||
TIM_ITConfig(TIM_SLV, TIM_IT_CC1, DISABLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_clear_interrupt(void) {
|
void us_ticker_clear_interrupt(void) {
|
||||||
TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1);
|
if (TIM_GetITStatus(TIM_MST, TIM_IT_CC1) == SET) {
|
||||||
TIM_ClearITPendingBit(TIM_SLV, TIM_IT_CC1);
|
TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue