RT-Thread nano+Finsh+STM32CubeMx+LL庫在MDK527中移植

RT-Thread nano+Finsh+STM32CubeMx+LL庫在MDK527中移植

前言

stm32CubeMx在stm32開發上提供了很大的便利性,咱們能夠用它來配置一些外設,系統時鐘。RTT是一款很棒的RTOS,可是Device框架對我這些初學者來講仍是有必定的難度,有時咱們只需使用RTOS的核心功能就行,而RTT能夠很方便地包含進本身的工程中來。下面是移植過程的一些筆記。本文大部份內容都能在RTT官網文檔中找到,可是有些細節的部分可能文檔中沒提到,下面結合CubeMx的LL庫移植RTT和Finsh。
感受CubeMx的LL庫和stm32的標準庫比較類似,LL庫比HAL庫底層,代碼簡潔,可是也會有些問題,好比在串口發送數據的時候不能直接使用庫提供發送函數,而須要咱們額外寫,好比添加發送完成標誌檢測等,要否則因爲發送數據操做太快致使串口發送會出錯。
本文假設已經安裝了CubeMx和MDK,而且相關pack也已經安裝好了。

shell

CubeMx配置

CubeMx我用的是舊版,講真CubeMx界面是越更新越醜,也有一些難以忍受的bug,用起來也不方便。因此仍是舊版的好使。
我用的板子是STM32F411CEU6的最小系統板。系統主頻最大100Mhz。
在這裏插入圖片描述
配置系統時鐘外部時鐘25Mhz:
在這裏插入圖片描述
在這裏插入圖片描述
配置串口,打開接收中斷(記得勾選全局中斷)。
在這裏插入圖片描述
在這裏插入圖片描述
配置工程
使用LL庫
直接生成MDK5工程便可。
生成的裸機程序,並進行簡單測試,delay函數本身寫











框架

將RTTHREAD NANO加進工程中

MDK中要提早安裝rtt的pack
在這裏插入圖片描述
中斷與異常處理
RT-Thread 會接管異常處理函數 HardFault_Handler() 和 PendSV_Handler(),這兩個函數由 RT-Thread 實現,因此須要刪除工程裏中斷服務例程文件 stm32f4xx_it.c中的這兩個函數還有就是刪除要用到的串口中斷函數,避免在編譯時產生重複定義錯誤。若是此時對工程進行編譯,沒有出現函數重複定義的錯誤,則不用作修改。
接下來就是系統時鐘,rtt用stm32的嘀嗒時鐘爲其提供時基。因此咱們還要改嘀嗒時鐘配置和中端函數,在中斷文件中咱們也刪除void SysTick_Handler(void)函數,而後在RTT的board文件中改,另外咱們將main中時鐘配置函數也複製過去:
在這裏插入圖片描述
而後在usart.c中實現Finsh輸出,輸入函數。這裏重寫串口數據發送函數不然數據發送會出錯。主要是添加標誌位檢測,防止發送數據過快。





函數

void uart_send(uint8_t c)
{
	  uint32_t t=0;
      LL_USART_TransmitData8(USART1,c);
	 while(LL_USART_IsActiveFlag_TC(USART1) == (uint16_t)RESET)
	 {
	   t++;
	   if(t>0xffff)return;
	 }
	
}
void rt_hw_console_output(const char *str)
{
    rt_size_t i = 0, size = 0;
    char a = '\r';
	  size = rt_strlen(str);
	  for (i = 0; i < size; i++)
    {
        if (*(str + i) == '\n')
        {
					 uart_send((uint8_t)a);
        }
				uart_send((uint8_t )(*(str + i)));
    }
}

//數據接收採用中斷+ ringbuffer 緩衝的方式,具體代碼和官網文檔同樣
//使用的時候要先初始化:
 
 rt_ringbuffer_init(&uart_rxcb, uart_rx_buf, UART_RX_BUF_LEN);
   
  rt_sem_init(&(shell_rx_sem), "shell_rx", 0, 0);

char rt_hw_console_getchar(void)
{
    char ch = 0;
  /* 從 ringbuffer 中拿出數據 */
    while (rt_ringbuffer_getchar(&uart_rxcb, (rt_uint8_t *)&ch) != 1)
    {
        rt_sem_take(&shell_rx_sem, RT_WAITING_FOREVER);
    } 
    return ch; 
	
	
}

/* uart 中斷 */
void USART1_IRQHandler(void)
{
    int ch = -1;
// rt_base_t level;
    /* enter interrupt */
    rt_interrupt_enter();          //在中斷中必定要調用這對函數,進入中斷
    if(LL_USART_IsActiveFlag_RXNE(USART1) && LL_USART_IsEnabledIT_RXNE(USART1))
  {
       while (1)
        {
            ch = -1;
            if (LL_USART_IsActiveFlag_RXNE(USART1)  != RESET)
            {
                ch =  LL_USART_ReceiveData8(USART1);
            }
            if (ch == -1)
            {
                break;
            }  
            /* 讀取到數據,將數據存入 ringbuffer */
            rt_ringbuffer_putchar(&uart_rxcb, ch);
        }        
        rt_sem_release(&shell_rx_sem);
  }
  /* USER CODE END USART1_IRQn 1 */  

    /* leave interrupt */
    rt_interrupt_leave();    //在中斷中必定要調用這對函數,離開中斷
}

而後咱們使用RTT的初始化機制:
在這裏插入圖片描述
在這裏插入圖片描述
main函數中延時函數改rtt的延時函數rt_thread_mdelay();這個函數會讓當前線程讓出CPU控制權。
在這裏插入圖片描述
這裏基本就完成RTT+Finsh移植了
rtconfig.h配置文件
而後編譯下載:發現能出RTT的LOGO
,但不能輸入:
在這裏插入圖片描述
後來發現串口中斷那裏還要加兩條語句打開串口中斷:
LL_USART_EnableIT_RXNE(USART1); //接收中斷
LL_USART_EnableIT_PE(USART1);//串口總中斷
從新編譯下載:
在這裏插入圖片描述
能夠看到能輸出也能接收命令輸入了。














測試

總結

LL庫比較接近寄存器操做的了。
最後工程代碼我已經上傳到這裏了。能夠到個人資源那找。
ui

相關文章
相關標籤/搜索