// ============================================================================= // 功能:读发送缓冲区数据,由总线驱动调用,总线驱动读取到数据后将数据写入寄存器发送, // 若阻塞发送,则直接读发送缓冲区指向的数据,若非阻塞发送,则需判断是否剩余数据 // 已达到缓冲区边界,若已到达缓冲区边界,则填写缓冲区,并释放阻塞信号量 // 参数:SPI,SPI控制块指针 // buf,读数据缓冲区指针 // len,读数据长度,字节单位 // 返回:字节数 // ============================================================================= s32 SPI_PortRead( struct tagSPI_CB *SPI,u8 *buf,u32 len) { u32 Result = 0,RingLen,CpyLen = 0; u8 *pbuf; if((len > 0) && (SPI->Frame.SendLen > 0)) { CpyLen = SPI->Frame.SendLen >= len ?len:SPI->Frame.SendLen; RingLen = SPI->SPI_Buf.MaxLen; if(SPI->BlockOption == true) //阻塞发送直接读缓冲区 { memcpy(buf,SPI->Frame.SendBuf,CpyLen); SPI->Frame.SendBuf += CpyLen; } else //非阻塞发送,则需区别读取 { //判断是否从缓冲区中读数据 if(SPI->Frame.SendLen <= RingLen) //从缓冲区中读数据 { pbuf = &SPI->SPI_Buf.pBuf[SPI->SPI_Buf.Offset]; SPI->SPI_Buf.Offset += CpyLen; memcpy(buf,pbuf,CpyLen); } else //从pbuf中读数据 { memcpy(buf,SPI->Frame.SendBuf,CpyLen); SPI->Frame.SendBuf += CpyLen; //将pbuf剩余数据写入缓冲,并释放阻塞信号量 if(SPI->Frame.SendLen - CpyLen <= RingLen) { memcpy(SPI->SPI_Buf.pBuf,SPI->Frame.SendBuf, SPI->Frame.SendLen-CpyLen); Lock_SempPost(SPI->SPI_BlockSemp); } } } } //只有发送接收都完成的时候才能拉高片选 if(SPI->Frame.SendLen + SPI->Frame.RecvLen == 0) { if(SPI->BlockOption == true) { Lock_SempPost(SPI->SPI_BlockSemp); //阻塞发送时,释放阻塞信号量 } if(SPI->CurrentDev->AutoCs == true) { __SPI_AutoCsInactive(SPI,SPI->CurrentDev->Cs); } } SPI->Frame.SendLen -= CpyLen; Result = CpyLen; return Result; }
bool_t debug_dm9000a_write_reg(char *param) { char *word, *next_param; u32 reg = 0; u32 value = 0; // 提取为SOCKET号 if (param) { next_param = param; word = Sh_GetWord(next_param, &next_param); reg = __sh_atol(word); word = Sh_GetWord(next_param, &next_param); value = __sh_atol(word); word = Sh_GetWord(next_param, &next_param); if(word != NULL) { printf("\r\n参数错误\r\n"); return false; } } if (Lock_SempPend(semp_dm9000, 10000*mS) == true) { Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断 printf("\r\n写入DM9000A的【%4x】寄存器:%4x", reg, value); iow(reg, value); printf("\r\n"); Int_RestoreAsynLine(cn_int_line_enet); // 打开DM9000A的外部中断 Lock_SempPost(semp_dm9000); } return true; }
// ============================================================================= // 功能:将接收到的数据写入用户提供的缓冲区中,接收是阻塞方式,因此使用用户的缓冲区 // 参数:SPI,SPI控制块指针 // buf,数据指针 // len,数据长度,字节单位 // 返回:字节数 // ============================================================================= s32 SPI_PortWrite(struct tagSPI_CB *SPI,u8 *buf,u32 len) { u32 cpylen; if((len > 0) && (SPI->Frame.RecvLen > 0)) { cpylen = SPI->Frame.RecvLen >= len ?len:SPI->Frame.RecvLen; memcpy(SPI->Frame.RecvBuf,buf,cpylen); SPI->Frame.RecvBuf += cpylen; SPI->Frame.RecvLen -= cpylen; } //只有发送接收都完成的时候才能拉高片选 if(SPI->Frame.SendLen + SPI->Frame.RecvLen == 0) { if(SPI->BlockOption == true) { Lock_SempPost(SPI->SPI_BlockSemp); //阻塞发送时,释放阻塞信号量 } if(SPI->CurrentDev->AutoCs == true) { __SPI_AutoCsInactive(SPI,SPI->CurrentDev->Cs); } } return cpylen; }
// ============================================================================= // 功能:设置RTC设备RTC时间,单位微秒,该时间从1970年1月1日0:0:0到现在的时间差 // 参数:time, 时间值 // 返回:true,正常操作,否则出错 // ============================================================================= bool_t Rtc_SetTime(s64 time) { atom_low_t atom_bak; atom_bak = Int_LowAtomStart(); UpdateTime = time; Int_LowAtomEnd(atom_bak); Lock_SempPost(pRtcSemp); return true; }
//----Multiplex执行------------------------------------------------------------ //功能:当MultiplexSets中的对象状态发生变化,由相关模块调用本函数告知Multiplex // 模块。 //参数: ObjectHead,被操作的Object队列头指针 // Status,Object的当前状态 //返回: true=成功,false=失败。 //----------------------------------------------------------------------------- bool_t Multiplex_Set(struct tagMultiplexObjectCB *ObjectHead, u32 Status) { struct tagMultiplexObjectCB *Object; struct tagMultiplexSetsCB *Sets; u32 Sensing, Type; u32 OldPend; if (ObjectHead == NULL) return false; Lock_MutexPend(&MultiplexMutex, CN_TIMEOUT_FOREVER); Object = ObjectHead; while (Object != NULL) { OldPend = Object->PendingBit; Sets = Object->MySets; Sensing = Object->SensingBit & ~0x80000000; Type = Object->SensingBit & 0x80000000; Object->PendingBit = Status & Sensing; //更新PendingBit if (__ObjectIsActived(OldPend, Sensing, Type)) { //调用前,Object已触发 if (!__ObjectIsActived(Object->PendingBit, Sensing, Type)) { //调用Multiplex_Set导致对象变成未触发 //把Object从Sets->ActiveQ队列拿出,放到ObjectQ队列中 __ChangeList(&(Sets->ActiveQ), &(Sets->ObjectQ), Object); if (Sets->Actived != 0) Sets->Actived--; if (Sets->Actived == 0) Sets->SetsActived = false; } } else { //调用前,Object未触发 if (__ObjectIsActived(Object->PendingBit, Sensing, Type)) { //调用Multiplex_Set导致对象被触发 //把Object从Sets->ObjectQ队列拿出,放到ActiveQ队列中 __ChangeList(&(Sets->ObjectQ), &(Sets->ActiveQ), Object); if (Sets->Actived < Sets->ObjectSum) Sets->Actived++; //异步触发模式,须释放信号量 if ((Sets->Actived >= Sets->ActiveLevel) || (Sets->Actived >= Sets->ObjectSum)) { if (false == Sets->SetsActived) { Sets->SetsActived = true; Lock_SempPost(&Sets->Lock); } } } } Object = Object->NextSets; } Lock_MutexPost(&MultiplexMutex); return true; }
// ============================================================================= // 功能:片选拉高,若传输为阻塞方式,则由该函数释放总线信号量和拉高片选,否则,拉高总 // 线和释放信号量由底层驱动完成。因为非阻塞方式时,运行到该函数时,传输未必完成 // 参数:Dev,器件指针 // block_option,阻塞选项,为true时,表明最后一次传输为阻塞方式,否则为非阻塞 // 返回:true,成功;false,失败 // ============================================================================= bool_t SPI_CsInactive(struct tagSPI_Device *Dev) { struct tagSPI_CB *SPI; if(NULL == Dev) return false; SPI = (struct tagSPI_CB *)Rsc_GetParent(&Dev->DevNode); if(NULL == SPI) return false; if(Dev->AutoCs == false) //自动片选时,手动调用无效 { Lock_SempPost(SPI->SPI_BusSemp); SPI->pCsInActive(SPI->SpecificFlag,Dev->Cs); } else { ; } return true; }
//----添加对象到MultiplexSets-------------------------------------------------- //功能: MultiplexSets中添加一个对象。如果该Object的初始状态是已经触发,则加入到 // ActiveQ队列,否则加入ObjectQ队列。 //参数: Sets,被操作的MultiplexSets指针 // ObjectHead,被操作的Object队列头指针的指针,*ObjectHead=NULL表示该对象尚 // 未加入任何MultiplexSets,因此,*ObjectHead初始化值应该是NULL。Object // 允许加入多个MultiplexSets,每加入一个MultiplexSets,将增加一个 // struct tagMultiplexObjectCB *类型的结点,所有结点的NextSets指针连接 // 成一个单向链表,*ObjectHead指向该链表头。*ObjectHead再也不允许在外部 // 修改,否则结果不可预料。 // ObjectStatus,加入时的状态,31bit的位元组,bit31无效 // ObjectID,被Multiplex的对象的ID。 // SensingBit,对象敏感位标志,31个bit,设为1表示本对象对这个bit标志敏感 // bit31表示敏感类型,CN_SENSINGBIT_AND,或者CN_SENSINGBIT_OR //返回: true=成功,false=失败。 //----------------------------------------------------------------------------- bool_t Multiplex_AddObject(struct tagMultiplexSetsCB *Sets, struct tagMultiplexObjectCB **ObjectHead, u32 ObjectStatus, ptu32_t ObjectID, u32 SensingBit) { struct tagMultiplexObjectCB *temp; struct tagMultiplexObjectCB **TargetQ; bool_t repeat = false; u32 ActivedInc = 0; if (Sets == NULL) return false; ObjectStatus &= ~0x80000000; //下面检查新加入的Object是否已经触发,以决定加入到MultiplexSets的哪个队列中 if (__ObjectIsActived(ObjectStatus, SensingBit & ~0x80000000, SensingBit & 0x80000000)) { TargetQ = &Sets->ActiveQ; ActivedInc = 1; } else TargetQ = &Sets->ObjectQ; Lock_MutexPend(&MultiplexMutex, CN_TIMEOUT_FOREVER); temp = *ObjectHead; //循环检查一个Object是否重复加入同一个MultiplexSets //如果ObjectHead=NULL,检查结果是不重复,后续处理能够正确运行。 while (temp != NULL) { if (temp->MySets != Sets) temp = temp->NextSets; else { repeat = true; break; } } Lock_MutexPost(&MultiplexMutex); if (repeat == false) { temp = Mb_Malloc(g_ptMultiplexObjectPool, CN_TIMEOUT_FOREVER); if (temp != NULL) { Sets->ObjectSum++; temp->SensingBit = SensingBit; temp->PendingBit = ObjectStatus; temp->ObjectID = ObjectID; Lock_MutexPend(&MultiplexMutex, CN_TIMEOUT_FOREVER); temp->MySets = Sets; //设定对象所属MultiplexSets //同一个MultiplexSets包含多个对象,NextObject把这些对象链接起来。 if (*TargetQ == NULL) { *TargetQ = temp; temp->NextObject = temp; temp->PreObject = temp; } else { //新加入MultiplexSets的对象插入队列头部 temp->PreObject = (*TargetQ)->PreObject; temp->NextObject = *TargetQ; (*TargetQ)->PreObject->NextObject = temp; (*TargetQ)->PreObject = temp; (*TargetQ) = temp; } //同一个对象被多个MultiplexSets包含,用NextSets链接。 //NextSets是单向链表,新对象插入链表头部 temp->NextSets = *ObjectHead; *ObjectHead = temp; Lock_MutexPost(&MultiplexMutex); if (ActivedInc == 1) { Sets->Actived += ActivedInc; if ((Sets->Actived >= Sets->ActiveLevel) || (Sets->Actived >= Sets->ObjectSum)) { if (false == Sets->SetsActived) { Sets->SetsActived = true; Lock_SempPost(&Sets->Lock); } } } } else return false; } else { //重复加入,无须做任何处理 } return true; }
//----从DM9000A中读出所有数据---------------------------------------------------- //功能:把DM9000A中的所有数据都读取出来,这些数据包会组织在lst链表中。 //参数:lst,数据包的接收链表头指针 //返回:数据包的接收链表头指针(可能与输入的lst不同) //----------------------------------------------------------------------------- struct enet_rcv_packet *__hw_read_in(struct enet_rcv_packet *lst) { u32 tmp; u32 len; u32 totlen = 0; static u32 times = 0; struct enet_rcv_packet *nlst = NULL; // 请求DM9000A硬件操作的信号量,等待5S秒如果没有发出去,则返回 if (Lock_SempPend(semp_dm9000, 0) == true) { // 接收过程中如果有中断发生,中断响应函数读 写DM9000的其他寄存器会打断接收过程。 Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断 ior(DM9000A_MRCMDX); // dummy read tmp = (u8)DATAR16(); if (tmp == 0x01) // 第一个字节读出为01h { switch (ehi.io) { case ENUM_DM9000A_IO_16BIT: // 16-bit while (tmp == 0x01) { len = dump_data16(lst, &nlst); if (len == -1) { dm9000a_reset_to_new(); totlen = 0; } else { totlen += len; // 试读下一帧数据,若为01h则继续读数,若为0则表示没有有效数据 ADDRW8(DM9000A_MRCMDX); tmp = (u8)DATAR16(); lst = nlst; } } __hw_ctrl(enum_enet_hw_ctrl_clear_rx_int); // 清除接收中断 break; case ENUM_DM9000A_IO_32BIT: // 32-bit break; case ENUM_DM9000A_IO_8BIT: // 8-bit break; default: break; } } else if (tmp != 0) { times++; if (times > 5) { debug_dm9000a_read_reg(NULL); } dm9000a_reset_to_new(); totlen = 0; if (times > 5) { debug_dm9000a_read_reg(NULL); times = 0; } } Int_RestoreAsynLine(cn_int_line_enet); // 打开DM9000A的外部中断 Lock_SempPost(semp_dm9000); } return nlst; }
bool_t debug_dm9000a_read_reg(char *param) { char *word, *next_param; int i; u32 reg = 0xFFFF; // 提取为SOCKET号 if (param) { next_param = param; word = Sh_GetWord(next_param, &next_param); reg = __sh_atol(word); word = Sh_GetWord(next_param, &next_param); if(word != NULL) { printf("\r\n参数错误\r\n"); return false; } } if (Lock_SempPend(semp_dm9000, 10000*mS) == true) { Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断 if (reg != 0xFFFF) { printf("\r\n读取DM9000A的【%4x】寄存器:", reg); printf("\r\n %4x:%4x", reg, ior(reg)); } else { printf("\r\n读取DM9000A的【所有】寄存器:"); printf("\r\n"); for (i=0; i<=0x1f; i++) { printf("\r\n %4x:%4x", i, ior(i)); } printf("\r\n"); for (i=0x22; i<=0x25; i++) { printf("\r\n %4x:%4x", i, ior(i)); } printf("\r\n"); for (i=0x28; i<=0x34; i++) { printf("\r\n %4x:%4x", i, ior(i)); } printf("\r\n"); i = 0x38; printf("\r\n %4x:%4x", i, ior(i)); i = 0x39; printf("\r\n %4x:%4x", i, ior(i)); printf("\r\n"); i = 0x50; printf("\r\n %4x:%4x", i, ior(i)); i = 0x51; printf("\r\n %4x:%4x", i, ior(i)); printf("\r\n"); i = 0xF0; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF1; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF2; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF4; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF5; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF6; printf("\r\n %4x:%4x", i, ior(i)); i = 0xF8; printf("\r\n %4x:%4x", i, ior(i)); printf("\r\n"); for (i=0xFA; i<=0xFF; i++) { printf("\r\n %4x:%4x", i, ior(i)); } } printf("\r\n"); Int_RestoreAsynLine(cn_int_line_enet); // 打开DM9000A的外部中断 Lock_SempPost(semp_dm9000); } return true; }
// ============================================================================= // 功能:IIC接收与发送中断服务函数。该函数实现的功能如下: // 1.每发送与接收一个或若干字节发生一次中断; // 2.若有多个中断使用同一个中断号,则需根据具体情况区分使用的是哪个中断; // 3.清中断标志,并判断ACK信号,每读写字节,计数器都需相应修改; // 4.接收达到倒数第一个字节时,需配置不发送ACK信号; // 5.接收或发送完成时,需post信号量IntParam->pDrvPostSemp; // 6.接收或发送完成时,需产生停止时序。 // 参数:i2c_int_line,中断号,本函数没用到 // 返回:无意义 // ============================================================================= static u32 __IIC_ISR(ufast_t i2c_int_line) { static struct tagIIC_IntParamSet *IntParam; static struct tagIIC_CB *ICB; tagI2CReg *reg; u8 ch; u32 IicErrorNo; u32 irptl_temp=*rTWIIRPTL;//read IRPTL reg = (tagI2CReg*)CN_IIC_REGISTER_BADDR0; ICB=&s_IIC0_CB; IntParam=&IntParamset0; //MASTER TX\RX COMPLETE if( (irptl_temp & TWITXINT) != 0 ) //发送中断 { if(!(CHKBIT(reg->rTWIMSTAT, TWIANAK)|CHKBIT(reg->rTWIMSTAT, TWIDNAK))) { //从泛设备读一个字节的数据,并发送 if(IIC_PortRead(ICB,&ch,1) > 0) { *rTXTWI8 = ch; IntParam->TransCount++; } else if(IntParam->TransCount == IntParam->TransTotalLen) { //in Master TX Mode , we need to STOP TWI by ourself Lock_SempPost(IntParam->pDrvPostSemp); __IIC_GenerateStop(reg); } else { IicErrorNo = CN_IIC_NO_ACK_ERR;//调用错处处理API函数 IIC_ErrPop(ICB,IicErrorNo); } } else //TX no ACK { IicErrorNo = CN_IIC_NO_ACK_ERR;//调用错处处理API函数 IIC_ErrPop(ICB,IicErrorNo); return 1; } //clear IIC interrupt irptl_temp = TWITXINT; *rTWIIRPTL = irptl_temp; } else if( (irptl_temp & TWIRXINT) != 0 ) //接收中断 { if(!(CHKBIT(reg->rTWIMSTAT, TWIANAK)|CHKBIT(reg->rTWIMSTAT, TWIDNAK))) { ch = *rRXTWI8; IIC_PortWrite(ICB,&ch,1); IntParam->TransCount ++; if(IntParam->TransCount == IntParam->TransTotalLen) { __IIC_GenerateStop(reg); Lock_SempPost(IntParam->pDrvPostSemp);//释放总线信号量 } } else //RX no ACK { } //clear IIC interrupt irptl_temp = TWIRXINT; *rTWIIRPTL = irptl_temp; } else //TWIMERR { } irptl_temp==*rTWIIRPTL; //update TWI_IRPTL //MASTER TRANS COMPLETE if( (irptl_temp & TWIMCOM) != 0 ) { _IIC_GenerateDisable(reg); Lock_SempPost(ICB->iic_bus_semp);//释放总线信号量 //clear STOP CLRBIT(reg->rTWIMCTL, TWISTOP); //clear IIC interrupt irptl_temp |= TWIMCOM; *rTWIIRPTL = irptl_temp; } return 0; }
bool_t __SPI_AutoCsInactive(struct tagSPI_CB *SPI,u8 CS) { Lock_SempPost(SPI->SPI_BusSemp); SPI->pCsInActive(SPI->SpecificFlag,CS); return true; }
// ============================================================================= // 功能: IIC接收与发送中断服务函数。该函数实现的功能如下: // 1.每发送与接收一个或若干字节发生一次中断; // 2.若有多个中断使用同一个中断号,则需根据具体情况区分使用的是哪个中断; // 3.清中断标志,并判断ACK信号,每读写字节,计数器都需相应修改; // 4.接收达到倒数第一个字节时,需配置不发送ACK信号; // 5.接收或发送完成时,需post信号量IntParam->pDrvPostSemp; // 6.接收或发送完成时,需产生停止时序。 // 参数:i2c_int_line,中断号,本函数没用到 // 返回:true falst // ============================================================================= static u32 __IIC_ISR(ufast_t i2c_int_line) { static struct IIC_CB *ICB; static struct IIC_IntParamSet *IntParam; tagI2CReg *reg; u8 ch; u32 IicErrorNo; switch (i2c_int_line) { case CN_INT_LINE_I2C1_EV: reg = (tagI2CReg*)CN_IIC1_BASE; ICB = &s_IIC1_CB; IntParam = &IntParamset0; break; case CN_INT_LINE_I2C2_EV: reg = (tagI2CReg*)CN_IIC2_BASE; ICB = &s_IIC2_CB; IntParam = &IntParamset1; break; default: return false; } if(reg->SR1 & I2C_SR1_BTF_MASK) //已经启动传输 { if(reg->SR1 & I2C_SR1_TxE_MASK) //发送中断 { if(!(reg->SR1 & I2C_SR1_RxNE_MASK)) { //从发送缓冲区读一个字节的数据,并发送 if(IIC_PortRead(ICB,&ch,1) > 0) { reg->DR = ch; IntParam->TransCount ++;; } else if(IntParam->TransCount == IntParam->TransTotalLen) { Lock_SempPost(IntParam->pDrvPostSemp); __IIC_IntDisable(reg);//关中断 __IIC_GenerateStop(reg); } } else //未收到ACK信号 { IicErrorNo = CN_IIC_POP_NO_ACK_ERR;//调用错处处理API函数 IIC_ErrPop(ICB,IicErrorNo); return 1; } } else //接收中断 { while((IntParam->TransCount < IntParam->TransTotalLen)) { // 最后一个字节master不发ACK,表示读操作终止 if(IntParam->TransCount == IntParam->TransTotalLen - 1) { reg->CR1 &=~ I2C_CR1_ACK_MASK; } while (!(reg->SR1 & I2C_SR1_RxNE_MASK));//等待接收完成 ch = reg->DR; //写数据 IIC_PortWrite(ICB,&ch,1); IntParam->TransCount ++; } if((IntParam->TransCount == IntParam->TransTotalLen) && (reg->SR1 & I2C_SR1_BTF_MASK)) { __IIC_GenerateStop(reg); __IIC_IntDisable(reg);//关中断 Lock_SempPost(IntParam->pDrvPostSemp);//释放总线信号量 } } } else//未启动通信 { if(reg->SR1 & I2C_SR1_ARLO_MASK)//仲裁丢失中断 { reg->SR1 &= ~I2C_SR1_ARLO_MASK;//清除仲裁丢失中断标志位 IicErrorNo = CN_IIC_POP_MAL_LOST_ERR; IIC_ErrPop(ICB,IicErrorNo); } } return true; }