//======================================================================
//文件名称：svc.S
//功能概要：svc源程序
//版权所有：苏州大学嵌入式系统与物联网研究所(sumcu.suda.edu.cn)
//版本更新：2018-11-07 V1.0
//功能描述： （1）其中包括所有BIOS对外接口函数，即API接口函数表
//       （2）SVC中断处理程序，蔡老师用汇编实现。
//添加对外函数步骤如下：
//       （1）在BIOS新建并实现该对外函数
//       （2）在【添加处】按照.long x函数名x 的格式添加函数名，以sysTimeGet为例，
//           .long sysTimeGet
//       （3）在USER程序中为该对外函数定义一个函数指针，以sysTimeGet为例，格式如下：
//           #define sysTimeGet ((uint_64 (*)(void))(bios_fun_point[1]))
//           注：bios_fun_point[x]中的x须于该函数在此文件中API表的偏移量一致。
//======================================================================
		.file    "svc.S"       //定义一个文件名，用处不大
		.syntax  unified       //指示下方指令为ARM和thumb通用格式
		.arch armv6-m
		.section ".rodata"

		//存放最大用户号以及用户程序API接口函数表首地址
		osRtxUserSVC:
		.long 1
        .long getBiosUserFun

        //为BIOS对用户程序提供的API接口函数表，其中有保留函数
		BiosUserFun:
		.long   130  //最终用户SVC号，
		//***************系统时钟********************
		.long   sysTimeGet           //1号系统时间获取
		.long   sysTimeSet           //2号系统时间设置
		.long   setVector            //3号设置向量号
		.long   bios_version         //4号bios版本
		.long   reserved_func        //5号保留
		.long   reserved_func        //6号保留
		.long   reserved_func        //7号保留
		//***************adc***********************
		.long   adc_init             //8号adc初始化
		.long   adc_read             //9号adc获取通道值
		.long   reserved_func        //10号保留
		.long   reserved_func        //11号保留
		.long   reserved_func        //12号保留
		//***************flash**********************
		.long   flash_init           //13号flash初始化
		.long   flash_erase          //14号flash擦除
		.long   flash_write          //15号flash写入
		.long   flash_read_logic     //16号flash按逻辑地址读取
		.long   flash_read_physical  //17号flash物理地址读取
		.long   flash_protect        //18号flash保护
		.long   flash_isempty        //19号检测flash是否为空
		.long   flash_write_physical //20号flash物理地址写入
		.long   reserved_func        //21号保留
		.long   reserved_func        //22号保留
		//***************gpio**********************
		.long   gpio_init            //23号gpio初始化
		.long   gpio_set             //24号gpio设置输出高低
		.long   gpio_get             //25号gpio获取输入电频
		.long   gpio_reverse         //26号gpio输出取反
		.long   gpio_pull            //27号gpio上下拉
		.long   gpio_enable_int      //28号gpio中断使能
		.long   gpio_disable_int     //29号gpio禁止中断
		.long   gpio_get_int         //30号gpio获取中断状态
		.long   gpio_clear_int       //31号gpio清中断
		.long   gpio_clear_allint    //32号gpio清所有中断
		.long   gpio_drive_strength  //33号gpio驱动设置
		.long   reserved_func        //34号保留
		.long   reserved_func        //35号保留
		.long   reserved_func        //36号保留
		//***************I2C**********************
		.long   i2c_init             //37号i2c初始化
		.long   i2c_read1            //38号i2c按指令读取一个字节
		.long   i2c_readN            //39号i2c按指令读取多个字节
