STM32 Flash Erase fails with a "Programming Parallelism error" and "Programming Sequence error" - stm32

I have an application running on an STM32F4 which uses the STM32 HAL framework + FreeRTOS. I occasionally need to store some settings in flash during runtime and have written the following function to erase the data at my target address of 0x08060000UL (I believe this is SECTOR_6 of this particular MCU).
HAL_StatusTypeDef Flash::erase(uint32_t address)
{
HAL_StatusTypeDef status;
HAL_FLASH_Unlock(); // unlock the flash API
__disable_irq(); // disable all interrupts
vTaskSuspendAll(); // suspend all FreeRTOS tasks
FLASH_EraseInitTypeDef eraseConfig = {0};
uint32_t sectorError;
uint32_t flashError = 0;
eraseConfig.TypeErase = FLASH_TYPEERASE_SECTORS;
eraseConfig.Sector = this->getSector(address);
eraseConfig.NbSectors = 1;
eraseConfig.VoltageRange = FLASH_VOLTAGE_RANGE_3;
status = HAL_FLASHEx_Erase(&eraseConfig, &sectorError); // <---- FAILS HERE
if (status != HAL_OK)
{
flashError = HAL_FLASH_GetError();
}
status = HAL_FLASH_Lock();
xTaskResumeAll(); // resume all FreeRTOS tasks
__enable_irq(); // re-enable interrupts
return status;
}
The flashError variable ends up getting set to 6, which means the following two errors occurred during the call to HAL_FLASHEx_Erase()
#define HAL_FLASH_ERROR_PGS 0x00000002U /*!< Programming Sequence error */
#define HAL_FLASH_ERROR_PGP 0x00000004U /*!< Programming Parallelism error */
I can't be 100% sure, but I think this code worked fine prior to implementing FreeRTOS. Regardless, what kind of behavior might cause such an error? I thought disabling all ISRs as well as suspending all tasks (even though there is only one running during this operation) would cover me, but no combination of these attempts alleviates the error 🤷‍♂️.

Turns out I had to reset some peripheral flags prior to using the HAL Flash API. Why? I don't know, but clearing all the flags prior to using the API fixed my problem.
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGPERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);

Related

STM32 HAL UART receive by interrupt cleaning buffer

I'm working on an application where I process commands of fixed length received via UART.
I'm also using FreeRTOS and the task that handles the incoming commands is suspended until the uart interrupt handler is called, so my code is like this
void USART1_IRQHandler()
{
HAL_UART_IRQHandler(&huart1);
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart){
HAL_UART_Receive_IT(&huart1, uart_rx_buf, CMD_LEN);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
BaseType_t higherTaskReady = pdFALSE;
HAL_UART_Receive_IT(&huart1, uart_rx_buf, CMD_LEN); //restart interrupt handler
xSemaphoreGiveFromISR(uart_mutex, &higherTaskReady);
portYIELD_FROM_ISR( higherTaskReady); //Relase the semaphore
}
I am using the ErrorCallBack in case if an overflow occurs. Now I successfully catch every correct command, even if they are issued char by char.
However, I'm trying to make the system more error-proof by considering the case where more characters are received than expected.
The command length is 4 but if I receive, for example, 5 chars, then the first 4 is processed normally but when another command is received it starts from the last unprocessed char, so another 3 chars are needed until I can correctly process the commands again.
Luckily, the ErrorCallback is called whenever I receive more than 4 chars, so I know when it happens, but I need a robust way of cleaning the UART buffer so the previous chars are gone.
One solution I can think of is using UART receive 1 char at a time until it can't receive anymore, but is there a better way to simply flush the buffer?
Yes, the problem is the lack of delimiter, because every byte can can carry a value to be processed from 0 to 255. So, how can you detect the inconsistency?
My solution is a checksum byte in the protocol. If the checksum fails, a blocking-mode UART_Receive function is called in order to put the rest of the data from the "system-buffer" to a "disposable-buffer". In my example the fix size of the protocol is 6, I use the UART6 and I have a global variable RxBuffer. Here is the code:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
if(UartHandle->Instance==USART6) {
if(your_checksum_is_ok) {
// You can process the incoming data
} else {
char TempBuffer;
HAL_StatusTypeDef hal_status;
do {
hal_status = HAL_UART_Receive(&huart6, (uint8_t*)&TempBuffer, 1, 10);
} while(hal_status != HAL_TIMEOUT);
}
HAL_UART_Receive_IT(&huart6, (uint8_t*)RxBuffer, 6);
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle) {
if(UartHandle->Instance==USART6) {
HAL_UART_Receive_IT(&huart6, (uint8_t*)RxBuffer, 6);
}
}

