I am programming a STM32F446 microcontroller and I am communicating it with an ESP8266 (startByte-command-size-dataArray-crc1-crc2). However I have a problem, whenever the ESP8266 resets it gives a serial debug (cannot turn it off) #74880 baud (also cannot change this) which is causing an error in the STM32 microcontroller, as it should since I programmed them to communicate at 9600.
The problem is that whenever that error occurs in the STM32 microcontroller the error never stops, since it cannot clear the error flag. In order to clear the error flag you just need to read the status register (HAL_UART_GetError function), but my code is unable to do it when running, and by that I mean that no matter how much I read the register it never changes, UNLESS I pause debugging and then resume
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
errorCounter++;
if(HAL_IS_BIT_CLR(huart->Instance->CR1, 1)) {
SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE | USART_CR1_PEIE);
SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
if(HAL_IS_BIT_CLR(huart->Instance->CR3, USART_CR3_DMAR)) {
SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);
}
}
while(huart->Instance->SR != 0x80) {
huart->Instance->SR
HAL_UART_GetError(huart);
HAL_UART_GetState(huart);
huart->Instance->SR = 0;
}
}
The while loop is there because I wanted to see if I could force my code to read the same register over and over until it cleared it, but it didn't matter.
I have also tried disabling UART (__HAL_UART_DISABLE) forcefully but still, the same problem, it only clears the flag whenever I pause debugging.
I have searched everywhere and I cannot find any way to make this work. I even disabled optimization, but the same thing kept happening.
EDIT:
Found a way to make it work. It worked when I paused debugging because, as already stated in the answer, the debugger was reading the DR register, thus clearing it, and when I read the SR register it actually cleared it (it wasn't clearing because there was something that still needed to be read).
Solution: read DR register and then read SR register
First of all your code is a total mess. It will not even compile and most of it does not make too much sense. You can't clear error flags by writing 0 to SR register. You must read the SR and then read the data register.
The debugger probably reads the DR register and that is the reason why the flags are being cleared when you break the execution of the program.
My advice - read the RM very carefully.
Related
I have been working on a project using the ESP32 with the ESP-IDF that will check it's NVS memory for wifi credentials before starting the network stack. If it has said credentials, it will connect to the wifi network in STA mode, if it lacks them, it will launch as it's own AP to allow the user to send it the credentials over HTTP.
After manually putting my test credentials into NVS, I started working on the AP code. Once all the AP code and logic was complete, I manually wiped the flash memory with esptool to force the board to launch in that mode. Doing so worked fine, and I was able to send it the updated credentials over HTTP.
At this point, the board attempted to connect as STA upon reset, however, the SYSTEM_EVENT_STA_WPS_ER_PIN event kept being caught by the wifi event loop. The board has since only experienced this event and has been completely unable to connect to wifi since. To make matters stranger, even after rolling back to a previous version with git, the problem still persists.
main.c
void app_main() {
// Start NVS
initNVS();
// Init Wifi Controller
initWifiController();
// Get Credentials to send to wifi
Creds creds = getCreds();
// Start wifi in STA mode with gathered creds
beginWifi(creds);
initializePins();
initializeTimers();
}
wifiController.c
void initWifiController(){
// * NVS must be initialized before wifi work can be done
// Handle when connected to the network
connectionSemaphore = xSemaphoreCreateBinary();
// Begin network stack
ESP_ERROR_CHECK(esp_netif_init());
// Create event loop for handling callbacks
ESP_ERROR_CHECK(esp_event_loop_create_default());
}
void beginWifi(Creds creds){
if(creds.status == ESP_OK){
ESP_LOGI(TAG, "Connection credentials have been found, connecting to network");
connectSTA(creds);
}
else if(creds.status == ESP_ERR_NVS_NOT_FOUND){
ESP_LOGW(TAG, "Missing credentials, starting as AP");
connectAP();
}
else{
ESP_LOGE(TAG, "ESP failed with error %s, not starting wifi", esp_err_to_name(creds.status));
}
void connectSTA(Creds creds){
ESP_LOGI(TAG, "Attempting to connect to wifi with following creds: %s | %s", creds.ssid, creds.pass);
// Set netif to sta
esp_netif_create_default_wifi_sta();
// Prepare and initialize wifi_init_config_t
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
// Register tracked events for event_handler
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, NULL));
// TODO: Check if this can be used to avoid havng to use NVS manually
esp_wifi_set_storage(WIFI_STORAGE_RAM);
// Config struct for wifi details
wifi_config_t wifi_config = {};
// Copy casted info into wifi_config
// * https://www.esp32.com/viewtopic.php?f=13&t=14611
// * See above link for details on this
strcpy((char *)wifi_config.sta.ssid, creds.ssid);
strcpy((char *)wifi_config.sta.password, creds.pass);
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
ESP_ERROR_CHECK(esp_wifi_start());
// ? Is this required to avoid a memory leak?
free(creds.pass);
free(creds.ssid);
}
void connectAP(){
// ? How important is it that these be called in this order?
ESP_LOGI(TAG, "Starting in AP Mode");
esp_netif_create_default_wifi_ap();
// TODO: maybe move this creation to initWifiController to avoid making it twice
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
// TODO: Consider moving this to init Wifi Controller to avoid running it twice as well
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
// Configuration for AP
wifi_config_t wifi_config = {
.ap = {
.ssid = "Grow System",
.password = "Password",
.ssid_len = strlen("Grow System"),
.max_connection = 4,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
}
};
// TODO: Enable password support on AP configuration
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "Wifi connectAP finished");
registerEndPoints();
}
The code essentially checks NVS for the credentials, if it finds them both it returns a struct containing both of them as well as ESP_OK. If one of them was not found, the struct instead contains ESP_ERR_NVS_NOT_FOUND. wifiController.c then receives this creds struct and calls beginWifi() which then either calls connectSTA() or connectAP() based on the status of the struct. When the credentials are present, connectSTA() is called, but for unknown reasons the event loop consistently only receives the SYSTEM_EVENT_STA_WPS_ER_PIN event. As I mentioned earlier, even after rolling my code back to a version that did not have the connectAP() function, this behavior persists.
Because of this, I have a hunch that the issue may be related to when I wiped the flash manually, as opposed to the code.
The header file contains the following line in it's typedef to define this event.
SYSTEM_EVENT_STA_WPS_ER_PIN, /*!< ESP32 station wps pin code in enrollee mode */
I do not know what that means, as I have not intentionally included anything regarding wps in this project.
So far my research hasn't returned anything incredibly useful, so if anyone has any ideas what SYSTEM_EVENT_STA_WPS_ER_PIN is or what could be causing my issue, I would be very appreciative. If you think that anymore detail would be useful to solve this issue, please let me know and I will be more than happy to provide it.
Useful to solve the problem.
I'm in the proces of learning to use the ESP32 wifi, read your message checked, the ESP-idf and esp-32 technical manual not much info there I found this URI
https://www.wi-fi.org/downloads-public/Wi-Fi_Protected_Setup_Best_Practices_v2.0.2.pdf/8188
Kind regards
Update: check the sdkconfig file in your projectmap against the one in the example map for wifi config settings.
I have been digging into this issue for several days now and I have not found the root cause but have managed to discovery a workaround and some details about the issue. the SYSTEM_EVENT_STA_WPS_ER_PIN event that kept arising actually is caused by the chip trying to use WPS Enrolle Pin mode to connect to the router. Supposedly this generates an eight digit long pin that can be put into your router which should allow it to connect. I really do not know why it was doing this, but I believe it may have had something to do with how I had AP mode set up. My primary confusion now is why rolling back the code did not fix it.
For the "workaround" I found that flashing Espressif's example STA wifi connection code managed to solve it. The chip properly connected to my network once it was flashed, and I was able to reflash my own code without any issues arriving. This seems extremely strange to me, so part of me thinks that maybe the chip just couldn't connect to my network for some reason and an edge case in the code caused it to go into enrollee mode.
Here is a link to the code that I used to "fix" the issue: https://github.com/espressif/esp-idf/blob/master/examples/wifi/getting_started/station/main/station_example_main.c
I will mark this answer as correct and continue looking for the root problem. In the event that someone else know what actually could have caused this, feel free to post and I will update the correct answer. In the event that I find what the root problem is, I will update this answer as well.
EDIT: After continuing to dig, I believe that the problem was actually do to a multitude of errors in my code. Particularly, I was calling esp_netif_create_default_wifi_sta() and then not setting the WI-FI mode. I needed to add esp_wifi_set_mode(WIFI_MODE_STA), which was absent in my program. I believe setting the network stack to sta without changing the wifi mode was what caused my issue.
I am trying to set up a potentiostat Xtralien by Ossila with LabView.
The way the instrument works in a string-in, string-out, so far so good.
The built-in code examples that are provided by the manufacturer contain firstly a string-in, string-out LabView program and secondly a preliminary console to record an I-V sweep (https://www.ossila.com/pages/basic-xtralien-commands-in-labview, https://www.ossila.com/pages/xtralien-x100-command-list). In the string interface, I can enter 'CLOI hello' and the device responds 'hello world', so far so good. If I proceed any further and send i.e. a 'smu1 measurev' command connecting to some photodiode, I just receive a near-zero value back, setting 'smu1 set voltage 0.5' or similar does not lead to an output voltage either. Running the sweep program over said photodiode gives noise in the µA range.
EDIT: All involved hardware components were double-checked.
Where am I doing something wrong? Is the error arising from communication errors or...? Has someone experienced this so far?
Received the answer from the Ossila support. The Xtralien X200 drivers were recently updated (http://files.ossila.com/source-measure-unit/Ossila-X200-SMU-Instr.zip), and you need to switch on each SMU channel sperately. This was implemented in a subVI in the Instrumentation -> X200.
Hope I helped all who get a similar problem in the future!
What I am doing is writing a WPF application to work with our device. The application writes some commands to the device and reads command's response from it. I got pinvoke declarations from pinvoke.net website for CreateFile, WriteFile, ReadFile, etc.
I made a function doing following things, CreateFile(with flag FILE_FLAG_OVERLAPPED
) to open device, WriteFile to send command, ReadFile to read response, WaitForSingleObject and GetOverlappedResult to capture timeout exception if device doesn't respond, and CloseHandle to close device.
This function always worked fine if I called it in UI thread. But I wanted to call it in background thread to keep UI active. So I created a thread in Window_Loaded method(Work is my function's name).
t = new Thread(Work);
t.Start();
Then ReadFile, WaitForSingleObject and GetOverlappedResult group may met error, these three functions returned success and GetOverlappedResult could capture correct read length returned from device. But no actual data read from device filled in the byte array buffer passed to ReadFile function. The failure rate was about 50%.
If I waited thread t to finish, then it always worked fine again.
t = new Thread(Work);
t.Start();
t.join();
Of cause UI would also hang in this situation.
I searched this problem but no exact same question was found. I tried to set background thread's apartment state to STA or MTA explicitly, but it didn't work.
t = new Thread(Work);
t.SetApartmentState(ApartmentState.STA);
t.Start();
It really confuses me. Please help me if you have any idea. Thank you for your reading.
I couldn't find the root cause. But I bypassed it by rewriting read process in C++ function and calling my C++ function with pInvoke.
How can i restrict my program to run only instance? Currently i'm running my program as daemon(starts and stops automatically), and when user clicks and tries to launch again(which is not a valid usecase), process gets launched in user context and i would like to avoid this for many reasons.
How can i achieve this?
As of now i'm getting list of processes and doing some checks and exiting at the begining itself but this method is not clean, though it solves my problem.
can someone give me a better solution?
And i'm using ps to get process list, is there any reliable API to get this done?
Use a named semaphore with count of 1. On startup, check if this semaphore is taken. If it is, quit. Otherwise, take it.
Proof of concept code: (put somewhere near application entry point)
#include <semaphore.h>
...
if (sem_open(<UUID string for my app>, O_CREAT, 600, 1) == SEM_FAILED) {
exit(0);
}
From the sem_open documentation,
The returned semaphore descriptor is available to the calling process until it is closed with sem_close(), or until the caller exits or execs.
I am working on Objective C to develop an app in I Pad. When I run the program its getting executed in Simulator of IPad. When I do the same connecting the device then I am facing an Error as GDB:Data Formatters temporarily unavailable,will re-try after a 'continue'.
Someone guide how to solve this issue.
Regards,
Vani.
This can be because of several reasons:
Memory issue. Try running your app with instruments to check
When it is unable to find a linked in shared library at launch time.
Also you can try running in a different target xcode and check if that works
Check all you breakpoints. In the Debugger window, click on "Show Breakpoints" and see if there are any unusually placed breakpoints
I also got the same problem in cocoa application.
Take a look at Data Formatters temporarily unavailable, will re-try after a 'continue'.
"Data Formatters temporarily unavailable, will re-try after a
'continue'." means that something has gone so horribly wrong in your
code that even the debugger bailed. As dragyn said, this usually
involves some form of rapid object creation or recursion calling. Add
a few NSLog lines into your code to help you see how far your code is
getting and where it might be looping/calling itself.