mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-12-01 03:28:53 +08:00
212 lines
5.5 KiB
Markdown
212 lines
5.5 KiB
Markdown
## 将 AWTK 移植到 STM32f103ze 裸系统
|
||
|
||
AWTK 的可移植性很高,在移植时只需要实现平台初始化、lcd 和 mainloop 三个方面的东西。本文以 STM32f103ze 为例介绍移植 AWTK 到新平台的过程。
|
||
|
||
### 一、平台初始化
|
||
|
||
除了基本的libc函数外,AWTK对平台没有特别要求,实现获取当前时间的函数get\_time\_ms64和sleep_ms函数即可。另外需要给GUI分配一块内存空间,并调用tk\_mem\_init。
|
||
|
||
我们使用 systick 来实现 get\_time\_ms64 和 sleep\_ms 两个函数,裸系统上只需加入 src/platforms/raw/sys\_tick.c 并初始化 sys\_tick 即可。
|
||
|
||
> 以下是初始化内存的代码。
|
||
|
||
```
|
||
ret_t platform_prepare(void) {
|
||
static bool_t inited = FALSE;
|
||
static uint32_t s_heam_mem[4000];
|
||
|
||
if (!inited) {
|
||
inited = TRUE;
|
||
tk_mem_init(s_heam_mem, sizeof(s_heam_mem));
|
||
}
|
||
|
||
return RET_OK;
|
||
}
|
||
```
|
||
|
||
> 参考:awtk-port/platform.c
|
||
|
||
> 以下是初始化 systick 的代码(在板子提供代码上修改而来)。
|
||
|
||
```
|
||
static u8 fac_us = 0;
|
||
static u16 fac_ms = 0;
|
||
|
||
void systick_enable_int(void) {
|
||
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
|
||
SysTick->LOAD = fac_ms;
|
||
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
|
||
}
|
||
|
||
void SysTick_Init(void) {
|
||
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
|
||
fac_us = SystemCoreClock / 8000000;
|
||
fac_ms = (u16)fac_us * 1000;
|
||
}
|
||
|
||
void delay_us(u32 nus) {
|
||
u32 temp = 0;
|
||
SysTick->LOAD = nus * fac_us;
|
||
SysTick->VAL = 0x00;
|
||
do {
|
||
temp = SysTick->CTRL;
|
||
} while ((temp & 0x01) && !(temp & (1 << 16)));
|
||
}
|
||
|
||
void delay_ms(u16 nms) {
|
||
u32 temp = 0;
|
||
SysTick->LOAD = (u32)nms * fac_ms;
|
||
SysTick->VAL = 0x00;
|
||
do {
|
||
temp = SysTick->CTRL;
|
||
} while ((temp & 0x01) && !(temp & (1 << 16)));
|
||
}
|
||
```
|
||
|
||
> 参考:awtk-port/SysTick.c
|
||
|
||
### 二、实现 lcd
|
||
|
||
lcd\_t 接口提供基本的显示功能,AWTK 提供基于*寄存器*、*帧缓冲*和*片段帧缓冲*三种缺省实现,在此基础上实现自己的 lcd\_t 接口非常方便。
|
||
|
||
stm32f103ze 使用基于*片段帧缓冲*的 lcd 的缺省实现,只需要提供 set\_window\_func 和 write\_data\_func 两个函数/宏即可。这里直接使用了 TFT\_SetWindow 和 TFT\_WriteData 两个函数。
|
||
|
||
> 直接写寄存器的方式容易闪烁,而帧缓冲又需要大量内存,片段帧缓冲能有效解决低内存平台的闪烁问题。
|
||
|
||
```
|
||
#include "tftlcd.h"
|
||
#include "tkc/mem.h"
|
||
#include "lcd/lcd_mem_fragment.h"
|
||
|
||
typedef uint16_t pixel_t;
|
||
|
||
#define LCD_FORMAT BITMAP_FMT_BGR565
|
||
#define pixel_from_rgb(r, g, b) \
|
||
((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
|
||
#define pixel_to_rgba(p) \
|
||
{ (0xff & ((p >> 11) << 3)), (0xff & ((p >> 5) << 2)), (0xff & (p << 3)) }
|
||
|
||
#define set_window_func LCD_Set_Window
|
||
#define write_data_func LCD_WriteData_Color
|
||
|
||
#include "base/pixel.h"
|
||
#include "blend/pixel_ops.inc"
|
||
#include "lcd/lcd_mem_fragment.inc"
|
||
|
||
```
|
||
|
||
> 参考 awtk-port/lcd\_stm32\_raw.c
|
||
|
||
### 三、实现 main\_loop
|
||
|
||
main\_loop 主要负责事件分发和绘制这个不断循环的过程。main\_loop\_raw.inc 里实现了裸系统 main\_loop 的基本功能,在移植时加上输入事件的的分发即可:
|
||
|
||
```
|
||
|
||
#include "key.h"
|
||
#include "led.h"
|
||
#include "rtc.h"
|
||
#include "stdlib.h"
|
||
#include "tftlcd.h"
|
||
#include "touch.h"
|
||
#include "usart.h"
|
||
|
||
|
||
#include "base/idle.h"
|
||
#include "base/timer.h"
|
||
#include "tkc/platform.h"
|
||
#include "base/main_loop.h"
|
||
#include "base/event_queue.h"
|
||
#include "base/font_manager.h"
|
||
#include "lcd/lcd_mem_fragment.h"
|
||
#include "main_loop/main_loop_simple.h"
|
||
|
||
|
||
ret_t platform_disaptch_input(main_loop_t *l) { return RET_OK; }
|
||
|
||
static lcd_t *platform_create_lcd(wh_t w, wh_t h) {
|
||
return lcd_mem_fragment_create(w, h);
|
||
}
|
||
|
||
void dispatch_input_events(void) {
|
||
int key = KEY_Scan(0);
|
||
|
||
switch (key) {
|
||
case KEY_UP: {
|
||
key = TK_KEY_UP;
|
||
break;
|
||
}
|
||
case KEY_DOWN: {
|
||
key = TK_KEY_DOWN;
|
||
break;
|
||
}
|
||
case KEY_LEFT: {
|
||
key = TK_KEY_RETURN;
|
||
break;
|
||
}
|
||
case KEY_RIGHT: {
|
||
key = TK_KEY_BACK;
|
||
break;
|
||
}
|
||
default: { key = 0; }
|
||
}
|
||
|
||
if (key) {
|
||
main_loop_post_key_event(main_loop(), TRUE, key);
|
||
} else {
|
||
main_loop_post_key_event(main_loop(), FALSE, key);
|
||
}
|
||
|
||
if (TOUCH_Scan() == 0) {
|
||
main_loop_post_pointer_event(main_loop(), TRUE, TouchData.lcdx,
|
||
TouchData.lcdy);
|
||
} else {
|
||
main_loop_post_pointer_event(main_loop(), FALSE, TouchData.lcdx,
|
||
TouchData.lcdy);
|
||
}
|
||
}
|
||
|
||
void TIM3_IRQHandler(void) {
|
||
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
|
||
dispatch_input_events();
|
||
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
|
||
}
|
||
}
|
||
|
||
#include "main_loop/main_loop_raw.inc"
|
||
```
|
||
|
||
> 参考 awtk-port/main\_loop\_stm32\_raw.c
|
||
|
||
四、Keil 设置
|
||
|
||
* 1. 勾选 c99
|
||
* 2. 定义 HAS\_AWTK\_CONFIG
|
||
* 3. 增加如下头文件路径:
|
||
|
||
```
|
||
awtk\src
|
||
awtk\3rd
|
||
awtk-port
|
||
```
|
||
|
||
> 请根据项目文件位置进行调整。
|
||
|
||
五、其它配置
|
||
|
||
其它配置请参考 awtk-port/awtk_config.h
|
||
|
||
注:目前以 [普中科技 STM32F103ZET6 开发实验板](https://item.taobao.com/item.htm?spm=a230r.1.14.1.50a130e8TMKYMC&id=558855281660&ns=1&abbucket=5#detail) 为载体移植,其它开发板应该差不多。
|
||
|
||
完整项目和源码请参考:[awtk-stm32f103ze-raw](https://github.com/zlgopen/awtk-stm32f103ze-raw)
|
||
|
||
六、常见问题
|
||
|
||
* 1.莫名其妙的崩溃,可能是栈溢出。请修 Stack_Size 的大小。
|
||
|
||
```
|
||
Stack_Size EQU 0x00001000
|
||
```
|
||
|
||
* 2.如果出现 wcsxxx 之类的函数没有定义时,请在 awtk-port/awtk\_config.h 中定义 WITH\_WCSXXX。
|