Explorar el Código

EPS-SBC-CAM co-working with ADC

implemented ADC fn., CAM error handling, and trouble-shooting.
need to do add SKKU AI.
Yoojin Lim hace 2 años
padre
commit
aec253ac2f

+ 2 - 2
.settings/language.settings.xml

@@ -5,7 +5,7 @@
 			<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
 			<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
 			<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
-			<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1536420537785334433" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+			<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-1090172336588582191" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
 				<language-scope id="org.eclipse.cdt.core.gcc"/>
 				<language-scope id="org.eclipse.cdt.core.g++"/>
 			</provider>
@@ -16,7 +16,7 @@
 			<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
 			<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
 			<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
-			<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1536420537785334433" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+			<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-1090172336588582191" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
 				<language-scope id="org.eclipse.cdt.core.gcc"/>
 				<language-scope id="org.eclipse.cdt.core.g++"/>
 			</provider>

+ 40 - 12
Core/Inc/ImC/imc_api.h

@@ -11,6 +11,9 @@
 #include "stm32l5xx_hal.h"
 #include "sc03mpd/sc03mpd.h"
 
+#define UART_HANDLER_SBC		huart1
+#define UART_HANDLER_CAM		huart3
+
 #define NUM_OF_LED				4
 
 #define LED0_GPIO				GPIOB
@@ -29,8 +32,16 @@
 #define SBC_POWER_GPIO_PIN		GPIO_PIN_11
 #define CAM_POWER_GPIO_PIN		GPIO_PIN_7
 
-#define POWER_ON				GPIO_PIN_RESET		// LOW
-#define POWER_OFF				GPIO_PIN_SET		// HIGH
+#define POWER_ON_SBC			GPIO_PIN_RESET		// LOW; only for SBC
+#define POWER_OFF_SBC			GPIO_PIN_SET		// HIGH; only for SBC
+#define POWER_ON				GPIO_PIN_SET		// CAM, Sensors, etc. (KETI, 230811)
+#define POWER_OFF				GPIO_PIN_RESET		// CAM, Sensors, etc. (KETI, 230811)
+
+#define EPS_CAP_VOLT_GPIO		0
+#define EPS_CAP_VOLT_ADC		1
+
+#if (EPS_CAP_VOLT_GPIO)
+#define EPS_SBC_OFF_LEVEL		1					// 1~7
 
 #define ENERGY_LV0_GPIO			GPIOF
 #define ENERGY_LV1_GPIO			GPIOF
@@ -39,18 +50,34 @@
 #define ENERGY_LV0_GPIO_PIN		GPIO_PIN_8
 #define ENERGY_LV1_GPIO_PIN		GPIO_PIN_9
 #define ENERGY_LV2_GPIO_PIN		GPIO_PIN_10
+#endif
 
-#define EPS_SBC_OFF_LEVEL		1					// 1~7
+#if (EPS_CAP_VOLT_ADC)
+#define ADC_HANDLER_SBC		hadc1
+#define ADC_HANDLER_CAM		hadc2
+#define EPS_CAP_VOLT_LOW_THRESHOLD_SBC	(3600) 		// Voltage threshold to do the checkpointing in MilliVolt
+#define EPS_CAP_VOLT_LOW_THRESHOLD_CAM	(3700) 		// Voltage threshold to do the checkpointing in MilliVolt
+#define EPS_CAP_VOLT_HIGH_THRESHOLD_CAM	(4800)		// Voltage threshold to do the checkpointing in MilliVolt
+#define DELAY_WAIT_CAP_CHECK	(2000)
+#define COUNTER_WAIT_CAP_CHECK	(60)
+#define EPS_CAP_ID_SBC			0
+#define EPS_CAP_ID_CAM			1
+
+int measure_voltage(ADC_HandleTypeDef hadc, uint8_t ch);
+int32_t imc_sc03mpd_cap_check (ADC_HandleTypeDef hadc);
+#endif
 
 #define	CAM_SHOT_PIN			GPIO_PIN_6
 
 #define	DELAY_IGNORE_REQ		(500)				// 500ticks
-#define DELAY_AFTER_POWERUP		(650)				// 2500 ms in manual
-#define DELAY_AFTER_CAPTURE		(250)				//
-#define DELAY_AFTER_LENGTH		(50)				//
-#define DELAY_BEFORE_ERR_HANDLING	(50)			// 50 ms
+#define DELAY_AFTER_POWERUP		(1000)				// 2500 ms in manual
+#define DELAY_AFTER_CAPTURE		(250)				// 250
+#define DELAY_AFTER_LENGTH		(10)				//
+#define DELAY_DURING_DOWNLOAD	(1)
+#define DELAY_BEFORE_ERR_HANDLING	(100)			// 50 ms
 #define DELAY_GET_ENERGY_LEVEL	(3)					// 3 ms
-#define DELAY_AFTER_WORK		(50)				// 50ms
+#define DELAY_AFTER_WORK		(100)				// 50ms
+#define DELAY_DO_SOMETHING		(1000)
 
 #define IMG_RAM_ADDR			(0x68200000)
 #define IMG_BLK_SIZE			(256)
