基于君正T32适配WIFI BK7236

内容纲要

摘要

本文详细介绍如何将博通(Broadcom)BK7236 Wi-Fi模块成功适配到君正半导体(Ingenic)T32嵌入式平台,介绍了如何在 君正 T32 平台 上通过内核补丁适配 BK7236 Wi-Fi 模块。补丁内容基于 Linux Kernel 3.10.14,对 GPIO、MMC/SDIO、Wi-Fi 模块初始化及驱动符号导出等部分进行了修改,以实现 BK7236 模块在 SDIO 接口下的稳定运行。

一、引言

  • 背景介绍:物联网设备对Wi-Fi连接的需求日益增长,君正T32作为低功耗嵌入式平台,适配高性能BK7236模块可提升应用灵活性。
  • 目标与意义:实现稳定、高效的Wi-Fi通信,降低开发门槛,适用于智能家居、工业控制等场景。
  • 文章结构概述:从硬件到软件逐步解析适配过程,提供实用指南。

二、硬件平台基础介绍

  • 君正T32芯片特性
    • 处理器架构(如MIPS或RISC-V核心)、主频、功耗范围。
    • 外设接口支持:SPI、UART、I2C等关键通信接口。
  • BK7236 Wi-Fi模块特性
    • 无线标准(802.11 b/g/n)、传输速率、工作频段。
    • 硬件接口要求:SPI或SDIO连接方式,电源管理设计。
  • 适配需求分析
    • 兼容性检查:T32接口与BK7236的匹配性。
    • 应用场景:数据传输速率、距离和功耗要求。

三、软件开发环境搭建

  • 开发工具链
    • 君正T32 SDK安装:基于Linux或RTOS的环境配置。
    • 交叉编译工具链设置(如GCC for MIPS)。
  • BK7236驱动集成
    • 驱动源码获取:从博通官方或开源社区下载。
    • SDK集成步骤:修改Makefile、添加驱动文件。
  • 初始配置与编译
    • 编译命令示例:参考T32 SDK编译
    • 常见错误解决:依赖库缺失处理。

四、软件驱动开发与代码实现

