Skip to content

Commit 0110c3e

Browse files
committed
[NUCLEO_L152RE] Add PWM output, ticker with one timer
The us_ticker uses now only one timer instead of two. Another PWM output on TIM4 has been added.
1 parent e9fe139 commit 0110c3e

File tree

3 files changed

+74
-63
lines changed

3 files changed

+74
-63
lines changed

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_L152RE/PeripheralNames.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ typedef enum {
6565
} I2CName;
6666

6767
typedef enum {
68-
PWM_2 = (int)TIM2_BASE,
69-
PWM_3 = (int)TIM3_BASE
68+
PWM_2 = (int)TIM2_BASE,
69+
PWM_3 = (int)TIM3_BASE,
70+
PWM_4 = (int)TIM4_BASE
7071
} PWMName;
7172

7273
#ifdef __cplusplus

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_L152RE/pwmout_api.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,10 @@
3434
#include "error.h"
3535

3636
static const PinMap PinMap_PWM[] = {
37-
{PB_3, PWM_2, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_TIM2)}, // TIM2_CH2
38-
{PB_4, PWM_3, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_TIM3)}, // TIM3_CH1
39-
//{PB_10, PWM_2, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_TIM2)}, // TIM2_CH3
40-
//{PC_7, PWM_3, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_TIM3)}, // TIM3_CH2
41-
{NC, NC, 0}
37+
{PB_3, PWM_2, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_TIM2)}, // TIM2_CH2
38+
{PB_4, PWM_3, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_TIM3)}, // TIM3_CH1
39+
{PB_6, PWM_4, STM_PIN_DATA(GPIO_Mode_AF, GPIO_OType_PP, GPIO_PuPd_UP, GPIO_AF_TIM4)}, // TIM4_CH1
40+
{NC, NC, 0}
4241
};
4342