@@ -67,6 +94,7 @@
 #define CAM_FAST_READY				0
 #define CAM_BLACK_WHITE				0
 #define CAM_COMP_ZERO				1
+#define CAM_ERROR_COUNT_MAX			5				// successive ERRORs -> SBC reboot
 
 #define IMAGE_RESOLUTION		SC03MPD_RES_160_120	// _640_480, _320_240 (default), _160_120
 #if CAM_COMP_ZERO
@@ -82,10 +110,10 @@ int32_t imc_sc03mpd_init(sc03mpd_ifx_t* ifx);
 int32_t imc_sc03mpd_capture (sc03mpd_ifx_t* ifx);
 int32_t imc_sc03mpd_reset (sc03mpd_ifx_t* ifx);
 
-void imc_sbc_power_off (uint32_t msec);
-void imc_sbc_power_on (uint32_t msec);
-void imc_cam_power_off (uint32_t msec);
-void imc_cam_power_on (uint32_t msec);
+void imc_sbc_power_off ();
+void imc_sbc_power_on ();
+void imc_cam_power_off ();
+void imc_cam_power_on ();
 
 uint8_t imc_get_energy_level ();
 

+ 80 - 18
Core/Src/ImC/imc_api.c

@@ -64,7 +64,6 @@ void imc_led_blink (uint8_t ledSet[], uint8_t length, uint32_t msec)
 	osDelay(msec);
 }
 
-
 int32_t imc_sc03mpd_init (sc03mpd_ifx_t* ifx)
 {
 	/* initial operation process :
@@ -79,15 +78,16 @@ int32_t imc_sc03mpd_init (sc03mpd_ifx_t* ifx)
 	 * OPTION for SKKU) manually step color, select black-white
 	 */
 
+
+/*	//move to main.c
 #if !CAM_FAST_READY
 	printf("[CAM] wait %dms for boot-up\r\n", DELAY_AFTER_POWERUP);
 	osDelay (DELAY_AFTER_POWERUP);
 #endif
 	//printf("[SC03MPD] init CAM ...\r\n");
 
-	// (M33) moved to caller (static fn.)
-	//MX_USART3_UART_Init();
-
+	MX_USART3_UART_Init();
+*/
 	SC03MPD_ASSERT(sc03mpd_reset(ifx), "[CAM] FAILED reset", INIT_ERROR)
 	SC03MPD_ASSERT(sc03mpd_set_ires(ifx, IMAGE_RESOLUTION),	"[CAM] FAILED set resolution", INIT_ERROR)
 	SC03MPD_ASSERT(sc03mpd_reset(ifx), "[CAM] FAILED reset for image setting", INIT_ERROR)
@@ -149,6 +149,8 @@ int32_t imc_sc03mpd_capture (sc03mpd_ifx_t* ifx) {
 	  rest -= nreq;
 	  addr += nreq;
 	  imem += nreq;
+
+	  //osDelay(DELAY_DURING_DOWNLOAD);
 	}
 
 	tsEnd = HAL_GetTick();
@@ -190,38 +192,31 @@ RESET_ERROR:
 }
 
 
-void imc_sbc_power_off (uint32_t msec)
+void imc_sbc_power_off ()
 {
 	printf("[EPS] SBC OFF\r\n");
-	osDelay(msec);
-
-	HAL_GPIO_WritePin(SBC_POWER_GPIO, SBC_POWER_GPIO_PIN, POWER_OFF);
+	HAL_GPIO_WritePin(SBC_POWER_GPIO, SBC_POWER_GPIO_PIN, POWER_OFF_SBC);
 }
 
-void imc_sbc_power_on (uint32_t msec)
+void imc_sbc_power_on ()
 {
 	printf("[EPS] SBC on\r\n");
-	osDelay(msec);
-
-	HAL_GPIO_WritePin(SBC_POWER_GPIO, SBC_POWER_GPIO_PIN, POWER_ON);
+	HAL_GPIO_WritePin(SBC_POWER_GPIO, SBC_POWER_GPIO_PIN, POWER_ON_SBC);
 }
 
-void imc_cam_power_off (uint32_t msec)
+void imc_cam_power_off ()
 {
 	printf("[EPS] CAM OFF\r\n");
-	osDelay(msec);
-
 	HAL_GPIO_WritePin(CAM_POWER_GPIO, CAM_POWER_GPIO_PIN, POWER_OFF);
 }
 
-void imc_cam_power_on (uint32_t msec)
+void imc_cam_power_on ()
 {
 	printf("[EPS] CAM ON\r\n");
-	osDelay(msec);
-
 	HAL_GPIO_WritePin(CAM_POWER_GPIO, CAM_POWER_GPIO_PIN, POWER_ON);
 }
 
