awtk/docs/porting_to_stm32f103ze.md
2020-01-02 14:59:56 +08:00

212 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 将 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。