T32 平台适配 BK7236基于MMC驱动的基础上新增几条指令,因此所需修改软件如下:

  1. board.h 文件改动
    修改内容,MMC 电源引脚使能信号从 低电平有效 修改为 高电平有效,Wi-Fi 模块的 唤醒主控引脚 和 电源使能引脚 设置为 -1,即不再由 GPIO 控制,改为外部固定电源。

    #define GPIO_MMC_PWR_LEVEL  HIGH_ENABLE
    #define WL_WAKE_HOST    -1 //GPIO_PB(7)
    #define WL_REG_EN       -1 //GPIO_PC(9)
  2. mmc.c 文件改动
    去掉 MMC_CAP_NONREMOVABLE,避免热插拔逻辑冲突,启用高速支持:MMC_CAP_MMC_HIGHSPEED 和 MMC_CAP_SD_HIGHSPEED,注释掉 cd_type 等卡检测相关字段,因为 BK7236 模块是焊接式模块无需卡检测,支持外部电源 GPIO 设置。

    #ifdef CONFIG_MMC_SDHCI_MMC1
    struct jz_sdhci_platdata jz_mmc1_pdata = {
    +   //.cd_type                  = JZ_SDHCI_CD_GPIO,
    +   //.ext_cd_gpio          = GPIO_MMC_CD_N,
    +   //.ext_cd_gpio_invert       = GPIO_MMC_CD_N_LEVEL,
    +   .ext_pwr_gpio           = GPIO_MMC_PWR,
    +   .ext_pwr_gpio_invert    = GPIO_MMC_PWR_LEVEL,
        .max_width              = 4,
    -   .host_caps              = (MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ | MMC_CAP_NONREMOVABLE),
    +   .host_caps              = (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
    +   //.capacity          = MMC_CAP_SDIO_IRQ | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_NONREMOVABLE,
    .pm_flags               = MMC_PM_IGNORE_PM_NOTIFY,
    #ifdef CONFIG_MMC1_PIO_MODE
    .pio_mode               = 1,
  3. gpio.c 文件改动
    将 jz_gpio_set_func 函数导出为全局符号,允许 Wi-Fi 驱动或外部模块调用此接口动态配置 GPIO 功能。

    EXPORT_SYMBOL_GPL(jz_gpio_set_func);
  4. block.c 文件改动
    取消对 mmc_blk_alloc_part 的 #if 0 屏蔽,启用 MMC 多分区逻辑支持;为 mmc_blk_alloc_parts 添加 idx 变量,避免局部未定义错误,此改动可确保 BK7236 Wi-Fi 模块固件或驱动分区在 MMC 中可正确访问。

    -#if 0
    +
     static int mmc_blk_alloc_part(struct mmc_card *card,
                      struct mmc_blk_data *md,
                      unsigned int part_type,
    @@ -2135,7 +2135,7 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
               mmc_card_name(card), part_md->part_type, cap_str);
        return 0;
     }
    -#endif
    +
     /* MMC Physical partitions consist of two boot partitions and
      * up to four general purpose partitions.
      * For each partition enabled in EXT_CSD a block device will be allocatedi
    @@ -2144,7 +2144,7 @@ static int mmc_blk_alloc_part(struct mmc_card *card,

     static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
     {
    -   int  ret = 0;
    +   int idx, ret = 0;

        if (!mmc_card_mmc(card))
            return 0;
    static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
    {
        int idx, ret = 0;
        ...
    }
  1. core.c文件改动
    增加对mmc1 BK7236对应模块的特殊模式的初始化,并添加workqueue的处理逻辑方式。
    -static struct workqueue_struct *workqueue;
    +#define CUSTOMED_HOST_NUM  3
    +static struct workqueue_struct *workqueue[CUSTOMED_HOST_NUM] = { NULL };
     static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
     /*
    @@ -88,15 +89,18 @@ MODULE_PARM_DESC(
     static int mmc_schedule_delayed_work(struct delayed_work *work,
                         unsigned long delay)
     {
    -   return queue_delayed_work(workqueue, work, delay);
    +   struct mmc_host *host =
    +       container_of(work, struct mmc_host, detect);
    +
    +   return queue_delayed_work(workqueue[host->index], work, delay);
     }
     /*
      * Internal function. Flush all scheduled work from the MMC work queue.
      */
    -static void mmc_flush_scheduled_work(void)
    +static void mmc_flush_scheduled_work(int index)
     {
    -   flush_workqueue(workqueue);
    +   flush_workqueue(workqueue[index]);
     }
     #ifdef CONFIG_FAIL_MMC_REQUEST
    @@ -136,6 +140,23 @@ static inline void mmc_should_fail_request(struct mmc_host *host,
     #endif /* CONFIG_FAIL_MMC_REQUEST */
    +/*
    + * mmc_wait_data_done() - done callback for data request
    + * @mrq: done data request
    + *
    + * Wakes up mmc context, passed as a callback to host controller driver
    + */
    +static void mmc_wait_data_done(struct mmc_request *mrq)
    +{
    +   mrq->host->context_info.is_done_rcv = true;
    +   wake_up_interruptible(&mrq->host->context_info.wait);
    +}
    +
    +static void mmc_wait_done(struct mmc_request *mrq)
    +{
    +   complete(&mrq->completion);
    +}
    +
     /**
      * mmc_request_done - finish processing an MMC request
      * @host: MMC host which completed request
    @@ -159,7 +180,7 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
             * Request starter must handle retries - see
             * mmc_wait_for_req_done().
             */
    -       if (mrq->done)
    +       if (mrq->done == mmc_wait_data_done || mrq->done == mmc_wait_done)
                mrq->done(mrq);
        } else {
            mmc_should_fail_request(host, mrq);
    @@ -186,7 +207,7 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
                    mrq->stop->resp[2], mrq->stop->resp[3]);
            }
    -       if (mrq->done)
    +       if (mrq->done == mmc_wait_data_done || mrq->done == mmc_wait_done)
                mrq->done(mrq);
            mmc_host_clk_release(host);
    @@ -323,23 +344,6 @@ out:
     }
     EXPORT_SYMBOL(mmc_start_bkops);
    -/*
    - * mmc_wait_data_done() - done callback for data request
    - * @mrq: done data request
    - *
    - * Wakes up mmc context, passed as a callback to host controller driver
    - */
    -static void mmc_wait_data_done(struct mmc_request *mrq)
    -{
    -   mrq->host->context_info.is_done_rcv = true;
    -   wake_up_interruptible(&mrq->host->context_info.wait);
    -}
    -
    -static void mmc_wait_done(struct mmc_request *mrq)
    -{
    -   complete(&mrq->completion);
    -}
    -
     /*
      *__mmc_start_data_req() - starts data request
      * @host: MMC host to start the request
    @@ -2314,12 +2318,26 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
        mmc_send_if_cond(host, host->ocr_avail);

        /* Order's important: probe SDIO, then SD, then MMC */
    +#ifdef CONFIG_BK7236_EN
    +   if (!(host->caps2 & MMC_CAP2_NO_SDIO))
    +       if (!mmc_attach_sdio(host))
    +           return 0;
    +
    +   if (!(host->caps2 & MMC_CAP2_NO_SD))
    +       if (!mmc_attach_sd(host))
    +           return 0;
    +
    +   if (!(host->caps2 & MMC_CAP2_NO_MMC))
    +       if (!mmc_attach_mmc(host))
    +           return 0;
    +#else
        if (!mmc_attach_sdio(host))
            return 0;
        if (!mmc_attach_sd(host))
            return 0;
        if (!mmc_attach_mmc(host))
            return 0;
    +#endif

        mmc_power_off(host);
        return -EIO;
    @@ -2500,7 +2518,7 @@ void mmc_stop_host(struct mmc_host *host)
        host->rescan_disable = 1;
        if (cancel_delayed_work_sync(&host->detect))
            wake_unlock(&host->detect_wake_lock);
    -   mmc_flush_scheduled_work();
    +   mmc_flush_scheduled_work(host->index);

        /* clear pm flags now and let card drivers set them as needed */
        host->pm_flags = 0;
    @@ -2699,7 +2717,7 @@ int mmc_suspend_host(struct mmc_host *host)

        if (cancel_delayed_work(&host->detect))
            wake_unlock(&host->detect_wake_lock);
    -   mmc_flush_scheduled_work();
    +   mmc_flush_scheduled_work(host->index);

        mmc_bus_get(host);
        if (host->bus_ops && !host->bus_dead) {
    @@ -2892,12 +2910,14 @@ EXPORT_SYMBOL(mmc_set_embedded_sdio_data);

     static int __init mmc_init(void)
     {
    -   int ret;
    -
    -   workqueue = alloc_ordered_workqueue("kmmcd", 0);
    -   if (!workqueue)
    -       return -ENOMEM;
    -
    +   int ret, i;
    +   for (i = 0; i < CUSTOMED_HOST_NUM; i++) {
    +       char qname[8];
    +       sprintf(qname, "kmmcd-%d", i);
    +       workqueue[i] = alloc_ordered_workqueue(qname, 0);
    +       if (!workqueue[i])
    +           return -ENOMEM;
    +   }
        ret = mmc_register_bus();
        if (ret)
            goto destroy_workqueue;
    @@ -2917,17 +2937,28 @@ unregister_host_class:
     unregister_bus:
        mmc_unregister_bus();
     destroy_workqueue:
    -   destroy_workqueue(workqueue);
    -
    +   for (i = 0; i < CUSTOMED_HOST_NUM; i++) {
    +       if (workqueue[i]) {
    +           destroy_workqueue(workqueue[i]);
    +           workqueue[i] = NULL;
    +       }
    +   }
        return ret;
     }

     static void __exit mmc_exit(void)
     {
    +   int i;
    +
        sdio_unregister_bus();
        mmc_unregister_host_class();
        mmc_unregister_bus();
    -   destroy_workqueue(workqueue);
    +   for (i = 0; i < CUSTOMED_HOST_NUM; i++) {
    +       if (workqueue[i]) {
    +           destroy_workqueue(workqueue[i]);
    +           workqueue[i] = NULL;
    +       }
    +   }
     }
     subsys_initcall(mmc_init);
以上除此之外还需要对sd.c ,sd_ops.c ,sdio.c,sdio_ops.c,jzmmc_v12.c等等文件进行修改,本章就不在这里一一详细说明了,详细参考补丁文件: http://blog.tomgzhe.com/wp-content/uploads/2025/09/wireless_drv_mmc1_20250701-3.7z

五、测试、验证与优化

  • 功能测试方法
    • 基础测试:Wi-Fi扫描、连接稳定性测试。
    • 数据传输测试:TCP/UDP吞吐量测量(如iperf工具)。
  • 性能优化策略
    • 功耗优化:睡眠模式配置、动态频率调整。
    • 延迟优化:中断优先级设置、缓冲区管理。
  • 问题诊断与日志
    • 常见错误:连接超时、数据丢包分析。
    • 日志工具使用:串口输出调试信息。
版权声明

版权声明

内容来源及使用限制

欢迎访问 TomgZHE研习社(网址:https://blog.tomgzhe.com)。本网站部分文章内容源自网络,仅作学习交流与参考分享;若您发现有内容涉嫌侵权,请立即联系 tomgzhe@qq.com,我们将在接到通知后的 48 小时内核实并删除相关侵权内容。

软件资源相关规定

本网站为个人非盈利性质的站点,所有软件资源均来自网络。这些资源仅用于个人学习、研究和参考,严禁用于任何商业用途。您下载和使用本网站软件资源即表示您同意仅将其用于学习目的,若因违反此规定导致任何法律纠纷或损失,责任由您自行承担。

原创版权

本网站上的原创内容,包括但不限于文字作品、自行设计的图片、独家制作的音频视频等,其版权均归本网站所有。未经本网站书面授权,任何组织或个人不得擅自复制、转载、摘编、传播或以其他任何方式使用这些原创内容。如需使用,请提前与我们联系并获得书面许可,同时需在显著位置注明出处及作者信息。

转载与引用规范

若您需转载本网站文章,务必注明文章来源为 “[],原文链接:[ https://blog.tomgzhe.com/index.php/2025/09/12/t32_wifi_bk7236/ ‎]”;对于有明确作者署名的文章,还需完整保留作者姓名。在引用本网站内容时,请确保内容准确无误,并遵循学术及行业的引用规范。

Like (1)
Donate 微信扫一扫打赏 微信扫一扫打赏 支付宝扫一扫打赏 支付宝扫一扫打赏
tomgzhe的头像tomgzhe
Previous 2025年9月11日
Next 2025年9月12日

相关推荐

发表回复

Please Login to Comment
联系我们

联系我们

400-800-6666

在线咨询: QQ交谈 邮件:tomgzhe@qq.com 工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
SHARE
TOP
蛇年新气象!从2025年2月起,本博客将在保留科技板块基础上,新增生活美学、个人成长等多元内容,希望能为大家带来更丰富的阅读体验,敬请期待!