2024-11-06 02:25 AM - edited 2024-11-06 04:12 AM
Hello everyone, I am integrating FreeRTOS into a project with an LCD16x2. The issue is when I initialize the LCD handle in the main function and use it in a task, it doesn't print the correct character. However, if I initialize the LCD handle in the task itself, it works fine. I suspect the issue is with the LCD_Write_4bit function. When using HAL_Delay(), I get a hard fault error. Can anyone help me with this?
I'm using STM32F407 Discovery Board (STM32F407-DISC1) and STM32CubeIDE
static LCD_HandleTypeDef lcd;
int main(void)
{
/* USER CODE BEGIN 1 */
TaskHandle_t task1_handle;
BaseType_t status;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
LCD_PortType ports[] = { GPIOB, GPIOB, GPIOB, GPIOB };
LCD_PinType pins[] = { GPIO_PIN_7, GPIO_PIN_5, GPIO_PIN_3, GPIO_PIN_9 };
// Create the LCD instance with the defined ports and pins
lcd = LCD_Define(ports, pins, GPIOD, GPIO_PIN_0, GPIOD, GPIO_PIN_2, LCD_4_BIT_MODE);
// Initialize the LCD display
LCD_Init(&lcd);
vSemaphoreCreateBinary( xWork );
//Enable the CYCCNT counter.
DWT_CTRL |= ( 1 << 0);
SEGGER_SYSVIEW_Conf();
SEGGER_SYSVIEW_Start();
status = xTaskCreate(print_handler, "print_task", 400, NULL, 3, &task1_handle);
configASSERT(status == pdPASS);
//start the freeRTOS scheduler
vTaskStartScheduler();
//if the control comes here, then the launch of the scheduler has failed due to
//insufficient memory in heap
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void print_handler(void *parameters)
{
//if using this code the task work fine
// LCD_PortType ports[] = { GPIOB, GPIOB, GPIOB, GPIOB };
// LCD_PinType pins[] = { GPIO_PIN_7, GPIO_PIN_5, GPIO_PIN_3, GPIO_PIN_9 };
//
// // Create the LCD instance with the defined ports and pins
// lcd = LCD_Define(ports, pins, GPIOD, GPIO_PIN_0, GPIOD, GPIO_PIN_2, LCD_4_BIT_MODE);
while (1)
{
if (xSemaphoreTake(xWork, portMAX_DELAY) == pdTRUE)
{
LCD_Write_Data(&lcd, 0x45);
LCD_Write_Data(&lcd, 0x31);
HAL_GPIO_TogglePin(GPIOD, LED_GREEN_PIN);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
}
////////////////////////////////////////LCD_FUNCTION/////////////////////////////////
LCD_HandleTypeDef LCD_Define(
LCD_PortType data_port[], LCD_PinType data_pin[],
LCD_PortType rs_port, LCD_PinType rs_pin,
LCD_PortType en_port, LCD_PinType en_pin, LCD_ModeTypeDef mode)
{
LCD_HandleTypeDef lcd;
lcd.mode = mode;
lcd.data_port = data_port;
lcd.data_pin = data_pin;
lcd.en_port = en_port;
lcd.en_pin = en_pin;
lcd.rs_port = rs_port;
lcd.rs_pin = rs_pin;
return lcd;
}
void LCD_Write_Data(LCD_HandleTypeDef * lcd ,uint8_t data)
{
HAL_GPIO_WritePin(lcd->rs_port, lcd->rs_pin, LCD_DATA_REG);
if(lcd->mode == LCD_4_BIT_MODE)
{
LCD_Write_4bit(lcd, data >> 4); /*Higher nibble*/
LCD_Write_4bit(lcd, data & 0x0F); /*Lower nibble*/
}else
{
LCD_Write_8bit(lcd, data);
}
}
static void LCD_Write_4bit(LCD_HandleTypeDef * lcd, uint8_t value)
{
HAL_GPIO_WritePin(lcd->data_port[0],lcd->data_pin[0], ((value >> 0) & 0x1) );
HAL_GPIO_WritePin(lcd->data_port[1],lcd->data_pin[1], ((value >> 1) & 0x1) );
HAL_GPIO_WritePin(lcd->data_port[2],lcd->data_pin[2], ((value >> 2) & 0x1) );
HAL_GPIO_WritePin(lcd->data_port[3],lcd->data_pin[3], ((value >> 3) & 0x1) );
HAL_GPIO_WritePin(lcd->en_port, lcd->en_pin, GPIO_PIN_SET); //figure 15, page 32 (rising edge & falling edge to)
// HAL_Delay(1);
// HAL_GPIO_WritePin(lcd->en_port, lcd->en_pin, GPIO_PIN_RESET);
// HAL_Delay(1);
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
vTaskDelay(1 / portTICK_PERIOD_MS);
}
else
{
HAL_Delay(1);
}
HAL_GPIO_WritePin(lcd->en_port, lcd->en_pin, GPIO_PIN_RESET);
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
vTaskDelay(1 / portTICK_PERIOD_MS);
}
else
{
HAL_Delay(1);
}
}
2024-11-06 02:29 AM
Hello @Quangvm and welcome to the community,
Please review tips on how to post a thread here.
Please read it and make the necessary changes: in the title, the code sharing (do not psot screen shots) and the used MCU part number.
Thank you for your understanding.
2024-11-06 02:35 AM
Sorry for the carelessness, I will follow the tip. Thank you so much