drv_lcd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2017-08-17 Tanek first implementation
  9. */
  10. #include <rtthread.h>
  11. #include <string.h>
  12. #include "stm32f4xx_hal.h"
  13. #define RT_HW_LCD_WIDTH ((uint16_t)800) /* LCD PIXEL WIDTH */
  14. #define RT_HW_LCD_HEIGHT ((uint16_t)480) /* LCD PIXEL HEIGHT */
  15. #define LCD_800_480_HSYNC ((uint16_t)96) /* Horizontal synchronization */
  16. #define LCD_800_480_HBP ((uint16_t)10) /* Horizontal back porch */
  17. #define LCD_800_480_HFP ((uint16_t)10) /* Horizontal front porch */
  18. #define LCD_800_480_VSYNC ((uint16_t)2) /* Vertical synchronization */
  19. #define LCD_800_480_VBP ((uint16_t)10) /* Vertical back porch */
  20. #define LCD_800_480_VFP ((uint16_t)10) /* Vertical front porch */
  21. #define LCD_BITS_PER_PIXEL 16
  22. static LTDC_HandleTypeDef hltdc;
  23. static DMA2D_HandleTypeDef hdma2d;
  24. static rt_uint16_t *lcd_framebuffer = RT_NULL;
  25. static rt_uint16_t *_rt_framebuffer = RT_NULL;
  26. static struct rt_device_graphic_info _lcd_info;
  27. static struct rt_device lcd;
  28. void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc)
  29. {
  30. GPIO_InitTypeDef GPIO_InitStruct;
  31. if(hltdc->Instance==LTDC)
  32. {
  33. /* Peripheral clock enable */
  34. __HAL_RCC_LTDC_CLK_ENABLE();
  35. __HAL_RCC_DMA2D_CLK_ENABLE();
  36. __HAL_RCC_GPIOE_CLK_ENABLE();
  37. __HAL_RCC_GPIOI_CLK_ENABLE();
  38. __HAL_RCC_GPIOJ_CLK_ENABLE();
  39. __HAL_RCC_GPIOK_CLK_ENABLE();
  40. /**LTDC GPIO Configuration
  41. PI12 ------> LTDC_HSYNC
  42. PI13 ------> LTDC_VSYNC
  43. PI14 ------> LTDC_CLK
  44. PI15 ------> LTDC_R0
  45. PJ0 ------> LTDC_R1
  46. PJ2 ------> LTDC_R3
  47. PJ3 ------> LTDC_R4
  48. PJ4 ------> LTDC_R5
  49. PJ5 ------> LTDC_R6
  50. PJ6 ------> LTDC_R7
  51. PJ9 ------> LTDC_G2
  52. PJ10 ------> LTDC_G3
  53. PJ11 ------> LTDC_G4
  54. PK0 ------> LTDC_G5
  55. PK1 ------> LTDC_G6
  56. PK2 ------> LTDC_G7
  57. PJ15 ------> LTDC_B3
  58. PK3 ------> LTDC_B4
  59. PK4 ------> LTDC_B5
  60. PK5 ------> LTDC_B6
  61. PK6 ------> LTDC_B7
  62. PK7 ------> LTDC_DE
  63. */
  64. GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  65. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  66. GPIO_InitStruct.Pull = GPIO_NOPULL;
  67. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  68. GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
  69. HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
  70. GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4
  71. |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_9|GPIO_PIN_10
  72. |GPIO_PIN_11|GPIO_PIN_15;
  73. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  74. GPIO_InitStruct.Pull = GPIO_NOPULL;
  75. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  76. GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
  77. HAL_GPIO_Init(GPIOJ, &GPIO_InitStruct);
  78. GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
  79. |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
  80. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  81. GPIO_InitStruct.Pull = GPIO_NOPULL;
  82. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  83. GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
  84. HAL_GPIO_Init(GPIOK, &GPIO_InitStruct);
  85. }
  86. }
  87. void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc)
  88. {
  89. if(hltdc->Instance==LTDC)
  90. {
  91. /* Peripheral clock disable */
  92. __HAL_RCC_LTDC_CLK_DISABLE();
  93. /**LTDC GPIO Configuration
  94. PE5 ------> LTDC_G0
  95. PE6 ------> LTDC_G1
  96. PI12 ------> LTDC_HSYNC
  97. PI13 ------> LTDC_VSYNC
  98. PI14 ------> LTDC_CLK
  99. PI15 ------> LTDC_R0
  100. PJ0 ------> LTDC_R1
  101. PJ1 ------> LTDC_R2
  102. PJ2 ------> LTDC_R3
  103. PJ3 ------> LTDC_R4
  104. PJ4 ------> LTDC_R5
  105. PJ5 ------> LTDC_R6
  106. PJ6 ------> LTDC_R7
  107. PJ9 ------> LTDC_G2
  108. PJ10 ------> LTDC_G3
  109. PJ11 ------> LTDC_G4
  110. PK0 ------> LTDC_G5
  111. PK1 ------> LTDC_G6
  112. PK2 ------> LTDC_G7
  113. PJ12 ------> LTDC_B0
  114. PJ13 ------> LTDC_B1
  115. PJ14 ------> LTDC_B2
  116. PJ15 ------> LTDC_B3
  117. PK3 ------> LTDC_B4
  118. PK4 ------> LTDC_B5
  119. PK5 ------> LTDC_B6
  120. PK6 ------> LTDC_B7
  121. PK7 ------> LTDC_DE
  122. */
  123. HAL_GPIO_DeInit(GPIOE, GPIO_PIN_5|GPIO_PIN_6);
  124. HAL_GPIO_DeInit(GPIOI, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
  125. HAL_GPIO_DeInit(GPIOJ, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
  126. |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_9
  127. |GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13
  128. |GPIO_PIN_14|GPIO_PIN_15);
  129. HAL_GPIO_DeInit(GPIOK, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
  130. |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
  131. }
  132. }
  133. static void LTDC_CLK_Config(void)
  134. {
  135. RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
  136. PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
  137. PeriphClkInitStruct.PLLSAI.PLLSAIN = 100;
  138. PeriphClkInitStruct.PLLSAI.PLLSAIR = 2;
  139. PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2;
  140. if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  141. {
  142. RT_ASSERT(RT_NULL);
  143. }
  144. }
  145. /* LTDC init function */
  146. static void MX_LTDC_Init(void)
  147. {
  148. LTDC_LayerCfgTypeDef pLayerCfg;
  149. hltdc.Instance = LTDC;
  150. hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;
  151. hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;
  152. hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;
  153. hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
  154. hltdc.Init.Backcolor.Blue = 0;
  155. hltdc.Init.Backcolor.Green = 0;
  156. hltdc.Init.Backcolor.Red = 0;
  157. hltdc.Init.HorizontalSync = LCD_800_480_HSYNC;
  158. hltdc.Init.VerticalSync = LCD_800_480_VSYNC;
  159. hltdc.Init.AccumulatedHBP = LCD_800_480_HSYNC + LCD_800_480_HBP;
  160. hltdc.Init.AccumulatedVBP = LCD_800_480_VSYNC + LCD_800_480_VBP;
  161. hltdc.Init.AccumulatedActiveW = RT_HW_LCD_WIDTH + LCD_800_480_HSYNC + LCD_800_480_HBP;
  162. hltdc.Init.AccumulatedActiveH = RT_HW_LCD_HEIGHT + LCD_800_480_VSYNC + LCD_800_480_VBP;
  163. hltdc.Init.TotalWidth = RT_HW_LCD_WIDTH + LCD_800_480_HSYNC + LCD_800_480_HBP + LCD_800_480_HFP;
  164. hltdc.Init.TotalHeigh = RT_HW_LCD_HEIGHT + LCD_800_480_VSYNC + LCD_800_480_VBP + LCD_800_480_VFP;
  165. hltdc.LayerCfg->ImageHeight = RT_HW_LCD_HEIGHT;
  166. hltdc.LayerCfg->ImageWidth = RT_HW_LCD_WIDTH;
  167. if (HAL_LTDC_Init(&hltdc) != HAL_OK)
  168. {
  169. RT_ASSERT(RT_NULL);
  170. }
  171. lcd_framebuffer = rt_malloc_align(sizeof(rt_uint16_t) * RT_HW_LCD_WIDTH * RT_HW_LCD_HEIGHT, 32);
  172. RT_ASSERT(lcd_framebuffer != RT_NULL);
  173. rt_memset(lcd_framebuffer, 0, sizeof(rt_uint16_t) * RT_HW_LCD_WIDTH * RT_HW_LCD_HEIGHT);
  174. pLayerCfg.WindowX0 = 0;
  175. pLayerCfg.WindowX1 = RT_HW_LCD_WIDTH;
  176. pLayerCfg.WindowY0 = 0;
  177. pLayerCfg.WindowY1 = RT_HW_LCD_HEIGHT;
  178. pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
  179. pLayerCfg.Alpha = 0xFF;
  180. pLayerCfg.Alpha0 = 0xFF;
  181. pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
  182. pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR1_CA;
  183. pLayerCfg.FBStartAdress = (uint32_t)lcd_framebuffer;
  184. pLayerCfg.ImageWidth = RT_HW_LCD_WIDTH;
  185. pLayerCfg.ImageHeight = RT_HW_LCD_HEIGHT;
  186. pLayerCfg.Backcolor.Blue = 0;
  187. pLayerCfg.Backcolor.Green = 0;
  188. pLayerCfg.Backcolor.Red = 0;
  189. if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)
  190. {
  191. RT_ASSERT(RT_NULL);
  192. }
  193. }
  194. /* DMA2D init function */
  195. static void MX_DMA2D_Init(void)
  196. {
  197. hdma2d.Instance = DMA2D;
  198. hdma2d.Init.Mode = DMA2D_M2M;
  199. hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
  200. hdma2d.Init.OutputOffset = 0;
  201. hdma2d.LayerCfg[0].InputOffset = 0;
  202. hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
  203. hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
  204. hdma2d.LayerCfg[0].InputAlpha = 0;
  205. if (HAL_DMA2D_Init(&hdma2d) != HAL_OK)
  206. {
  207. RT_ASSERT(RT_NULL);
  208. }
  209. if (HAL_DMA2D_ConfigLayer(&hdma2d, 0) != HAL_OK)
  210. {
  211. RT_ASSERT(RT_NULL);
  212. }
  213. }
  214. static void lcd_backlight_init(void)
  215. {
  216. GPIO_InitTypeDef GPIO_InitStruct;
  217. __HAL_RCC_GPIOA_CLK_ENABLE();
  218. GPIO_InitStruct.Pin = GPIO_PIN_0;
  219. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  220. GPIO_InitStruct.Pull = GPIO_NOPULL;
  221. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  222. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  223. HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
  224. }
  225. static rt_err_t rt_lcd_init(rt_device_t dev)
  226. {
  227. return RT_EOK;
  228. }
  229. static rt_err_t rt_lcd_open(rt_device_t dev, rt_uint16_t oflag)
  230. {
  231. return RT_EOK;
  232. }
  233. static rt_err_t rt_lcd_close(rt_device_t dev)
  234. {
  235. return RT_EOK;
  236. }
  237. static rt_err_t rt_lcd_control(rt_device_t dev, rt_uint8_t cmd, void *args)
  238. {
  239. switch (cmd)
  240. {
  241. case RTGRAPHIC_CTRL_RECT_UPDATE:
  242. {
  243. memcpy((void *)lcd_framebuffer, _rt_framebuffer, sizeof(rt_uint16_t)*RT_HW_LCD_HEIGHT * RT_HW_LCD_WIDTH);
  244. }
  245. break;
  246. case RTGRAPHIC_CTRL_POWERON:
  247. break;
  248. case RTGRAPHIC_CTRL_POWEROFF:
  249. break;
  250. case RTGRAPHIC_CTRL_GET_INFO:
  251. memcpy(args, &_lcd_info, sizeof(_lcd_info));
  252. break;
  253. case RTGRAPHIC_CTRL_SET_MODE:
  254. break;
  255. }
  256. return RT_EOK;
  257. }
  258. int stm32_hw_lcd_init(void)
  259. {
  260. _rt_framebuffer = rt_malloc_align(sizeof(rt_uint16_t) * RT_HW_LCD_WIDTH * RT_HW_LCD_HEIGHT, 32);
  261. if (_rt_framebuffer == RT_NULL)
  262. return -1; /* no memory yet */
  263. LTDC_CLK_Config();
  264. MX_LTDC_Init();
  265. lcd_backlight_init();
  266. MX_DMA2D_Init();
  267. _lcd_info.bits_per_pixel = LCD_BITS_PER_PIXEL;
  268. _lcd_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565; // RTGRAPHIC_PIXEL_FORMAT_ARGB888
  269. _lcd_info.framebuffer = (void *)_rt_framebuffer;
  270. _lcd_info.width = RT_HW_LCD_WIDTH;
  271. _lcd_info.height = RT_HW_LCD_HEIGHT;
  272. /* init device structure */
  273. lcd.type = RT_Device_Class_Graphic;
  274. lcd.init = rt_lcd_init;
  275. lcd.open = rt_lcd_open;
  276. lcd.close = rt_lcd_close;
  277. lcd.read = NULL;
  278. lcd.write = NULL;
  279. lcd.control = rt_lcd_control;
  280. lcd.user_data = (void *)&_lcd_info;
  281. /* register lcd device to RT-Thread */
  282. rt_device_register(&lcd, "lcd", RT_DEVICE_FLAG_RDWR);
  283. return 0;
  284. }
  285. INIT_APP_EXPORT(stm32_hw_lcd_init);