一救巷,前言
上次blogQemu虛化HW相關(guān)—Apple的學(xué)習(xí)筆記已經(jīng)分析了要修改qemu源碼自定義開發(fā)板其實(shí)就是要看懂graphic.c绣版,而里面用到的就是SDL2和其擴(kuò)展庫SDL2_Image擴(kuò)展庫台舱,而我之前已經(jīng)搭建了SLD2的mingw開發(fā)環(huán)境赁豆,并且在官網(wǎng)了解了SDL2的API看懂了graphic.c那么就開始修改為自定義開發(fā)板叠萍。
二或颊,在SDL2中實(shí)現(xiàn)開發(fā)板LED閃爍界面
效果為按下鼠標(biāo)后城菊,右下角的LED燈顏色會(huì)變秘蛇。
codeblocks源碼如下:
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
//Screen dimension constants
const int SCREEN_WIDTH = 346;
const int SCREEN_HEIGHT = 452;
typedef struct {
SDL_Renderer *renderer;
SDL_Window *window;
} App;
App app;
typedef struct {
int x;
int y;
SDL_Texture *texture;
} Entity;
Entity player;
unsigned int click=0;
void prepareScene(void)
{
#if 0
if(click == 1)
{
SDL_SetRenderDrawColor(app.renderer, 255, 128, 0, 255);
}
else
{
SDL_SetRenderDrawColor(app.renderer, 96, 128, 255, 255);
}
SDL_RenderClear(app.renderer);
#endif // 0
if(click == 1)
{
SDL_SetRenderDrawColor(app.renderer, 255, 128, 0, 255);
}
else
{
SDL_SetRenderDrawColor(app.renderer, 0, 255, 0, 255);
}
SDL_Rect rectangle;
rectangle.x = 318;
rectangle.y = 378;
rectangle.w = 12;
rectangle.h = 6;
SDL_RenderFillRect(app.renderer, &rectangle);
}
void presentScene(void)
{
SDL_RenderPresent(app.renderer);
}
void initSDL(void)
{
int rendererFlags, windowFlags;
rendererFlags = SDL_RENDERER_ACCELERATED;
windowFlags = 0;
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("Couldn't initialize SDL: %s\n", SDL_GetError());
exit(1);
}
app.window = SDL_CreateWindow("Apple's STM32 EK-board", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, windowFlags);
if (!app.window)
{
printf("Failed to open %d x %d window: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_GetError());
exit(1);
}
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
app.renderer = SDL_CreateRenderer(app.window, -1, rendererFlags);
if (!app.renderer)
{
printf("Failed to create renderer: %s\n", SDL_GetError());
exit(1);
}
IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
}
void cleanup(void)
{
SDL_DestroyRenderer(app.renderer);
SDL_DestroyWindow(app.window);
SDL_Quit();
}
void doInput(void)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
exit(0);
break;
case SDL_MOUSEBUTTONUP:
click = !click;
break;
default:
break;
}
}
}
int main(int argc, char *argv[])
{
memset(&app, 0, sizeof(App));
memset(&player, 0, sizeof(Entity));
initSDL();
SDL_Surface* board_bitmap = IMG_Load("pic/AppleSTM32.png");
if (board_bitmap == NULL) {
printf("Cannot load image file '%s' (%s).\n",
"pic/player.png",
IMG_GetError());
exit(1);
}
SDL_Surface* board_bitmap_rgb = SDL_ConvertSurfaceFormat(board_bitmap,SDL_PIXELFORMAT_RGB888, 0);
if (board_bitmap_rgb == 0) {
printf("Could not create surface: %s\n", SDL_GetError());
exit(1);
}
player.texture = SDL_CreateTextureFromSurface(app.renderer,board_bitmap_rgb);
if (player.texture == NULL) {
printf("Could not create texture: %s\n", SDL_GetError());
exit(1);
}
SDL_RenderClear(app.renderer);
SDL_RenderCopy(app.renderer, player.texture, NULL, NULL);
SDL_RenderPresent(app.renderer);
SDL_FreeSurface(board_bitmap);
atexit(cleanup);
while (1)
{
prepareScene();
doInput();
presentScene();
SDL_Delay(16);
}
return 0;
}
三其做,修改qemu中的開發(fā)板圖片
boards-discovery.c中修改LED的rect,修改要打開的圖片
//修改1彤叉,LED0位置
static GPIOLEDInfo stm32f429i_discovery_leds_info[] = {
{
.name = "led:green",
.active_low = false,
.colour_name = "green",
.x = 486,//519,
.y = 574,//109,
.w = 12,//10,
.h = 8,//8,
.gpio_path = DEVICE_PATH_STM32_GPIO_G,
.irq_name = STM32_IRQ_GPIO_ODR_OUT,
.gpio_bit = 13,
//修改2庶柿,背景開發(fā)板圖片
BoardGraphicContext *board_graphic_context =cortexm_board_init_graphic_image(board, "AppleSTM32.png");
//cortexm_board_init_graphic_image(board, "STM32F429I-Discovery.jpg");
//修改3,窗口臺頭名稱
mc->desc = "Apple Cai's STM32F429ZG board";//"ST Discovery kit for STM32F429/439 lines";
qemu運(yùn)行我的stm32開發(fā)板效果秽浇,右下角D1處為LED燈浮庐。
四,qemu添加自定義虛擬開發(fā)板
剛剛在第三個(gè)步驟中柬焕,只是在原來的開發(fā)板基礎(chǔ)上修改了圖片审残。至于開發(fā)板的IO口等還是原來的。所以第四步是要在qemu中添加自定義開發(fā)板的仿真代碼斑举,而不破壞原來的開發(fā)板仿真代碼搅轿。
關(guān)于如何添加開發(fā)板,要看我最早的一篇qemu源碼分析富玷,主要是調(diào)試了vl.c了解其框架及傳參的作用璧坟,大家可以參考Qemu2.8虛擬機(jī)源碼分析—Apple的學(xué)習(xí)筆記和qemu虛化原理入門--Apple的學(xué)習(xí)筆記,在qemu中添加一個(gè)開發(fā)板還是比較簡單的赎懦。參考其它hw中的board.c文件依樣畫葫蘆即可雀鹃。我在stm32_machines_init中注冊了type_register_static(&appleSTM32F429ZG_machine)
設(shè)置了board名字為AppleSTM32
。添加代碼如下:
/* ----- AppleCai's STM32F429ZG board ----- */
static GPIOLEDInfo appleSTM32_leds_info[] = {
{
.name = "led:green",
.active_low = false,
.colour_name = "green",
.x = 486,
.y = 574,
.w = 12,
.h = 8,
.gpio_path = DEVICE_PATH_STM32_GPIO_F,
.irq_name = STM32_IRQ_GPIO_ODR_OUT,
.gpio_bit = 9,
/**/
},
{
.name = "led:red",
.active_low = false,
.colour_name = "red",
.x = 486,
.y = 584,
.w = 10,
.h = 8,
.gpio_path = DEVICE_PATH_STM32_GPIO_F,
.irq_name = STM32_IRQ_GPIO_ODR_OUT,
.gpio_bit = 10,
/**/
},
{ },
/**/
};
static void appleSTM32F4_board_init_callback(MachineState *machine)
{
CortexMBoardState *board = CORTEXM_BOARD_STATE(machine);
cortexm_board_greeting(board);
BoardGraphicContext *board_graphic_context =cortexm_board_init_graphic_image(board, "AppleSTM32.png");
{
// Create the MCU
Object *mcu = cm_object_new_mcu(machine, TYPE_STM32F429ZI);
// Set the board specific oscillator frequencies.
cm_object_property_set_int(mcu, 8000000, "hse-freq-hz"); // 8.0 MHz
cm_object_property_set_int(mcu, 32768, "lse-freq-hz"); // 32 kHz
cm_object_realize(mcu);
}
Object *peripheral = cm_container_get_peripheral();
// Create board LEDs.
gpio_led_create_from_info(peripheral, appleSTM32_leds_info,
board_graphic_context);
}
static void appleSTM32_discovery_init_callback(ObjectClass *oc,void *data);
static const TypeInfo appleSTM32F429ZG_machine = {
.name = BOARD_TYPE_NAME("AppleSTM32"),
.parent = TYPE_CORTEXM_BOARD,
.class_init = appleSTM32_discovery_init_callback
};
static void appleSTM32_discovery_init_callback(ObjectClass *oc,void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "Apple Cai's STM32F429ZG board";
mc->init = appleSTM32F4_board_init_callback;
}
編譯通過后励两,查看Apple cai'sboard已經(jīng)添加成功
接著修改了LED工程的引腳為PF9和PF10黎茎。原來的是PG14和PG14,直接運(yùn)行LED燈是不會(huì)亮的当悔。LED工程make通過后傅瞻,結(jié)合qemu進(jìn)行仿真踢代。記得傳入?yún)?shù)
--board AppleSTM32
這樣才可以調(diào)用我添加的函數(shù)。輸入仿真命令qemu-system-gnuarmeclipse --verbose --verbose --board AppleSTM32 --mcu STM32F429ZI -d unimp,guest_errors --image led.elf
led工程中我設(shè)置了D1和D2兩個(gè)LED燈輪流閃爍嗅骄。效果如下胳挎,自定義最小開發(fā)板完工。
五掸读,總結(jié)
通過化繁為簡的方法串远,進(jìn)行分步學(xué)習(xí),逐漸熟悉qemu源碼框架及其子系統(tǒng)儿惫,并且掌握qemu自定義開發(fā)板和外設(shè)的方法澡罚。真的好好玩啊~