主頁 > 移動端開發 > 基于STM32F767的UCOSIII移植學習

基于STM32F767的UCOSIII移植學習

2020-11-05 16:29:45 移動端開發

(一)移植前的準備

1.HAL庫基本工程模板

新建一個工程模塊,其中包含LED驅動和串口驅動程式即可,用于驗證UCOS-III系統能夠正常作業,

2.UCOS-III原始碼準備

去Micrium官網下載最新的UCOSIII原始碼,下載地址:Micrium官網下載地址,沒有注冊過的用戶需要注冊一下,我自己注冊的程序都是淚,由于我選擇的是正點原子F7的開發板,所以在官網上選擇合適原始碼時就選擇F7的,具體版本選擇下圖中19年2月6號的版本:在這里插入圖片描述
下載完成之后發現,發現原始碼檔案夾中東西很多大部分都是和網路移植相關的,目前我們只移植最新版本的UCOSIII,所以這些檔案夾都不需要去看,進入原始碼目錄下的uCOS-III檔案夾,發現里面只有針對IAR的編譯器的檔案,難道MDK就涼涼了嗎?凡是先不要慌,雖然編譯器不同,但是實作的功能就是相同的,并不會影響到移植后作業系統的運行,

UCOSIII的移植

(一)原始碼檔案的摘選

1.在準備好的工程檔案夾下新建一個UCOS-III目錄,用于存放和UCOSIII相關的所有代碼,在UCOS-III目錄下新建如下目錄,用于UCOS原始碼的分類,在這里插入圖片描述
(1)將原始碼目錄Micrium_STM32F746G-DISCO_Crypto\Micrium\Software\uC-CPU下的檔案全部拷貝到我們創建的uC-CPU目錄下,為了減少檔案夾的個數,我把ARM-Cortex-M\ARMv7-M目錄下和ARM-Cortex-M\ARMv7-M\ARM目錄下的檔案都移到了自己創建的uC-CPU目錄下了,這里我要說明下一下IAR和ARM目錄下的檔案,除了匯編檔案有些不同以外,頭檔案內容都是相同的,這邊選擇ARM目錄下的匯編檔案還是IAR目錄下的匯編檔案都行,因為我們都是要修改成MDK支持的形式的,
(2)將原始碼目錄Micrium_STM32F746G-DISCO_Crypto\Micrium\Software\uC-LIB檔案夾下的檔案全部拷貝到自己創建的uC-LIB目錄下,這邊我直接把Micrium\Software\uC-LIB\Ports\ARM-Cortex-M4\RealView目錄下的檔案和其他檔案放在了一個檔案夾下,具體如下圖所示:在這里插入圖片描述
由于我們使用的是MDK編譯,所以這邊選擇的是RealView目錄下的匯編檔案,具體什么原因的話,網上有很多解釋,我就不復制他們的解釋了,
(3)將Micrium_STM32F746G-DISCO_Crypto\Micrium\Software\uCOS-III目錄下的檔案全部拷貝到自己創建uCOS-III目錄下,點開Ports的目錄,發現最后只有一個IAR檔案下,這邊我們先不用關注,只需將檔案都拷貝過來,具體內容如下圖所示:在這里插入圖片描述
在這里插入圖片描述
(4)將原始碼例程目錄Micrium_STM32F746G-DISCO_Crypto\ST\STM32F746G_Disco\Crypto下的部分檔案和OS3下的部分檔案拷貝到自己創建的UCOS-CONFIG檔案夾下,具體檔案如下圖所示:在這里插入圖片描述
在原始碼例程檔案中,發現很多都是網路相關的移植代碼,所以沒有拷貝過來,但是有一個clk_cfg.h很明顯不是和網路相關的,為什么不移植過來呢?從名字上看就是和時鐘相關的,難道說不需要時鐘配置嗎?時鐘當然是需要配置的,但是裸機工程中時鐘已經配置OK了,這邊和時鐘相關的檔案也就不需要了,后面作業系統的時鐘需要自己通過HAL庫配置,這邊就不詳細說明了,
(5)將Micrium_STM32F746G-DISCO_Crypto\ST\BSP\STM32F746G_Disco目錄下的bsp_cpu.c檔案拷貝到自己創建的UCOS-BSP目錄下,并且新建一個bsp_cpu.h頭檔案(用于包含作業系統的頭檔案),其他檔案都不需要拷貝,大多是和芯片外設相關的初始化,

(二)檔案添加

