我正在研究我们的软件组件中的 RTOS 支持。
在某些情况下,将全局变量的副本创建为关键部分中的局部变量(例如受互斥锁保护)是有意义的,然后在关键部分之外的耗时操作中进一步使用本地副本。
我担心C编译器可能会优化局部变量赋值并直接使用全局变量,这会破坏消除代码中竞争条件的努力。
我写了一个过于简化的 LCD 显示示例代码来说明问题。
我有以下问题:
uint8_t page_sel = 0;
char lcd_text[PAGE_CNT][ROW_CNT][COLUMN_CNT];
void lcd_print_text(uint8_t page, uint8_t row, const char* text)
{
lock();
// Store text in global variable which represents
// the text on the display
copy_text_to_lcd_text(page, row, text);
unlock();
// Display update request to run the lcd background task
refresh_semaphore_set();
}
void lcd_select_page(uint8_t page)
{
lock();
// Store the selected page
page_sel = page;
unlock();
// Display update request to run the lcd background task
// If the selected page changes then lcd shall be updated
refresh_semaphore_set();
}
void lcd_task(void)
{
while(1) {
// Update the display only if there are modifications
refresh_semaphore_get();
refresh();
}
}
void refresh(void)
{
char page_lcd_text[ROW_CNT][COLUMN_CNT]
uint8_t page;
lock();
// Page number and text shall be consistent
// so critical section is necessary
page = page_sel;
// Copy is created to avoid partial overwrites during
// display update
copy_page(page_lcd_text, lcd_text, page);
// It is essential to have a local copy before
// the critical section is left
unlock();
// Create pixel data in frame buffer from text (slow)
render_text(page_lcd_text);
// Create pixel data in frame buffer to display (slow)
// selected page number on display
render_page_num(page);
// Transfer pixel data to LCD driver chip (even slower)
lcd_spi_transfer();
}
如果它总是被写入,而不是被优化掉,您应该使用
volatile
关键字。它允许您始终写入变量,而无需优化任何内容。 C 语言中为什么需要 volatile?
就像该线程中提到的那样,易失性也用于跨线程写入局部变量,因此它应该按预期工作。为了确保这种情况发生,您可以使用compiler explorer等工具来留意写入您的值。