4443
void pwmout_init(pwmout_t* obj, PinName pin) {
@@ -52,7 +51,8 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
5251
// Enable TIM clock
5352
if (obj->pwm == PWM_2) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
5453
if (obj->pwm == PWM_3) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
55-
54+
if (obj->pwm == PWM_4) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
55+
5656
// Configure GPIO
5757
pinmap_pinout(pin, PinMap_PWM);
5858

@@ -77,10 +77,7 @@ void pwmout_write(pwmout_t* obj, float value) {
7777
} else if (value > 1.0) {
7878
value = 1.0;
7979
}
80-
81-
//while(TIM_GetFlagStatus(tim, TIM_FLAG_Update) == RESET);
82-
//TIM_ClearFlag(tim, TIM_FLAG_Update);
83-
80+
8481
obj->pulse = (uint32_t)((float)obj->period * value);
8582

8683
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
@@ -89,7 +86,7 @@ void pwmout_write(pwmout_t* obj, float value) {
8986
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
9087

9188
// Configure channel 1
92-
if (obj->pin == PB_4) {
89+
if ((obj->pin == PB_4) || (obj->pin == PB_6)) {
9390
TIM_OC1PreloadConfig(tim, TIM_OCPreload_Enable);
9491
TIM_OC1Init(tim, &TIM_OCInitStructure);
9592
}

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_L152RE/us_ticker.c

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -29,60 +29,68 @@
2929
#include "us_ticker_api.h"
3030
#include "PeripheralNames.h"
3131

32-
// Timers selection:
33-
// The Master timer clocks the Slave timer
32+
// Timer selection:
33+
#define TIM_MST TIM9
34+
#define TIM_MST_IRQ TIM9_IRQn
35+
#define TIM_MST_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE)
3436

35-
#define TIM_MST TIM9
36-
#define TIM_MST_IRQ TIM9_IRQn
37-
#define TIM_MST_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE)
37+
static int us_ticker_inited = 0;
38+
static uint32_t SlaveCounter = 0;
39+
static uint32_t us_ticker_int_counter = 0;
40+
static uint16_t us_ticker_int_remainder = 0;
3841

39-
#define TIM_SLV TIM4
40-
#define TIM_SLV_IRQ TIM4_IRQn
41-
#define TIM_SLV_RCC RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE)
42-
43-
#define MST_SLV_ITR TIM_TS_ITR3
42+
static void tim_update_oc_irq_handler(void) {
43+
// Update interrupt: increment the slave counter
44+
if (TIM_GetITStatus(TIM_MST, TIM_IT_Update) == SET) {
45+
TIM_ClearITPendingBit(TIM_MST, TIM_IT_Update);
46+
SlaveCounter++;
47+
}
4448

45-
int us_ticker_inited = 0;
49+
// Output compare interrupt: used by interrupt system
50+
if (TIM_GetITStatus(TIM_MST, TIM_IT_CC1) == SET) {
51+
TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1);
52+
if (us_ticker_int_counter > 0) {
53+
TIM_SetCompare1(TIM_MST, 0xFFFF);
54+
us_ticker_int_counter--;
55+
} else {
56+
if (us_ticker_int_remainder > 0) {
57+
TIM_SetCompare1(TIM_MST, us_ticker_int_remainder);
58+
us_ticker_int_remainder = 0;
59+
} else {
60+
// This function is going to disable the interrupts if there are
61+
// no other events in the queue
62+
us_ticker_irq_handler();
63+
}
64+
}
65+
}
66+
}
4667

47-
void us_ticker_init(void) {
48-
68+
void us_ticker_init(void) {
4969
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
50-
TIM_OCInitTypeDef TIM_OCInitStructure;
51-
70+
5271
if (us_ticker_inited) return;
5372
us_ticker_inited = 1;
5473

55-
// Enable Timers clock
74+
// Enable Timer clock
5675
TIM_MST_RCC;
57-
TIM_SLV_RCC;
5876

59-
// Master and Slave timers time base configuration
77+
// Configure time base
6078
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
6179
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
6280
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1; // 1 µs tick
6381
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
6482
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
6583
TIM_TimeBaseInit(TIM_MST, &TIM_TimeBaseStructure);
66-
TIM_TimeBaseStructure.TIM_Prescaler = 0;
67-
TIM_TimeBaseInit(TIM_SLV, &TIM_TimeBaseStructure);
68-
69-
// Master timer configuration
70-
TIM_OCStructInit(&TIM_OCInitStructure);
71-
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
72-
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
73-
TIM_OCInitStructure.TIM_Pulse = 0;
74-
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
75-
TIM_OC1Init(TIM_MST, &TIM_OCInitStructure);
76-
TIM_SelectMasterSlaveMode(TIM_MST, TIM_MasterSlaveMode_Enable);
77-
TIM_SelectOutputTrigger(TIM_MST, TIM_TRGOSource_Update);
7884

79-
// Slave timer configuration
80-
TIM_SelectSlaveMode(TIM_SLV, TIM_SlaveMode_External1);
81-
// The connection between Master and Slave is done here
82-
TIM_SelectInputTrigger(TIM_SLV, MST_SLV_ITR);
85+
// Configure interrupts
86+
TIM_ITConfig(TIM_MST, TIM_IT_Update, ENABLE);
87+
TIM_ITConfig(TIM_MST, TIM_IT_CC1, ENABLE);
88+
89+
// For 32-bit counter and output compare
90+
NVIC_SetVector(TIM_MST_IRQ, (uint32_t)tim_update_oc_irq_handler);
91+
NVIC_EnableIRQ(TIM_MST_IRQ);
8392

84-
// Enable timers
85-
TIM_Cmd(TIM_SLV, ENABLE);
93+
// Enable timer
8694
TIM_Cmd(TIM_MST, ENABLE);
8795
}
8896

@@ -94,10 +102,10 @@ uint32_t us_ticker_read() {
94102
// previous (incorrect) value of Slave and the new value of Master, which would return a
95103
// value in the past. Avoid this by computing consecutive values of the timer until they
96104
// are properly ordered.
97-
counter = (uint32_t)((uint32_t)TIM_GetCounter(TIM_SLV) << 16);
105+
counter = (uint32_t)(SlaveCounter << 16);
98106
counter += (uint32_t)TIM_GetCounter(TIM_MST);
99107
while (1) {
100-
counter2 = (uint32_t)((uint32_t)TIM_GetCounter(TIM_SLV) << 16);
108+
counter2 = (uint32_t)(SlaveCounter << 16);
101109
counter2 += (uint32_t)TIM_GetCounter(TIM_MST);
102110
if (counter2 > counter) {
103111
break;
@@ -108,26 +116,31 @@ uint32_t us_ticker_read() {
108116
}
109117

110118
void us_ticker_set_interrupt(unsigned int timestamp) {
111-
if (timestamp > 0xFFFF) {
112-
TIM_SetCompare1(TIM_SLV, (uint16_t)((timestamp >> 16) & 0xFFFF));
113-
TIM_ITConfig(TIM_SLV, TIM_IT_CC1, ENABLE);
114-
NVIC_SetVector(TIM_SLV_IRQ, (uint32_t)us_ticker_irq_handler);
115-
NVIC_EnableIRQ(TIM_SLV_IRQ);
119+
int delta = (int)(timestamp - us_ticker_read());
120+
121+
if (delta <= 0) { // This event was in the past
122+
us_ticker_irq_handler();
123+
return;
116124
}
117125
else {
118-
TIM_SetCompare1(TIM_MST, (uint16_t)timestamp);
119-
TIM_ITConfig(TIM_MST, TIM_IT_CC1, ENABLE);
120-
NVIC_SetVector(TIM_MST_IRQ, (uint32_t)us_ticker_irq_handler);
121-
NVIC_EnableIRQ(TIM_MST_IRQ);
126+
us_ticker_int_counter = (uint32_t)(delta >> 16);
127+
us_ticker_int_remainder = (uint16_t)(delta & 0xFFFF);
128+
if (us_ticker_int_counter > 0) { // means delta > 0xFFFF
129+
TIM_SetCompare1(TIM_MST, 0xFFFF);
130+
us_ticker_int_counter--;
131+
} else {
132+
TIM_SetCompare1(TIM_MST, us_ticker_int_remainder);
133+
us_ticker_int_remainder = 0;
134+
}
122135
}
123136
}
124137

125138
void us_ticker_disable_interrupt(void) {
126139
TIM_ITConfig(TIM_MST, TIM_IT_CC1, DISABLE);
127-
TIM_ITConfig(TIM_SLV, TIM_IT_CC1, DISABLE);
128140
}
129141

130142
void us_ticker_clear_interrupt(void) {
131-
TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1);
132-
TIM_ClearITPendingBit(TIM_SLV, TIM_IT_CC1);
143+
if (TIM_GetITStatus(TIM_MST, TIM_IT_CC1) == SET) {
144+
TIM_ClearITPendingBit(TIM_MST, TIM_IT_CC1);
145+
}
133146
}

0 commit comments

Comments
 (0)