日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
鴻蒙移植樹莓派(下)修改源碼

想了解更多內(nèi)容,請訪問:

創(chuàng)新互聯(lián)公司從2013年創(chuàng)立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目網(wǎng)站設(shè)計、成都做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元宏偉做網(wǎng)站,已為上家服務(wù),為宏偉各地企業(yè)和個人服務(wù),聯(lián)系電話:028-86922220

和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos./#zz

項目最新更新,可以查看碼倉 https://gitee.com/liangzili/harmony-raspberry

1、切換啟動模式

樹莓派默認(rèn)啟動在HYP模式,我們需要在內(nèi)核啟動前改為SVC模式

kernel\liteos_a\arch\arm\arm\src\startup\reset_vector_up.S 在115行左右,reset_vector:下面添加

 
 
 
 
  1. mrs r0,cpsr         //讀取CPU模式寄存器
  2.    bic r0,r0,#0x1F     //清除CPU模式位(如果處于催眠模式,它將是1A)保留所有其他  
  3.    orr r0,r0,#0x13     //設(shè)置CPU_MODE為SVC_MODE (0x13),而ORR仍然保留所有其他位
  4.    msr spsr_cxsf,r0    //將其寫入spsr_cxsf寄存器,以便在調(diào)用交換機時加載該寄存器。
  5.    add r0,pc,#4        //從pc計算要進(jìn)入SVC_MODE的地址(后面的兩個操作碼很長)
  6.    msr ELR_hyp,r0      //將地址值寫入ELR_hyp寄存器
  7.    eret                //執(zhí)行了回車指令

 2、修改串口驅(qū)動

2.1、為了方便調(diào)試,先設(shè)置一個字符打印函數(shù)

kernel\liteos_a\platform\uart\amba_pl011\amba_pl011.c在46行左右處添加下面的代碼,uart_putc_phy使用物理地址打印字符,uart_putc_virt使用虛擬地址打印。當(dāng)內(nèi)核代碼啟動MMU之后,需用使用uart_putc_virt來打印字符。

 
 
 
 
  1. /*---------自定義函數(shù)----------*/
  2. #define RPI_BASE_UART_REGISTER (0x3f201000) //HI3516:0x120A0000 rpi2:0x3F201000
  3. #define AMBA_UART_DR (*(volatile unsigned char *)(RPI_BASE_UART_REGISTER + 0x00))
  4. #define AMBA_UART_FR (*(volatile unsigned char *)(RPI_BASE_UART_REGISTER + 0x18))
  5. ?
  6. #define RPI_BASE_UART_REGISTER1 IO_DEVICE_ADDR(0x3F201000) //HI3516:0x120A0000 rpi2:0x3F201000
  7. #define AMBA_UART_DR1 (*(volatile unsigned char *)(RPI_BASE_UART_REGISTER1 + 0x00))
  8. #define AMBA_UART_FR1 (*(volatile unsigned char *)(RPI_BASE_UART_REGISTER1 + 0x18))
  9. /*---------------------------*/
  10. ?
  11. void uart_putc_phy(unsigned char c)
  12. {
  13.     //UART_Type *uartRegs = (UART_Type *)UART4_REG_PBASE;
  14.     //while ((uartRegs->USART_ISR & (1<<5)) == 0);
  15.     //uartRegs->USART_TDR = c;
  16.     while (AMBA_UART_FR & (1 << 5));
  17.     AMBA_UART_DR = c;
  18. }
  19. ?
  20. void uart_putc_virt(unsigned char c)
  21. {
  22.     //UART_Type *uartRegs = (UART_Type *)UART_REG_BASE;
  23.     //while ((uartRegs->USART_ISR & (1<<5)) == 0);
  24.     //uartRegs->USART_TDR = c;
  25.     while (AMBA_UART_FR1 & (1 << 5));
  26.     AMBA_UART_DR1 = c;
  27. }

 例如:kernel\liteos_a\arch\arm\arm\src\startup\reset_vector_up.S

 
 
 
 
  1. ldr sp, =0x00000000 + 0x5000000  //調(diào)用C函數(shù)前,得先設(shè)置棧,樹莓派物理內(nèi)存從0x0開始
  2.    mov r0, #'m'
  3.    bl uart_putc_phy                //在MMU啟動之前使用的是物理地址打印
  4.    
  5.    bl      mmu_setup                           /* set up the mmu */
  6.    
  7.    mov r0, #'M'
  8.    bl uart_putc_virt               //在MMU啟動之后使用的是虛擬地址打印

 2.2、添加串口中斷,串口輸入代碼

 
 
 
 
  1. vendor\broadcom\BCM2836\driver\uart\uart_hardware.c

