Steps 1+2: clock init (INTOSC1 60MHz), LED heartbeat, comparator/DAC/TripZone safety + EMUSTOP (build OK, HW validation pending)
This commit is contained in:
12
src/bsp_clock.c
Normal file
12
src/bsp_clock.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include "DSP28x_Project.h"
|
||||
#include "bsp_clock.h"
|
||||
#include "calib.h"
|
||||
|
||||
void bsp_clock_init(void)
|
||||
{
|
||||
EALLOW;
|
||||
SysCtrlRegs.PLLLOCKPRD = CLK_PLLLOCKPRD;
|
||||
EDIS;
|
||||
|
||||
InitSysCtrl();
|
||||
}
|
||||
6
src/bsp_clock.h
Normal file
6
src/bsp_clock.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef BSP_CLOCK_H
|
||||
#define BSP_CLOCK_H
|
||||
|
||||
void bsp_clock_init(void);
|
||||
|
||||
#endif
|
||||
59
src/bsp_gpio.c
Normal file
59
src/bsp_gpio.c
Normal file
@ -0,0 +1,59 @@
|
||||
#include "DSP28x_Project.h"
|
||||
#include "bsp_gpio.h"
|
||||
#include "calib.h"
|
||||
|
||||
void bsp_gpio_leds_init(void)
|
||||
{
|
||||
EALLOW;
|
||||
GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0;
|
||||
GpioCtrlRegs.GPADIR.bit.GPIO12 = 1;
|
||||
GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 0;
|
||||
GpioCtrlRegs.GPBDIR.bit.GPIO33 = 1;
|
||||
EDIS;
|
||||
|
||||
led_set(LED_BLUE, false);
|
||||
led_set(LED_RED, false);
|
||||
}
|
||||
|
||||
void bsp_gpio_analog_init(void)
|
||||
{
|
||||
EALLOW;
|
||||
GpioCtrlRegs.AIOMUX1.bit.AIO2 = GPIO_ANALOG_MODE;
|
||||
GpioCtrlRegs.AIOMUX1.bit.AIO4 = GPIO_ANALOG_MODE;
|
||||
GpioCtrlRegs.AIOMUX1.bit.AIO10 = GPIO_ANALOG_MODE;
|
||||
GpioCtrlRegs.AIOMUX1.bit.AIO12 = GPIO_ANALOG_MODE;
|
||||
GpioCtrlRegs.AIOMUX1.bit.AIO14 = GPIO_ANALOG_MODE;
|
||||
EDIS;
|
||||
}
|
||||
|
||||
void led_set(led_id_t led, bool on)
|
||||
{
|
||||
#if LED_ACTIVE_LOW
|
||||
bool pin_high = !on;
|
||||
#else
|
||||
bool pin_high = on;
|
||||
#endif
|
||||
|
||||
if (led == LED_BLUE)
|
||||
{
|
||||
if (pin_high)
|
||||
{
|
||||
GpioDataRegs.GPASET.bit.GPIO12 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
GpioDataRegs.GPACLEAR.bit.GPIO12 = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pin_high)
|
||||
{
|
||||
GpioDataRegs.GPBSET.bit.GPIO33 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
GpioDataRegs.GPBCLEAR.bit.GPIO33 = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/bsp_gpio.h
Normal file
19
src/bsp_gpio.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef BSP_GPIO_H
|
||||
#define BSP_GPIO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LED_BLUE = 0,
|
||||
LED_RED
|
||||
} led_id_t;
|
||||
|
||||
void bsp_gpio_leds_init(void);
|
||||
void led_set(led_id_t led, bool on);
|
||||
|
||||
// Bascule AIO2, AIO4, AIO10, AIO12, AIO14 en mode analogique (shunts,
|
||||
// COMP1A/COMP2A, VOUT, V1, NTC1). A appeler avant safety_init()/adc_init().
|
||||
void bsp_gpio_analog_init(void);
|
||||
|
||||
#endif
|
||||
24
src/calib.h
Normal file
24
src/calib.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef CALIB_H
|
||||
#define CALIB_H
|
||||
|
||||
// Horloge : INTOSC1 (10 MHz nominal) + PLL (DSP28_PLLCR=12, DSP28_DIVSEL=2,
|
||||
// deja les valeurs par defaut de f2802x_examples.h pour ce device) -> 60 MHz.
|
||||
// PLLLOCKPRD doit etre ecrit AVANT InitSysCtrl() (qui attend le verrouillage
|
||||
// PLL en interne) car l'oscillateur interne impose un minimum de 10000.
|
||||
#define CLK_PLLLOCKPRD 10000
|
||||
#define CLK_SYSCLKOUT_HZ 60000000UL
|
||||
|
||||
// LEDs (LQFP48 PT) : bleue = GPIO12 (broche 47), rouge = GPIO33 (broche 35)
|
||||
#define LED_ACTIVE_LOW 1
|
||||
|
||||
// Valeur de champ AIOMUX1 pour basculer une broche AIOx en mode analogique
|
||||
#define GPIO_ANALOG_MODE 2
|
||||
|
||||
// Seuil de protection courant shunt (identique etage 1 et 2)
|
||||
// Shunt 0.02 ohm, gain x30 -> Vadc = I * 0.02 * 30 = I * 0.6
|
||||
#define SAFETY_ISHUNT_THRESHOLD_A 3.0f
|
||||
#define SAFETY_DAC_VREF_V 3.3f
|
||||
#define SAFETY_DAC_CODE \
|
||||
((uint16_t)((SAFETY_ISHUNT_THRESHOLD_A * 0.6f) / SAFETY_DAC_VREF_V * 1023.0f + 0.5f))
|
||||
|
||||
#endif
|
||||
60
src/main.c
Normal file
60
src/main.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include "DSP28x_Project.h"
|
||||
#include "bsp_clock.h"
|
||||
#include "bsp_gpio.h"
|
||||
#include "safety.h"
|
||||
|
||||
extern uint16_t RamfuncsLoadStart;
|
||||
extern uint16_t RamfuncsLoadSize;
|
||||
extern uint16_t RamfuncsRunStart;
|
||||
|
||||
interrupt void cpu_timer0_isr(void);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
#ifdef _FLASH
|
||||
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
|
||||
#endif
|
||||
|
||||
bsp_clock_init();
|
||||
bsp_gpio_leds_init();
|
||||
|
||||
DINT;
|
||||
InitPieCtrl();
|
||||
IER = 0x0000;
|
||||
IFR = 0x0000;
|
||||
InitPieVectTable();
|
||||
|
||||
bsp_gpio_analog_init();
|
||||
safety_init();
|
||||
|
||||
EALLOW;
|
||||
PieVectTable.TINT0 = &cpu_timer0_isr;
|
||||
EDIS;
|
||||
|
||||
InitCpuTimers();
|
||||
ConfigCpuTimer(&CpuTimer0, 60, 500000); // 500 ms -> 1 Hz sur la LED
|
||||
|
||||
IER |= M_INT1;
|
||||
PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // TINT0
|
||||
|
||||
EINT;
|
||||
ERTM;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// Etape 1-2 : validation clock/LED/securite. Rien d'autre pour
|
||||
// l'instant, tout se passe dans les ISR.
|
||||
}
|
||||
}
|
||||
|
||||
interrupt void cpu_timer0_isr(void)
|
||||
{
|
||||
static bool blue_on = false;
|
||||
|
||||
CpuTimer0.InterruptCount++;
|
||||
|
||||
blue_on = !blue_on;
|
||||
led_set(LED_BLUE, blue_on);
|
||||
|
||||
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
|
||||
}
|
||||
33
src/protocol.h
Normal file
33
src/protocol.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef PROTOCOL_H
|
||||
#define PROTOCOL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
// Squelette du protocole UART TMS320<->ESP32 (voir docs/ESP32-UART.md).
|
||||
// Rempli/utilise a partir de l'etape 7 (uart_link.c).
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float freq1_hz;
|
||||
float freq2_hz;
|
||||
float duty1_pct;
|
||||
float duty2_pct;
|
||||
float vin_v;
|
||||
float iin_a;
|
||||
float v1_v;
|
||||
float i1_a;
|
||||
float t1_c;
|
||||
float vout_v;
|
||||
float i2_a;
|
||||
float t2_c;
|
||||
float iout_a;
|
||||
} telemetry_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool ht_enabled;
|
||||
bool pwm1_enabled;
|
||||
bool pwm2_enabled;
|
||||
} command_state_t;
|
||||
|
||||
#endif
|
||||
115
src/safety.c
Normal file
115
src/safety.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include "DSP28x_Project.h"
|
||||
#include "safety.h"
|
||||
#include "bsp_gpio.h"
|
||||
#include "calib.h"
|
||||
|
||||
static volatile bool s_stage1_fault = false;
|
||||
static volatile bool s_stage2_fault = false;
|
||||
|
||||
interrupt void epwm1_tzint_isr(void);
|
||||
interrupt void epwm2_tzint_isr(void);
|
||||
|
||||
void safety_init(void)
|
||||
{
|
||||
EALLOW;
|
||||
|
||||
// Le comparateur partage la reference bandgap de l'ADC : elle doit etre
|
||||
// alimentee meme si l'ADC lui-meme n'est pas encore utilise (etape 4).
|
||||
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
|
||||
SysCtrlRegs.PCLKCR3.bit.COMP1ENCLK = 1;
|
||||
SysCtrlRegs.PCLKCR3.bit.COMP2ENCLK = 1;
|
||||
AdcRegs.ADCCTL1.bit.ADCBGPWD = 1;
|
||||
EDIS;
|
||||
DELAY_US(1000L);
|
||||
|
||||
EALLOW;
|
||||
|
||||
// Comparateur 1 : shunt etage 1 sur COMP1A (entree non-inverseuse fixe),
|
||||
// seuil DAC sur l'entree inverseuse (COMPSOURCE=0).
|
||||
Comp1Regs.COMPCTL.bit.COMPDACEN = 1;
|
||||
Comp1Regs.COMPCTL.bit.COMPSOURCE = 0;
|
||||
Comp1Regs.COMPCTL.bit.SYNCSEL = 0; // asynchrone -> ~30 ns vers le Trip Zone
|
||||
Comp1Regs.COMPCTL.bit.CMPINV = 1; // driver actif haut : 1=OK, 0=defaut
|
||||
Comp1Regs.COMPCTL.bit.QUALSEL = 0; // pas de qualification pour l'instant
|
||||
Comp1Regs.DACVAL.bit.DACVAL = SAFETY_DAC_CODE;
|
||||
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 3; // COMP1OUT
|
||||
|
||||
// Comparateur 2 : idem, shunt etage 2 sur COMP2A.
|
||||
Comp2Regs.COMPCTL.bit.COMPDACEN = 1;
|
||||
Comp2Regs.COMPCTL.bit.COMPSOURCE = 0;
|
||||
Comp2Regs.COMPCTL.bit.SYNCSEL = 0;
|
||||
Comp2Regs.COMPCTL.bit.CMPINV = 1;
|
||||
Comp2Regs.COMPCTL.bit.QUALSEL = 0;
|
||||
Comp2Regs.DACVAL.bit.DACVAL = SAFETY_DAC_CODE;
|
||||
GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 3; // COMP2OUT
|
||||
|
||||
// Digital Compare : COMPxOUT -> DCAEVT1 -> Trip Zone one-shot (latche)
|
||||
EPwm1Regs.DCTRIPSEL.bit.DCAHCOMPSEL = DC_COMP1OUT;
|
||||
EPwm1Regs.TZDCSEL.bit.DCAEVT1 = TZ_DCAH_LOW;
|
||||
EPwm1Regs.TZSEL.bit.DCAEVT1 = 1;
|
||||
EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
|
||||
EPwm1Regs.TZEINT.bit.OST = 1;
|
||||
// TZ6 = EMUSTOP (signal cable en dur depuis le CPU, TRM SPRUI09A section
|
||||
// 3.2.7) : coupe le PWM des que le debugger arrete le coeur. FREE_SOFT
|
||||
// seul ne suffit pas, il ne fait que geler le compteur de base de temps,
|
||||
// la broche reste figee dans son dernier etat.
|
||||
EPwm1Regs.TZSEL.bit.OSHT6 = 1;
|
||||
EPwm1Regs.TBCTL.bit.FREE_SOFT = 0;
|
||||
|
||||
EPwm2Regs.DCTRIPSEL.bit.DCAHCOMPSEL = DC_COMP2OUT;
|
||||
EPwm2Regs.TZDCSEL.bit.DCAEVT1 = TZ_DCAH_LOW;
|
||||
EPwm2Regs.TZSEL.bit.DCAEVT1 = 1;
|
||||
EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
|
||||
EPwm2Regs.TZEINT.bit.OST = 1;
|
||||
EPwm2Regs.TZSEL.bit.OSHT6 = 1;
|
||||
EPwm2Regs.TBCTL.bit.FREE_SOFT = 0;
|
||||
|
||||
PieVectTable.EPWM1_TZINT = &epwm1_tzint_isr;
|
||||
PieVectTable.EPWM2_TZINT = &epwm2_tzint_isr;
|
||||
EDIS;
|
||||
|
||||
IER |= M_INT2;
|
||||
PieCtrlRegs.PIEIER2.bit.INTx1 = 1; // EPWM1_TZINT
|
||||
PieCtrlRegs.PIEIER2.bit.INTx2 = 1; // EPWM2_TZINT
|
||||
}
|
||||
|
||||
safety_faults_t safety_get_fault_flags(void)
|
||||
{
|
||||
safety_faults_t f;
|
||||
f.stage1_fault = s_stage1_fault;
|
||||
f.stage2_fault = s_stage2_fault;
|
||||
return f;
|
||||
}
|
||||
|
||||
void safety_clear_faults(void)
|
||||
{
|
||||
EALLOW;
|
||||
EPwm1Regs.TZCLR.bit.OST = 1;
|
||||
EPwm2Regs.TZCLR.bit.OST = 1;
|
||||
EDIS;
|
||||
s_stage1_fault = false;
|
||||
s_stage2_fault = false;
|
||||
led_set(LED_RED, false);
|
||||
}
|
||||
|
||||
void safety_force_trip_test(void)
|
||||
{
|
||||
EALLOW;
|
||||
EPwm1Regs.TZFRC.bit.OST = 1;
|
||||
EPwm2Regs.TZFRC.bit.OST = 1;
|
||||
EDIS;
|
||||
}
|
||||
|
||||
interrupt void epwm1_tzint_isr(void)
|
||||
{
|
||||
s_stage1_fault = true;
|
||||
led_set(LED_RED, true);
|
||||
PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
|
||||
}
|
||||
|
||||
interrupt void epwm2_tzint_isr(void)
|
||||
{
|
||||
s_stage2_fault = true;
|
||||
led_set(LED_RED, true);
|
||||
PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
|
||||
}
|
||||
24
src/safety.h
Normal file
24
src/safety.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef SAFETY_H
|
||||
#define SAFETY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool stage1_fault;
|
||||
bool stage2_fault;
|
||||
} safety_faults_t;
|
||||
|
||||
void safety_init(void);
|
||||
safety_faults_t safety_get_fault_flags(void);
|
||||
|
||||
// Ecrit TZCLR[OST] sur les deux etages. Ne doit JAMAIS etre appele
|
||||
// automatiquement par le firmware (voir document PROMPT, section 8) --
|
||||
// uniquement sur commande explicite (UART, etape 7).
|
||||
void safety_clear_faults(void);
|
||||
|
||||
// Force un trip logiciel (TZFRC[OSHT]) pour valider le mecanisme de
|
||||
// protection sans provoquer de vrai court-circuit (critere de test etape 2).
|
||||
void safety_force_trip_test(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user