//		.long   i2c_rece1            //40号i2c接受1个字节
//		.long   i2c_receN            //41号i2c接受多个字节
		.long   i2c_write1           //42号i2c写入1个字节
		.long   i2c_writeN           //43号i2c写入多个字节
		.long   i2c_enable_re_int    //44号i2c使能接受中断
		.long   i2c_disable_re_int   //45号i2c禁用接受中断
		.long   reserved_func        //46号保留
		.long   reserved_func        //47号保留
		.long   reserved_func        //48号保留
		//***************timer*********************
		.long   timer_init           //49号用户SVC地址
		.long   timer_reset          //50号用户SVC地址
		.long   timer_enable_int     //51号用户SVC地址
		.long   timer_disable_int    //52号用户SVC地址
		.long   reserved_func        //53号保留
		.long   reserved_func        //54号保留
		//***************spi**********************
		.long   MKW01Drv_SPI0_Init  //55号用户SVC地址
		.long   spi_init            //56号用户SVC地址
		.long   spi_send1           //57号用户SVC地址
		.long   spi_sendN           //58号用户SVC地址
		.long   spi_receive1        //59号用户SVC地址
		.long   spi_receiveN        //60号用户SVC地址
		.long   spi_enable_re_int   //61号用户SVC地址
		.long   spi_disable_re_int  //62号用户SVC地址
		.long   MKW01Drv_ReadRegister//63号用户SVC地址
		.long   MKW01Drv_WriteRegister//64号用户SVC地址
		.long   MKW01Drv_WriteRegisterFast//65号用户SVC地址
		//***************pit**********************
		.long   pit_init            //66号用户SVC地址
		.long   pit_enable_int      //67号用户SVC地址
		.long   pit_disable_int     //68号用户SVC地址
		.long   pit_isr_time        //69号用户SVC地址
		.long   reserved_func       //70号保留
		.long   reserved_func       //71号保留
		.long   reserved_func       //72号保留
		.long   reserved_func       //73号保留
		.long   reserved_func       //74号保留
		//***************uart**********************
		.long   uart_init           //75号用户SVC地址
		.long   uart_send1          //76号用户SVC地址
		.long   uart_sendN          //77号用户SVC地址
		.long   uart_send_string    //78号用户SVC地址
		.long   uart_re1            //79号用户SVC地址
		.long   uart_reN            //80号用户SVC地址
		.long   uart_enable_re_int  //81号用户SVC地址
		.long   uart_disable_re_int //82号用户SVC地址
		.long   uart_get_re_int     //83号用户SVC地址
		.long   uart_deint          //84号用户SVC地址
		.long   reserved_func       //85号保留
        //***************pwm**********************
		.long   pwm_init            //86号用户SVC地址
		.long   pwm_update          //87号用户SVC地址
        //***************rf**********************
/*  	.long   RF_Init             //88号用户SVC地址
		.long   MKW01xDrv_IRQ_PortConfig //89号用户SVC地址
		.long   RF_ReceiveFrame     //90号用户SVC地址
		.long   RFEnergyDetect      //91号用户SVC地址
		.long   RFTempDetect        //92号用户SVC地址
		.long   RF_SendData         //93号用户SVC地址
		.long   MKW01Drv_IRQ_DIO1_Enable //94号用户SVC地址
		.long   RFSendDataByCSMACA //95号用户SVC地址
		.long   RFIRQ              //96号用户SVC地址
		.long   PortClean          //97号用户SVC地址
		.long   UartClean          //98号用户SVC地址
		.long   reserved_func      //99号保留
		.long   reserved_func      //100号保留
		.long   reserved_func      //101号保留
		.long   reserved_func      //102号保留
		.long   reserved_func      //103号保留*/

		.long   reserved_func      //88号保留
		.long   reserved_func      //89号保留
		.long   reserved_func      //90号保留
		.long   reserved_func      //91号保留
		.long   reserved_func      //92号保留
		.long   reserved_func      //93号保留
		.long   reserved_func      //94号保留
		.long   reserved_func      //95号保留
		.long   reserved_func      //96号保留
		.long   reserved_func      //97号保留
		.long   reserved_func      //98号保留
		.long   reserved_func      //99号保留
		.long   reserved_func      //100号保留
		.long   reserved_func      //101号保留
		.long   reserved_func      //102号保留
		.long   reserved_func      //103号保留
		//***************incapture*****************
		.long   incapture_init      //104号用户SVC地址
		.long   get_incapture_value //105号用户SVC地址
		.long   cap_enable_int  //106号用户SVC地址
		.long   cap_disable_int //107号用户SVC地址
		.long   cap_clear_flag     //108号用户SVC地址
		.long   cap_get_flag       //109号用户SVC地址
		.long   reserved_func       //110号保留
		.long   reserved_func       //111号保留
		.long   reserved_func       //112号保留
		//***************tpm********************
		.long   tpm_timer_init     //113号用户SVC地址
		.long   tpm_enable_int     //114号用户SVC地址
		.long   tpm_disable_int    //115号用户SVC地址
		.long   tpm_get_int        //116号用户SVC地址
		.long   tpm_clear_int      //117号用户SVC地址
		.long   reserved_func      //118号保留
		.long   reserved_func      //119号保留
				//***************outcmp********************
		.long   outcmp_init          //120号用户SVC地址
		.long   outcmp_enable_int    //121号用户SVC地址
		.long   outcmp_disable_int   //122号用户SVC地址
		.long   outcmp_get_int       //123号用户SVC地址
		.long   outcmp_chl_get_int   //124号用户SVC地址
		.long   outcmp_clear_int     //125号用户SVC地址
		.long   outcmp_clear_chl_int //126号用户SVC地址
		.long   reserved_func        //127号保留
		.long   reserved_func        //128号保留
		//***************FlashData*********************
		.long   FlashData_get       //129号用户SVC地址
		.long   FlashData_set       //130号用户SVC地址
		//【添加处】