2.2.1、 串口的中斷函數(shù),產(chǎn)生中斷時,這個函數(shù)調(diào)用

 
 
 
 
  1. static irqreturn_t BCM2836_uart_irq(int irq, void *data)
  2. {
  3.     char buf[FIFO_SIZE];
  4.     unsigned int count = 0;
  5.     struct BCM2836_port *port = NULL;
  6.     struct uart_driver_data *udd = (struct uart_driver_data *)data;
  7.     UART_Type *uartRegs;
  8.     uint32_t status;
  9.     
  10.     if (udd == NULL) {
  11.         uart_error("udd is null!\n");
  12.         return IRQ_HANDLED;
  13.     }
  14.     port = (struct BCM2836_port *)udd->private;
  15.     uartRegs = (UART_Type *)port->phys_base;
  16.     READ_UINT32(status, UART_REG_BASE + UART_FR);
  17.     if ((UARTREG(UART_REG_BASE,UART_FR)&(1<<4)) == 0) {
  18.         do {
  19.             buf[count++] = UARTREG(UART_REG_BASE,UART_DR);//*(volatile UINT32 *)((UINTPTR)(UART_REG_BASE + UART_DR)); //去讀取硬件得到數(shù)據(jù)
  20.             if (udd->num != CONSOLE_UART) {
  21.                 continue;
  22.             }
  23.             if (CheckMagicKey(buf[count - 1])) { //數(shù)據(jù)放在buf里
  24.                 goto end;
  25.             }
  26. ?
  27.             if (buf[count-1] == '\r') //對windows和liteos回車換行的處理
  28.                 buf[count-1] = '\n';
  29.         } while (UARTREG(UART_REG_BASE,UART_DR));
  30.         udd->recv(udd, buf, count); //調(diào)用udd里的recv函數(shù)把數(shù)據(jù)發(fā)送給上一級
  31.     }
  32.     UARTREG(UART_REG_BASE, UART_ICR) = 0x3ff;
  33. end:
  34.     /* clear all interrupt */
  35.     return 0;
  36. }

 2.2.2、串口的初始化函數(shù)

 
 
 
 
  1. static int BCM2836_startup(struct uart_driver_data *udd) 
  2. {
  3.     int ret = 0;
  4.     struct BCM2836_port *port = NULL;
  5.     if (udd == NULL) {
  6.         uart_error("udd is null!\n");
  7.         return -EFAULT;
  8.     }
  9.     port = (struct BCM2836_port *)udd->private;//*private是一個指針,指向 struct {enable,phys_base,irq_num,*udd}
  10.     if (!port) {
  11.         uart_error("port is null!");
  12.         return -EFAULT;
  13.     }
  14.     /* enable the clock */
  15.     LOS_TaskLock();
  16.     LOS_TaskUnlock();
  17. ?
  18.     ret = request_irq(port->irq_num, (irq_handler_t)BCM2836_uart_irq,0, "uart_dw", udd);  //去注冊一個串口的接收中斷函數(shù)
  19.     /* 1.uart interrupt priority should be the highest in interrupt preemption mode */
  20.     //ret = LOS_HwiCreate(NUM_HAL_INTERRUPT_UART, 0, 0, (HWI_PROC_FUNC)uart_handler, NULL);
  21. ?
  22.     /* 2.clear all irqs */
  23.     UARTREG(UART_REG_BASE, UART_ICR) = 0x3ff;
  24.     //*(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F201044)) = 0x3ff;
  25. ?
  26.     /* disable FIFO mode */
  27.     //uartRegs->USART_CR1 &= ~(1<<29);
  28.     //*(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F20102C)) = 0x60;
  29.     UARTREG(UART_REG_BASE, UART_LCR_H) = (1 << 6 | 1 << 5| 1 << 4); 
  30. ?
  31.     /* 3.set fifo trigger level */
  32.     //*(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F201034)) = 0x0;
  33.     UARTREG(UART_REG_BASE, UART_IFLS) = 0;
  34. ?
  35.     /* 4.enable rx interrupt 開啟串口接收中斷,第4位*/
  36.     UARTREG(UART_REG_BASE, UART_IMSC) = (1 << 4 | 1 << 6); //*(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F201038)) = 0x10;
  37. ?
  38.     /* 5.enable receive */
  39.     UARTREG(UART_REG_BASE, UART_CR) |= (1 << 9); //*(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F201030)) = 0x301;
  40. ?
  41.     //HalIrqUnmask(NUM_HAL_INTERRUPT_UART);//6. 
  42.     *(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F00B214)) = 0x02000000;//Unmask接收25號中斷
  43. ?
  44.     BCM2836_config_in(udd);
  45. ?
  46.     return ret;
  47. }

 2.2.3、串口寫函數(shù)

 
 
 
 
  1. static int BCM2836_start_tx(struct uart_driver_data *udd, const char *buf, size_t count)
  2. {
  3.     unsigned int tx_len = count;
  4.     struct BCM2836_port *port = NULL;
  5.     char value;
  6.     unsigned int i;
  7.     int ret = 0;
  8. ?
  9.     if (udd == NULL) {
  10.         uart_error("udd is null!\n");
  11.         return -EFAULT;
  12.     }
  13.     port = (struct BCM2836_port *)udd->private;
  14.     if (!port) {
  15.         uart_error("port is null!");
  16.         return -EFAULT;
  17.     }
  18.     /* UART_WITH_LOCK: there is a spinlock in the function to write reg in order. */
  19.     for (i = 0; i < tx_len; i++ ){
  20.         ret = LOS_CopyToKernel((void *)&value, sizeof(char),(void *)(buf++), sizeof(char));
  21.         if (ret) {
  22.             return i;
  23.         }
  24.         (void)UartPutsReg(port->phys_base, &value, 1, UART_WITH_LOCK);
  25.     }
  26.     return count;
  27. }

 2、系統(tǒng)時鐘初始化

