更多内容请访问:https://harmonyos.51cto.com/#zz与华为官方共建的鸿蒙技术社区最新更新,你可以查看代码仓库https://gitee.com/liangzili/harmony-raspberry1,切换启动方式树莓派默认以HYP模式启动,我们需要在内核启动前改为SVC模式kernel\liteos_a\arch\arm\arm\src\startup\reset_vector_up.S在第115行附近,reset_vector:在mrsr0,cpsr下面添加//读取CPU模式寄存器bicr0,r0,#0x1F//清除CPU模式位(如果处于催眠模式,则为1A)keepallothersorrr0,r0,#0x13//将CPU_MODE设置为SVC_MODE(0x13),而ORR仍保留所有其他位msrsspsr_cxsf,r0//将其写入spsr_cxsf寄存器,以便在调用开关时加载它。addr0,pc,#4//计算从pc进入SVC_MODE的地址(下面两个操作码很长)msrELR_hyp,r0//将地址值写入ELR_hyp寄存器eret//执行回车指令2、修改串口驱动2.1。为了调试方便,先设置一个字符打印函数kernel\liteos_a\platform\uart\amba_pl011\amba_pl011.c,在第46行左右添加如下代码,uart_putc_phy使用物理地址打印字符,uart_putc_virt使用虚拟地址打印.内核代码启动MMU后,需要使用uart_putc_virt打印字符。/*--------自定义义数----------*/#defineRPI_BASE_UART_REGISTER(0x3f201000)//HI3516:0x120A0000rpi2:0x3F201000#defineAMBA_UART_DR(*(volatile+unsignedchar*)(RPI_REBASE_UART_UART_REGISTER(0x3f201000)))#defineAMBA_UART_FR(*(volatileunsignedchar*)(RPI_BASE_UART_REGISTER+0x18))?#defineRPI_BASE_UART_REGISTER1IO_DEVICE_ADDR(0x3F201000)//HI3516:0x120A0000rpi2:0x3F201000#defineAMBA_UART_DR1(*(volatileunsignedchar*)(RPI_BASE_UART_REGISTER1+0x00))#defineAMBA_UART_FR1(*(volatileunsignedchar*)(RPI_BASE_UART_REGISTER1+0x18))/*----------------------------*/voiduart_putc_phy(unsignedcharc){//UART_Type*uartRegs=(UART_Type*)UART4_REG_PBASE;//while((uartRegs->USART_ISR&(1<<5))==0);//uartRegs->USART_TDR=c;while(AMBA_UART_FR&(1<<5));AMBA_UART_DR=c;}voiduart_putc_virt(unsignedcharc){//UART_Type*uartRegs=(UART_Type*)UART_REG_BASE;//while((uartRegs->USART_ISR&(1<<5))==0);//uartRegs->USART_TDR=c;而(AMBA_UART_FR1&(1<<5));AMBA_UART_DR1=c;}例如:kernel\liteos_a\arch\arm\arm\src\startup\reset_vector_up.Sldrsp,=0x00000000+0x5000000//调用C函数前,必须先设置栈,树莓派物理内存从0x0开始movr0,#'m'bluart_putc_phy//在MMU启动前使用物理地址打印blmmu_setup/*setupthemmu*/movr0,#'M'bluart_putc_virt//在MMU启动后使用虚拟地址打印2.2,增加串口中断,串口输入代码vendor\broadcom\BCM2836\driver\uart\uart_hardware.c2.2.1,串口中断函数,当中断发生时,该函数调用staticirqreturn_tBCM2836_uart_irq(intirq,void*data){charbuf[FIFO_SIZE];unsignedintcount=0;structBCM2836_port*port=NULL;structuart_driver_data*udd=(structuart_driver_data*)data;UART_Type*uartRegs;uint32_tstatus;if(udd==NULL){uart_error("uddisnull!\n");returnIRQ_HANDLED;}port=(structBCM2836_port*)udd->private;uartRegs=(UART_Type*)port->phys_base;READ_UINT32(status,UART_REG_BASE+UART_FR);if((UARTREG(UART_REG_BASE,UART_FR)&(1<<4))==0){do{buf[count++]=UARTREG(UART_REG_BASE,UART_DR);//*(volatileUINT32*)((UINTPTR)(UART_REG_BASE+UART_DR));//读取硬件获取数据if(udd->num!=CONSOLE_UART){continue;}if(CheckMagicKey(buf[count-1])){//数据放在buf中gotoend;}if(buf[count-1]=='\r')//回车换行的处理在windows和liteos中buf[count-1]='\n';}while(UARTREG(UART_REG_BASE,UART_DR));udd->recv(udd,buf,count);//调用udd中的recv函数发送}UARTREG(UART_REG_BASE,UART_ICR)=0x3ff;end:/*clearallinterrupt*/return0;}2.2.2、串口初始化函数staticintBCM2836_startup(structuart_driver_data*udd){intret=0;structBCM2836_port*port=NULL;if(udd==NULL){uart_error("uddisnull!\n");return-EFAULT;}port=(structBCM2836_port*)udd->private;//*private是指向struct{enable,phys_base,irq_num,*udd}if(!port){uart_error("portisnull!");return-EFAULT;}/*enabletheclock*/LOS_TaskLock();LOS_TaskUnlock();ret=request_irq(port->irq_num,(irq_handler_t)BCM2836_uart_irq,0,"uart_dw",udd);//注册串口接收中断函数/*1.uartinterruptpriorityshouldbethehighestininterruptpreemptionmode*///ret=LOS_HwiCreate(NUM_HAL_INTERRUPT_UART,0,0,(HWI_PROC_FUNC)uart_handler,NULL);/*2.clearallirqs*/UARTREG(UART_REG_BASE,UART_ICR)=0x3ff;//*(volatileUINT32*)((UINTPTR)IO_DEVICE_ADDR(0x3F201044))=0x3ff;/*禁用FIFO模式*///uartRegs->USART_CR1&=~(1<<29);//*(volatileUINT32*)((UINTPTR)IO_DEVICE_ADDR(0x3F20102C))=0x60;UARTREG(UART_REG_BASE,UART_LCR_H)=(1<<6|1<<5|1<<4);/*3.setfifotriggerlevel*///*(volatileUINT32*)((UINTPTR)IO_DEVICE_ADDR(0x3F201034))=0x0;UARTREG(UART_REG_BASE,UART_IFLS)=0;/*4.enablerxinterrupt使能串口接收中断,bit4*/UARTREG(UART_REG_BASE,UART_IMSC)=(1<<4|1<<6);//*(volatileUINT32*)((UINTPTR)IO_DEVICE_ADDR(0x3F201038))=0x10;/*5.enablereceive*/UARTREG(UART_REG_BASE,UART_CR)|=(1<<9);//*(volatileUINT32*)((UINTPTR)IO_DEVICE_ADDR(0x3F201030))=0x301;//HalIrqUnmask(NUM_HAL_INTERRUPT_UART);//6.*(volatileUINT32*)((UINTPTR)IO_DEVICE_ADDR(0x3F00B214))=0x02000000;//Unmask收到25号中断BCM2836_config_in(udd);returnret;}2.2.3、串口写函数staticintBCM2836_start_tx(structuart_driver_data*udd,constchar*buf,size_tcount){unsignedinttx_len=count;structBCM2836_port*port=NULL;charvalue;unsignedinti;intret=0;if(udd==NULL){uart_error("uddisnull!\n");返回-EFAULT;}port=(structBCM2836_port*)udd->private;if(!port){uart_error("portisnull!");return-EFAULT;}/*UART_WITH_LOCK:thereisaspinlockinthefunctiontowritereginorder.*/for(i=0;i