+#if (EPS_CAP_VOLT_GPIO)
 /*
  * energy level : 0~7 with 3bits of GPIO pins
  * ignore level update between reading each pin
@@ -248,3 +243,70 @@ uint8_t imc_get_energy_level ()
 
 	return bigger;
 }
+#endif
+
+#if (EPS_CAP_VOLT_ADC)
+int compare(const void *a, const void *b) {
+    return (*(int*)a - *(int*)b);
+}
+
+int medianCalc(int* input, int arr_size){
+    qsort(input, arr_size, sizeof(int), compare);
+    if (arr_size%2)
+    	return input[arr_size/2];
+    else
+    	return (input[arr_size/2-1] + input[arr_size/2])/2;
+
+}
+
+uint16_t MEAS_COEF[2] = {812, 782};	// for EPS CAP ch0 and ch1
+int measure_voltage(ADC_HandleTypeDef hadc, uint8_t ch){
+	int res_value[5];
+
+/* UCR ref.
+	#define MEAS_COEF 3051	// UCR 2790, ETRI 3051
+	int v_value = ((uint32_t)medianCalc(res_value, 5))*5000/MEAS_COEF; // in milliVolt
+*/
+	for (int i=0; i<5; i++)
+	{
+		HAL_ADC_Start(&hadc);
+		// Poll ADC Peripheral & TimeOut = 1mSec
+		HAL_ADC_PollForConversion(&hadc, 1);
+		res_value[i] = HAL_ADC_GetValue(&hadc);
+	}
+
+	int v_value = ((uint32_t)medianCalc(res_value, 5)) * MEAS_COEF[ch] / 500; //
+//	int voltage_d = v_value/1000;
+//	int voltage_f = v_value%1000;
+//	printf("ADC Value:     %d.%03d \r\n", voltage_d, voltage_f);
+	return v_value;
+}
+
+int32_t imc_sc03mpd_cap_check (ADC_HandleTypeDef hadc)
+{
+	int count = 0;
+	int capacitor_voltage = measure_voltage(hadc, EPS_CAP_ID_CAM);
+
+	if (capacitor_voltage < EPS_CAP_VOLT_LOW_THRESHOLD_CAM)
+	{
+		imc_cam_power_off();
+		printf ("[CAM] CAP#%d < %dmV\r\n", EPS_CAP_ID_CAM, EPS_CAP_VOLT_LOW_THRESHOLD_CAM);
+
+		while (capacitor_voltage < EPS_CAP_VOLT_HIGH_THRESHOLD_CAM) {
+			printf ("\twait(%2d) %dmV\r\n", count, capacitor_voltage);
+			osDelay (DELAY_WAIT_CAP_CHECK);
+
+			if (count >= COUNTER_WAIT_CAP_CHECK){
+				return CAM_STS_EINI;
+			}
+
+			capacitor_voltage = measure_voltage(hadc, EPS_CAP_ID_CAM);
+			count++;
+		}
+
+		printf ("[CAM] CAP#%d > %dV\r\n", EPS_CAP_ID_CAM, EPS_CAP_VOLT_HIGH_THRESHOLD_CAM);
+	}
+
+	return CAM_STS_ENON;
+}
+#endif

+ 0 - 44
Core/Src/ImC/uartBufferIT.c

@@ -1,44 +0,0 @@
-/*
- * uartBufferIT.h
- *
- *  Created on: Aug 22, 2022
- *      Author: yoojin.lim
- *
- *  1. Current MAX buffer size : 65535 (ref. range of uint16)
- *  2. Consider DMA and circular queue if you need data read over 65535 bytes
- */
-
-#include <stdio.h>
-
-#include "main.h"
-#include "ImC/uartBufferIT.h"
-#include "string.h"
-
-uint8_t		rxBuffer[RX_BUFFER_SIZE];
-
-/* Initialize the Ring Buffer */
-void uartBufferInit (void)
-{
-	memset(rxBuffer, '\0', RX_BUFFER_SIZE);
-	HAL_UARTEx_ReceiveToIdle_IT	(&UART, (uint8_t *) rxBuffer, RX_BUFFER_SIZE);
-}
-
-/* Resets the Ring buffer */
-void uartBufferReset (void)
-{
-	memset(rxBuffer, '\0', RX_BUFFER_SIZE);
-}
-
-void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
-{
-	if (huart->Instance == UART_INSTANCE)
-	{
-		/* start the interrupt again */
-		HAL_UARTEx_ReceiveToIdle_IT	(&UART, (uint8_t *) rxBuffer, RX_BUFFER_SIZE);
-	}
-	printf("%s\r\n", rxBuffer);
-
-	// DO SOMETHING HERE
-
-	uartBufferReset();
-}

+ 133 - 31
Core/Src/main.c

@@ -82,6 +82,7 @@ typedef StaticTask_t osStaticThreadDef_t;
 
 /* Private variables ---------------------------------------------------------*/
 ADC_HandleTypeDef hadc1;
+ADC_HandleTypeDef hadc2;
 
 FDCAN_HandleTypeDef hfdcan1;
 
@@ -105,7 +106,7 @@ SRAM_HandleTypeDef hsram4;
 
 /* Definitions for taskEPS */
 osThreadId_t taskEPSHandle;