(1)打開MDK工程,將拷貝的檔案添加至工程當中,具體內容如下圖所示:在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
以及頭檔案路徑添加,如下圖所示:在這里插入圖片描述
上述檔案都添加完成之后,點擊編譯,提示下圖錯誤:在這里插入圖片描述
出現unknown opcode什么的錯誤,而且出現在os_cpu_a.asm檔案中,那就打開這個匯編檔案看一下,是什么問題,發現PUBLIC關鍵字都沒有標藍,那肯定是由于這個關鍵字不是MDK的關鍵字,所以講PUBLIC修改為MDK所用的關鍵字EXPORT,具體EXPORT這個關鍵字怎么來的,我是查看了其他版本的UCOS在STM32的移植,看到用的是這個關鍵字,就直接抄過來了,還有錯誤與FPU相關,如下圖所示:

#ifdef __ARMVFP__
    EXPORT  OS_CPU_FP_Reg_Push
    EXPORT  OS_CPU_FP_Reg_Pop
#endif

查看了正點原子的移植手冊,發現上面說到

Cortex-M7內核中有個Lazy Stacking的功能,如果使用FPU功能的話就需要關閉這個功能,需要修改startup_stm32f767xx.s匯編檔案,在里面關閉這個功能,

具體代碼如下所示:

 IF {FPU} != "SoftVFP"
                                        ; Enable Floating Point Support at reset for FPU
		LDR.W   R0, =0xE000ED88         ; Load address of CPACR register
		LDR     R1, [R0]                ; Read value at CPACR
    	ORR     R1,  R1, #(0xF <<20)    ; Set bits 20-23 to enable CP10 and CP11 coprocessors
                                        ; Write back the modified CPACR value
	    STR     R1, [R0]                ; Wait for store to complete
        DSB
                
	                                    ; Disable automatic FP register content
                                        ; Disable lazy context switch
      	LDR.W   R0, =0xE000EF34         ; Load address to FPCCR register
       	LDR     R1, [R0]
   		AND     R1,  R1, #(0x3FFFFFFF)  ; Clear the LSPEN and ASPEN bits
   		STR     R1, [R0]
     	ISB                             ; Reset pipeline now the FPU is enabled
     	ENDIF

在startup_stm32f767xx.s中就如下圖所示:在這里插入圖片描述
修改完這些,接下去就解決… error: A1163E: Unknown opcode ARMVFP , expecting opcode or Macro 這個錯誤,將原先的判斷陳述句修改為如下陳述句:

	IF {FPU} != "SoftVFP"
    EXPORT  OS_CPU_FP_Reg_Push
    EXPORT  OS_CPU_FP_Reg_Pop
	ENDIF
	IF {FPU} != "SoftVFP"
OS_CPU_FP_Reg_Push
    MRS     R1, PSP                                             ; PSP is process stack pointer
    CBZ     R1, OS_CPU_FP_nosave                                ; Skip FP register save the first time

    VSTMDB  R0!, {S16-S31}
    LDR     R1, =OSTCBCurPtr
    LDR     R2, [R1]
    STR     R0, [R2]
OS_CPU_FP_nosave
    BX      LR
	ENDIF
	IF {FPU} != "SoftVFP"
OS_CPU_FP_Reg_Pop
    VLDMIA  R0!, {S16-S31}
    LDR     R1, =OSTCBHighRdyPtr
    LDR     R2, [R1]
    STR     R0, [R2]
    BX      LR
	ENDIF

修改完成之后,再次編譯,依舊存在 error: A1163E: Unknown opcode RSEG , expecting opcode or Macro 的錯誤,這主要是由于編譯器關鍵字的問題,所以這里直接借鑒其他其他版本在MDK上的移植,具體修改代碼如下:

    PRESERVE8
    THUMB

    AREA CODE, CODE, READONLY

再次編譯,發現這個匯編檔案中還有一個警告: warning: A1581W: Added 2 bytes of padding at address 0x112,這是提示地址沒對齊,那就在末尾添加一個對齊指令,具體代碼如下:

OS_CPU_PendSVHandler
    CPSID   I                                                   ; Cortex-M7 errata notice. See Note #5
    MOV32   R2, OS_KA_BASEPRI_Boundary                          ; Set BASEPRI priority level required for exception preemption
    LDR     R1, [R2]
    MSR     BASEPRI, R1
    DSB
    ISB
    CPSIE   I

    MRS     R0, PSP                                             ; PSP is process stack pointer
    STMFD   R0!, {R4-R11, R14}                                  ; Save remaining regs r4-11, R14 on process stack

    MOV32   R5, OSTCBCurPtr                                     ; OSTCBCurPtr->StkPtr = SP;
    LDR     R1, [R5]
    STR     R0, [R1]                                            ; R0 is SP of process being switched out

                                                                ; At this point, entire context of process has been saved
    MOV     R4, LR                                              ; Save LR exc_return value
    BL      OSTaskSwHook                                        ; Call OSTaskSwHook() for FPU Push & Pop

    MOV32   R0, OSPrioCur                                       ; OSPrioCur   = OSPrioHighRdy;
    MOV32   R1, OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    MOV32   R1, OSTCBHighRdyPtr                                 ; OSTCBCurPtr = OSTCBHighRdyPtr;
    LDR     R2, [R1]
    STR     R2, [R5]

    ORR     LR,  R4, #0x04                                      ; Ensure exception return uses process stack
    LDR     R0,  [R2]                                           ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
    LDMFD   R0!, {R4-R11, R14}                                  ; Restore r4-11, R14 from new process stack
    MSR     PSP, R0                                             ; Load PSP with new process SP

    MOV32   R2, #0                                              ; Restore BASEPRI priority level to 0
    MSR     BASEPRI, R2
    BX      LR                                                  ; Exception return will restore remaining context

	ALIGN

    END

再次編譯,os_cpu_a.asm檔案內沒有錯誤,還有兩個小錯誤:
在這里插入圖片描述
將os_cpu_c.c中os.h的頭檔案路徑修改意見,將bsp_cpu.c中的bsp_clk.h頭檔案注釋掉,再次編譯,報錯資訊如下圖:
在這里插入圖片描述
發現報錯資訊都在bsp_cpu.c當中,而且都是和時鐘頻率相關的,打開原始碼例程中的bsp_clk.c檔案,查看BSP_ClkFreqGet()函式,發現里面呼叫的函式不就是HAL庫提供的嗎,那我們直接將bsp_cpu.c中的時鐘獲取函式修改為HAL庫提供的函式,不就OK了嗎,修改后的代碼如下所示:

#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void  CPU_TS_TmrInit (void)
{
    CPU_INT32U  fclk_freq;
    CPU_INT32U  reg_val;

                                                                /* ---- DWT WRITE ACCESS UNLOCK (CORTEX-M7 ONLY!!) ---- */
    reg_val = CPU_BSP_REG_DWT_LSR;                              /* Read lock status register.                           */
    if ((reg_val & CPU_BSP_BIT_DWT_LSR_SLI) != 0) {             /* Check if Software lock control mechanism exits       */
        if ((reg_val & CPU_BSP_BIT_DWT_LSR_SLK) != 0) {         /* Check if DWT access needs to be unlocked             */
            CPU_BSP_REG_DWT_LAR = CPU_BSP_DWT_LAR_KEY;          /* Unlock DWT write access.                             */
        }
    }

    fclk_freq =  HAL_RCC_GetHCLKFreq();

    CPU_BSP_REG_DEMCR  |= DEF_BIT_24;                           /* Set DEM_CR_TRCENA                                    */
    CPU_BSP_REG_DWT_CR |= DEF_BIT_00;                           /* Set DWT_CR_CYCCNTENA                                 */

    CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq);
}
#endif
#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
CPU_INT64U  CPU_TS32_to_uSec (CPU_TS32  ts_cnts)
{
    CPU_INT64U  ts_us;
    CPU_INT64U  fclk_freq;


    fclk_freq =  HAL_RCC_GetHCLKFreq();
    ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);

    return (ts_us);
}
#endif


#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
CPU_INT64U  CPU_TS64_to_uSec (CPU_TS64  ts_cnts)
{
    CPU_INT64U  ts_us;
    CPU_INT64U  fclk_freq;


    fclk_freq = HAL_RCC_GetHCLKFreq();
    ts_us     = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);

    return (ts_us);
}
#endif

修改完之后,再次編譯,發現了很多重復定義的錯誤,都適合__dbg_ucos-iii.c檔案相關,那就直接移除掉這個檔案,再編譯看看結果如何,
編譯之后發現只有一個未定義的錯誤,打開os_cpu.h頭檔案,發現了下面這行代碼:

#define  OS_TASK_SW_SYNC()          __ISB()

明明定義了,卻還是提示未定義的錯誤,那我搜索了一下__ISB()函式,在cmsis_armcc.h中明確定義了,難道沒添加頭檔案引起的嗎,那就添加頭檔案再編譯一下,報錯資訊更多了,那很明顯不是這個問題了,看到cmsis_armcc.h中有這一行代碼:

#define __ISB() do {\
                   __schedule_barrier();\
                   __isb(0xF);\
                   __schedule_barrier();\
                } while (0U)

那就直接修改成

#define  OS_TASK_SW_SYNC()          __isb(0xF)

