EXC_RETURN does not work in PendSV on ARM Cortex-M3 - cortex-m3

I want to use EXC_RETURN in PendSV but I always get HardFault with INVPC (Invalid PC load UsageFault, caused by an invalid PC load by EXC_RETURN). This works, if I move the assembly code to Systick_Handler().
What do I miss?
I use NXP LPC1769 with the latest MCUXpressoIDE.
void Systick_Handler(void){
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
__attribute__ ((naked)) void Pendsv_Handler(void) {
__ASM volatile (
"NOP \n"
"ldr r0, =0xFFFFFFFD \n"
"bx r0"
);
}
int main(void) {
SysTick_Config(100);
__enable_irq();
__set_PSP(0x10007800);
__set_CONTROL(0x3); // Thread mode with PSP
while(1) {
__NOP();
}
return 0 ;
}
The Pendsv_Handler() compiled to:
Pendsv_Handler:
000003b4: nop
000003b6: mvn.w r0, #2
000003ba: bx r0
27 }
000003bc: nop
Update: Based on Tom V comments. But still not working.
Solution
I missed to set the priority of SysTick and PendSV, like:
NVIC_SetPriority(PendSV_IRQn, 0xFF);
NVIC_SetPriority(SysTick_IRQn, 0x00);

Related

Running WebServerSecure and PubSubClient on ESP8266