-uint32_t taskEPSBuffer[ 128 ];
+uint32_t taskEPSBuffer[ 256 ];
 osStaticThreadDef_t taskEPSControlBlock;
 const osThreadAttr_t taskEPS_attributes = {
   .name = "taskEPS",
@@ -125,7 +126,7 @@ const osThreadAttr_t taskSnap_attributes = {
   .stack_size = sizeof(taskSnapBuffer),
   .cb_mem = &taskSnapControlBlock,
   .cb_size = sizeof(taskSnapControlBlock),
-  .priority = (osPriority_t) osPriorityNormal,
+  .priority = (osPriority_t) osPriorityRealtime,
 };
 /* Definitions for taskAI */
 osThreadId_t taskAIHandle;
@@ -161,12 +162,12 @@ static void MX_USART2_UART_Init(void);
 static void MX_USART3_UART_Init(void);
 static void MX_ICACHE_Init(void);
 static void MX_GTZC_Init(void);
+static void MX_ADC2_Init(void);
 void taskEPSRunner(void *argument);
 void taskSnapRunner(void *argument);
 void taskAIRunner(void *argument);
 
 /* USER CODE BEGIN PFP */
-
 /* USER CODE END PFP */
 
 /* Private user code ---------------------------------------------------------*/
@@ -176,7 +177,7 @@ extern "C" int _write(int32_t file, uint8_t *ptr, int32_t len) {
 #else
 int _write(int32_t file, uint8_t *ptr, int32_t len) {
 #endif
-    if( HAL_UART_Transmit(&huart1, ptr, len, len) == HAL_OK ) return len;
+    if( HAL_UART_Transmit(&UART_HANDLER_SBC, ptr, len, len) == HAL_OK ) return len;
     else return 0;
 }
 
@@ -251,16 +252,17 @@ int main(void)
   MX_USART3_UART_Init();
   MX_ICACHE_Init();
   MX_USB_Device_Init();
+  MX_ADC2_Init();
   /* USER CODE BEGIN 2 */
   printf("\r\n\r\n\r\n");
   printf("**************************\r\n");
   printf("** TEST APP INFORMATION **\r\n");
-  printf(" - SBC M33 freeRTOS, truztzone, CAM, EPS\r\n");
-  printf(" - 2023. 7. 13. 12:00\r\n");
+  printf(" - SBC M33 freeRTOS, truztzone, ADC test\r\n");
+  printf(" - 2023.10.20. 10:00\r\n");
   printf("**************************\r\n");
   printf("\r\n\r\n\r\n");
   /* after SBC boot-up, sbc power gpio pin should be ON */
-  imc_sbc_power_on(0);	// delay(param) should be 0ms
+  imc_sbc_power_on();	// delay(param) should be 0ms
 
   /* USER CODE END 2 */
 
@@ -303,6 +305,7 @@ int main(void)
 
   /* Start scheduler */
   osKernelStart();
+
   /* We should never get here as control is now taken by the scheduler */
   /* Infinite loop */
   /* USER CODE BEGIN WHILE */
@@ -470,6 +473,64 @@ static void MX_ADC1_Init(void)
 
 }
 
+/**
+  * @brief ADC2 Initialization Function
+  * @param None
+  * @retval None
+  */
+static void MX_ADC2_Init(void)
+{
+
+  /* USER CODE BEGIN ADC2_Init 0 */
+
+  /* USER CODE END ADC2_Init 0 */
+
+  ADC_ChannelConfTypeDef sConfig = {0};
+
+  /* USER CODE BEGIN ADC2_Init 1 */
+
+  /* USER CODE END ADC2_Init 1 */
+
+  /** Common config
+  */
+  hadc2.Instance = ADC2;
+  hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
+  hadc2.Init.Resolution = ADC_RESOLUTION_12B;
+  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
+  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
+  hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
+  hadc2.Init.LowPowerAutoWait = DISABLE;
+  hadc2.Init.ContinuousConvMode = DISABLE;
+  hadc2.Init.NbrOfConversion = 1;
+  hadc2.Init.DiscontinuousConvMode = DISABLE;
+  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
+  hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
+  hadc2.Init.DMAContinuousRequests = DISABLE;
+  hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
+  hadc2.Init.OversamplingMode = DISABLE;
+  if (HAL_ADC_Init(&hadc2) != HAL_OK)
+  {
+    Error_Handler();
+  }
+
+  /** Configure Regular Channel
+  */
+  sConfig.Channel = ADC_CHANNEL_2;
+  sConfig.Rank = ADC_REGULAR_RANK_1;
+  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
+  sConfig.SingleDiff = ADC_SINGLE_ENDED;
+  sConfig.OffsetNumber = ADC_OFFSET_NONE;
+  sConfig.Offset = 0;
+  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
+  {
+    Error_Handler();
+  }
+  /* USER CODE BEGIN ADC2_Init 2 */
+
+  /* USER CODE END ADC2_Init 2 */
+
+}
+
 /**
   * @brief FDCAN1 Initialization Function
   * @param None
@@ -940,18 +1001,14 @@ static void MX_USART3_UART_Init(void)
 /*
  * use below code if code is re-generated by .ioc modification
 #if CAM_CHANGE_BAUDRATE
-  huart3.Init.BaudRate = 38400;
+  UART_HANDLER_CAM.Init.BaudRate = 38400;
 #else
-  huart3.Init.BaudRate = 115200;
+  UART_HANDLER_CAM.Init.BaudRate = 115200;
 #endif
 */
   /* USER CODE END USART3_Init 1 */
   huart3.Instance = USART3;
-#if CAM_CHANGE_BAUDRATE
-  huart3.Init.BaudRate = 38400;
-#else
   huart3.Init.BaudRate = 115200;
-#endif
   huart3.Init.WordLength = UART_WORDLENGTH_8B;
   huart3.Init.StopBits = UART_STOPBITS_1;
   huart3.Init.Parity = UART_PARITY_NONE;
@@ -1282,11 +1339,35 @@ static void MX_GPIO_Init(void)
 void taskEPSRunner(void *argument)
 {
   /* USER CODE BEGIN 5 */
+#if (EPS_CAP_VOLT_ADC)
+	int capacitor_voltage0 = 0;
+	//int capacitor_voltage1 = 0;
+
 	/* Infinite loop */
+	for(;;)
+	{
+		capacitor_voltage0 = measure_voltage(ADC_HANDLER_SBC, EPS_CAP_ID_SBC);
+		//capacitor_voltage1 = measure_voltage(ADC_HANDLER_CAM, EPS_CAP_ID_CAM);
+
+		//printf("\t\t\t\t\t\t[EPS] CAP VOLT: %d.%03d, %d.%03d\r\n", capacitor_voltage0/1000, capacitor_voltage0%1000, capacitor_voltage1/1000, capacitor_voltage1%1000);
+
+		if (capacitor_voltage0 < EPS_CAP_VOLT_LOW_THRESHOLD_SBC)
+		{
+			printf("[EPS] CAP#%d < %dmV (TODO JIT CHECKPOINT)\r\n", EPS_CAP_ID_SBC, EPS_CAP_VOLT_LOW_THRESHOLD_SBC);
+			// TODO: JIT CHECKPOINT
+			imc_sbc_power_off();
+		}
+
+		osDelay(DELAY_AFTER_WORK);
+	}
+#endif
+
+#if (EPS_CAP_VOLT_GPIO)
 	/* energy_level: 1~7, and SBC power off when the level is 1 */
 	uint8_t	energy_level_prev	= 8;
 	uint8_t	energy_level_curr	= 8;
 
+	/* Infinite loop */
 	for(;;)
 	{
 		energy_level_curr = imc_get_energy_level();
@@ -1298,7 +1379,7 @@ void taskEPSRunner(void *argument)
 
 			if (energy_level_curr <= EPS_SBC_OFF_LEVEL)
 			{
-				imc_sbc_power_off(0);
+				imc_sbc_power_off();
 			}
 
 			energy_level_prev = energy_level_curr;
@@ -1306,6 +1387,7 @@ void taskEPSRunner(void *argument)
 
 		osDelay(DELAY_AFTER_WORK);
 	}
+#endif
   /* USER CODE END 5 */
 }
 
@@ -1322,26 +1404,36 @@ void taskSnapRunner(void *argument)
 {
   /* USER CODE BEGIN taskSnapRunner */
 	sc03mpd_ifx_t ifx = {
-		.context = (void*)&huart3,
+		.context = (void*)&UART_HANDLER_CAM,
 		.sendif  = hal_uart_ifx_send,
 		.recvif  = hal_uart_ifx_recv,
 	};
 
+	uint8_t error_count = 0;
+
   /* Infinite loop */
 	while (1)
 	{
+		printf ("\r\n\r\n\r\n#%ld\r\n\r\n", trial);
+		trial++;
+
 //		osSemaphoreWait(empty, osWaitForever);
 
+#if EPS_CAP_VOLT_ADC
+		SC03MPD_ASSERT(imc_sc03mpd_cap_check (ADC_HANDLER_CAM), "[CAM] FAILED CAP volt", ERROR)
+#endif
+
 		/*
 		 * 2022. 11. 10. TEST for EPS-SBC-CAM; SBC controls CAM ON/OFF; KETI EPS does NOT wait 2.5s for CAM init.
 		 */
-		printf ("\r\n\r\n#%lu\r\n\r\n", trial);
-		trial++;
+		imc_cam_power_on();
 
-		imc_cam_power_on(0);
+		// (M33) moved from imc_sc03mpd_init
+		printf("[CAM] wait %dms for boot-up\r\n", DELAY_AFTER_POWERUP);
+		osDelay (DELAY_AFTER_POWERUP);
+		MX_USART3_UART_Init();
+		// (M33) moved from imc_sc03mpd_init
 
-		/* camera init */
-		MX_USART3_UART_Init();	// (M33) moved from imc_sc03mpd_init
 		SC03MPD_ASSERT(imc_sc03mpd_init(&ifx), "[CAM] FAILED init", ERROR)
 
 		/* execute once when change CAM default baudrate */
@@ -1373,7 +1465,10 @@ void taskSnapRunner(void *argument)
 		/*
 		 * 2022. 11. 10. TEST for EPS-SBC-CAM
 		 */
-		imc_cam_power_off(0);
+		imc_cam_power_off();
+
+		// error_count reset
+		error_count = 0;
 
 		/* DO SOMETHING */
 #if 0
@@ -1383,8 +1478,8 @@ void taskSnapRunner(void *argument)
 
 //		osSemaphoreRelease(full);
 #else
-		printf ("[SBC] wait %dms for next job\r\n", DELAY_AFTER_WORK);
-		osDelay(DELAY_AFTER_WORK);
+		printf ("[SBC] wait %dms for DO SOMETHING\r\n", DELAY_DO_SOMETHING);
+		osDelay(DELAY_DO_SOMETHING);
 #endif
 
 		continue;
@@ -1395,20 +1490,27 @@ ERROR:
 		 * 2022. 8. 25. add USART3 init. and reset fn.; download or capture failure --> normal
 		 * 2022. 8. 25. after SC03MPD power off/on, works well after few failures
 		 * 2022. 11. 11. start of this while loop, CAM init is called
+		 * 2023. 10. 20. add error_count for handling successive errors
 		 */
-#if 1
+		error_count++;
+
 		printf("[CAM] ERROR HANDLING; CAM OFF > %dms delay > CAM ON\r\n", DELAY_BEFORE_ERR_HANDLING);
-		imc_cam_power_off(0);
+		imc_cam_power_off();
 //		osSemaphoreRelease(empty);
 
-		osDelay(DELAY_BEFORE_ERR_HANDLING);
+		osDelay(DELAY_BEFORE_ERR_HANDLING);	//imc_sbc_power_off();
 
-		continue;
-#else
-		osDelay(DELAY_BEFORE_ERR_HANDLING);
+		// ERROR 3 times -> SBC reboot
+		if (error_count >= CAM_ERROR_COUNT_MAX) {
+			error_count = 0;
 
-		SC03MPD_ASSERT(imc_sc03mpd_init(&ifx), "[CAM] FAILED ERROR HANDLING; init", ERROR)
-#endif
+			printf("[CAM] %d ERRORs continue and SBC OFF\r\n", CAM_ERROR_COUNT_MAX);
+			imc_sbc_power_off();
+
+			osDelay(DELAY_DO_SOMETHING);
+		}
+
+		continue;
 	}
 #if 0
 EXIT:

+ 55 - 2
Core/Src/stm32l5xx_hal_msp.c

@@ -20,6 +20,7 @@
 
 /* Includes ------------------------------------------------------------------*/
 #include "main.h"
+
 /* USER CODE BEGIN Includes */
 
 /* USER CODE END Includes */
@@ -83,6 +84,8 @@ void HAL_MspInit(void)
   /* USER CODE END MspInit 1 */
 }
 
+static uint32_t HAL_RCC_ADC_CLK_ENABLED=0;
+
 /**
 * @brief ADC MSP Initialization
 * This function configures the hardware resources used in this example
@@ -98,7 +101,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
 
   /* USER CODE END ADC1_MspInit 0 */
     /* Peripheral clock enable */
-    __HAL_RCC_ADC_CLK_ENABLE();
+    HAL_RCC_ADC_CLK_ENABLED++;
+    if(HAL_RCC_ADC_CLK_ENABLED==1){
+      __HAL_RCC_ADC_CLK_ENABLE();
+    }
 
     __HAL_RCC_GPIOC_CLK_ENABLE();
     __HAL_RCC_GPIOA_CLK_ENABLE();
@@ -133,6 +139,30 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
 
   /* USER CODE END ADC1_MspInit 1 */
   }
