Skip to content

Commit 0588d38

Browse files
committed
added teensy 4 6pwm tiemer sync and better support for low-side current sensing
1 parent 81db3f5 commit 0588d38

File tree

3 files changed

+207
-62
lines changed

3 files changed

+207
-62
lines changed

src/current_sense/hardware_specific/teensy/teensy4_mcu.cpp

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,23 @@
11
#include "teensy4_mcu.h"
22
#include "../../../drivers/hardware_specific/teensy/teensy4_mcu.h"
3+
// #include "../../../common/lowpass_filter.h"
34
#include "../../../common/foc_utils.h"
45

56
// if defined
67
// - Teensy 4.0
78
// - Teensy 4.1
89
#if defined(__arm__) && defined(CORE_TEENSY) && ( defined(__IMXRT1062__) || defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) || defined(ARDUINO_TEENSY_MICROMOD) )
910

10-
// function finding the TRIG event given the flexpwm timer and the submodule
11-
// returning -1 if the submodule is not valid or no trigger is available
12-
// allowing flexpwm1-4 and submodule 0-3
13-
//
14-
// the flags are defined in the imxrt.h file
15-
// https://github.com/PaulStoffregen/cores/blob/dd6aa8419ee173a0a6593eab669fbff54ed85f48/teensy4/imxrt.h#L9662
16-
int flexpwm_submodule_to_trig(IMXRT_FLEXPWM_t* flexpwm, int submodule){
17-
if(submodule <0 && submodule > 3) return -1;
18-
if(flexpwm == &IMXRT_FLEXPWM1){
19-
return XBARA1_IN_FLEXPWM1_PWM1_OUT_TRIG0 + submodule;
20-
}else if(flexpwm == &IMXRT_FLEXPWM2){
21-
return XBARA1_IN_FLEXPWM2_PWM1_OUT_TRIG0 + submodule;
22-
}else if(flexpwm == &IMXRT_FLEXPWM3){
23-
return XBARA1_IN_FLEXPWM3_PWM1_OUT_TRIG0 + submodule;
24-
}else if(flexpwm == &IMXRT_FLEXPWM4){
25-
return XBARA1_IN_FLEXPWM4_PWM1_OUT_TRIG0 + submodule;
26-
}
27-
return -1;
28-
}
11+
// #define TEENSY4_ADC_INTERRUPT_DEBUG
12+
2913

14+
// #define _BANDWIDTH_CS 10000.0f // [Hz] bandwidth for the current sense
3015
volatile uint32_t val0, val1, val2;
3116