這樣編譯倒是沒問題了,但是系統運行起來有沒有問題就不知道,先這么做吧,這個頭檔案中還有一行代碼也需要修改:

#ifdef	__ARMVFP__	
#define  OS_CPU_ARM_FP_EN              1u
#else
#define  OS_CPU_ARM_FP_EN              0u
#endif

修改為

#ifdef __TARGET_FPU_SOFTVFP
#define  OS_CPU_ARM_FP_EN              1u
#else
#define  OS_CPU_ARM_FP_EN              0u
#endif

編譯后無錯誤,現在這系統能夠正常運行起來了嗎?講實話我也不太清楚,那就測驗一下吧,

(三)測驗系統

拷貝如下代碼至main.c中,

#include  <stdio.h>
#include  <string.h>
#include  <ctype.h>
#include  <stdlib.h>
#include  <stdarg.h>
#include  <math.h>

#include  <os.h>

#include  <cpu.h>
#include  <lib_def.h>
#include  <lib_ascii.h>
#include  <lib_math.h>
#include  <lib_mem.h>
#include  <lib_str.h>

#include  <app_cfg.h>
#include  "bsp_cpu.h"

//任務優先級
#define START_TASK_PRIO		2
//任務堆疊大小	
#define START_STK_SIZE 		512
//任務控制塊
OS_TCB StartTaskTCB;
//任務堆疊	
CPU_STK START_TASK_STK[START_STK_SIZE];
//任務函式
void start_task(void *p_arg);

//任務優先級
#define LED0_TASK_PRIO		3
//任務堆疊大小	
#define LED0_STK_SIZE 		128
//任務控制塊
OS_TCB Led0TaskTCB;
//任務堆疊	
CPU_STK LED0_TASK_STK[LED0_STK_SIZE];
void led0_task(void *p_arg);

//任務優先級
#define LED1_TASK_PRIO		4
//任務堆疊大小	
#define LED1_STK_SIZE       128
//任務控制塊
OS_TCB Led1TaskTCB;
//任務堆疊	
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
//任務函式
void led1_task(void *p_arg);

//任務優先級
#define FLOAT_TASK_PRIO		5
//任務堆疊大小
#define FLOAT_STK_SIZE		256
//任務控制塊
OS_TCB	FloatTaskTCB;
//任務堆疊
CPU_STK	FLOAT_TASK_STK[FLOAT_STK_SIZE];
//任務函式
void float_task(void *p_arg);

/*****************************************************************************************************************************************
 * Function Name: main
 * Input:         None
 * Output:        None
 * Returns:       None
 * Description:   主函式
 * Note:          None
*****************************************************************************************************************************************/
int main(void)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	
	HW_Init();
	MT_Init();
	
	OSInit(&err);		            //初始化UCOSIII
	CPU_CRITICAL_ENTER();            //進入臨界區
	//創建開始任務
	OSTaskCreate((OS_TCB 	* )&StartTaskTCB,		//任務控制塊
				 (CPU_CHAR	* )"start task", 		//任務名字
                 (OS_TASK_PTR )start_task, 			//任務函式
                 (void		* )0,					//傳遞給任務函式的引數
                 (OS_PRIO	  )START_TASK_PRIO,     //任務優先級
                 (CPU_STK   * )&START_TASK_STK[0],	//任務堆疊基地址
                 (CPU_STK_SIZE)START_STK_SIZE/10,	//任務堆疊深度限位
                 (CPU_STK_SIZE)START_STK_SIZE,		//任務堆疊大小
                 (OS_MSG_QTY  )0,					//任務內部訊息佇列能夠接收的最大訊息數目,為0時禁止接收訊息
                 (OS_TICK	  )0,					//當使能時間片輪轉時的時間片長度,為0時為默認長度,
                 (void   	* )0,					//用戶補充的存盤區
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, //任務選項,為了保險起見,所有任務都保存浮點暫存器的值
                 (OS_ERR 	* )&err);				//存放該函式錯誤時的回傳值
	CPU_CRITICAL_EXIT();	//退出臨界區	 
	OSStart(&err);      //開啟UCOSIII
	
	while(1)
	{
		
		
	}
}
//開始任務函式
void start_task(void *p_arg)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;

	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);  	//統計任務                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了測量中斷關閉時間
    CPU_IntDisMeasMaxCurReset();	
#endif

#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //當使用時間片輪轉的時候
	 //使能時間片輪轉調度功能,設定默認的時間片長度s
	OSSchedRoundRobinCfg(DEF_ENABLED,10,&err);  