+  else if(hadc->Instance==ADC2)
+  {
+  /* USER CODE BEGIN ADC2_MspInit 0 */
+
+  /* USER CODE END ADC2_MspInit 0 */
+    /* Peripheral clock enable */
+    HAL_RCC_ADC_CLK_ENABLED++;
+    if(HAL_RCC_ADC_CLK_ENABLED==1){
+      __HAL_RCC_ADC_CLK_ENABLE();
+    }
+
+    __HAL_RCC_GPIOC_CLK_ENABLE();
+    /**ADC2 GPIO Configuration
+    PC1     ------> ADC2_IN2
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_1;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+  /* USER CODE BEGIN ADC2_MspInit 1 */
+
+  /* USER CODE END ADC2_MspInit 1 */
+  }
 
 }
 
@@ -150,7 +180,10 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
 
   /* USER CODE END ADC1_MspDeInit 0 */
     /* Peripheral clock disable */
-    __HAL_RCC_ADC_CLK_DISABLE();
+    HAL_RCC_ADC_CLK_ENABLED--;
+    if(HAL_RCC_ADC_CLK_ENABLED==0){
+      __HAL_RCC_ADC_CLK_DISABLE();
+    }
 
     /**ADC1 GPIO Configuration
     PC0     ------> ADC1_IN1
@@ -173,6 +206,26 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
 
   /* USER CODE END ADC1_MspDeInit 1 */
   }
