diff --git a/workspace/TS100/inc/FRToSI2C.hpp b/workspace/TS100/inc/FRToSI2C.hpp index b62d1ac3..35213a9f 100644 --- a/workspace/TS100/inc/FRToSI2C.hpp +++ b/workspace/TS100/inc/FRToSI2C.hpp @@ -34,6 +34,7 @@ public: private: static I2C_HandleTypeDef *i2c; + static void I2C1_ClearBusyFlagErratum(); static SemaphoreHandle_t I2CSemaphore; }; diff --git a/workspace/TS100/inc/Settings.h b/workspace/TS100/inc/Settings.h index 65dccd67..140bab92 100644 --- a/workspace/TS100/inc/Settings.h +++ b/workspace/TS100/inc/Settings.h @@ -12,7 +12,7 @@ #include #include "stm32f1xx_hal.h" #define SETTINGSVERSION \ - 0x16 /*Change this if you change the struct below to prevent people getting \ + 0x18 /*Change this if you change the struct below to prevent people getting \ out of sync*/ /* diff --git a/workspace/TS100/src/FRToSI2C.cpp b/workspace/TS100/src/FRToSI2C.cpp index 10f8e616..6504d77a 100644 --- a/workspace/TS100/src/FRToSI2C.cpp +++ b/workspace/TS100/src/FRToSI2C.cpp @@ -4,95 +4,182 @@ * Created on: 14Apr.,2018 * Author: Ralim */ - +#include "hardware.h" #include "FRToSI2C.hpp" #define I2CUSESDMA I2C_HandleTypeDef* FRToSI2C::i2c; SemaphoreHandle_t FRToSI2C::I2CSemaphore; void FRToSI2C::CpltCallback() { - i2c->State = HAL_I2C_STATE_READY; // Force state reset (even if tx error) - if (I2CSemaphore) { - - xSemaphoreGiveFromISR(I2CSemaphore, NULL); - } + i2c->State = HAL_I2C_STATE_READY; // Force state reset (even if tx error) + if (I2CSemaphore) { + xSemaphoreGiveFromISR(I2CSemaphore, NULL); + } } void FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, - uint16_t MemAddSize, uint8_t* pData, uint16_t Size) { + uint16_t MemAddSize, uint8_t* pData, uint16_t Size) { + + if (I2CSemaphore == NULL) { + // no RToS, run blocking code + HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size, + 5000); + } else { + // RToS is active, run threading + // Get the mutex so we can use the I2C port + // Wait up to 1 second for the mutex + if (xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE) { #ifdef I2CUSESDMA - if (I2CSemaphore == NULL) { - // no RToS, run blocking code - HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size, - 5000); - } else { - // RToS is active, run threading - // Get the mutex so we can use the I2C port - // Wait up to 1 second for the mutex - if (xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE) { - if (HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size, - 5000) != HAL_OK) { - } - xSemaphoreGive(I2CSemaphore); - } else { - } - } + if (HAL_I2C_Mem_Read_DMA(i2c, DevAddress, MemAddress, MemAddSize, + pData, Size) != HAL_OK) { + + I2C1_ClearBusyFlagErratum(); + xSemaphoreGive(I2CSemaphore); + } #else - HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size, - 5000); + + HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size, + 5000); + xSemaphoreGive(I2CSemaphore); #endif + } else { + } + } + } void FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { - Mem_Write(address, reg, I2C_MEMADD_SIZE_8BIT, &data, 1); + Mem_Write(address, reg, I2C_MEMADD_SIZE_8BIT, &data, 1); } uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { - uint8_t tx_data[1]; - Mem_Read(add, reg, I2C_MEMADD_SIZE_8BIT, tx_data, 1); - return tx_data[0]; + uint8_t tx_data[1]; + Mem_Read(add, reg, I2C_MEMADD_SIZE_8BIT, tx_data, 1); + return tx_data[0]; } void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, - uint16_t MemAddSize, uint8_t* pData, uint16_t Size) { -#ifdef I2CUSESDMA - if (I2CSemaphore == NULL) { - // no RToS, run blocking code - HAL_I2C_Mem_Write(i2c, DevAddress, MemAddress, MemAddSize, pData, Size, - 5000); - } else { - // RToS is active, run threading - // Get the mutex so we can use the I2C port - // Wait up to 1 second for the mutex - if (xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE) { - if (HAL_I2C_Mem_Write(i2c, DevAddress, MemAddress, MemAddSize, pData, - Size, 5000) != HAL_OK) { - } - xSemaphoreGive(I2CSemaphore); + uint16_t MemAddSize, uint8_t* pData, uint16_t Size) { - } else { - } - } + if (I2CSemaphore == NULL) { + // no RToS, run blocking code + HAL_I2C_Mem_Write(i2c, DevAddress, MemAddress, MemAddSize, pData, Size, + 5000); + } else { + // RToS is active, run threading + // Get the mutex so we can use the I2C port + // Wait up to 1 second for the mutex + if (xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE) { +#ifdef I2CUSESDMA + if (HAL_I2C_Mem_Write_DMA(i2c, DevAddress, MemAddress, MemAddSize, + pData, Size) != HAL_OK) { + + I2C1_ClearBusyFlagErratum(); + xSemaphoreGive(I2CSemaphore); + } #else - HAL_I2C_Mem_Write(i2c, DevAddress, MemAddress, MemAddSize, pData, Size, - 5000); + if (HAL_I2C_Mem_Write(i2c, DevAddress, MemAddress, MemAddSize, pData, + Size, 5000) != HAL_OK) { + } + xSemaphoreGive(I2CSemaphore); #endif + } else { + } + } + } void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t* pData, uint16_t Size) { + if (I2CSemaphore == NULL) { + // no RToS, run blocking code + HAL_I2C_Master_Transmit(i2c, DevAddress, pData, Size, 5000); + } else { + // RToS is active, run threading + // Get the mutex so we can use the I2C port + // Wait up to 1 second for the mutex + if (xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE) { #ifdef I2CUSESDMA - if (I2CSemaphore == NULL) { - // no RToS, run blocking code - HAL_I2C_Master_Transmit(i2c, DevAddress, pData, Size, 5000); - } else { - // RToS is active, run threading - // Get the mutex so we can use the I2C port - // Wait up to 1 second for the mutex - if (xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE) { - if (HAL_I2C_Master_Transmit_DMA(i2c, DevAddress, pData, Size) != HAL_OK) { - } - // xSemaphoreGive(I2CSemaphore); - } else { - } - } + + if (HAL_I2C_Master_Transmit_DMA(i2c, DevAddress, pData, Size) + != HAL_OK) { + + I2C1_ClearBusyFlagErratum(); + xSemaphoreGive(I2CSemaphore); + + } #else - HAL_I2C_Master_Transmit(i2c, DevAddress, pData, Size, 5000); + HAL_I2C_Master_Transmit(i2c, DevAddress, pData, Size, 5000); + xSemaphoreGive(I2CSemaphore); #endif + + } else { + } + } + +} + +void FRToSI2C::I2C1_ClearBusyFlagErratum() { + GPIO_InitTypeDef GPIO_InitStruct; + int timeout = 100; + int timeout_cnt = 0; + + // 1. Clear PE bit. + i2c->Instance->CR1 &= ~(0x0001); + /**I2C1 GPIO Configuration + PB6 ------> I2C1_SCL + PB7 ------> I2C1_SDA + */ + // 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + + GPIO_InitStruct.Pin = SCL_Pin; + HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct); + HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); + + GPIO_InitStruct.Pin = SDA_Pin; + HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct); + HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); + + while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) { + //Move clock to release I2C + HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET); + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); + + timeout_cnt++; + if (timeout_cnt > timeout) + return; + } + + // 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain. + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + + GPIO_InitStruct.Pin = SCL_Pin; + HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = SDA_Pin; + HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct); + + HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); + + // 13. Set SWRST bit in I2Cx_CR1 register. + i2c->Instance->CR1 |= 0x8000; + + asm("nop"); + + // 14. Clear SWRST bit in I2Cx_CR1 register. + i2c->Instance->CR1 &= ~0x8000; + + asm("nop"); + + // 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register + i2c->Instance->CR1 |= 0x0001; + + // Call initialization function. + HAL_I2C_Init(i2c); } diff --git a/workspace/TS100/src/Setup.c b/workspace/TS100/src/Setup.c index 0a0f3d42..ce834931 100644 --- a/workspace/TS100/src/Setup.c +++ b/workspace/TS100/src/Setup.c @@ -361,13 +361,13 @@ static void MX_DMA_Init(void) { /* DMA interrupt init */ /* DMA1_Channel1_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 15, 0); + HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); /* DMA1_Channel6_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 15, 0); + HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); /* DMA1_Channel7_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 15, 0); + HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn); } diff --git a/workspace/TS100/src/main.cpp b/workspace/TS100/src/main.cpp index 08f72851..e7c566ab 100644 --- a/workspace/TS100/src/main.cpp +++ b/workspace/TS100/src/main.cpp @@ -69,7 +69,7 @@ int main(void) { /* Create the thread(s) */ /* definition and creation of GUITask */ - osThreadDef(GUITask, startGUITask, osPriorityBelowNormal, 0, 4 * 1024 / 4); + osThreadDef(GUITask, startGUITask, osPriorityBelowNormal, 0, 5 * 1024 / 4); GUITaskHandle = osThreadCreate(osThread(GUITask), NULL); /* definition and creation of PIDTask */ @@ -77,7 +77,7 @@ int main(void) { PIDTaskHandle = osThreadCreate(osThread(PIDTask), NULL); if (PCBVersion < 3) { /* definition and creation of MOVTask */ - osThreadDef(MOVTask, startMOVTask, osPriorityNormal, 0, 2 * 1024 / 4); + osThreadDef(MOVTask, startMOVTask, osPriorityNormal, 0, 3 * 1024 / 4); MOVTaskHandle = osThreadCreate(osThread(MOVTask), NULL); } @@ -266,36 +266,36 @@ static void gui_drawBatteryIcon() { // we need to calculate which of the 10 levels they are on uint8_t cellCount = systemSettings.cutoutSetting + 2; uint16_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) - / cellCount; + / cellCount; // Should give us approx cell voltage X10 // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 if (cellV < 33) - cellV = 33; - cellV -= 33;// Should leave us a number of 0-9 + cellV = 33; + cellV -= 33; // Should leave us a number of 0-9 if (cellV > 9) - cellV = 9; + cellV = 9; OLED::drawBattery(cellV + 1); } else - OLED::drawSymbol(15); // Draw the DC Logo + OLED::drawSymbol(15); // Draw the DC Logo #else - // On TS80 we replace this symbol with the voltage we are operating on - // If <9V then show single digit, if not show duals - uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); - if (V % 10 >= 5) - V = V / 10 + 1; // round up - else - V = V / 10; - if (V >= 10) { - int16_t xPos = OLED::getCursorX(); - OLED::setFont(1); - OLED::printNumber(1, 1); - OLED::setCursor(xPos, 8); - OLED::printNumber(V % 10, 1); - OLED::setFont(0); - OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char - } else { - OLED::printNumber(V, 1); - } + // On TS80 we replace this symbol with the voltage we are operating on + // If <9V then show single digit, if not show duals + uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); + if (V % 10 >= 5) + V = V / 10 + 1;// round up + else + V = V / 10; + if (V >= 10) { + int16_t xPos = OLED::getCursorX(); + OLED::setFont(1); + OLED::printNumber(1, 1); + OLED::setCursor(xPos, 8); + OLED::printNumber(V % 10, 1); + OLED::setFont(0); + OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char + } else { + OLED::printNumber(V, 1); + } #endif } static void gui_solderingTempAdjust() { @@ -367,7 +367,7 @@ static void gui_solderingTempAdjust() { #ifdef MODEL_TS80 if (!OLED::getRotation()) #else - if (OLED::getRotation()) + if (OLED::getRotation()) #endif OLED::drawChar('-'); else @@ -383,7 +383,7 @@ static void gui_solderingTempAdjust() { #ifdef MODEL_TS80 if (!OLED::getRotation()) #else - if (OLED::getRotation()) + if (OLED::getRotation()) #endif OLED::drawChar('+'); else @@ -410,7 +410,7 @@ static int gui_SolderingSleepingMode() { || (xTaskGetTickCount() - lastButtonTime < 100)) return 0; // user moved or pressed a button, go back to soldering #ifdef MODEL_TS100 - if (checkVoltageForExit()) + if (checkVoltageForExit()) return 1; // return non-zero on error #endif if (systemSettings.temperatureInF) { @@ -501,6 +501,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { * --> Double button to exit */ bool boostModeOn = false; + uint8_t badTipCounter = 0; uint32_t sleepThres = 0; if (systemSettings.SleepTime < 6) sleepThres = systemSettings.SleepTime * 10 * 100; @@ -549,14 +550,10 @@ static void gui_solderingMode(uint8_t jumpToSleep) { OLED::clearScreen(); OLED::setFont(0); uint16_t tipTemp = getTipRawTemp(0); - if (tipTemp > 32752) { - OLED::print(BadTipString); - OLED::refresh(); - currentlyActiveTemperatureTarget = 0; - waitForButtonPress(); - currentlyActiveTemperatureTarget = 0; - return; + if (tipTemp > 32760) { + badTipCounter++; } else { + badTipCounter = 0; if (systemSettings.detailedSoldering) { OLED::setFont(1); OLED::print(SolderingAdvancedPowerPrompt); // Power: @@ -615,6 +612,14 @@ static void gui_solderingMode(uint8_t jumpToSleep) { } } } + if (badTipCounter > 128) { + OLED::print(BadTipString); + OLED::refresh(); + currentlyActiveTemperatureTarget = 0; + waitForButtonPress(); + currentlyActiveTemperatureTarget = 0; + return; + } OLED::refresh(); // Update the setpoints for the temperature @@ -671,7 +676,7 @@ __DATE__, "Heap: ", "HWMG: ", "HWMP: ", "HWMM: ", "Time: ", "Move: ", "RTip: ", "Tm ", "Ralim-", #endif - }; + }; void showVersion(void) { uint8_t screen = 0; @@ -681,9 +686,9 @@ void showVersion(void) { OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) OLED::setFont(1); // small font #ifdef MODEL_TS100 - OLED::print((char *) "V2.06 TS100"); // Print version number + OLED::print((char *) "V2.06 TS100"); // Print version number #else - OLED::print((char *) "V2.06 TS80"); // Print version number + OLED::print((char *) "V2.06 TS80"); // Print version number #endif OLED::setCursor(0, 8); // second line OLED::print(HEADERS[screen]); @@ -870,7 +875,7 @@ void startGUITask(void const *argument __unused) { #ifdef MODEL_TS80 if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif OLED::drawArea(12, 0, 84, 16, idleScreenBG); OLED::setCursor(0, 0); @@ -891,7 +896,7 @@ void startGUITask(void const *argument __unused) { #ifdef MODEL_TS80 if (!OLED::getRotation()) { #else - if (OLED::getRotation()) { + if (OLED::getRotation()) { #endif // in right handed mode we want to draw over the first part OLED::fillArea(55, 0, 41, 16, 0); // clear the area for the temp @@ -920,14 +925,14 @@ void startPIDTask(void const *argument __unused) { */ setTipMilliWatts(0); // disable the output driver if the output is set to be off #ifdef MODEL_TS80 - idealQCVoltage = calculateMaxVoltage(systemSettings.cutoutSetting); + idealQCVoltage = calculateMaxVoltage(systemSettings.cutoutSetting); #endif uint8_t rawC = ctoTipMeasurement(101) - ctoTipMeasurement(100); // 1*C change in raw. #ifdef MODEL_TS80 - //Set power management code to the tip resistance in ohms * 10 - setupPower(calculateTipR() / 100); - size_t lastPowerPulse = 0; + //Set power management code to the tip resistance in ohms * 10 + setupPower(calculateTipR() / 100); + size_t lastPowerPulse = 0; #else setupPower(85); @@ -944,10 +949,11 @@ void startPIDTask(void const *argument __unused) { if (currentlyActiveTemperatureTarget) { // Cap the max set point to 450C if (currentlyActiveTemperatureTarget > ctoTipMeasurement(450)) { + //Maximum allowed output currentlyActiveTemperatureTarget = ctoTipMeasurement(450); - } - if (currentlyActiveTemperatureTarget > 32500) { - currentlyActiveTemperatureTarget = 32500; + } else if (currentlyActiveTemperatureTarget > 32400) { + //Cap to max adc reading + currentlyActiveTemperatureTarget = 32400; } // As we get close to our target, temp noise causes the system @@ -1033,9 +1039,9 @@ void startMOVTask(void const *argument __unused) { #ifdef MODEL_TS80 startQC(systemSettings.voltageDiv); while (pidTaskNotification == 0) - osDelay(20); // To ensure we return after idealQCVoltage/tip resistance + osDelay(20); // To ensure we return after idealQCVoltage/tip resistance - seekQC(idealQCVoltage, systemSettings.voltageDiv); // this will move the QC output to the preferred voltage to start with + seekQC(idealQCVoltage, systemSettings.voltageDiv);// this will move the QC output to the preferred voltage to start with #else osDelay(250); // wait for accelerometer to stabilize @@ -1121,9 +1127,9 @@ void startMOVTask(void const *argument __unused) { osDelay(100); // Slow down update rate #ifdef MODEL_TS80 - if (currentlyActiveTemperatureTarget) { - seekQC(idealQCVoltage, systemSettings.voltageDiv); // Run the QC seek again to try and compensate for cable V drop - } + if (currentlyActiveTemperatureTarget) { + seekQC(idealQCVoltage, systemSettings.voltageDiv); // Run the QC seek again to try and compensate for cable V drop + } #endif } } @@ -1185,9 +1191,13 @@ void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); } void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c __unused) { + asm("bkpt"); + FRToSI2C::CpltCallback(); } void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c __unused) { + asm("bkpt"); + FRToSI2C::CpltCallback(); } void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { @@ -1195,6 +1205,7 @@ void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { } void vApplicationStackOverflowHook(xTaskHandle *pxTask __unused, signed portCHAR *pcTaskName __unused) { + asm("bkpt"); // We dont have a good way to handle a stack overflow at this point in time NVIC_SystemReset(); } diff --git a/workspace/TS100/src/stm32f1xx_hal_msp.c b/workspace/TS100/src/stm32f1xx_hal_msp.c index 28cbd206..6715d4bf 100644 --- a/workspace/TS100/src/stm32f1xx_hal_msp.c +++ b/workspace/TS100/src/stm32f1xx_hal_msp.c @@ -88,7 +88,7 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) { GPIO_InitStruct.Pin = SCL_Pin | SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* Peripheral clock enable */