//=====================================================================
//函数名称：getBiosUserFun
//功能概要：获取BIOS中API接口函数表首地址
//参数说明：无
//函数返回：API接口函数表首地址
//=====================================================================
//void * getBiosUserFun()
//{
//	return (void *) BiosUserFun;
//}
	.thumb_func     //表明函数使用的是thumb指令集的函数
	.type    getBiosUserFun, %function  //指定getBiosUserFun为函数类型
	.global  getBiosUserFun  // 声明全局函数getBiosUserFun
    .fnstart                //getBiosUserFun函数开始标志
    .cantunwind    //防止通过当前功能展开

getBiosUserFun:
	ldr	r0,=BiosUserFun
	bx	lr
    .size    getBiosUserFun, .-getBiosUserFun  //为函数分配内存
	//getBiosUserFun函数结束
//=====================================================================
//函数名称：SVC_handler
//功能概要：SVC中断处理函数，如果SVC指令参数不为0，则根据调用号去执行用户自定义函数。
//参数说明：无
//函数返回：无
//=====================================================================
    .thumb_func     //表明函数使用的是thumb指令集的函数
    .type    SVC_HandlerS, %function  //指定SVC_handler为函数类型
    .global  SVC_HandlerS  // 声明全局函数SVC_handler

SVC_HandlerS:
  //(1)判断SVC指令参数是否为0
  SVC_Handler_1:
	MRS  R0,MSP            //让R0指向主栈指针指向的地址
	LDR      R1,[R0,#28]   //R1=PC(执行SVC指令前入栈的PC寄存器值)
	SUBS      R1,R1,#2     //R1=SVC指令地址(入栈前PC寄存器-2)
	LDRB     R1,[R1]       //R1=R1中保存的字节地址的值(即SVC指令的入口参数)
	CMP      R1,#0         //测试SVC指令入口参数是否为零
	BNE       SVC_User     //入口参数不为0转SVC_User
  //(2)SVC指令参数为0，执行默认的SVC服务【BIOS中不会去执行这段代码，该段代码暂无实际功能】
  SVC_Default:
	PUSH     {R0,LR}       //将R0，LR入栈(R0存放PSP指针，LR存放EXC_RETURN)
	LDMIA  R0,{R0-R3}      //R0指向的地址的内容依次弹出装入R0~R3中(地址累加)
	BLX      R6            //跳转到R6指向的函数，LR保存返回地址
	POP     {R2,R3}        //R2=PSP，R3=EXC_RETURN
	STMIA  R2!,{R0-R1}     //将R0~R1的数据装入R2指向的地址（地址累加）
	SUBS  R3,R3,#2
	MOV   LR,R3            //LR=R3(EXC_RETURN)
  //(3)退出SVC
  SVC_Exit:
	BX       LR            //跳转到LR指向的地址，退出SVC
  //(4)若SVC指令参数不为0，去执行SVC用户自定义函数
  SVC_User:
    //(4.1)判断SVC调用号是否大于最大调用号，是则去执行 SVC调用处理函数
	CMP      R1,#1         //测试R1(SVC调用号)的值是否为1
	BNE      SVC_Exit      //不是，转SVC_Exit
	PUSH    {R4,LR}        //是，将R4、LR入栈
	LDR      R2,=osRtxUserSVC//R2=SVC表数组osRtxUserSVC的首地址
	LDR      R3,[R2]       //R3=SVC最大的调用号(最大调用号保存在首地址中)
	CMP      R6,R3         //比较最大调用号
	BHI     SVC_Done       //测试入口参数是否大于数组最大调用号，是，转SVC_Done去执行
	//(4.2)SVC调用处理子函数
	LSLS     R6,R6,#2      //R6=入口参数*4
	LDR     R4,[R2,R6]     //将地址为(R2+R6)处的存储内容，也就是处理函数的地址装入R4
	ADDS     R0,R0,#4      //原本主栈指针指向最后入栈的数据，此时地址加4让R0指向R0
	MOV     R6,R0          //将R0装入R6，R0指向R0,存在R6中
	LDMIA   R0,{R0-R3}     //R0~R3保存处理函数参数
	BLX     R4             //跳转到R4指向的处理函数
	STMIA   R6!,{R0-R3}    //将R0~R3的数据装入R6指向的地址(地址累加)
  //(4.3)SVC调用完成
  SVC_Done:
	POP     {R4,PC}        //将R4、PC出栈，从处理程序返回

    .size    SVC_HandlerS, .-SVC_HandlerS    //为函数分配内存
    .end    //SVC_Handler函数结束