+  else if(hadc->Instance==ADC2)
+  {
+  /* USER CODE BEGIN ADC2_MspDeInit 0 */
+
+  /* USER CODE END ADC2_MspDeInit 0 */
+    /* Peripheral clock disable */
+    HAL_RCC_ADC_CLK_ENABLED--;
+    if(HAL_RCC_ADC_CLK_ENABLED==0){
+      __HAL_RCC_ADC_CLK_DISABLE();
+    }
+
+    /**ADC2 GPIO Configuration
+    PC1     ------> ADC2_IN2
+    */
+    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1);
+
+  /* USER CODE BEGIN ADC2_MspDeInit 1 */
+
+  /* USER CODE END ADC2_MspDeInit 1 */
+  }
 
 }
 

+ 3 - 3
imc_freertos_app_m33.cfg

@@ -25,9 +25,9 @@ set CLOCK_FREQ 8000
 # Reset configuration
 # use hardware reset, connect under reset
 # connect_assert_srst needed if low power mode application running (WFI...)
-# reset_config srst_only srst_nogate connect_assert_srst
-# set CONNECT_UNDER_RESET 1
-# set CORE_RESET 0
+reset_config srst_only srst_nogate connect_assert_srst
+set CONNECT_UNDER_RESET 1
+set CORE_RESET 0
 
 # ACCESS PORT NUMBER
 set AP_NUM 0