#endif		
	
	CPU_CRITICAL_ENTER();	//進入臨界區
	//創建LED0任務
	OSTaskCreate((OS_TCB 	* )&Led0TaskTCB,		
				 (CPU_CHAR	* )"led0 task", 		
                 (OS_TASK_PTR )led0_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )LED0_TASK_PRIO,     
                 (CPU_STK   * )&LED0_TASK_STK[0],	
                 (CPU_STK_SIZE)LED0_STK_SIZE/10,	
                 (CPU_STK_SIZE)LED0_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
                 (OS_ERR 	* )&err);				
				 
	//創建LED1任務
	OSTaskCreate((OS_TCB 	* )&Led1TaskTCB,		
				 (CPU_CHAR	* )"led1 task", 		
                 (OS_TASK_PTR )led1_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )LED1_TASK_PRIO,     	
                 (CPU_STK   * )&LED1_TASK_STK[0],	
                 (CPU_STK_SIZE)LED1_STK_SIZE/10,	
                 (CPU_STK_SIZE)LED1_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, 
                 (OS_ERR 	* )&err);
				 
	//創建浮點測驗任務
	OSTaskCreate((OS_TCB 	* )&FloatTaskTCB,		
				 (CPU_CHAR	* )"float test task", 		
                 (OS_TASK_PTR )float_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )FLOAT_TASK_PRIO,     	
                 (CPU_STK   * )&FLOAT_TASK_STK[0],	
                 (CPU_STK_SIZE)FLOAT_STK_SIZE/10,	
                 (CPU_STK_SIZE)FLOAT_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, 
                 (OS_ERR 	* )&err);
				 
	CPU_CRITICAL_EXIT();	//進入臨界區				 
	OSTaskSuspend((OS_TCB*)&StartTaskTCB,&err);		//掛起開始任務			 
}

//led0任務函式
void led0_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	while(1)
	{
		HW_Led0_On();    //LED0打開
		OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err); //延時200ms
		HW_Led0_Off();    //LED0關閉
		OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延時500ms
	}
}

//led1任務函式
void led1_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	
	while(1)
	{
		HW_Led1_On();
        HW_Delay_ms(500);//延時500ms
		HW_Led1_Off();
		HW_Delay_ms(500);
		OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_HMSM_STRICT,&err); 
	}
}

//浮點測驗任務
void float_task(void *p_arg)
{
	OS_ERR err;
	
	CPU_SR_ALLOC();
	static double double_num=0.00;
	while(1)
	{
		double_num+=0.01f;
		CPU_CRITICAL_ENTER();	//進入臨界區
		printf("double_num的值為: %.4f\r\n",double_num);
		CPU_CRITICAL_EXIT();		//退出臨界區
		OSTimeDlyHMSM(0,0,0,20,OS_OPT_TIME_HMSM_STRICT,&err);
	}
}

編譯后,燒寫進開發板,查看現象:LED燈沒亮;那系統肯定沒有運行起來,通過Debug看看哪里出問題了,結果發現程式停在了如下地方:
在這里插入圖片描述
那說明是PendSV中斷處理出了問題,看看整個工程中哪里需要調整,os_cpu_a.asm匯編檔案中定義了OS_CPU_PendSVHandler函式,這是Micrium官方移植例程中修改了PendSV中斷函式的名稱,所以這邊需要修改回來,然后再編譯報該函式的重定義錯誤,在這里插入圖片描述
這邊屏蔽掉stm32f7xx_it.c中的PendSV_Handler函式定義,再次編譯;沒有報錯,那就再下載驗證一下,結果還是失敗了,那就再Debug一下,看看是哪里的問題,發現程式運行之后,開始任務調度之后就掛在空閑任務上,找來找去沒發現什么問題,本來都準備放棄了,后來看到作業系統的時間都是通過滴答定時器中斷產生的,然后仔細看了一下代碼,雖然使用了滴答定時器,但是沒有使用中斷,那趕緊加上試試,順便將stm32f7xx_it.h中定義的滴答定時器中斷函式屏蔽掉,編譯之后沒報錯,那就在測驗一下,終于,LED燈如愿的閃爍起來 ,串口也正常作業起來了,說明作業系統真正運行起來了,在這里插入圖片描述
下面附上移植后的工程,
鏈接:https://pan.baidu.com/s/1AGw1SWNMI_BpX7NLsxvQdg
提取碼:bzne
復制這段內容后打開百度網盤手機App,操作更方便哦

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/203445.html

標籤:其他

上一篇:【IoT】產品設計之結構工藝:鋅合金表面處理及壓鑄件優缺點

下一篇:密碼學中的各類密碼匯總(二)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more