I2C communication between two stm32 board in interrupt mode by low layer functions of STM32CUBEMX

I am working on a project which needs data communication between two stm32 (stm32f103rb and stm32f429zg).
I use stm32f103rb-nucleo examples_ll (I2C _OneBoard_Communication_IT) but it works for one byte and after that, it stops working. I want it to work repetitively.
the code structure is exactly in the way the example is written in the folder related to stm32cubemx repository.
I don't know how to make it work in a loop and by pressing the button, communication gets done every time I push the master and slave push buttons.
I have put the master completion callback function here :
void Master_Complete_Callback(void)
{
if(ubNbDataToReceive == 3)
{
/* Prepare the generation of a Non ACKnowledge condition after next received bytes */
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
/* Read character in Receive Data register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
ubNbDataToReceive--;
/* Disable Buffer Interrupts */
LL_I2C_DisableIT_BUF(I2C1);
}
else if(ubNbDataToReceive == 2)
{
/* Generate Stop condition */
LL_I2C_GenerateStopCondition(I2C1);
/* Read character from Receive Data register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
ubNbDataToReceive--;
/* Read character from shift register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
ubNbDataToReceive--;
}
else
{
if(ubNbDataToReceive > 0)
{
/* Read character from shift register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C2);
/* Update ubNbDataToReceive variable */
ubNbDataToReceive--;
}
}
if(ubNbDataToReceive == 0)
{
/* (1) Disable I2C1 transfer event/error interrupts:
* - Disable Events Interrupt
* - Disable Error interrupts
*/
LL_I2C_DisableIT_EVT(I2C1);
LL_I2C_DisableIT_ERR(I2C1);
LL_I2C_EnableIT_EVT(I2C1);
LL_I2C_EnableIT_ERR(I2C1);
/* Read Received character.
RXNE flag is cleared by reading of RXDR register */
if(aReceiveBuffer[ubReceiveIndex-1] == SLAVE_BYTE_TO_SEND)
{
/* Turn LED2 On:
* - Expected byte has been received
* - Master Rx sequence completed successfully
*/
//LED_On();
HAL_UART_Transmit_IT(&huart2,(uint8_t*)"#Data transfer is OK!$",strlen("#Data transfer is OK!$"));
ubNbDataToTransmit = sizeof(SLAVE_BYTE_TO_SEND);
ubNbDataToReceive = sizeof(SLAVE_BYTE_TO_SEND);
}
else
{
/* Call Error function */
Error_Callback();
}
}
}
it is easily understood that the end of the transmission process is when I add HAL_UART function to send to serial port the transmission completion.
but after this time , it works one more time and after that it stops.
I have checked the oscilloscope signal show and after the second time transmission SCL pin gets LOW .
Thanks
Did not use LL for a long time, but isnt I2C interrupt disabled after single transfer with LL_I2C_DisableIT_EVT(I2C1);?? Make sure to enable it again before next transmission.
There is such a thing that two master devices cannot communicate each other via I2C bus. Because master devices do not have DEVICE_ADDRESS. Master devices can communicate only slave devices.

STM32 FreeRTOS - UART Deferred Interrupt Problem