+ 45 - 34
imc_freertos_app_m33.ioc

@@ -7,6 +7,13 @@ ADC1.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE
 ADC1.Rank-0\#ChannelRegularConversion=1
 ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_2CYCLES_5
 ADC1.master=1
+ADC2.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_2
+ADC2.CommonPathInternal=null|null|null|null
+ADC2.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,CommonPathInternal
+ADC2.NbrOfConversionFlag=1
+ADC2.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE
+ADC2.Rank-0\#ChannelRegularConversion=1
+ADC2.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_2CYCLES_5
 CAD.formats=
 CAD.pinconfig=
 CAD.provider=
@@ -27,7 +34,7 @@ FMC.WriteOperation2=FMC_WRITE_OPERATION_ENABLE
 FMC.WriteOperation3=FMC_WRITE_OPERATION_ENABLE
 FREERTOS.FootprintOK=true
 FREERTOS.IPParameters=Tasks01,FootprintOK
-FREERTOS.Tasks01=taskEPS,24,128,taskEPSRunner,Default,NULL,Static,taskEPSBuffer,taskEPSControlBlock;taskSnap,24,512,taskSnapRunner,Default,NULL,Static,taskSnapBuffer,taskSnapControlBlock;taskAI,24,37968,taskAIRunner,Default,NULL,Static,taskAIBuffer,taskAIControlBlock
+FREERTOS.Tasks01=taskEPS,24,256,taskEPSRunner,Default,NULL,Static,taskEPSBuffer,taskEPSControlBlock;taskSnap,48,512,taskSnapRunner,Default,NULL,Static,taskSnapBuffer,taskSnapControlBlock;taskAI,24,37968,taskAIRunner,Default,NULL,Static,taskAIBuffer,taskAIControlBlock
 File.Version=6
 GPIO.groupedBy=Group By Peripherals
 I2C1.IPParameters=Timing
@@ -39,28 +46,29 @@ Mcu.CPN=STM32L552ZET3
 Mcu.ContextProject=TrustZoneDisabled
 Mcu.Family=STM32L5
 Mcu.IP0=ADC1
-Mcu.IP1=DEBUG
-Mcu.IP10=PWR
-Mcu.IP11=RCC
-Mcu.IP12=SPI1
-Mcu.IP13=SPI2
-Mcu.IP14=SYS
-Mcu.IP15=TIM7
-Mcu.IP16=UART4
-Mcu.IP17=USART1
-Mcu.IP18=USART2
-Mcu.IP19=USART3
-Mcu.IP2=FDCAN1
-Mcu.IP20=USB
-Mcu.IP21=USB_DEVICE
-Mcu.IP3=FMC
-Mcu.IP4=FREERTOS
-Mcu.IP5=GTZC
-Mcu.IP6=I2C1
-Mcu.IP7=I2C3
-Mcu.IP8=ICACHE
-Mcu.IP9=NVIC
-Mcu.IPNb=22
+Mcu.IP1=ADC2
+Mcu.IP10=NVIC
+Mcu.IP11=PWR
+Mcu.IP12=RCC
+Mcu.IP13=SPI1
+Mcu.IP14=SPI2
+Mcu.IP15=SYS
+Mcu.IP16=TIM7
+Mcu.IP17=UART4
+Mcu.IP18=USART1
+Mcu.IP19=USART2
+Mcu.IP2=DEBUG
+Mcu.IP20=USART3
+Mcu.IP21=USB
+Mcu.IP22=USB_DEVICE
+Mcu.IP3=FDCAN1
+Mcu.IP4=FMC
+Mcu.IP5=FREERTOS
+Mcu.IP6=GTZC
+Mcu.IP7=I2C1
+Mcu.IP8=I2C3
+Mcu.IP9=ICACHE
+Mcu.IPNb=23
 Mcu.Name=STM32L552ZETx
 Mcu.Package=LQFP144
 Mcu.Pin0=PE2
