Added Interlock
Fixed PID regulation functionality git-svn-id: https://svn.vbchaos.nl/svn/hsb/trunk@250 05563f52-14a8-4384-a975-3d1654cca0fa
This commit is contained in:
@@ -138,7 +138,15 @@ ErrorStatus Display_clearScreen(struct Display* self)
|
||||
|
||||
ErrorStatus Display_clearLine(struct Display* self, size_t line)
|
||||
{
|
||||
return DisplayDevice_clearLine(self->displayDevice, line);
|
||||
char buffer[self->displayDevice->parameters.numberOfColumns];
|
||||
|
||||
int loopcounter;
|
||||
for (loopcounter = 0; loopcounter < self->displayDevice->parameters.numberOfColumns; loopcounter++)
|
||||
{
|
||||
buffer[loopcounter] = 0x20;
|
||||
}
|
||||
|
||||
return Display_write(self, buffer, self->displayDevice->parameters.numberOfColumns, line, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -881,8 +881,8 @@ static void hwValidationMenuSM(struct HwValidationMenu* self, Button_Pressed_t b
|
||||
bool value2 = false;
|
||||
if( self->menuItemSelected == MENU_TEST_INTERLOCK_1)
|
||||
{
|
||||
if( GPIO_getValue(self->testItems->interlock1, &value1) == SUCCESS &&
|
||||
GPIO_getValue(self->testItems->interlock2, &value2) == SUCCESS
|
||||
if( GPIO_getValue(self->testItems->interlockNO, &value1) == SUCCESS &&
|
||||
GPIO_getValue(self->testItems->interlockNC, &value2) == SUCCESS
|
||||
){
|
||||
outputBufferLength = sprintf(self->outputBuffer, "Interlock: NO: %d - NC: %d\r\n", value1, value2);
|
||||
}
|
||||
@@ -898,8 +898,8 @@ static void hwValidationMenuSM(struct HwValidationMenu* self, Button_Pressed_t b
|
||||
if(pcba->pcba == Tesla)
|
||||
{
|
||||
|
||||
if( GPIO_getValue(self->testItems->tesla1, &value1) == SUCCESS &&
|
||||
GPIO_getValue(self->testItems->tesla2, &value2) == SUCCESS
|
||||
if( GPIO_getValue(self->testItems->teslaNO, &value1) == SUCCESS &&
|
||||
GPIO_getValue(self->testItems->teslaNC, &value2) == SUCCESS
|
||||
){
|
||||
outputBufferLength = sprintf(self->outputBuffer, "Interlock (tesla): NO: %d - NC: %d\r\n", value1, value2);
|
||||
}
|
||||
@@ -1106,7 +1106,6 @@ static void hwValidationMenuSM(struct HwValidationMenu* self, Button_Pressed_t b
|
||||
{
|
||||
if( self->menuItemSelected == MENU_TEST_GENERIC_KEYPAD)
|
||||
{
|
||||
char key;
|
||||
Keypad_KeyState keyState;
|
||||
char data[CMD_BUFFER_SIZE] = {0};
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ static void initTask(void* parameters)
|
||||
|
||||
xTaskCreate(ledBlinkTask, (const char* const)"ledTask", 100, &ledTaskArguments, 0, &ledTaskHandle);
|
||||
|
||||
Logger_construct(mainLog, &uart3->device, 1, 512);
|
||||
Logger_construct(mainLog, &uart1->device, 1, 512);
|
||||
|
||||
Storm700_construct(storm700, &keypad->device);
|
||||
|
||||
@@ -242,10 +242,10 @@ static void initTask(void* parameters)
|
||||
hwTestItems.internalADC = adc1;
|
||||
hwTestItems.externalDAC = &max5715;
|
||||
hwTestItems.power6v5Enable = power6v5Enable;
|
||||
hwTestItems.interlock1 = interlock1;
|
||||
hwTestItems.interlock2 = interlock2;
|
||||
hwTestItems.tesla1 = tesla1;
|
||||
hwTestItems.tesla1 = tesla2;
|
||||
hwTestItems.interlockNO = interlockNO;
|
||||
hwTestItems.interlockNC = interlockNC;
|
||||
hwTestItems.teslaNO = teslaNO;
|
||||
hwTestItems.teslaNC = teslaNC;
|
||||
hwTestItems.solenoid = solenoid;
|
||||
hwTestItems.mcp0Relay = mcp0Relay;
|
||||
hwTestItems.mcp1Relay = mcp1Relay;
|
||||
@@ -253,11 +253,10 @@ static void initTask(void* parameters)
|
||||
hwTestItems.cat0Relay = cat0Relay;
|
||||
hwTestItems.cat1Relay = cat1Relay;
|
||||
hwTestItems.cat2Relay = cat2Relay;
|
||||
hwTestItems.teslaLock = teslaLock;
|
||||
hwTestItems.pcba = pcba;
|
||||
hwTestItems.keypad = keypad;
|
||||
// EEPROM TO BE DONE
|
||||
HwValidationMenu_construct(hwValidation, &uart1->device, &hwTestItems, 1, 512);
|
||||
// HwValidationMenu_construct(hwValidation, &uart1->device, &hwTestItems, 1, 1024);
|
||||
|
||||
// Construct the repair menu
|
||||
repairMenu_construct(rm, display, 2, 512);
|
||||
|
||||
@@ -155,8 +155,8 @@ static void repairMenu_task(void* parameters)
|
||||
// struct RepairPresetParameters presetStage1 = {.voltage = 0xE00, .duration = 300, .softstartDuration = 120};
|
||||
// struct RepairPresetParameters presetStage2 = {.voltage = 0x600, .duration = 120, .softstartDuration = 30};
|
||||
|
||||
struct RepairPresetParameters presetStage1 = {.voltage = 0xE00, .duration = 300, .softstartDuration = 120};
|
||||
struct RepairPresetParameters presetStage2 = {.voltage = 0x600, .duration = 120, .softstartDuration = 30};
|
||||
struct RepairPresetParameters presetStage1 = {.voltage = 0xE00, .duration = 7200, .softstartDuration = 1800};
|
||||
struct RepairPresetParameters presetStage2 = {.voltage = 0x600, .duration = 1800, .softstartDuration = 900};
|
||||
|
||||
struct RepairPreset repairPreset;
|
||||
repairPreset.numberOfStages = 2;
|
||||
@@ -186,15 +186,15 @@ static void repairMenu_task(void* parameters)
|
||||
Display_write(self->display, "R3", strlen("R3"), 3, 17);
|
||||
|
||||
uint16_t value;
|
||||
ADCChannel_read(rp->adcRow1, &value);
|
||||
ADCChannel_read(rp->adc[0], &value);
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%04xV", value);
|
||||
Display_write(self->display, buffer, strlen(buffer), 4, 1);
|
||||
|
||||
ADCChannel_read(rp->adcRow2, &value);
|
||||
ADCChannel_read(rp->adc[1], &value);
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%04xV", value);
|
||||
Display_write(self->display, buffer, strlen(buffer), 4, 8);
|
||||
|
||||
ADCChannel_read(rp->adcRow3, &value);
|
||||
ADCChannel_read(rp->adc[2], &value);
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%04xV", value);
|
||||
Display_write(self->display, buffer, strlen(buffer), 4, 15);
|
||||
|
||||
|
||||
@@ -55,13 +55,14 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static void repairProcess_task(void* parameters);
|
||||
|
||||
static int SignalProfileGenerator(uint32_t startTime, uint32_t currentTime, struct RepairPreset* repairPreset, int presetIndex);
|
||||
static int SignalProfileGenerator(struct RepairProcess* self);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function definitions
|
||||
@@ -91,21 +92,21 @@ ErrorStatus repairProcess_construct(struct RepairProcess* self, struct RepairPro
|
||||
self->initialized = true;
|
||||
self->currentState = PREPARE;
|
||||
|
||||
self->adcRow1 = parameters->adcRow1;
|
||||
self->adcRow2 = parameters->adcRow2;
|
||||
self->adcRow3 = parameters->adcRow3;
|
||||
self->dacRow1 = parameters->dacRow1;
|
||||
self->dacRow2 = parameters->dacRow2;
|
||||
self->dacRow3 = parameters->dacRow3;
|
||||
self->adc[0] = parameters->adcRow1;
|
||||
self->adc[1] = parameters->adcRow2;
|
||||
self->adc[2] = parameters->adcRow3;
|
||||
self->dac[0] = parameters->dacRow1;
|
||||
self->dac[1] = parameters->dacRow2;
|
||||
self->dac[2] = parameters->dacRow3;
|
||||
|
||||
self->pidRow1.initialized = false;
|
||||
self->pidRow2.initialized = false;
|
||||
self->pidRow3.initialized = false;
|
||||
self->pid[0].initialized = false;
|
||||
self->pid[1].initialized = false;
|
||||
self->pid[2].initialized = false;
|
||||
|
||||
|
||||
PID_construct(&self->pidRow1, 10, 10, 10, 0, 10000000);
|
||||
PID_construct(&self->pidRow2, 100, 0, 0, 0, 10000000);
|
||||
PID_construct(&self->pidRow3, 10, 10, 10, 0, 10000000);
|
||||
PID_construct(&self->pid[0], 5000, 3000, 0, 0, 10000000);
|
||||
PID_construct(&self->pid[1], 5000, 3000, 0, 0, 100000000);
|
||||
PID_construct(&self->pid[2], 5000, 3000, 0, 0, 10000000);
|
||||
|
||||
LOGGER_INFO(mainLog, "Repair Process task started");
|
||||
}
|
||||
@@ -165,34 +166,73 @@ static void repairProcess_task(void* parameters)
|
||||
{
|
||||
struct RepairProcess* self = (struct RepairProcess*)parameters;
|
||||
|
||||
uint8_t presetIndex = 0;
|
||||
uint32_t startTime = 0;
|
||||
uint32_t softStartTimer = 0;
|
||||
uint32_t voltageHoldTimer = 0;
|
||||
|
||||
uint32_t pidError;
|
||||
|
||||
uint16_t voltageRow1 = 0;
|
||||
uint16_t voltageRow2 = 0;
|
||||
uint16_t voltageRow3 = 0;
|
||||
|
||||
uint16_t adcVoltageRow1 = 0;
|
||||
uint16_t adcVoltageRow2 = 0;
|
||||
uint16_t adcVoltageRow3 = 0;
|
||||
|
||||
uint16_t voltageTarget = 0;
|
||||
uint16_t dacVoltageRow1 = 0;
|
||||
uint16_t dacVoltageRow2 = 0;
|
||||
uint16_t dacVoltageRow3 = 0;
|
||||
|
||||
int signal;
|
||||
uint16_t adcValue;
|
||||
int error;
|
||||
int pid;
|
||||
int loopCounter;
|
||||
|
||||
// Reset the seconds counter to 0
|
||||
self->secondsCounter = 0;
|
||||
MAX5715Channel_setValue(self->dac[0], 0);
|
||||
MAX5715Channel_setValue(self->dac[1], 0);
|
||||
MAX5715Channel_setValue(self->dac[2], 0);
|
||||
|
||||
while(self->runTask)
|
||||
{
|
||||
xSemaphoreTake(self->secondsSyncronisation, portMAX_DELAY);
|
||||
|
||||
LOGGER_DEBUG(mainLog, "----------------------------------------");
|
||||
|
||||
// The signal profile is identical for all rows in the regulation process
|
||||
signal = SignalProfileGenerator(self);
|
||||
LOGGER_DEBUG(mainLog, "Signal: %d", signal);
|
||||
|
||||
// Check for correct signal
|
||||
if (signal >= 0)
|
||||
{
|
||||
// Regulation is unique for each row
|
||||
// For TESLA repair only row 1 (out of 0,1,2) is used
|
||||
// For ANODE and Cathode/MCP, all 3 rows are used
|
||||
for (loopCounter = ((PCBA_getInstance()->pcba == Tesla) ? 1 : 0); loopCounter <= ((PCBA_getInstance()->pcba == Tesla) ? 1 : 2); loopCounter++)
|
||||
{
|
||||
// Read the last ADC channel value
|
||||
ADCChannel_read(self->adc[loopCounter], &adcValue);
|
||||
// Calculate the error
|
||||
error = signal - (int)adcValue;
|
||||
// Calculate the PID
|
||||
pid = PID_calculate(&self->pid[loopCounter], error);
|
||||
///TODO MUST BE MOVED TO DACDevice
|
||||
// Verify that pid value does not overflow the DAC
|
||||
if (pid > 0xFFF)
|
||||
{
|
||||
pid = 0xFFF;
|
||||
}
|
||||
else if (pid < 0)
|
||||
{
|
||||
pid = 0;
|
||||
}
|
||||
// Send the PID value to the DAC
|
||||
MAX5715Channel_setValue(self->dac[loopCounter], pid);
|
||||
|
||||
LOGGER_DEBUG(mainLog, "Row %d --- ADC: %d Error: %d PID: %d", loopCounter, adcValue, error, pid);
|
||||
}
|
||||
}
|
||||
|
||||
self->secondsCounter++;
|
||||
}
|
||||
|
||||
LOGGER_INFO(mainLog, "Deleting repairProcess task");
|
||||
vTaskDelete(self->taskHandle);
|
||||
}
|
||||
|
||||
|
||||
static int SignalProfileGenerator(struct RepairProcess* self)
|
||||
{
|
||||
int returnValue = 0;
|
||||
|
||||
if (self->initialized)
|
||||
{
|
||||
|
||||
switch (self->currentState)
|
||||
{
|
||||
@@ -201,110 +241,61 @@ static void repairProcess_task(void* parameters)
|
||||
LOGGER_DEBUG(mainLog, "Repair Process: Preparing new stage of repair process");
|
||||
// Prepare a new repair process
|
||||
//Load the timers
|
||||
startTime = self->secondsCounter;
|
||||
softStartTimer = self->secondsCounter + self->repairPreset->preset[presetIndex].softstartDuration;
|
||||
LOGGER_DEBUG(mainLog, "Softstart timer is %d (%d + %d)", softStartTimer, self->secondsCounter, self->repairPreset->preset[presetIndex].softstartDuration);
|
||||
voltageHoldTimer = self->secondsCounter + self->repairPreset->preset[presetIndex].duration;
|
||||
LOGGER_DEBUG(mainLog, "Voltagehold timer is %d (%d + %d)", voltageHoldTimer, self->secondsCounter, self->repairPreset->preset[presetIndex].duration);
|
||||
|
||||
voltageTarget = self->repairPreset->preset[presetIndex].voltage;
|
||||
|
||||
|
||||
voltageRow1 = 0;
|
||||
voltageRow2 = 0;
|
||||
voltageRow3 = 0;
|
||||
// Anode and CathodeMCP run all 3 ADCs and DACs
|
||||
MAX5715Channel_setValue(self->dacRow1, voltageRow1);
|
||||
MAX5715Channel_setValue(self->dacRow2, voltageRow2);
|
||||
MAX5715Channel_setValue(self->dacRow3, voltageRow3);
|
||||
|
||||
|
||||
|
||||
///TODO CHECK FOR SAFETLY BEFORE START
|
||||
self->startTime = self->secondsCounter;
|
||||
self->softStartTimer = self->secondsCounter + self->repairPreset->preset[self->currentPresetIndex].softstartDuration;
|
||||
LOGGER_DEBUG(mainLog, "Softstart timer is %d (%d + %d)", self->softStartTimer, self->secondsCounter, self->repairPreset->preset[self->currentPresetIndex].softstartDuration);
|
||||
self->voltageHoldTimer = self->secondsCounter + self->repairPreset->preset[self->currentPresetIndex].duration;
|
||||
LOGGER_DEBUG(mainLog, "Voltagehold timer is %d (%d + %d)", self->voltageHoldTimer, self->secondsCounter, self->repairPreset->preset[self->currentPresetIndex].duration);
|
||||
|
||||
self->currentState = SOFTSTART;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SOFTSTART:
|
||||
{
|
||||
// Perform softstart / ramp-up
|
||||
// Still in Softstart
|
||||
int startVoltage = 0;
|
||||
|
||||
LOGGER_DEBUG(mainLog, "------------------------------");
|
||||
|
||||
if (PCBA_getInstance()->pcba == Tesla)
|
||||
// If first preset, start voltage is 0
|
||||
if (self->currentPresetIndex == 0)
|
||||
{
|
||||
// Tesla repair only runs ADC row2 and DAC row2
|
||||
voltageRow2 = SignalProfileGenerator(startTime, self->secondsCounter, self->repairPreset, presetIndex);
|
||||
LOGGER_DEBUG(mainLog, "Softstart running -> new target is %x", voltageRow2);
|
||||
ADCChannel_read(self->adcRow3, &adcVoltageRow2);
|
||||
LOGGER_DEBUG(mainLog, "Softstart running ->ADC reads %x", adcVoltageRow2);
|
||||
pidError = voltageRow2 - adcVoltageRow2;
|
||||
LOGGER_DEBUG(mainLog, "Softstart running ->PID Error %x", pidError);
|
||||
int pidCalc = PID_calculate(&self->pidRow2, voltageRow2, pidError);
|
||||
LOGGER_DEBUG(mainLog, "Softstart running ->PID calculates %x", pidCalc);
|
||||
|
||||
if (pidCalc >= 0)
|
||||
{
|
||||
MAX5715Channel_setValue(self->dacRow2, pidCalc);
|
||||
}
|
||||
startVoltage = 0;
|
||||
}
|
||||
else if ((PCBA_getInstance()->pcba == Anode) || (PCBA_getInstance()->pcba == CathodeMCP))
|
||||
else
|
||||
{
|
||||
|
||||
// Softstart for another stage - start voltage is hold voltage of previous preset
|
||||
startVoltage = self->repairPreset->preset[self->currentPresetIndex - 1].voltage;
|
||||
}
|
||||
returnValue = ((self->repairPreset->preset[self->currentPresetIndex].voltage - startVoltage) / self->repairPreset->preset[self->currentPresetIndex].softstartDuration) * (self->secondsCounter - self->startTime) + startVoltage;
|
||||
|
||||
// Check for end of softstart
|
||||
if (softStartTimer < self->secondsCounter)
|
||||
if (self->softStartTimer < self->secondsCounter)
|
||||
{
|
||||
// softstart finished
|
||||
self->currentState = VOLTAGE_HOLD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VOLTAGE_HOLD:
|
||||
{
|
||||
// Actual repair state - hold target voltage until duration has passed
|
||||
LOGGER_DEBUG(mainLog, "------------------------------");
|
||||
returnValue = self->repairPreset->preset[self->currentPresetIndex].voltage;
|
||||
|
||||
if (PCBA_getInstance()->pcba == Tesla)
|
||||
{
|
||||
// Tesla repair only runs ADC row2 and DAC row2
|
||||
|
||||
voltageRow2 = SignalProfileGenerator(startTime, self->secondsCounter, self->repairPreset, presetIndex);
|
||||
LOGGER_DEBUG(mainLog, "Voltage Hold running -> new target is %x", voltageRow2);
|
||||
ADCChannel_read(self->adcRow3, &adcVoltageRow2);
|
||||
LOGGER_DEBUG(mainLog, "Voltage Hold running ->ADC reads %x", adcVoltageRow2);
|
||||
pidError = voltageRow2 - adcVoltageRow2;
|
||||
LOGGER_DEBUG(mainLog, "Voltage Hold running ->PID Error %x", pidError);
|
||||
int pidCalc = PID_calculate(&self->pidRow2, voltageRow2, pidError);
|
||||
LOGGER_DEBUG(mainLog, "Voltage Hold running ->PID calculates %x", pidCalc);
|
||||
|
||||
if (pidCalc >= 0)
|
||||
{
|
||||
MAX5715Channel_setValue(self->dacRow2, pidCalc);
|
||||
}
|
||||
}
|
||||
else if ((PCBA_getInstance()->pcba == Anode) || (PCBA_getInstance()->pcba == CathodeMCP))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Check for end of softstart
|
||||
if (voltageHoldTimer < self->secondsCounter)
|
||||
// Check for end of voltage hold
|
||||
if (self->voltageHoldTimer < self->secondsCounter)
|
||||
{
|
||||
// softstart finished
|
||||
self->currentState = FINISH_VERIFY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PAUSE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case PAUSE_RESTORE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case FINISH_VERIFY:
|
||||
{
|
||||
// The current preset might contain multiple stages, so before going to FINISHED state
|
||||
@@ -313,10 +304,10 @@ static void repairProcess_task(void* parameters)
|
||||
// presetIndex carries the current index in the preset array
|
||||
// number of stages is 1-based (Starting with 1) while presetIndex is 0-based
|
||||
// So, the verification must compensate for the different bases
|
||||
if (self->repairPreset->numberOfStages > (presetIndex + 1))
|
||||
if (self->repairPreset->numberOfStages > (self->currentPresetIndex + 1))
|
||||
{
|
||||
// A next stage is available
|
||||
presetIndex++;
|
||||
self->currentPresetIndex++;
|
||||
self->currentState = PREPARE;
|
||||
LOGGER_DEBUG(mainLog, "Another stage is available");
|
||||
}
|
||||
@@ -327,62 +318,17 @@ static void repairProcess_task(void* parameters)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FINISHED:
|
||||
{
|
||||
voltageRow1 = 0;
|
||||
voltageRow2 = 0;
|
||||
voltageRow3 = 0;
|
||||
// Anode and CathodeMCP run all 3 ADCs and DACs
|
||||
MAX5715Channel_setValue(self->dacRow1, voltageRow1);
|
||||
MAX5715Channel_setValue(self->dacRow2, voltageRow2);
|
||||
MAX5715Channel_setValue(self->dacRow3, voltageRow3);
|
||||
|
||||
// LOGGER_DEBUG(mainLog, "Repair process finished");
|
||||
returnValue = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOGGER_ERROR(mainLog, "Repair Process state machine reached unknown state");
|
||||
}
|
||||
|
||||
|
||||
self->secondsCounter++;
|
||||
}
|
||||
|
||||
LOGGER_INFO(mainLog, "Deleting repairProcess task");
|
||||
vTaskDelete(self->taskHandle);
|
||||
}
|
||||
|
||||
|
||||
static int SignalProfileGenerator(uint32_t startTime, uint32_t currentTime, struct RepairPreset* repairPreset, int presetIndex)
|
||||
{
|
||||
int returnValue = 0;
|
||||
|
||||
// Differ between softstart period and voltage hold
|
||||
if (currentTime - startTime < repairPreset->preset[presetIndex].softstartDuration)
|
||||
{
|
||||
// Still in Softstart
|
||||
int startVoltage = 0;
|
||||
|
||||
// If first preset, start voltage is 0
|
||||
if (presetIndex == 0)
|
||||
{
|
||||
startVoltage = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Softstart for another stage - start voltage is hold voltage of previous preset
|
||||
startVoltage = repairPreset->preset[presetIndex - 1].voltage;
|
||||
}
|
||||
returnValue = ((repairPreset->preset[presetIndex].voltage - startVoltage) / repairPreset->preset[presetIndex].softstartDuration) * (currentTime - startTime) + startVoltage;
|
||||
}
|
||||
else
|
||||
{
|
||||
// In voltage hold
|
||||
returnValue = repairPreset->preset[presetIndex].voltage;
|
||||
returnValue = -1;
|
||||
}
|
||||
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ void IRQ_setKeypadEXTI(struct Keypad* self, FunctionalState command)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function handles SVCall exception.
|
||||
* @param None
|
||||
@@ -229,6 +230,10 @@ void SPI3_IRQHandler (void)
|
||||
portEND_SWITCHING_ISR(higherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void EXTI4_IRQHandler(void)
|
||||
{
|
||||
static signed portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
Reference in New Issue
Block a user