SDL2库使用及QEMU添加虚拟开发板--Apple的学习笔记

一,前言

上次blogQemu虚化HW相关—Apple的学习笔记已经分析了要修改qemu源码自定义开发板其实就是要看懂graphic.c,而里面用到的就是SDL2和其扩展库SDL2_Image扩展库,而我之前已经搭建了SLD2的mingw开发环境,并且在官网了解了SDL2的API看懂了graphic.c那么就开始修改为自定义开发板。

二,在SDL2中实现开发板LED闪烁界面

效果为按下鼠标后,右下角的LED灯颜色会变。


image.png

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中的开发板图片

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,背景开发板图片
    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运行我的stm32开发板效果,右下角D1处为LED灯。


image.png

四,qemu添加自定义虚拟开发板

刚刚在第三个步骤中,只是在原来的开发板基础上修改了图片。至于开发板的IO口等还是原来的。所以第四步是要在qemu中添加自定义开发板的仿真代码,而不破坏原来的开发板仿真代码。
关于如何添加开发板,要看我最早的一篇qemu源码分析,主要是调试了vl.c了解其框架及传参的作用,大家可以参考Qemu2.8虚拟机源码分析—Apple的学习笔记qemu虚化原理入门--Apple的学习笔记,在qemu中添加一个开发板还是比较简单的。参考其它hw中的board.c文件依样画葫芦即可。我在stm32_machines_init中注册了type_register_static(&appleSTM32F429ZG_machine)设置了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已经添加成功

image.png

接着修改了LED工程的引脚为PF9和PF10。原来的是PG14和PG14,直接运行LED灯是不会亮的。LED工程make通过后,结合qemu进行仿真。记得传入参数--board AppleSTM32这样才可以调用我添加的函数。输入仿真命令
qemu-system-gnuarmeclipse --verbose --verbose --board AppleSTM32 --mcu STM32F429ZI -d unimp,guest_errors --image led.elf
led工程中我设置了D1和D2两个LED灯轮流闪烁。效果如下,自定义最小开发板完工。
image.png

五,总结

通过化繁为简的方法,进行分步学习,逐渐熟悉qemu源码框架及其子系统,并且掌握qemu自定义开发板和外设的方法。真的好好玩啊~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容