17+
// LowPassFilter lp1 = LowPassFilter(1.0/_BANDWIDTH_CS);
18+
// LowPassFilter lp2 = LowPassFilter(1.0/_BANDWIDTH_CS);
19+
// LowPassFilter lp3 = LowPassFilter(1.0/_BANDWIDTH_CS);
20+
3221
void read_currents(uint32_t *a, uint32_t*b, uint32_t *c=nullptr){
3322
*a = val0;
3423
*b = val1;
@@ -38,24 +27,32 @@ void read_currents(uint32_t *a, uint32_t*b, uint32_t *c=nullptr){
3827
// interrupt service routine for the ADC_ETC0
3928
// reading the ADC values and clearing the interrupt
4029
void adcetc0_isr() {
30+
#ifdef TEENSY4_ADC_INTERRUPT_DEBUG
4131
digitalWrite(30,HIGH);
32+
#endif
4233
// page 3509 , section 66.5.1.3.3
4334
ADC_ETC_DONE0_1_IRQ |= 1; // clear Done0 for trg0 at 1st bit
44-
val0 = ADC_ETC_TRIG0_RESULT_1_0 & 4095;
35+
// val0 = lp1(ADC_ETC_TRIG0_RESULT_1_0 & 4095);
36+
val0 = (ADC_ETC_TRIG0_RESULT_1_0 & 4095);
37+
// val1 = lp2((ADC_ETC_TRIG0_RESULT_1_0 >> 16) & 4095);
4538
val1 = (ADC_ETC_TRIG0_RESULT_1_0 >> 16) & 4095;
46-
asm("dsb");
39+
#ifdef TEENSY4_ADC_INTERRUPT_DEBUG
4740
digitalWrite(30,LOW);
41+
#endif
4842
}
4943

5044

5145
void adcetc1_isr() {
52-
digitalWrite(30,HIGH);
46+
#ifdef TEENSY4_ADC_INTERRUPT_DEBUG
47+
digitalWrite(30,HIGH);
48+
#endif
5349
// page 3509 , section 66.5.1.3.3
5450
ADC_ETC_DONE0_1_IRQ |= 1 << 16; // clear Done1 for trg0 at 16th bit
5551
val2 = ADC_ETC_TRIG0_RESULT_3_2 & 4095;
56-
// val2 = (ADC_ETC_TRIG0_RESULT_3_2 >> 16) & 4095;
57-
asm("dsb");
58-
digitalWrite(30,LOW);
52+
// val2 = lp3( ADC_ETC_TRIG0_RESULT_3_2 & 4095);
53+
#ifdef TEENSY4_ADC_INTERRUPT_DEBUG
54+
digitalWrite(30,LOW);
55+
#endif
5956
}
6057

6158
// function initializing the ADC2
@@ -65,7 +62,7 @@ void adc1_init(int pin1, int pin2, int pin3=NOT_SET) {
6562
ADC1_CFG = ADC_CFG_OVWREN //Allow overwriting of the next converted Data onto the existing
6663
| ADC_CFG_ADICLK(0) // input clock select - IPG clock
6764
| ADC_CFG_MODE(2) // 12-bit conversion 0 8-bit conversion 1 10-bit conversion 2 12-bit conversion
68-
| ADC_CFG_ADIV(1) // Input clock / 2 (0 for /1, 1 for /2 and 2 for / 4)
65+
| ADC_CFG_ADIV(2) // Input clock / 2 (0 for /1, 1 for /2 and 2 for / 4) (1 is faster and maybe with some filtering could provide better results but 2 for now)
6966
| ADC_CFG_ADSTS(0) // Sample period (ADC clocks) = 3 if ADLSMP=0b
7067
| ADC_CFG_ADHSC // High speed operation
7168
| ADC_CFG_ADTRG; // Hardware trigger selected
@@ -91,7 +88,7 @@ void adc2_init(){
9188
ADC1_CFG = ADC_CFG_OVWREN //Allow overwriting of the next converted Data onto the existing
9289
| ADC_CFG_ADICLK(0) // input clock select - IPG clock
9390
| ADC_CFG_MODE(2) // 12-bit conversion 0 8-bit conversion 1 10-bit conversion 2 12-bit conversion
94-
| ADC_CFG_ADIV(1) // Input clock / 2 (0 for /1, 1 for /2 and 2 for / 4)
91+
| ADC_CFG_ADIV(2) // Input clock / 2 (0 for /1, 1 for /2 and 2 for / 4)
9592
| ADC_CFG_ADSTS(0) // Sample period (ADC clocks) = 3 if ADLSMP=0b
9693
| ADC_CFG_ADHSC // High speed operation
9794
| ADC_CFG_ADTRG; // Hardware trigger selected
@@ -140,22 +137,6 @@ void adc_etc_init(int pin1, int pin2, int pin3=NOT_SET) {
140137
}
141138
}
142139

143-
void xbar_connect(unsigned int input, unsigned int output)
144-
{
145-
if (input >= 88) return;
146-
if (output >= 132) return;
147-
volatile uint16_t *xbar = &XBARA1_SEL0 + (output / 2);
148-
uint16_t val = *xbar;
149-
if (!(output & 1)) {
150-
val = (val & 0xFF00) | input;
151-
} else {
152-
val = (val & 0x00FF) | (input << 8);
153-
}
154-
*xbar = val;
155-
}
156-
void xbar_init() {
157-
CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON); //turn clock on for xbara1
158-
}
159140

160141

161142
// function reading an ADC value and returning the read voltage
@@ -178,9 +159,10 @@ float _readADCVoltageLowSide(const int pinA, const void* cs_params){
178159
// cannot do much but
179160
void* _configureADCLowSide(const void* driver_params, const int pinA,const int pinB,const int pinC){
180161
_UNUSED(driver_params);
181-
// _UNUSED(pinC);
182162

163+
#ifdef TEENSY4_ADC_INTERRUPT_DEBUG
183164
pinMode(30,OUTPUT);
165+
#endif
184166

185167
if( _isset(pinA) ) pinMode(pinA, INPUT);
186168
if( _isset(pinB) ) pinMode(pinB, INPUT);
@@ -196,9 +178,6 @@ void* _configureADCLowSide(const void* driver_params, const int pinA,const int p
196178

197179

198180
adc1_init(pins[0], pins[1], pins[2]);
199-
SIMPLEFOC_DEBUG("pins: ",pins[0]);
200-
SIMPLEFOC_DEBUG("pins: ",pins[1]);
201-
SIMPLEFOC_DEBUG("pins: ",pins[2]);
202181
adc_etc_init(pins[0], pins[1], pins[2]);
203182

204183
xbar_init();
@@ -223,12 +202,29 @@ void _driverSyncLowSide(void* driver_params, void* cs_params){
223202
// allow theFlexPWM to trigger the ADC_ETC
224203
xbar_connect((uint32_t)xbar_trig_pwm, XBARA1_OUT_ADC_ETC_TRIG00); //FlexPWM to adc_etc
225204

205+
// setup the ADC_ETC trigger to be triggered by the FlexPWM channel 1 (val1)
206+
//This val1 interrupt on match is in the center of the PWM
207+
flexpwm->SM[submodule].TCTRL = FLEXPWM_SMTCTRL_OUT_TRIG_EN(1<<1);
208+
209+
210+
// if needed the interrupt can be moved to some other point in the PWM cycle by using an addional val register example: VAL4
226211
// setup the ADC_ETC trigger to be triggered by the FlexPWM channel 4 (val4)
227-
flexpwm->SM[submodule].TCTRL = FLEXPWM_SMTCTRL_OUT_TRIG_EN(1<<4);
212+
// flexpwm->SM[submodule].TCTRL = FLEXPWM_SMTCTRL_OUT_TRIG_EN(1<<4);
228213
// setup this val4 for interrupt on match for ADC sync
229214
// this code assumes that the val4 is not used for anything else!
230215
// reading two ADC takes about 2.5us. So put the interrupt 2.5us befor the center
231-
flexpwm->SM[submodule].VAL4 = -int(2.5e-6*par->pwm_frequency*flexpwm->SM[submodule].VAL1) ; // 2.5us before center
216+
// flexpwm->SM[submodule].VAL4 = int(flexpwm->SM[submodule].VAL1*(1.0f - 2.5e-6*par->pwm_frequency)) ; // 2.5us before center
217+
218+
219+
#ifdef TEENSY4_ADC_INTERRUPT_DEBUG
220+
// pin 4 observes out trigger line for 'scope
221+
xbar_connect (xbar_trig_pwm, XBARA1_OUT_IOMUX_XBAR_INOUT08) ;
222+
IOMUXC_GPR_GPR6 |= IOMUXC_GPR_GPR6_IOMUXC_XBAR_DIR_SEL_8 ; // select output mode for INOUT8
223+
// Select alt 3 for EMC_06 (XBAR), rather than original 5 (GPIO)
224+
CORE_PIN4_CONFIG = 3 ; // shorthand for IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_06 = 3 ;
225+
// turn up drive & speed as very short pulse
226+
IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_06 = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_SPEED(3) | IOMUXC_PAD_SRE ;
227+
#endif
232228

233229
}
234230

0 commit comments

Comments
 (0)