// Macros to enable/disable global interrupts #define enable_interrupts() asm(" cpsie i ") #define disable_interrupts() asm(" cpsid i ") // DBGMCU Register Adressen #define DBGMCU_BASE 0x40015800 #define DBGMCU_IDCODE (*(volatile uint32_t*)(DBGMCU_BASE + 0x00)) #define DBGMCU_CR (*(volatile uint32_t*)(DBGMCU_BASE + 0x04)) #define DBGMCU_APB_FZ1 (*(volatile uint32_t*)(DBGMCU_BASE + 0x08)) #define DBGMCU_APB_FZ2 (*(volatile uint32_t*)(DBGMCU_BASE + 0x0C)) // Flash Size Register #define FLASHSIZE_BASE 0x1FFF0FFC #define FLASH_SIZE (*(volatile uint16_t*)FLASHSIZE_BASE) // Unique ID (96-bit) #define UID_BASE 0x1FFF0E00 #define UID0 (*(volatile uint32_t*)(UID_BASE + 0x00)) #define UID1 (*(volatile uint32_t*)(UID_BASE + 0x04)) #define UID2 (*(volatile uint32_t*)(UID_BASE + 0x08)) // RCC Register (NUR EINMAL definiert!) ✅ #define RCC_BASE 0x40021000 #define RCC_CR (*(volatile uint32_t*)(RCC_BASE + 0x00)) #define RCC_ICSCR (*(volatile uint32_t*)(RCC_BASE + 0x04)) #define RCC_CFGR (*(volatile uint32_t*)(RCC_BASE + 0x08)) #define RCC_APB1ENR (*(volatile uint32_t*)(RCC_BASE + 0x1C)) #define RCC_BDCR (*(volatile uint32_t*)(RCC_BASE + 0x20)) // Kalibrierungswerte aus Flash (bei 30°C und 3.3V) #define TS_CAL1_ADDR 0x1FFF0F1C // Temp Kalibrierung bei 30°C #define VREFINT_CAL_ADDR 0x1FFF0F18 // VREFINT Kalibrierung bei 3.3V // ADC Kanäle #define VREFINT_CHANNEL 12 // ADC Kanal für VREFINT #define TEMP_CHANNEL 11 // ADC Kanal für Temperatursensor // Temperatur Koeffizienten (aus Datenblatt) #define AVG_SLOPE 4.3f // mV/°C (typisch) #define V30 1.43f // Spannung bei 30°C in Volt uint16_t ts_cal1 = 0; uint16_t vrefint_cal = 0; void initCalibrationValues(void); // NEUE FUNKTION: Kalibrierungswerte laden void initCalibrationValues(void) { ts_cal1 = *((uint16_t*)TS_CAL1_ADDR); vrefint_cal = *((uint16_t*)VREFINT_CAL_ADDR); } void iwdg_setup(void) { // Enable the LSI (Low-Speed Internal) oscillator used by the IWDG // ACHTUNG: LSI wird auch für RTC verwendet! RCC->CSR |= RCC_CSR_LSION; while (!(RCC->CSR & RCC_CSR_LSIRDY)) { // Wait until LSI is stable } IWDG->KR = 0x5555; // Unlock IWDG->PR = 0x06; // Prescaler /64 IWDG->RLR = 0x0FFF; // Max reload IWDG->KR = 0xCCCC; // Start } void refreshIWDG(void) { IWDG->KR = 0xAAAA; } const char* getDeviceName(uint16_t device_id) { switch(device_id) { case 0x200: return "PY32F030x6"; case 0x201: return "PY32F030x8"; case 0x202: return "PY32F030x4"; default: return "Unknown"; } } const char* getRevisionName(uint16_t rev) { switch(rev) { case 0x1000: return "Rev A"; case 0x1001: return "Rev B"; case 0x1002: return "Rev C"; case 0x2000: return "Rev X"; default: return "Unknown"; } } const char* getClockSource(void) { uint32_t sws = (RCC_CFGR >> 2) & 0x03; switch(sws) { case 0: return "HSI (Internal 8MHz/24MHz)"; case 1: return "HSE (External)"; case 2: return "PLL"; case 3: return "LSI (Internal 32kHz)"; default: return "Unknown"; } } uint32_t getSystemClock(void) { uint32_t sws = (RCC_CFGR >> 2) & 0x03; uint32_t sysclk = 8000000; if(sws == 0) { if(RCC_ICSCR & (1 << 13)) { sysclk = 24000000; } else { sysclk = 8000000; } } return sysclk; } void printDebugConfig(uint32_t cr) { Serial.println("\nDebug Configuration (CR):"); Serial.printf(" DBG_STOP : %s\n", (cr & (1<<1)) ? "Enabled" : "Disabled"); Serial.printf(" DBG_STANDBY : %s\n", (cr & (1<<2)) ? "Enabled" : "Disabled"); } void printAPBFreeze(void) { uint32_t apb_fz1 = DBGMCU_APB_FZ1; uint32_t apb_fz2 = DBGMCU_APB_FZ2; Serial.println("\nAPB Peripheral Freeze (Debug Mode):"); Serial.printf(" APB_FZ1: 0x%08lX\n", apb_fz1); if(apb_fz1 & (1<<0)) Serial.println(" - TIM1 stopped"); if(apb_fz1 & (1<<4)) Serial.println(" - TIM3 stopped"); if(apb_fz1 & (1<<10)) Serial.println(" - RTC stopped"); if(apb_fz1 & (1<<11)) Serial.println(" - WWDG stopped"); if(apb_fz1 & (1<<12)) Serial.println(" - IWDG stopped"); Serial.printf(" APB_FZ2: 0x%08lX\n", apb_fz2); if(apb_fz2 & (1<<2)) Serial.println(" - TIM14 stopped"); } uint16_t getRAMSize(uint16_t device_id) { switch(device_id) { case 0x200: return 4; case 0x201: return 8; case 0x202: return 4; default: return 0; } } void dumpDBGMCU(void) { Serial.println("\n╔════════════════════════════════════════════╗"); Serial.println("║ PY32F030 SYSTEM & DEBUG INFORMATION ║"); Serial.println("╚════════════════════════════════════════════╝"); uint32_t id = DBGMCU_IDCODE; uint16_t device = (uint16_t)(id & 0x0FFF); uint16_t revision = (uint16_t)(id >> 16); Serial.println("\n[DEVICE IDENTIFICATION]"); Serial.printf("IDCODE : 0x%08lX\n", id); Serial.printf("Device ID : 0x%03X (%s)\n", device, getDeviceName(device)); Serial.printf("Revision : 0x%04X (%s)\n", revision, getRevisionName(revision)); Serial.println("\n[UNIQUE DEVICE ID - 96 bit]"); Serial.printf("UID[31:0] : 0x%08lX\n", UID0); Serial.printf("UID[63:32] : 0x%08lX\n", UID1); Serial.printf("UID[95:64] : 0x%08lX\n", UID2); Serial.print("Serial Number : "); Serial.printf("%08lX-%08lX-%08lX\n", UID2, UID1, UID0); uint16_t flash_kb = FLASH_SIZE; uint16_t ram_kb = getRAMSize(device); Serial.println("\n[MEMORY CONFIGURATION]"); Serial.printf("Flash Size : %d KB\n", flash_kb); Serial.printf("RAM Size : %d KB (estimated)\n", ram_kb); Serial.printf("Flash Base : 0x08000000\n"); Serial.printf("RAM Base : 0x20000000\n"); uint32_t sysclk = getSystemClock(); Serial.println("\n[CLOCK CONFIGURATION]"); Serial.printf("RCC_CR : 0x%08lX\n", RCC_CR); Serial.printf("RCC_ICSCR : 0x%08lX\n", RCC_ICSCR); Serial.printf("RCC_CFGR : 0x%08lX\n", RCC_CFGR); Serial.printf("Clock Source : %s\n", getClockSource()); Serial.printf("System Clock : %lu Hz (%lu MHz)\n", sysclk, sysclk / 1000000); Serial.printf("HSI Ready : %s\n", (RCC_CR & (1<<1)) ? "Yes" : "No"); Serial.printf("HSE Ready : %s\n", (RCC_CR & (1<<17)) ? "Yes" : "No"); Serial.printf("PLL Ready : %s\n", (RCC_CR & (1<<25)) ? "Yes" : "No"); Serial.println("\n[DEBUG CONFIGURATION]"); Serial.printf("DBGMCU_CR : 0x%08lX\n", DBGMCU_CR); printDebugConfig(DBGMCU_CR); printAPBFreeze(); Serial.println("\n[RUNTIME INFORMATION]"); Serial.printf("Uptime : %lu ms\n", millis()); Serial.printf("Free Heap : N/A (bare metal)\n"); Serial.println("\n[FACTORY CALIBRATION]"); Serial.printf("VREFINT Cal : %d (@ 3.3V)\n", vrefint_cal); Serial.printf("Temp Cal : %d (@ 30°C)\n", ts_cal1); Serial.println("\n╚════════════════════════════════════════════╝\n"); } float getVDD() { // Sicherstellen dass vrefint_cal initialisiert ist if(vrefint_cal == 0) { initCalibrationValues(); } uint16_t vrefint_raw = analogRead(VREFINT_CHANNEL); return (3.3f * vrefint_cal) / vrefint_raw; } float getTemperature() { // Sicherstellen dass ts_cal1 initialisiert ist if(ts_cal1 == 0) { initCalibrationValues(); } uint16_t temp_raw = analogRead(TEMP_CHANNEL); float vdd = getVDD(); float temp_normalized = (temp_raw * 3.3f) / vdd; float ts_cal1_normalized = (ts_cal1 * 3.3f) / 3.3f; float temp_mv = (temp_normalized - ts_cal1_normalized) * (3300.0f / 4095.0f); float temperature = 30.0f + (temp_mv / AVG_SLOPE); return temperature; } float getTemperature_V2() { if(ts_cal1 == 0) { initCalibrationValues(); } uint16_t temp_raw = analogRead(TEMP_CHANNEL); float vdd = getVDD(); float vsense = (temp_raw * vdd) / 4095.0f; float temperature = ((V30 - vsense) * 1000.0f / AVG_SLOPE) + 30.0f; return temperature; } float getTemperature_Average(uint8_t samples) { if(ts_cal1 == 0) { initCalibrationValues(); } uint32_t sum = 0; for(uint8_t i = 0; i < samples; i++) { sum += analogRead(TEMP_CHANNEL); delay(10); } uint16_t temp_avg = sum / samples; float vdd = getVDD(); float temp_normalized = (temp_avg * 3.3f) / vdd; float ts_cal1_normalized = (ts_cal1 * 3.3f) / 3.3f; float temp_mv = (temp_normalized - ts_cal1_normalized) * (3300.0f / 4095.0f); return 30.0f + (temp_mv / AVG_SLOPE); } void printDetailedInfo() { uint16_t temp_raw = analogRead(TEMP_CHANNEL); uint16_t vrefint_raw = analogRead(VREFINT_CHANNEL); float vdd = getVDD(); float temp = getTemperature(); Serial.println("=== Detaillierte Infos ==="); Serial.print("TEMP RAW: "); Serial.println(temp_raw); Serial.print("VREFINT RAW: "); Serial.println(vrefint_raw); Serial.print("VDD: "); Serial.print(vdd, 3); Serial.println(" V"); Serial.print("Temperatur: "); Serial.print(temp, 2); Serial.println(" °C"); Serial.println(); }