I am trying to read data with unkown size using UART Receive Interrupt. In the call back function, I enabled Rx interrupt in order to read characters until \n is gotten. If \n is get, then higher priority task which is deferred interrupt handler is woken. The problem is that I tried to read one by one byte via call back function and I tried to put each character into a buffer, but unfortunately buffer could not get any character. Moreover, deferred interrupt handler could not be woken.
My STM32 board is STM32F767ZI, and my IDE is KEIL.
Some Important notes before sharing the code:
1. rxIndex and gpsBuffer are declared as global.
2. Periodic function works without any problem.
Here is my code:
Periodic Function, Priority = 1
void vPeriodicTask(void *pvParameters)
{
const TickType_t xDelay500ms = pdMS_TO_TICKS(500UL);
while (1) {
vTaskDelay(xDelay500ms);
HAL_UART_Transmit(&huart3,(uint8_t*)"Imu\r\n",sizeof("Imu\r\n"),1000);
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_7);
}
}
Deferred Interrupt, Priority = 3
void vHandlerTask(void *pvParameters)
{
const TickType_t xMaxExpectedBlockTime = pdMS_TO_TICKS(1000);
while(1) {
if (xSemaphoreTake(xBinarySemaphore,xMaxExpectedBlockTime) == pdPASS) {
HAL_UART_Transmit(&huart3,(uint8_t*)"Semaphore Acquired\r\n",sizeof("Semaphore
Acquired\r\n"),1000);
// Some important processes will be added here
rxIndex = 0;
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_14);
}
}
}
Call back function:
void HAL_UART_RxCptlCallBack(UART_HandleTypeDef *huart)
{
gpsBuffer[rxIndex++] = rData;
if (rData == 0x0A) {
BaseType_t xHigherPriorityTaskWoken;
xSemaphoreGiveFromISR(xBinarySemaphore,&xHigherPriorityTaskWoken);
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
HAL_UART_Receive_IT(huart,(uint8_t*)&rData,1);
}
Main function
HAL_UART_Receive_IT(&huart3,&rData,1);
xBinarySemaphore = xSemaphoreCreateBinary();
if (xBinarySemaphore != NULL) {
//success
xTaskCreate(vHandlerTask,"Handler",128,NULL,1,&vHandlerTaskHandler);
xTaskCreate(vPeriodicTask,"Periodic",128,NULL,3,&vPeriodicTaskHandler);
vTaskStartScheduler();
}
Using HAL for it is a best way to get into the troubles. It uses HAL_Delay which is systick dependant and you should rewrite this function to read RTOS tick instead.
I use queues to pass the data (the references to data) but it should work. There is always a big question mark when using the HAL functions.
void HAL_UART_RxCptlCallBack(UART_HandleTypeDef *huart)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
gpsBuffer[rxIndex++] = rData;
if (rData == 0x0A) {
if(xSemaphoreGiveFromISR(xBinarySemaphore,&xHigherPriorityTaskWoken) == pdFALSE)
{
/* some error handling */
}
}
HAL_UART_Receive_IT(huart,(uint8_t*)&rData,1);
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
Concluding if I use HAL & RTOS I always modify the way HAL handles timeouts.

RTOS μC/OS-II not running as expected

I'm using ST STM32F101xB and μC/OS-II, I was having external clock (HSE) on old board and it's running fine. We wanted to use internal clock (HSI) on new board, however, the RTOS (Appmaintask()) doesn't run using internal clock, i have changed my code as below, any idea what's wrong with the change:
void BSP_Init (void)
{
RCC_DeInit();
//RCC_HSEConfig(RCC_HSE_ON);
//RCC_WaitForHSEStartUp();
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1); // APB2 clock divide by 1 => 64MHz
RCC_PCLK1Config(RCC_HCLK_Div2); // APB1 clock divide by 2 => 32MHz
FLASH_SetLatency(FLASH_Latency_2);
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_8); // 64MHz
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_8);
RCC_PLLCmd(ENABLE);
RCC_LSEConfig(RCC_LSE_OFF);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
;
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while (RCC_GetSYSCLKSource() != 0x08) {
;
}
//Set the Vector Table base location at 0x08000000
//NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
// Need to finalize and arange priority for each interrupts in future,
// So that 1 interrupt wont blocks another interrupt.
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
}
void main()
{
INT8U err;
cpuObj = new Cstm32f10x();
BSP_Init();
BSP_IntDisAll(); /* Disable all ints until we are ready to accept them. */
OSInit();
err = OSTaskCreateExt (AppMainTask,
(void *)0,
(OS_STK *)&AppMainTaskStk[APP_MAIN_TASK_STK_SIZE-1],
APP_MAIN_TASK_PRIO,
APP_MAIN_TASK_ID,
(OS_STK *)&AppMainTaskStk[0],
APP_MAIN_TASK_STK_SIZE,
(void *)0,
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
OSStart(); // Start multitasking (i.e. give control to uC/OS-II)
}
void AppMainTask (void *p_arg)
{
OS_CPU_SysTickInit();
while(TRUE)
{
OSTimeDly(1);
}
}
Thanks.
Setting up of the PLL is normally performed in the CMSIS start-up code provided by ST/ARM. This code executes as part of the runtime environment start-up before main() is called. I recommend that you use this code for chip initialisation since static data initialisation and static object constructors run before main() and will be running before possibly critical initialisation.
The CMSIS with Cortex-M3 core and STM32F1xx specific device support is included in the STM32 Standard Peripheral Library. The file that actually does the work is system_stm32f10x.c. Other functions you are performing in BSP_Init() such as flash latency are also dealt with by the CMSIS start-up code. Even if you customise this code, I strongly recommend that you use this method of early environment initialisation.
Another possibility is to use the STM32CubeMX utility to generate configuration code. This appears to be a replacement for the apparently now unavailable STM32 MicroXplorer utility.

Can't get Notification after connecting serial dock connector between iPhone and iMac

Is it possible to connect iMac to iPhone through the dock connector ? Also I am using the EAAccessory framework but I am not get any notifications when I connect the serial cable to iPhone. If any one knows about this please give me a suggestion.
There seems to be a lot of confusion regarding EAAccessoryManager and the accompanying classes. These are only for use with MFI sanctioned hardware i.e. those manufacturers that have taken the time to follow the MFI program and integrate the requisite hardware into their device.
The use of a chip and the establishment of a protocol allows for the facilitation of a communication stream between the app and the device.
Sam is correct in his statement but there is no need to jailbreak your app in order to bypass the MFI program however, you will not be able to submit to the App Store if you follow the procedure I am about to briefly outine:
Obtain all of the header files for the IOKit iOS OpenSource Browser
Add them to your solution
Include the IOKit.h framework
Head to http://www.arduino.cc/playground/Interfacing/Cocoa#IOKit for an example of how to use IOKit and icotl commands to achieve what you require
I have successfully implemented IOKit operations on an iOS device so this is definitely possible as long as you are willing to forego submission to the App Store.
Raj..
for get notification for connection accessory first of you have to register your accessory to MFI. otherwise you have to jailbreak your iPhone. for jail break check this code
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
static struct termios gOriginalTTYAttrs;
static int OpenSerialPort()
{
int fileDescriptor = -1;
int handshake;
struct termios options;
// Open the serial port read/write, with no controlling terminal, and don't wait for a connection.
// The O_NONBLOCK flag also causes subsequent I/O on the device to be non-blocking.
// See open(2) ("man 2 open") for details.
fileDescriptor = open("/dev/tty.iap", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fileDescriptor == -1)
{
printf("Error opening serial port %s - %s(%d).\n",
"/dev/tty.iap", strerror(errno), errno);
goto error;
}
// Note that open() follows POSIX semantics: multiple open() calls to the same file will succeed
// unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned
// processes.
// See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
if (ioctl(fileDescriptor, TIOCEXCL) == -1)
{
printf("Error setting TIOCEXCL on %s - %s(%d).\n",
"/dev/tty.iap", strerror(errno), errno);
goto error;
}
// Now that the device is open, clear the O_NONBLOCK flag so subsequent I/O will block.
// See fcntl(2) ("man 2 fcntl") for details.
if (fcntl(fileDescriptor, F_SETFL, 0) == -1)
{
printf("Error clearing O_NONBLOCK %s - %s(%d).\n",
"/dev/tty.iap", strerror(errno), errno);
goto error;
}
// Get the current options and save them so we can restore the default settings later.
if (tcgetattr(fileDescriptor, &gOriginalTTYAttrs) == -1)
{
printf("Error getting tty attributes %s - %s(%d).\n",
"/dev/tty.iap", strerror(errno), errno);
goto error;
}
// The serial port attributes such as timeouts and baud rate are set by modifying the termios
// structure and then calling tcsetattr() to cause the changes to take effect. Note that the
// changes will not become effective without the tcsetattr() call.
// See tcsetattr(4) ("man 4 tcsetattr") for details.
options = gOriginalTTYAttrs;
// Print the current input and output baud rates.
// See tcsetattr(4) ("man 4 tcsetattr") for details.
printf("Current input baud rate is %d\n", (int) cfgetispeed(&options));
printf("Current output baud rate is %d\n", (int) cfgetospeed(&options));
// Set raw input (non-canonical) mode, with reads blocking until either a single character
// has been received or a one second timeout expires.
// See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") for details.
cfmakeraw(&options);
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 10;
// The baud rate, word length, and handshake options can be set as follows:
cfsetspeed(&options, B19200); // Set 19200 baud
options.c_cflag |= (CS8); // RTS flow control of input
printf("Input baud rate changed to %d\n", (int) cfgetispeed(&options));
printf("Output baud rate changed to %d\n", (int) cfgetospeed(&options));
// Cause the new options to take effect immediately.
if (tcsetattr(fileDescriptor, TCSANOW, &options) == -1)
{
printf("Error setting tty attributes %s - %s(%d).\n",
"/dev/tty.iap", strerror(errno), errno);
goto error;
}
// Success
return fileDescriptor;
// Failure "/dev/tty.iap"
error:
if (fileDescriptor != -1)
{
close(fileDescriptor);
}
return -1;
}
int main(int args, char *argv[])
{
int fd;
char somechar[8];
fd=OpenSerialPort(); // Open tty.iap with no hardware control, 8 bit, BLOCKING and at 19200 baud
if(fd>-1)
{
write(fd,"*",1); // Write handshaking message over serial
///////////////////////////////////////////////////////////////////////////////////////////////////
// After this, our device or our PC program should be strobing serial ground to gain access to the Iphone Serial Line
//////////////////////////////////////////////////////////////////////////////////////////////////
read(fd,&somechar[0],1); // Read 1 byte over serial. This will block (wait) untill the byte has been received
if(somechar[0]=='*') // Check if this byte is a "handshaking" message
{
printf("Serial connection established!\n"); // If it is, we have established a connection to the device and can freely read/write over serial!
while(1) // Do this forever or untill someone presses CTRL+C
{
read(fd,&somechar[0],1); // Read a character over serial!
putchar(somechar[0]); // Write the character to the Terminal!!
}
}
}
return 0;
}
If you connect your iPhone to an iMac and you have either iTunes or Xcode running, you would be able to see that the iPhone is connected.
In Xcode, go to the Organizer window. In iTunes, look under the Devices in the left-hand column.
The EAAccessory framework, which I have not used, should have nothing to do with this.
Here is the answer: Launch specific app when external accessory attached - not all accessories can signal to launch app when they are connected. I think that ordinal USB cable also can't.
About IOKit: You can add nesessary files from Xcode itself - open Xcode.app package. IOKit framework is located in Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks
simply copy absent files (or make link) to
Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/IOKit.framework
and to
Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/System/Library/Frameworks/IOKit.framework
and also for all simulator platforms
You should know that not all functions of IOKit can work on real device (but they work under simulator) due to iOS sandbox security.
But You can work with IORegistry well. My first project on iOS was implemetation of the IORegistryExplorer.
Good luck!