2.1、main函數(shù)的各種調(diào)用,驗證參數(shù)

kernel\liteos_a\platform\main.c->main()

kernel\liteos_a\kernel\common\los_config.c->OsMain()

kernel\liteos_a\arch\arm\arm\src\los_hw_tick.c->OsTickInit()

 
 
 
 
  1. systemClock     //vendor里設(shè)置的是50000000
  2. tickPerSecond   //鴻蒙默認(rèn)設(shè)置的是100
  3. LITE_OS_SEC_TEXT_INIT UINT32 OsTickInit(UINT32 systemClock, UINT32 tickPerSecond)
  4. {    //只是驗證了下傳入的這兩個參數(shù),并未使用
  5.     HalClockInit();
  6.     return LOS_OK;
  7. }

 2.2、先獲取當(dāng)前時鐘頻率,注冊中斷

kernel\liteos_a\platform\hw\arm\timer\arm_generic\arm_generic_timer.c

 
 
 
 
  1. OS_TICK_INT_NUM//中斷號,在vendor\***\***\board\include\asm\hal_platform_ints.h下定義,查手冊確定
  2. MIN_INTERRUPT_PRIORITY//優(yōu)先級
  3. OsTickEntry//中斷函數(shù)
  4. LITE_OS_SEC_TEXT_INIT VOID HalClockInit(VOID)
  5. {   ...
  6.     g_sysClock = HalClockFreqRead(); //先獲取當(dāng)前時鐘頻率
  7.     
  8.     //調(diào)用LOS_HwiCreate函數(shù)新建中斷,系統(tǒng)中斷由它注冊
  9.     ret = LOS_HwiCreate(OS_TICK_INT_NUM, MIN_INTERRUPT_PRIORITY, 0, OsTickEntry, 0);//參數(shù)1:中斷號、參數(shù)4:執(zhí)行函數(shù)
  10.     //這個函數(shù)就不深入了,大體就是將中斷號好和對應(yīng)的執(zhí)行函數(shù)放到一個數(shù)組
  11.     //比如這里就是,當(dāng)發(fā)生OS_TICK_INT_NUM這個中斷時,執(zhí)行OsTickEntry()函數(shù)
  12.     ...
  13. }

 2.3、時鐘中斷的執(zhí)行函數(shù)OsTickEntry()

kernel\liteos_a\platform\hw\arm\timer\arm_generic\arm_generic_timer.c

 
 
 
 
  1. 不過此時這是注冊了這個函數(shù),時鐘并未啟動,得執(zhí)行了(三.啟動時鐘)之后才會調(diào)用這個函數(shù)
  2. LITE_OS_SEC_TEXT VOID OsTickEntry(VOID)
  3. {
  4.     TimerCtlWrite(0);
  5.     OsTickHandler();
  6.     TimerCvalWrite(TimerCvalRead() + OS_CYCLE_PER_TICK);
  7.     TimerCtlWrite(1);
  8.     //使用最后一個cval生成下一個tick的時間是絕對和準(zhǔn)確的。不要使用tval來驅(qū)動一般時間,在這種情況下tick會變慢。
  9. }

 2.3、啟動時鐘

main() => OsStart(VOID) => OsTickStart() => HalClockStart(VOID)

