日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

华大 MCU 之四 使用问题记录

發(fā)布時(shí)間:2024/10/14 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 华大 MCU 之四 使用问题记录 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

??在最近使用華大 MCU 時(shí),遇到了不少坑,這里記錄一下,以方便在以后升級(jí)驅(qū)動(dòng)庫(kù)!其中,有些問題僅僅是在由 ST 切換到 華大之后不太適于的問題,有些是驅(qū)動(dòng)庫(kù)的更改問題!

??如果您發(fā)現(xiàn)我說的問題是由于我還沒完全了解華大 MCU 造成的,歡迎在評(píng)論區(qū)指出。亦或是您有更好的見解也歡迎給與指點(diǎn)。

進(jìn)步始于交流,收獲源于分享,不勝感激!

中斷向量偏移

??在實(shí)際項(xiàng)目中,在線升級(jí)一般是必須的。在以前 ST 的片子中,IAP + APP 的程序框架是個(gè)很不錯(cuò)的選擇。該程序框架中,需要配置 APP 的中斷向量表偏移(中斷向量表偏移寄存器),然而,驅(qū)動(dòng)庫(kù)并沒有給出配置接口。因此,需要自己來實(shí)現(xiàn):

中斷弱函數(shù)

??驅(qū)動(dòng)庫(kù)提供了一個(gè)名為 hc32f46x_interrupts.c/h 的文件,該文件將所有的中斷進(jìn)行了統(tǒng)一的處理,然后以弱函數(shù)的形式開發(fā)對(duì)外接口(hc32f46x_it.c 中定義的函數(shù)均為 hc32f46x_interrupts.c/h 中聲明的弱函數(shù)接口)。但是,驅(qū)動(dòng)庫(kù)的這種弱函數(shù)的使用并不是規(guī)范(可以說不正確,導(dǎo)致自己定義的同名函數(shù)根本無效)。下面我們以 ST HAL 庫(kù)最為對(duì)比來說明一下。

  • 首先,華大驅(qū)動(dòng)庫(kù)和 ST HAL 庫(kù)弱函數(shù)所使用的的弱函數(shù)關(guān)鍵字是有區(qū)別的,如下對(duì)比圖所示:

    ??在使用 GUN 編譯器的時(shí)候,兩者均使用 __attribute__((weak)) 關(guān)鍵字,然而,在使用 ARM 自家編譯器時(shí),華大的驅(qū)動(dòng)庫(kù)仍然使用 __attribute__((weak)) 關(guān)鍵字,而 ST HAL 庫(kù)則會(huì)使用 ARM 自家的 __weak 關(guān)鍵字。
  • 再來看看兩者對(duì)于弱函數(shù)的使用方法,如下對(duì)比圖所示:
  • ??那么,為啥說華大驅(qū)動(dòng)庫(kù)的這種使用是不正確的呢?這主要是由于 __attribute__((weak)) 關(guān)鍵字的原因。使用 __attribute__((weak)) 聲明的函數(shù),對(duì)于所有實(shí)現(xiàn)的實(shí)體都將被編譯器認(rèn)為為弱函數(shù),不管我們定義多少個(gè)接口,都沒有用。具體見博文 ARM 之十一__weak 和 attribute((weak)) 關(guān)鍵字的使用。

    具體的解決方法有以下兩個(gè):

  • 修改驅(qū)動(dòng)庫(kù)改為 ST HAL 庫(kù)的使用方式。缺點(diǎn)就是需要修改驅(qū)動(dòng)庫(kù),不方便后續(xù)升級(jí)驅(qū)動(dòng)庫(kù)。
  • 如下配置 MDK-ARM 開發(fā)環(huán)境:

    缺點(diǎn)就是,對(duì)其他編譯器可能并不適用!
  • 中斷的使用

    ??在 hc32f46x_interrupts.c/h 的文件中定義的結(jié)構(gòu)體中對(duì)中斷區(qū)分為三大部分,這就導(dǎo)致在我們使用 en_result_t enIrqRegistration(const stc_irq_regi_conf_t *pstcIrqRegiConf) 進(jìn)行中斷注冊(cè)的時(shí)候需要注意分配的中斷號(hào)。如下圖所示:

  • 第一部分應(yīng)該是 Cortex-M 核的中斷,他這里處理后,我們就可以自己定義或函數(shù)的實(shí)體(忽略上面說的問題)來使用中斷!
  • 第二步部分應(yīng)該是留給用戶自己隨便定義的
  • 第三部分應(yīng)該是對(duì)于常用的外設(shè),可能為了方便大家使用,他給處理了一層(固定好了中斷號(hào))。但是,這里仍然需要我們配置外設(shè)中斷。當(dāng)然,我們可以不使用這部分,仍然使用第二部分來自定義。
  • ??下面我以我最近使用的 ADC 來看看中斷的具體配置。首先,hc32f46x_interrupts.c/h 中對(duì)于 ADC 的中斷默認(rèn)分配了中斷號(hào) 142,如下:

    /*********************************************************************************** \brief Int No.142 share IRQ handler********************************************************************************/ void IRQ142_Handler(void) {uint32_t u32VSSEL142 = M4_INTC->VSSEL142;uint16_t u16Tmp = 0u;/* ADC unit.1 seq. A */if (1ul == bM4_ADC1_ICR_EOCAIEN){if ((1ul == bM4_ADC1_ISR_EOCAF) && (u32VSSEL142 & BIT_MASK_00)){ADC1A_IrqHandler();}}/* ADC unit.1 seq. B */if (1ul == bM4_ADC1_ICR_EOCBIEN){if ((1ul == bM4_ADC1_ISR_EOCBF) && (u32VSSEL142 & BIT_MASK_01)){ADC1B_IrqHandler();}}/* ADC unit.1 seq. A */u16Tmp = M4_ADC1->AWDSR0;if (1ul == bM4_ADC1_AWDCR_AWDIEN){if (((1ul == bM4_ADC1_AWDSR1_AWDF16) || (u16Tmp)) && (u32VSSEL142 & BIT_MASK_02)){ADC1ChCmp_IrqHandler();}}/* ADC unit.1 seq. cmp */if (1ul == bM4_ADC1_AWDCR_AWDIEN){if (((1ul == bM4_ADC1_AWDSR1_AWDF16) || (u16Tmp)) && (u32VSSEL142 & BIT_MASK_03)){ADC1SeqCmp_IrqHandler();}}/* ADC unit.2 seq. A */if (1ul == bM4_ADC2_ICR_EOCAIEN){if ((1ul == bM4_ADC2_ISR_EOCAF) && (u32VSSEL142 & BIT_MASK_04)){ADC2A_IrqHandler();}}/* ADC unit.2 seq. B */if (1ul == bM4_ADC2_ICR_EOCBIEN){if ((1ul == bM4_ADC2_ISR_EOCBF) && (u32VSSEL142 & BIT_MASK_05)){ADC2B_IrqHandler();}}/* ADC unit.2 seq. A */if (1ul == bM4_ADC2_AWDCR_AWDIEN){if ((M4_ADC2->AWDSR0 & 0x1FFu) && (u32VSSEL142 & BIT_MASK_06)){ADC2ChCmp_IrqHandler();}}/* ADC unit.2 seq. cmp */if (1ul == bM4_ADC2_AWDCR_AWDIEN){if ((M4_ADC2->AWDSR0 & 0x1FFu) && (u32VSSEL142 & BIT_MASK_07)){ADC2SeqCmp_IrqHandler();}} }

    其中的 ADC1A_IrqHandler(); 等都是放給用戶的弱函數(shù)接口。我們的使用方法基本就是,給 ADC 配置 142 號(hào)中斷,然后實(shí)現(xiàn)對(duì)應(yīng)的弱函數(shù)實(shí)體就應(yīng)該可以了。下面是驅(qū)動(dòng)庫(kù)的示例給出的代碼:

    static void AdcIrqConfig(void) {en_result_t enIrqRegResult;stc_irq_regi_conf_t stcAdcIrqCfg;/* Config ADC1 interrupt. */stcAdcIrqCfg.enIntSrc = INT_ADC1_EOCA;stcAdcIrqCfg.enIRQn = Int117_IRQn;stcAdcIrqCfg.pfnCallback = &ADC1A_IrqHandler;enIrqRegResult = enIrqRegistration(&stcAdcIrqCfg);if (Ok == enIrqRegResult){NVIC_ClearPendingIRQ(stcAdcIrqCfg.enIRQn);NVIC_SetPriority(stcAdcIrqCfg.enIRQn, DDL_IRQ_PRIORITY_03);NVIC_EnableIRQ(stcAdcIrqCfg.enIRQn);}/* Config ADC2 interrupt, use sharing interrupt. */stcAdcIrqCfg.enIntSrc = INT_ADC2_EOCA;stcAdcIrqCfg.enIRQn = Int142_IRQn;enShareIrqEnable(stcAdcIrqCfg.enIntSrc);NVIC_ClearPendingIRQ(stcAdcIrqCfg.enIRQn);NVIC_SetPriority(stcAdcIrqCfg.enIRQn, DDL_IRQ_PRIORITY_04);NVIC_EnableIRQ(stcAdcIrqCfg.enIRQn); }

    注意上面的 enShareIrqEnable(stcAdcIrqCfg.enIntSrc); 要不然會(huì)死的很慘哦!從上面的示例可以看出,對(duì)于上面說的第三部分的中斷使用,需要使用 enShareIrqEnable(stcAdcIrqCfg.enIntSrc); 而不是 enIrqRegistration(&stcAdcIrqCfg);。

    中斷反注冊(cè)

    ??由于我們使用中斷(部分)時(shí)需要在 hc32f46x_interrupts.c/h 的文件中定義的結(jié)構(gòu)體中進(jìn)行注冊(cè),如果想第二次注冊(cè)(例如,更改回調(diào)接口)時(shí),必須要反注冊(cè),否則不能正常注冊(cè)。這個(gè)問題在我們使用 IAP 和 APP 兩個(gè)程序時(shí)尤為明顯!

    en_result_t enIrqRegistration(const stc_irq_regi_conf_t *pstcIrqRegiConf) {// todo, assert ...stc_intc_sel_field_t *stcIntSel;en_result_t enRet = Ok;//DDL_ASSERT(NULL != pstcIrqRegiConf->pfnCallback);DDL_ASSERT(IS_NULL_POINT(pstcIrqRegiConf->pfnCallback));/* IRQ032~127 whether out of range */if (((((pstcIrqRegiConf->enIntSrc/32)*6 + 32) > pstcIrqRegiConf->enIRQn) || \(((pstcIrqRegiConf->enIntSrc/32)*6 + 37) < pstcIrqRegiConf->enIRQn)) && \(pstcIrqRegiConf->enIRQn >= 32)){enRet = ErrorInvalidParameter;}else{stcIntSel = (stc_intc_sel_field_t *)((uint32_t)(&M4_INTC->SEL0) + \(4u * pstcIrqRegiConf->enIRQn));if (0x1FFu == stcIntSel->INTSEL) /* 如果已經(jīng)初始化過,這里將不能再初始化 */{stcIntSel->INTSEL = pstcIrqRegiConf->enIntSrc;IrqHandler[pstcIrqRegiConf->enIRQn] = pstcIrqRegiConf->pfnCallback;}else{enRet = ErrorUninitialized;}}return enRet; }

    具體方法就是使用 enIrqResign 函數(shù)進(jìn)行重新標(biāo)記!

    DMA 配置

    ??根據(jù)手冊(cè),使用 DMA 時(shí)需要先寫寄存器將 DMA 控制器使能,使能方法是寫 DMA 使能寄存器 DMA_EN.EN 位。 如下圖所示:

    我試了一下,不先使能貌似也沒法發(fā)現(xiàn)啥問題啊!不知道為啥!?

    DMA 無法獲取當(dāng)前傳出數(shù)據(jù)長(zhǎng)度

    ??先來說一下需求:在串口驅(qū)動(dòng)中,串口的接收使用 DMA 來實(shí)現(xiàn),DMA 配置為循環(huán)模式,在指定緩沖區(qū)中循環(huán)存放收到的數(shù)據(jù),通過讀寫指針來標(biāo)記數(shù)據(jù)的讀和寫位置。
    ??然而,驅(qū)動(dòng)庫(kù)中 DMA 接口并沒有能獲取當(dāng)前 DMA 傳輸了多少字節(jié)的接口!!!無奈只能選擇修改驅(qū)動(dòng)庫(kù),添加一些指定的接口,如下圖所示:

    ??后來,為了不修改驅(qū)動(dòng)庫(kù),我直接把接口放到了自己的驅(qū)動(dòng)里面,然后使用寄存器直接讀取:M4DMA1->MONRPT0_f.DRPT,這樣的話,需要注意與通道號(hào)的對(duì)應(yīng)關(guān)系,如 MONRPT0 即通道 0。

    DMA 中斷的使用

    ??在華大的 DMA 中,中斷默認(rèn)都是開啟的,這點(diǎn)在配置 DMA 的時(shí)候需要特殊注意。我們需要使用 DMA 的屏蔽中斷寄存器來屏蔽不使用的中斷。如下圖示:

    在實(shí)際寫代碼時(shí),需要調(diào)用 en_result_t DMA_DisableIrq(M4_DMA_TypeDef* pstcDmaReg, uint8_t u8Ch, en_dma_irq_sel_t enIrqSel); 來關(guān)閉不需要的中中斷。例如,DMA 的塊傳輸完成中斷 和 傳輸完成中斷 通常不會(huì)一起使用!這點(diǎn)對(duì)于用慣了 ST MCU 的人來說需要特殊注意!

    看門狗

    ??在華大 MCU 中,看門狗也是有兩個(gè):SWDT 和 WDT,看手冊(cè)的介紹應(yīng)該是分別對(duì)應(yīng)于 ST 的 IWDG 和 WWDG。在實(shí)際使用中,多數(shù)情況下我們需要使用 SWDT。

    ??目前,SWDT 的配置可以必須在庫(kù)文件 hc32f46x_icg.h 中進(jìn)行配置(WDT 可以使用 hc32f46x_wdt.c/h 中進(jìn)行配置),然后將 hc32f46x_icg.c 包含到自己的項(xiàng)目中,否則配置依舊無效!在更改了驅(qū)動(dòng)庫(kù)源碼之后,在更新驅(qū)動(dòng)庫(kù)時(shí)需要注意!

    ??此外,上面這種配置方法會(huì)間接導(dǎo)致一個(gè)問題:由于我們的程序分為 IAP 和 APP 兩部分。看門狗的配置必須放到 IAP 中,且 APP 中不能再包含該文件,否則在調(diào)試燒寫時(shí)會(huì)報(bào)錯(cuò)!這是由于 APP 位置的偏移地址導(dǎo)致的!

    enumeration value is out of “int” range

    在使用 MDK-ARM 編譯華大驅(qū)動(dòng)庫(kù)時(shí),會(huì)提示 warning: enumeration value is out of "int" range,這是由于驅(qū)動(dòng)庫(kù)中(hc32f46x_exint_nmi_swi.h、hc32f46x_interrupts.h)對(duì)于枚舉類型的值超過了 enum 中的枚舉值默認(rèn)為 int 類型的限制:

    我們可以通過以上修改以消除警告!

    總結(jié)

    以上是生活随笔為你收集整理的华大 MCU 之四 使用问题记录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 69日本xxxxxxxxx30| 亚洲欲| 求欧美精品网址 | 日本午夜免费 | 国产91国语对白在线 | 国产91在线亚洲 | 超碰97人人在线 | 免费观看视频在线观看 | 久久精品网址 | 色哟哟日韩精品 | 亚洲av色区一区二区三区 | 久久九九久精品国产免费直播 | 吸咬奶头狂揉60分钟视频 | 欧美高潮视频 | 欧美精品二区三区四区免费看视频 | 日日爱99 | 黄色国产一区二区 | 99久久久无码国产精品性波多 | 国产婷婷一区二区三区久久 | 国语对白少妇spa私密按摩 | 老熟女一区二区三区 | 免费成人一级片 | 五月婷丁香 | 亚洲图片欧美在线 | 白白色在线播放 | 人人爱人人草 | 成人在线天堂 | 小向美奈子在线观看 | 亚洲视频一区在线播放 | 欧美成人精品一区二区男人小说 | 男人午夜免费视频 | 日本黄动漫 | 日韩av手机在线免费观看 | 精品久久久蜜桃 | 国产毛片儿| 久久精品中文闷骚内射 | 久久亚洲一区二区 | 国产经典三级在线 | 久久久一区二区三区四区 | 操人小视频 | 91爱| 这里只有精品久久 | 亚洲av无码乱码国产麻豆 | 亚洲熟女一区二区三区 | 日韩中文娱乐网 | 国产成人免费片在线观看 | 1024亚洲 | 成人激情在线视频 | 久久一二区 | 中文字幕亚洲欧美 | 91九色蝌蚪91por成人 | 久久久久久国产精品三级玉女聊斋 | 麻豆视频在线观看免费 | 亚洲欧美字幕 | 日本一区二区三区在线看 | 奶波霸巨乳一二三区乳 | 亚洲AV成人无码久久 | 中文字幕一二三四区 | 日韩在线观看你懂的 | 麻豆疯狂做受xxxx高潮视频 | 欧美aa级 | 同人动漫在线观看 | 天天综合网在线观看 | h网站在线播放 | 少妇熟女一区二区 | 深夜成人福利 | 国产精品无码成人片 | 欧美日韩一区电影 | 久草视频免费在线播放 | 久久对白 | 最好看的2019年中文视频 | 91精品视频网 | 韩国三级黄色 | 丁香婷婷综合网 | 久草视频在 | 中文字幕视频免费观看 | 成人av动漫在线 | 亚洲三级影院 | 日韩三级在线免费观看 | 国产精品成人一区二区三区电影毛片 | 亚洲国产精品视频 | 午夜成人在线视频 | 综合久久网 | 中国极品少妇xxxx做受 | 91中文字幕在线视频 | 久久在线看 | 成人在线不卡 | 亚洲欧美日韩精品久久 | 欧美黄色精品 | 综合视频在线 | 亚洲一区二区三区午夜 | 成人国产精品入口免费视频 | 国产日韩精品一区 | 亚洲国产日韩欧美一区二区三区 | 青青自拍视频 | 办公室荡乳欲伦交换bd电影 | jlzzjlzz国产精品久久 | 国产精品精品国产色婷婷 | 哪个网站可以看毛片 |