diff --git a/src/command.c b/src/command.c index 54b8475..fdda867 100644 --- a/src/command.c +++ b/src/command.c @@ -393,8 +393,15 @@ static bool cmd_target_power(target *t, int argc, const char **argv) } else if (argc == 2) { bool want_enable = false; if (parse_enable_or_disable(argv[1], &want_enable)) { - platform_target_set_power(want_enable); - gdb_outf("%s target power\n", want_enable ? "Enabling" : "Disabling"); + if (want_enable + && !platform_target_get_power() + && platform_target_voltage_sense() > POWER_CONFLICT_THRESHOLD) { + /* want to enable target power, but VREF > 0.5V sensed -> cancel */ + gdb_outf("Target already powered (%s)\n", platform_target_voltage()); + } else { + platform_target_set_power(want_enable); + gdb_outf("%s target power\n", want_enable ? "Enabling" : "Disabling"); + } } } else { gdb_outf("Unrecognized command format\n"); diff --git a/src/include/platform_support.h b/src/include/platform_support.h index 59720cb..94f27c3 100644 --- a/src/include/platform_support.h +++ b/src/include/platform_support.h @@ -37,7 +37,9 @@ void platform_timeout_set(platform_timeout *t, uint32_t ms); bool platform_timeout_is_expired(platform_timeout *t); void platform_delay(uint32_t ms); +#define POWER_CONFLICT_THRESHOLD 5 /* in 0.1V, so 5 stands for 0.5V */ extern bool connect_assert_srst; +uint32_t platform_target_voltage_sense(void); const char *platform_target_voltage(void); int platform_hwversion(void); void platform_srst_set_val(bool assert); diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 798a7f0..09f21d2 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -251,12 +251,16 @@ static void adc_init(void) adc_calibrate(ADC1); } -const char *platform_target_voltage(void) +uint32_t platform_target_voltage_sense(void) { + /* returns the voltage in volt scaled by 10 (so 33 means 3.3V), except + * for hardware version 1 + * this function is only needed for implementations that allow the + * target to be powered from the debug probe + */ if (platform_hwversion() == 0) - return gpio_get(GPIOB, GPIO0) ? "OK" : "ABSENT!"; + return 0; - static char ret[] = "0.0V"; const uint8_t channel = 8; adc_set_regular_sequence(ADC1, 1, (uint8_t*)&channel); @@ -265,9 +269,19 @@ const char *platform_target_voltage(void) /* Wait for end of conversion. */ while (!adc_eoc(ADC1)); - uint32_t val = adc_read_regular(ADC1) * 99; /* 0-4095 */ - ret[0] = '0' + val / 81910; - ret[2] = '0' + (val / 8191) % 10; + uint32_t val = adc_read_regular(ADC1); /* 0-4095 */ + return (val * 99) / 8191; +} + +const char *platform_target_voltage(void) +{ + if (platform_hwversion() == 0) + return gpio_get(GPIOB, GPIO0) ? "OK" : "ABSENT!"; + + static char ret[] = "0.0V"; + uint32_t val = platform_target_voltage_sense(); + ret[0] = '0' + val / 10; + ret[2] = '0' + val % 10; return ret; } diff --git a/src/remote.c b/src/remote.c index 87bf5be..e6c9f71 100644 --- a/src/remote.c +++ b/src/remote.c @@ -296,8 +296,18 @@ static void remotePacketProcessGEN(unsigned i, char *packet) case REMOTE_PWR_SET: #ifdef PLATFORM_HAS_POWER_SWITCH - platform_target_set_power(packet[2]=='1'); - _respond(REMOTE_RESP_OK,0); + if (packet[2]=='1' + && !platform_target_get_power() + && platform_target_voltage_sense() > POWER_CONFLICT_THRESHOLD) + { + /* want to enable target power, but voltage > 0.5V sensed + * on the pin -> cancel + */ + _respond(REMOTE_RESP_ERR,0); + } else { + platform_target_set_power(packet[2]=='1'); + _respond(REMOTE_RESP_OK,0); + } #else _respond(REMOTE_RESP_NOTSUP,0); #endif