@@ -179,8 +187,8 @@ Mcu.PinsNb=112
 Mcu.ThirdPartyNb=0
 Mcu.UserConstants=
 Mcu.UserName=STM32L552ZETx
-MxCube.Version=6.8.1
-MxDb.Version=DB.6.0.81
+MxCube.Version=6.9.0
+MxDb.Version=DB.6.0.90
 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
 NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
 NVIC.ForceEnableDMAVector=true
@@ -437,8 +445,10 @@ ProjectManager.RegisterCallBack=
 ProjectManager.StackSize=0x400
 ProjectManager.TargetToolchain=STM32CubeIDE
 ProjectManager.ToolChainLocation=
+ProjectManager.UAScriptAfterPath=
+ProjectManager.UAScriptBeforePath=
 ProjectManager.UnderRoot=true
-ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_ADC1_Init-ADC1-false-HAL-true,4-MX_FDCAN1_Init-FDCAN1-false-HAL-true,5-MX_FMC_Init-FMC-false-HAL-true,6-MX_I2C1_Init-I2C1-false-HAL-true,7-MX_I2C3_Init-I2C3-false-HAL-true,8-MX_SPI1_Init-SPI1-false-HAL-true,9-MX_SPI2_Init-SPI2-false-HAL-true,10-MX_TIM7_Init-TIM7-false-HAL-true,11-MX_UART4_Init-UART4-false-HAL-true,12-MX_USART1_UART_Init-USART1-false-HAL-true,13-MX_USART2_UART_Init-USART2-false-HAL-true,14-MX_USART3_UART_Init-USART3-false-HAL-true,15-MX_ICACHE_Init-ICACHE-false-HAL-true,16-MX_USB_Device_Init-USB_DEVICE-false-HAL-false,17-MX_GTZC_Init-GTZC-false-HAL-true,0-MX_PWR_Init-PWR-false-HAL-true
+ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_ADC1_Init-ADC1-false-HAL-true,4-MX_FDCAN1_Init-FDCAN1-false-HAL-true,5-MX_FMC_Init-FMC-false-HAL-true,6-MX_I2C1_Init-I2C1-false-HAL-true,7-MX_I2C3_Init-I2C3-false-HAL-true,8-MX_SPI1_Init-SPI1-false-HAL-true,9-MX_SPI2_Init-SPI2-false-HAL-true,10-MX_TIM7_Init-TIM7-false-HAL-true,11-MX_UART4_Init-UART4-false-HAL-true,12-MX_USART1_UART_Init-USART1-false-HAL-true,13-MX_USART2_UART_Init-USART2-false-HAL-true,14-MX_USART3_UART_Init-USART3-false-HAL-true,15-MX_ICACHE_Init-ICACHE-false-HAL-true,16-MX_USB_Device_Init-USB_DEVICE-false-HAL-false,17-MX_GTZC_Init-GTZC-false-HAL-true,18-MX_ADC2_Init-ADC2-false-HAL-true,0-MX_PWR_Init-PWR-false-HAL-true
 RCC.ADCFreq_Value=48000000
 RCC.AHBCLKDivider=RCC_SYSCLK_DIV2
 RCC.AHBFreq_Value=32000000
@@ -505,19 +515,20 @@ RCC.VCOSAI2OutputFreq_Value=32000000
 RCC.WatchDogFreq_Value=32000
 SH.ADCx_IN1.0=ADC1_IN1,IN1-Single-Ended
 SH.ADCx_IN1.ConfNb=1
-SH.ADCx_IN12.0=ADC1_IN12,IN12-Single-Ended
+SH.ADCx_IN12.0=ADC1_IN12
 SH.ADCx_IN12.ConfNb=1
-SH.ADCx_IN13.0=ADC1_IN13,IN13-Single-Ended
+SH.ADCx_IN13.0=ADC1_IN13
 SH.ADCx_IN13.ConfNb=1
-SH.ADCx_IN15.0=ADC1_IN15,IN15-Single-Ended
+SH.ADCx_IN15.0=ADC1_IN15
 SH.ADCx_IN15.ConfNb=1
-SH.ADCx_IN16.0=ADC1_IN16,IN16-Single-Ended
+SH.ADCx_IN16.0=ADC1_IN16
 SH.ADCx_IN16.ConfNb=1
-SH.ADCx_IN2.0=ADC1_IN2,IN2-Single-Ended
-SH.ADCx_IN2.ConfNb=1
-SH.ADCx_IN3.0=ADC1_IN3,IN3-Single-Ended
+SH.ADCx_IN2.0=ADC1_IN2
+SH.ADCx_IN2.1=ADC2_IN2,IN2-Single-Ended
+SH.ADCx_IN2.ConfNb=2
+SH.ADCx_IN3.0=ADC1_IN3
 SH.ADCx_IN3.ConfNb=1
-SH.ADCx_IN4.0=ADC1_IN4,IN4-Single-Ended
+SH.ADCx_IN4.0=ADC1_IN4
 SH.ADCx_IN4.ConfNb=1
 SH.FMC_A0.0=FMC_A0,24b-a2
 SH.FMC_A0.1=FMC_A0,21b-a1