I wrote a sketch for ESP8266. This sketch reads some sensor data and published it via MQTT. In addition I want to let a Web server provide the same data as HTML, or JSON web service.
The MQTT publish is triggered via a TaskScheduler timer.
Both functions, MQTT and Web server, work for itself, but sadly not together. Here's a simplified sketch:
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServerSecure.h>
#include <PubSubClient.h>
#include <TaskScheduler.h>
#include <My_WLAN.h> // provices connection to local WLAN and network settings
const char DNS_NAME[] = "myserver.local";
const int HTTPS_PORT = 443; // HTTPS
const char MQTT_SVR[] = "myserver.local";
const unsigned int MQTT_PORT = 8883; // MQTTS
WiFiClientSecure wifiClient;
PubSubClient mqttClient(wifiClient); // MQTT client instance
ESP8266WebServerSecure server(HTTPS_PORT); // web server instance
void t1Callback(void); // callback method prototypes
Task t1(60000, TASK_FOREVER, &t1Callback); // main loop task
Scheduler timer; // task scheduler
static const uint8_t SVR_FINGERPRINT[20] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20 };
static const char deviceCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
[... certificate ...]
-----END CERTIFICATE-----
)EOF";
static const char deviceKey[] PROGMEM = R"EOF(
-----BEGIN RSA PRIVATE KEY-----
[... key ...]
-----END RSA PRIVATE KEY-----
)EOF";
/* *****************************
MQTT_connect
* *****************************/
void MQTT_connect()
{
int attempt = 0;
/* loop until reconnected */
while (!mqttClient.connected() && attempt < 10) {
attempt++;
Serial.print("Attempting MQTT connection ("); Serial.print(attempt); Serial.print(")...");
mqttClient.setServer(MQTT_SVR, MQTT_PORT);
if (mqttClient.connect(DNS_NAME)) {
Serial.println("success");
} else {
Serial.print("failed, status code = "); Serial.print(mqttClient.state());
Serial.println(". - Try again in 5 seconds...");
delay(5000);
}
}
}
/* *****************************
Web Server handleRoot
* *****************************/
void handleRoot() {
digitalWrite(LED_BUILTIN, LOW); // on
Serial.println("WebServer ROOT");
server.send(200, "text/html", "WebServer ROOT");
digitalWrite(LED_BUILTIN, HIGH); // off
}
/* *****************************
Web Server handleNotFound
* *****************************/
void handleNotFound() {
digitalWrite(LED_BUILTIN, LOW); // on
String message = "File not found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
digitalWrite(LED_BUILTIN, HIGH); // off
}
/* *************************
MQTT_publish_something
* *************************/
void MQTT_publish_something() {
digitalWrite(LED_BUILTIN, LOW); // on
char payload[30] = "some_payload_data";
if (!mqttClient.publish("MQTT/Test", payload, true)) { // retain message
Serial.println("MQTT message lost!");
}
digitalWrite(LED_BUILTIN, HIGH); // off
}
/* *************************
t1: main timer (callback)
* *************************/
void t1Callback() {
my.WiFi_connect(); // check and re-connect to WLAN (in My_WLAN.h)
if (WiFi.status() == WL_CONNECTED) {
MQTT_connect();
MQTT_publish_something();
}
}
/* *************************
setup
* *************************/
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // internal LED
digitalWrite(LED_BUILTIN, HIGH); // off
/* -----------------------
open Serial |
----------------------- */
Serial.begin(74880);
while (!Serial); // wait for Serial being ready
/* -----------------------
connect to WLAN |
----------------------- */
my.WiFi_connect(); // this is connecting to WLAN & error handling (in My_WLAN.h)
wifiClient.setFingerprint(SVR_FINGERPRINT);
/* -----------------------
set mDNS |
----------------------- */
if (MDNS.begin(DNS_NAME)) {
Serial.printf("mDNS responder started for %s\n", DNS_NAME);
MDNS.addService("https", "tcp", HTTPS_PORT); // add service to MDNS-SD
MDNS.addService("mqtt", "tcp", MQTT_PORT);
} else
Serial.println("Error setting up mDNS responder!");
/* -----------------------
start HTTPS server |
----------------------- */
server.getServer().setRSACert(new X509List(deviceCert), new PrivateKey(deviceKey));
server.on("/", handleRoot); // standard HTML root
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTPS server started.");
Serial.println();
/* -----------------------
start timer |
----------------------- */
timer.init();
timer.addTask(t1);
// line 177:
timer.enableAll();
}
void loop() {
MDNS.update();
// line 184:
server.handleClient();
mqttClient.loop();
timer.execute();
}
Running MQTT only works fine and publishes data (I use the mosquitto broker).
Running the Web server (https://...) works fine as well, if commenting out line 177 (so MQTT does not get triggered).
With both functions active, as soon as the first MQTT message had been sent, the web server does not answer any more. I get PR_END_OF_FILE_ERROR in FF and ERR_CONNECTION_CLOSED in Chrome.
I guess, that these libraries somehow mess with each other, or that something confuses with the certificates. However, the fingerprint belongs to the server running mosquitto, while the X509 certificate belongs to the web server running on the ESP8266. These are two different machines and have nothing to do with each other.
Any idea welcome.
I suspect both libraries use port 443, and you can only have one listener on a given port. I've tried creating a BearSSL::ESP8266WebServerSecure object with alternate ports, such as 80 and 8443 but can't get them to work. Worse, there doesn't seem to be a way to stop a listener once a BearSSL::ESP8266WebServerSecure object has started, so it can't be released for later reuse.
I ended up using HTTP to get WiFi credentials, then HTTPS from there on out. Not a very satisfactory solution but it works.
Update: I was able to run a provisioning server on port 443, stop it by calling
BearSSL::ESP8266WebServerSecure provisioningServer(443);
BearSSL::ESP8266WebServerSecure server(443);
provisioningServer.close();
provisioningServer.~ESP8266WebServerSecure(); // note: cannot use TLS on both servers without this line
After calling the provisioning server's destructor I was able to start my server on port 443.

USART not working on STM32L475 after setup

I work with a demo board B-L475E-IOT01A. On CN3 connector - pin1 - PA1-RX, pin2 - PA0-TX. So I configure for UART4.
#define UART4_PORT GPIOA
#define UART4_TX_PIN LL_GPIO_PIN_0
#define UART4_RX_PIN LL_GPIO_PIN_1
int USART_Setup(USART_TypeDef *USARTx, uint32_t baud_rate)
{
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
if (USARTx == UART4)
{
irq_num = UART4_IRQn;
/* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(UART4_PORT, UART4_TX_PIN, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15(UART4_PORT, UART4_TX_PIN, LL_GPIO_AF_8);
LL_GPIO_SetPinSpeed(UART4_PORT, UART4_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(UART4_PORT, UART4_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(UART4_PORT, UART4_TX_PIN, LL_GPIO_PULL_UP);
/* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(UART4_PORT, UART4_RX_PIN, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15(UART4_PORT, UART4_RX_PIN, LL_GPIO_AF_8);
LL_GPIO_SetPinSpeed(UART4_PORT, UART4_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(UART4_PORT, UART4_RX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(UART4_PORT, UART4_RX_PIN, LL_GPIO_PULL_UP);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART4);
LL_RCC_SetUSARTClockSource(LL_RCC_UART4_CLKSOURCE_PCLK1);
}
NVIC_SetPriority(irq_num, 0);
NVIC_EnableIRQ(irq_num);
/* TX/RX direction */
LL_USART_SetTransferDirection(USARTx, LL_USART_DIRECTION_TX_RX);
/* 8 data bit, 1 start bit, 1 stop bit, no parity */
LL_USART_ConfigCharacter(USARTx, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
LL_USART_SetBaudRate(USARTx, SystemCoreClock, LL_USART_OVERSAMPLING_16, baud_rate);
LL_USART_Enable(USARTx);
//enable RX buffer not empty interrupt
USARTx->CR1 |= USART_CR1_RXNEIE;
/* Polling USART initialisation */
while((!(LL_USART_IsActiveFlag_TEACK(USARTx))) || (!(LL_USART_IsActiveFlag_REACK(USARTx))))
{
timeout++;
if (timeout > 1000000)
{
return USART_ERROR;
}
}
return USART_OK;
}
I go line by line in the debugger and it seems to be OK. However when I connect to a terminal with TTL-USB convertor there is no transmission and no reception. Both LEDs TX/RX on TTL-USB convertor are on. TTL-USB convertor tested on other boards and works OK. Do I miss something?
first I enable port clocks
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
after that I see
GPIOA->AFRL - 0x00000000
GPIOA->AFRH - 0x00000000
Then after
LL_GPIO_SetAFPin_8_15(UART4_PORT, UART4_TX_PIN, LL_GPIO_AF_8);
LL_GPIO_SetAFPin_8_15(UART4_PORT, UART4_RX_PIN, LL_GPIO_AF_8);
it stays all zeroes.
GPIOA->AFRL - 0x00000000
GPIOA->AFRH - 0x00000000

Communucation between 2 stm32

I am trying to communicate 2 STM32 with I2C.My configuration is as followed:
7-bit addressing mode (no dual address, only OAR1)
100khz speed
ACK enabled (on slave)
ACK disabled (on master, since only 1 byte is transferred between master/slave at any time)
on both master/slave, using GPIOB (PB6) as SCL as AF and GPIOB (PB7) as SDA as AF.Where is the problem?
Master code:
#include "stm32f10x.h" // Device header #include "delay.h"
void pinConfig(void);
void i2c_Master_Config(void);
void sendData(uint8_t data);
int main() {
delay_init();
pinConfig();
i2c_Master_Config();
while(1)
{
uint8_t butonState=GPIOA->IDR & 0x00001000;
sendData(0x68,butonState);
delay_ms(10);
}
}
void pinConfig() {
RCC->APB1ENR |=1<<21;//Enable I2C 1 clock
RCC->APB2ENR |=1<<2;//Enable GPIOA clock
RCC->APB2ENR |=1<<3;//Enable GPIOB clock
RCC->APB2ENR |=1<<0;//Enable AFIO clock
GPIOA->CRL |= 0x00008000; //PA3 button pull-down
GPIOB->CRL = 0xFF000000; //SCL and SDA AF Open Drain SCL => PB6 SDA =>PB7
}
void i2c_Master_Config() {
I2C1->CR2 |=1<<5; //36 Mhz peripheral clock.
I2C1->CR2 |=1<<2; //36 Mhz peripheral clock.
I2C1->CCR =0x28;//100 khz clock
I2C1->TRISE =9;//1/8MHZ= 125 ns => 1000ns/125ns =8 => 8+1 =9
I2C1->CR1 |=(1<<0);//Peripheral enable..
}
void sendData(uint8_t data) {
volatile int temp;
while(I2C1->SR2 &(1<<1));//BUSY bit.
I2C1->CR1 |=1<<8;//START bit.
while(!(I2C1->SR1 & (1<<0))); //wait until start flag is set
I2C1->DR = slaveAdres<<1;//7 bit adress.
while(!(I2C1->SR1 &(1<<1)));//wait until addr flag is set
gecici=I2C1->SR2;//clear addr flag.
I2C1->DR = data;
while (!(I2C1->SR1 & (1<<7))){} //wait until txe is set
while (!(I2C1->SR1 & (1<<2)));//BTF(Byte transfer finished)=1 .
I2C1->CR1 |= 1<<9;//STOP bit.
I2C1->CR1 &=~(1<<0);//Peripheral disable.
}
Slave code:
#include "stm32f10x.h" // Device header
void pinConfig(void);
void i2c_Slave_Config(void);
uint8_t readData(void);
uint8_t data;
int main()
{
pinConfig();
i2c_Slave_Config();
while(1)
{
data=readData();
if(data==0)
GPIOB->BSRR |=1<<3;
else if(data==1)
GPIOB->BRR |=1<<3;
}
}
void pinConfig()
{
RCC->APB1ENR |=1<<21;//I2C 1 Clock Aktif.
RCC->APB2ENR |=1<<2;//Enable GPIOA clock
RCC->APB2ENR |=1<<3;//Enable GPIOB clock
RCC->APB2ENR |=1<<0;//Enable AFIO clock
GPIOA->CRL |= 0x00002000; //PA3 led.
GPIOB->CRL = 0xFF000000; //SCL and SDA AF Open Drain SCL => PB6 SDA =>PB7
GPIOA->BSRR |=1<<3;//Turn off the led.
}
void i2c_Slave_Config() {
RCC->APB1ENR |=1<<21;//I2C 1 Clock Enable.
I2C1->CR2 |=1<<5; //36 Mhz peripheral clock.
I2C1->CR2 |=1<<2; //36 Mhz peripheral clock.
I2C1->CCR =0x28;//100 khz clock
I2C1->OAR1 &=~(1<<15);//7-bit slave adress.
I2C1 ->CR1 |= 1<<10;//ACK enable.
//0x68 Slave Adress Configured.
I2C1 ->OAR1 &=~(1<<1);
I2C1 ->OAR1 &=~(1<<2);
I2C1 ->OAR1 &=~(1<<3);
I2C1 ->OAR1 &=~(1<<5);
I2C1 ->OAR1 |=(1<<4);
I2C1 ->OAR1 |=(1<<6);
I2C1 ->OAR1 |=(1<<7);
//0x68 Slave Adress Configured.
}
uint8_t readData()
{
volatile int temp;
uint8_t data;
I2C1->CR1 |=(1<<0);//Peripheral enable.
while(I2C1->SR2 &(1<<1));//BUSY bit.
I2C1->CR1 |=1<<8;//START bit.
while(!(I2C1->SR1 & (1<<0))); // wait until start flag is set.
while(!(I2C1->SR1 &(1<<1)));// wait until addr flag is set
temp=I2C1->SR2;//clear addr .
while (!(I2C1->SR1 & (1<<6))){} // wait until rxne is set
data=I2C1->DR;
while (!(I2C1->SR1 & (1<<4))){} // wait until STOPF is set
gecici=I2C1->SR1;
I2C1->SR1 |=1<<9;
I2C1->CR1 &=~(1<<0);//Peripheral disable.
return data;
}
Adress doesnt match. I do not see the any response on the SDA and SCL signals on the scope.I pulled both SCL and SDA to 3.3v using 4.7kohms on
each line.(STM32F103C6).
For now master I2C module enabled at main start in i2c_Master_Config(), then disabled at end of sendData() and never enabled again.
Slave I2C module enabled at the begining and disabled at the end of readData().
That is enough for broken communication. I2C peripheral module should be enabled all time (until you will understand when it should be disabled).
p.s. Sorry, I not analysed your code deeply — a lot of "magic numbers" instead of mnemonic bit names makes the analysis difficult. Perhaps, there are other mistakes.

Pull GPIO pin low as last act prior to shutting down

I want to signal a power off state by pulling a GPIO pin low for 10 seconds. I have discovered the run levels in the /etc/rc.* directories. Eventually the "halt" command gets run.
I'd like to edit and recompile the halt.c file, but I am unable to locate it. I have two questions:
Is this the right approach?
Where is the source code? (pending positive answer from Q1).
Thank you.
Justin
I haven't used the Raspberry Pi, but on most systems halt, poweroff and reboot are all links to the same binary. Another way to do this would be to just write a program to do what you want and make it the last thing to be called in /etc/rc.d/rc0.d. Runlevel 0 is what the system does when it shuts down.
Here is my take on this problem 'powerctl_pin'
https://pastebin.com/BdzGM5TJ
/*
Raspi3B Power Control Pin Raspbian Jessie
Bilgus -- 2017 CC-BY-SA 3.0
Requires WiringPI http://wiringpi.com/
Compiling:
gcc -o powerctl_pin powerctl_pin.c -l wiringPi && chmod +x powerctl_pin &&
sudo cp powerctl_pin /bin/
Install:
sudo /bin/powerctl_pin 21 install
Uninstall:
sudo /bin/powerctl_pin 21 uninstall
Shutdown:
sudo /bin/powerctl_pin 21 poweroff
/bin/powerctl_pin Broadcom_pin#, mode
Valid Modes: poweroff, poweron, install, uninstall
Works with mosfet latch switch
https://easyeda.com/Bilgus/New_Project-4ce1316bb1f6402985f8d1c4f196448d
Original Circuit:
http://www.mosaic-industries.com/embedded-systems/microcontroller-projects
/raspberry-pi/on-off-power-controller
*/
/*
Raspi3B Power Control Pin Raspbian Jessie
Bilgus -- 2017 CC-BY-SA 3.0
Requires WiringPI http://wiringpi.com/
Compiling:
gcc -o powerctl_pin powerctl_pin.c -l wiringPi && chmod +x powerctl_pin &&
sudo cp powerctl_pin /bin/
Install:
sudo /bin/powerctl_pin 21 install
Uninstall:
sudo /bin/powerctl_pin 21 uninstall
Shutdown:
sudo /bin/powerctl_pin 21 poweroff
/bin/powerctl_pin Broadcom_pin#, mode
Valid Modes: poweroff, poweron, install, uninstall
Works with mosfet latch switch
https://easyeda.com/Bilgus/New_Project-4ce1316bb1f6402985f8d1c4f196448d
Original Circuit:
http://www.mosaic-industries.com/embedded-systems/microcontroller-projects
/raspberry-pi/on-off-power-controller
*/
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <signal.h> //sigterm, sigint()
#include "wiringPi.h"
#define WIRINGPI_CODES 999 /* enable error checking on setup */
#define POWEROFF_SVC "PwrCtl_Pin.service"
#define POWEROFF_SVC_PATH "/lib/systemd/system/"POWEROFF_SVC
#define REQUIRES "shutdown.target umount.target final.target poweroff.target"
#define AFTER "shutdown.target umount.target final.target"
#define BEFORE "systemd-poweroff.service"
#define WANTEDBY "poweroff.target"
#define POWERINT_SVC "PwrCtl_Pin-Interrupt.service"
#define POWERINT_SVC_PATH "/lib/systemd/system/"POWERINT_SVC
static void poweroff_ISR_INIT(int pin);
static int g_pin = 0;
/* enables pullup - unneeded to hold latch */
static void poweron_pin(int pin)
{
pullUpDnControl(pin, PUD_UP);
pinMode(pin, INPUT);
}
/* pulls pin low in short loop to turn power off */
static void poweroff_pin(int pin)
{
pullUpDnControl(pin, PUD_OFF);
int c;
for(c=0;c<20;c++)
{
//pinMode(pin, INPUT);
//pullUpDnControl(pin, PUD_DOWN);
digitalWrite(pin,LOW);
pinMode(pin, OUTPUT);
digitalWrite(pin,LOW);
delay(500);
}
}
/* ISR Called when pin goes from high to low debounce checks that still low */
static void poweroff_ISR(void)
{
delay(100);
if (digitalRead(g_pin) == LOW) /* pin debounce */
{
openlog ("Poweroff ISR", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
syslog (LOG_NOTICE, "ISR Triggered - Shutdown -h now");
closelog();
system("shutdown -h now");
exit(0);
}
else
poweroff_ISR_INIT(g_pin);
}
/* signal handler recieves shutdown signals */
static void signal_handler(int signal_0)
{
if (signal_0 == SIGINT || signal_0 == SIGTERM || signal_0 == SIGSTOP)
exit(0);
}
/* Initialize Poweroff ISR handler */
static void poweroff_ISR_INIT(int pin)
{
g_pin = pin;
pinMode(pin, INPUT);
pullUpDnControl(pin, PUD_UP);
wiringPiISR(pin, INT_EDGE_FALLING, &poweroff_ISR);
while(1)
{
delay(100);
;;
}
}
/* creates service daemons */
static void install(int pin, char *prog_path)
{
FILE *f = fopen(POWEROFF_SVC_PATH, "w");
if (f == NULL)
{
fprintf(stderr, "Error opening file! %s\n", POWEROFF_SVC_PATH);
exit(-6);
}
fprintf(f, "# POWER CONTROL PIN SERVICE \n# %s\n\n", prog_path);
fprintf(f, "[Unit]\nDescription=PowerCtl_Pin pulls GPIO pin %i LOW\n", pin);
fprintf(f, "DefaultDependencies=no\n");
fprintf(f, "Requires=%s\n", REQUIRES);
fprintf(f, "After=%s\nBefore=%s\n\n", AFTER, BEFORE);
fprintf(f, "[Service]\nType=oneshot\n");
fprintf(f, "ExecStart=%s %i poweroff\n\n", prog_path, pin);
fprintf(f, "[Install]\nWantedBy=%s\n\n", WANTEDBY);
fclose(f);
printf("Service file created: %s\n", POWEROFF_SVC_PATH);
system("systemctl enable " POWEROFF_SVC);
FILE *f1 = fopen(POWERINT_SVC_PATH, "w");
if (f1 == NULL)
{
fprintf(stderr, "Error opening file! %s\n", POWERINT_SVC_PATH);
exit(-7);
}
fprintf(f1, "# POWER CONTROL PIN INTERRUPT SERVICE \n");
fprintf(f1, "# %s\n\n", prog_path);
fprintf(f1, "[Unit]\nDescription=PowerCtl_Pin Interrupt watches GPIO ");
fprintf(f1, "for pin %i LOW calls shutdown now\n", pin);
fprintf(f1, "DefaultDependencies=no\n");
fprintf(f1, "After=network.target\n\n");
fprintf(f1, "[Service]\nType=simple\n");
fprintf(f1, "ExecStart=%s %i interrupt &\n", prog_path, pin);
fprintf(f1, "TimeoutSec=0\nRestart=always\n\n");
fprintf(f1, "[Install]\nWantedBy=multi-user.target\n\n");
fclose(f1);
printf("\n\rService file created: %s\n", POWERINT_SVC_PATH);
system("systemctl enable " POWERINT_SVC);
printf("Attempting to start: %s\n\r", POWERINT_SVC_PATH);
system("systemctl start " POWERINT_SVC);
}/*install*/
/* disables/stops service daemons */
static void uninstall(int pin, char *prog_path)
{
system("systemctl disable " POWEROFF_SVC);
printf("Service file still exists: %s\n\n", POWEROFF_SVC_PATH);
system("systemctl stop " POWERINT_SVC);
system("systemctl disable " POWERINT_SVC);
printf("Service file still exists: %s\n", POWERINT_SVC_PATH);
}
int main(int argc, char **argv)
{
int pin = 0;
if (geteuid() != 0)
{
fprintf (stderr, "You need to be root to run this program. (sudo?)\n") ;
exit(-1);
}
putenv("WIRINGPI_CODES=WhOkNoWs??");
if (wiringPiSetupGpio() != 0) /* change to wiringPiSetup() for WiringPi Pins*/
{
fprintf(stderr, "wiringPiSetup error\n");
exit(-2);
}
if(argc < 3)
{
fprintf (stderr, "not enough args poweroff_pin(brcm_pin# mode)\n") ;
fprintf (stderr, "Valid Mode [power[off/on], interrupt, install, uninstall]])\n") ;
exit(-3);
}
else if (sscanf (argv[1],"%i", &pin) != 1)
{
fprintf (stderr, "invalid pin number, poweroff_pin(brcm_pin# mode) ");
fprintf (stderr, "Valid Mode [power[off/on], interrupt, install, uninstall]])\n") ;
exit(-4);
}
else if(strncmp(argv[2],"interrupt",10) == 0)
{
openlog (argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
syslog (LOG_NOTICE, "%s - interrupt mode pin = %s", argv[0], argv[1]);
closelog();
if (signal(SIGINT, signal_handler) == SIG_ERR)
{
fprintf(stderr, "Unable to register signal handler\n");
exit(-5);
}
poweroff_ISR_INIT(pin);
}
else if(strncmp(argv[2],"poweroff",10) == 0)
{
poweroff_pin(pin);
}
else if(strncmp(argv[2],"install",10) == 0)
{
openlog (argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
syslog (LOG_NOTICE, "%s - install pin = %s", argv[0], argv[1]);
closelog();
install(pin, argv[0]);
}
else if(strncmp(argv[2],"uninstall",10) == 0)
{
openlog (argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
syslog (LOG_NOTICE, "%s - uninstall pin = %s", argv[0], argv[1]);
closelog();
uninstall(pin, argv[0]);
}
else
{
poweron_pin(pin);
}
return 0;
}/*main*/

Windbg Dump Generated programmatically can't be Debugged

I have a simple program:
int ExecuteCommand(wchar_t* commandLine)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL bRet;
DWORD lpExitCode;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
bRet = CreateProcess(
NULL, // pointer to name of executable module
commandLine, // pointer to command line string
NULL, // process security attributes
NULL, // thread security attributes
FALSE, // handle inheritance flag
NORMAL_PRIORITY_CLASS, // creation flags
NULL, // pointer to new environment block
NULL, // pointer to current directory name
&si, // pointer to STARTUPINFO
&pi // pointer to PROCESS_INFORMATION
);
if(bRet) WaitForSingleObject(pi.hProcess, INFINITE); // wait for process to finish
GetExitCodeProcess(pi.hProcess, &lpExitCode);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return lpExitCode;
}
void CreateCoreDump()
{
wchar_t buffer[256];
wsprintf(buffer, _T("windbg -p %d -c \".dump /mfh /u C:\\Tmp\\crashdump.dmp\""), GetCurrentProcessId());
ExecuteCommand(buffer);
}
DWORD ExceptionFilter()
{
CreateCoreDump();
return EXCEPTION_CONTINUE_SEARCH;
}
int _tmain(int argc, _TCHAR* argv[])
{
__try
{
int* p = NULL;
*p = 100;
}
__except(ExceptionFilter())
{
}
return 0;
}
It will generate a core dump when there is an exception, using function CreateCoreDump. Although the dump file could be generated successfully, it seems useless:
If I open this dump file using windbg, there is nothing in call stack!!!
But, if I debug this application directly in windbg, and set breakpoint at the line of calling CreateCoreDump, and then run windbg command:
.dump /mfh C:\Tmp\mydump.dmp
Open this dump file with WinDbg, I can see the full call stack.
Did I do something wrong, either in generating the dump file, or debugging the dump file using windbg?
When you attach the debugger after the exception happens, the debugger does not see the exception event. It creates a thread that has a breakpoint so the stack on that thread looks something like this:
0:001> kc
Call Site
ntdll!DbgBreakPoint
ntdll!DbgUiRemoteBreakin+0x38
kernel32!BaseThreadInitThunk+0xd
ntdll!RtlUserThreadStart+0x1d
If you manually set the current thread to thread 0 (use ~0s) you will see your stack
0:001> ~0s
ntdll!ZwWaitForSingleObject+0xa:
00000000`76e5135a c3 ret
0:000> kc
Call Site
ntdll!ZwWaitForSingleObject
KERNELBASE!WaitForSingleObjectEx
tmp!ExceptionFilter
tmp!main$filt$0
ntdll!__C_specific_handler
ntdll!RtlpExecuteHandlerForException
ntdll!RtlDispatchException
ntdll!KiUserExceptionDispatch
tmp!main
tmp!__mainCRTStartup
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
When you start your program under the debugger two things happen, first, there is only one thread, and second the debugger knows about the exception so it will print something like this:
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
which tells you that you need to use the .ecxr commmand to get to the interesting thread. In this case you do not need to because the current debugger thread is already the one you want.
You have to add the exception record to the dump. For instance, I changed your sample to retrieve the exception information in the filter and pass it on the command line when generating the dump.
void CreateCoreDump(LPEXCEPTION_POINTERS p)
{
wchar_t buffer[256];
// I used the command line debugger, cdb, and added a "qd" command for it to exit after dumping.
wsprintf(buffer, _T("cdb.exe -p %d -c \".dump /mfh /u /xt 0x%x /xp 0x%p C:\\Tmp\\crashdump.dmp\";qd"), GetCurrentProcessId(), GetCurrentThreadId(), p);
ExecuteCommand(buffer);
}
DWORD ExceptionFilter(LPEXCEPTION_POINTERS p)
{
CreateCoreDump(p);
return EXCEPTION_CONTINUE_SEARCH;
}
int _tmain(int argc, _TCHAR* argv[])
{
__try
{
int* p = NULL;
*p = 100;
}
__except(ExceptionFilter(GetExceptionInformation()))
{
}
return 0;
}
Then when you open the dump in windgb, the debugger knows about the exception event. You can use .ecxr to set the current thread and stack at the exception point.
0:000> .ecxr
eax=00000000 ebx=00000000 ecx=6ec4471c edx=00000000 esi=00000001 edi=010c337c
eip=010c108b esp=0038f5e8 ebp=0038f818 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
test!wmain+0x14:
010c108b c70064000000 mov dword ptr [eax],64h ds:002b:00000000=????????
0:000> kc
test!wmain
test!__tmainCRTStartup
kernel32!BaseThreadInitThunk
ntdll!__RtlUserThreadStart
ntdll!_RtlUserThreadStart