kernel\liteos_a\platform\hw\arm\timer\arm_generic\arm_generic_timer.c => HalClockStart(VOID)

 
 
 
 
  1. //樹莓派2沒有GIC所以這個函數(shù)要爆改
  2. LITE_OS_SEC_TEXT_INIT VOID HalClockStart(VOID)
  3. {
  4.     HalIrqUnmask(OS_TICK_INT_NUM);  //wendor里定義的 OS_TICK_INT_NUM = 29
  5.     TimerCtlWrite(0);
  6.     TimerTvalWrite(OS_CYCLE_PER_TICK);
  7.     TimerCtlWrite(1);
  8. }

 2.3.1、HalIrqUnmask; //接收中斷(通過設(shè)置寄存器,允許CPU響應(yīng)該中斷)

 
 
 
 
  1. HalIrqUnmask(OS_TICK_INT_NUM);
  2. HalIrqUnmask(29);
  3. GIC_REG_32(GICD_ISENABLER(29 >> 5)) = 1U << (29 % 32);
  4. ?
  5. (GICD_ISENABLER(29 >> 5))拆開
  6. GIC_REG_32(GICD_OFFSET + 0x100 + (29 >> 5) * 4) = 1U << (29 % 32);/* 中斷使能 Registers */
  7. ?
  8. GIC_REG_32拆開,(29 % 32)=1D
  9. GIC_BASE_ADDR + (GICD_OFFSET + 0x100 + (29 >> 5) * 4) = 1U << (29 % 32)
  10. ?
  11. #define GIC_BASE_ADDR             IO_DEVICE_ADDR(0x3F00A100)
  12. #define GICD_OFFSET               0x1000     /* interrupt distributor offset */

 2.3.2、TimerCtlWrite(0); //關(guān)閉Timer

參考:ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf

《B3.17 Organization of the CP15 registers in a VMSA implementation》

 
 
 
 
  1. WRITE_TIMER_REG32(TIMER_REG_CTL, 0);
  2. ARM_SYSREG_WRITE(TIMER_REG_CTL, 0)
  3. ARM_SYSREG_WRITE(TIMER_REG(_CTL), 0)
  4. ARM_SYSREG_WRITE(CP15_REG(c14, 0, c2, 1)), 0)
  5. "mcr " (CP15_REG(c14, 0, c2, 1) :: "r" (val)
  6. 反匯編
  7. r8 0
  8. mcr p15, #0, r8, c14, c2, #1    CNTP_CTL,PL1物理定時器控制寄存器

 2.3.3、TimerTvalWrite(OS_CYCLE_PER_TICK); //設(shè)置Tval

 
 
 
 
  1. 反匯編
  2. r0 192000
  3. mcr p15, #0, r0, c14, c2, #0    CNTP_TVAL,PL1物理時間值寄存器

 2.3.4、TimerCtlWrite(1); //再開啟Timer

 
 
 
 
  1. 反匯編
  2. r5 1
  3. mcr p15, #0, r5, c14, c2, #1    CNTP_CTL,PL1物理定時器控制寄存器

 2.4、代碼移植

Z:\bright\harmony-100ask\kernel\liteos_a\platform\hw\arm\interrupt\gic\gic_v2.c

 
 
 
 
  1. VOID HalIrqUnmask(UINT32 vector)
  2. {
  3.     if ((vector > OS_USER_HWI_MAX) || (vector < OS_USER_HWI_MIN)) {
  4.         return;
  5.     }
  6.     //GIC_REG_32(GICD_ISENABLER(vector >> 5)) = 1U << (vector % 32);  //替換
  7.     *(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F00B218)) = 1; //使能ARM Timer IRQ    
  8. ?}

 Z:\bright\harmony-100ask\kernel\liteos_a\platform\hw\arm\timer\arm_generic\arm_generic_timer.c

 
 
 
 
  1. STATIC_INLINE VOID TimerCtlWrite(UINT32 cntpCtl)
  2. {
  3.     //WRITE_TIMER_REG32(TIMER_REG_CTL, cntpCtl);//替換
  4.     if(cntpCtl == 0){
  5.         *(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F00B408)) = 0x003E0000;
  6.         }
  7.     else
  8.     {
  9.         *(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F00B408)) = 0x003E00A2;
  10.     }
  11. }
  12. ?STATIC_INLINE VOID TimerTvalWrite(UINT32 tval)
  13. {
  14.     //WRITE_TIMER_REG32(TIMER_REG_TVAL, tval);//替換
  15.     *(volatile UINT32 *)((UINTPTR)IO_DEVICE_ADDR(0x3F00B400)) = tval;  //設(shè)置倒計時時間,鴻蒙是10ms    
  16. }

 =======完整內(nèi)容======

#2020征文-開發(fā)板# 鴻蒙 移植 樹莓派(上)搭建環(huán)境下載源碼

#2020征文-開發(fā)板# 鴻蒙 移植 樹莓派(中)添加單板

#2020征文-開發(fā)板# 鴻蒙 移植 樹莓派(下)修改源碼

?著作權(quán)歸作者和HarmonyOS技術(shù)社區(qū)共同所有,如需轉(zhuǎn)載,請注明出處,否則將追究法律責(zé)任.

想了解更多內(nèi)容,請訪問:

和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos./#zz


當(dāng)前文章:鴻蒙移植樹莓派(下)修改源碼
文章分享:http://www.5511xx.com/article/dpchpgc.html