예제 #1
0
파일: dm9000a.c 프로젝트: Mars-Wu/djyos
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;
}
예제 #2
0
파일: multiplex.c 프로젝트: Mars-Wu/djyos
//----等待MultiplexSets-----------------------------------------------------------
//功能: 设置好MultiplexSets后,应用程序调用本函数等待MultiplexSets被触发,根据
//      Type值,等待方式分轮询和异步触发两种。
//参数: Sets,被操作的MultiplexSets指针
//      Status,返回对象当前状态的指针,如果应用程序不关心其状态,可以给NULL。
//      Timeout,阻塞等待的最长时间,uS。
//返回:如果MultiplexSets被触发,则返回MultiplexSets中一个被触发对象的ObjectID,
//      否则返回-1.
//-----------------------------------------------------------------------------
ptu32_t Multiplex_Wait(struct tagMultiplexSetsCB *Sets, u32 *Status, u32 Timeout)
{
    struct tagMultiplexObjectCB *Object;
    ptu32_t result;
    if (Sets == NULL)
        return -1;
    if ((Sets->ActiveQ == NULL) && (Sets->ObjectQ == NULL))
        return -1;

    //判断或等待直到MultiplexSets被触发。
    if (!__SetsIsActived(Sets)) {
        Lock_SempPend(&Sets->Lock, Timeout);
    }

    if (Sets->ActiveQ != NULL) {   //阻塞等待结束后,SetsActived非空即视为触发。
        Sets->SetsActived = true;
        Object = Sets->ActiveQ;
        result = Object->ObjectID;
        if (Status != NULL)
            *Status = Object->PendingBit;
    } else
        result = -1;

    return result;
}
예제 #3
0
파일: spibus.c 프로젝트: Mars-Wu/djyos
// =============================================================================
// 功能:片选拉低,该函数运行必须获得总线信号量,即SPI_BusSemp,然后根据CS是否具有
//       自己的配置寄存器标志,判断是否需要配置寄存器。若csctrl标志为false,则每次CS
//       使能时,都需要配置寄存器
// 参数:Dev,器件指针
//       timeout,请求总线信号量超时时间,us
// 返回:true,成功;false,失败
// =============================================================================
bool_t SPI_CsActive(struct tagSPI_Device *Dev,u32 timeout)
{
    struct tagSPI_CB *SPI;
    tagSpiConfig spicfg;
    if(NULL == Dev)
        return false;

    SPI = (struct tagSPI_CB *)Rsc_GetParent(&Dev->DevNode);
    if(NULL == SPI)
        return false;

    if(Dev->AutoCs == false)                                //手动调用才有效
    {
        if(false == Lock_SempPend(SPI->SPI_BusSemp,timeout))    //需要等待总线空闲
            return false;

        //如果没有独立的CS参数配置寄存器,则每次操作都需要配置SPI参数配置寄存器,
        //因为多个CS共用同一套参数配置寄存器
        if((SPI->MultiCsReg == false) && (SPI->CurrentDev != Dev))
        {
            spicfg.CharLen = Dev->CharLen;
            spicfg.Mode    = Dev->Mode;
            spicfg.Freq    = Dev->Freq;
            SPI->pBusCtrl(SPI->SpecificFlag,CN_SPI_CS_CONFIG,
                            (ptu32_t)Dev->Cs,(ptu32_t)&spicfg);
        }
        //如果每个CS都有独立的配置寄存器,则无需每次调用都配置,用户可通过调用pBusCtrl
        //控制CS相关的寄存器配置
        SPI->CurrentDev = Dev;
        SPI->pCsActive(SPI->SpecificFlag,Dev->Cs);
    }
    return true;
}
예제 #4
0
파일: cpu_peri_rtc.c 프로젝트: djyos/djyos
// =============================================================================
// 功能:RTC时间更新任务,由于Atmel芯片的RTC更新时间最长可能达到1秒因此,因此专门用一个低
//      优先级的任务作为更新RTC任务,以防占用其他线程的CPU时间
// 参数:无
// 返回:无
// =============================================================================
ptu32_t Rtc_UpdateTime(void)
{

    while(1)
    {
        if(Lock_SempPend(pRtcSemp,CN_TIMEOUT_FOREVER))
        {
            __Rtc_SetTime(UpdateTime);
        }
    }
    return 0;
}
예제 #5
0
파일: dm9000a.c 프로젝트: Mars-Wu/djyos
//----发送一帧数据---------------------------------------------------------------
//功能:发送一个数据包到以太网上
//参数:upsec,上层数据包(一个链表结构)的头指针
//返回:正常时为发送的字节数;错误时为-1
//-----------------------------------------------------------------------------
s32 __hw_write_out(struct enet_send_section *upsec)
{
    u16 dat;
    u32 i, len, times, totlen;
    struct enet_send_section* pt_ssec;

    // 请求DM9000A硬件操作的信号量,如果没有发出去,则返回
    if (Lock_SempPend(semp_dm9000, 0) == true)
    {
        Int_SaveAsynLine(cn_int_line_enet); // 关闭DM9000A的外部中断
        totlen = 0;
        pt_ssec = upsec;

        ADDRW8(DM9000A_MWCMD);
        if (ehi.io == 0)    // 16-bit
        {
            u8* pt_data;    // 定义字节为8位的,下面进行强制转换
            while (pt_ssec != NULL)
            {
                pt_data = (u8*)pt_ssec->data;
                len = pt_ssec->count;
                totlen += len;
                if ((ptu32_t)pt_data & 0x01)    //判断指针是否双字节对齐
                {
                    for (i=0; i<len; i+=2)
                    {
                        dat = pt_data[i] + (pt_data[i+1]<<8);
                        DATAW16(dat);
                    }
                }
                else
                {
                    times = (len+1)/2;
                    for (i=0; i<times; i++)
                        DATAW16(((u16*)pt_data)[i]);
                }

                pt_ssec = pt_ssec->next_data_ssection;
            }
        }
        else if (ehi.io == 1) // 32-bit
        {
        }
        else if (ehi.io == 2) // 8-bit
        {
        }

        if (totlen > 0)
        {
            iow(DM9000A_TXPLH, (totlen>>8) & 0xff);
            iow(DM9000A_TXPLL, totlen & 0xff);
            iow(DM9000A_NSR, 0x2c);     // 清除状态寄存器
            iow(DM9000A_TCR, ior(DM9000A_TCR) | 0x01);      //发送数据到以太网上

            // 等待发送完成
            // NSR中TX1END及TX2END(发送完成)
            // ISR中PTM(发送完成)
            times = 100;    // 相当等待于3S
            while (!(ior(DM9000A_NSR) & 0x0C) || !(ior(DM9000A_ISR) & 0x02))
            {
                if (times == 0)
                {
                    dm9000a_reset_to_new();
                    break ;
                }
                times--;
                Djy_DelayUs(10);
            }
        }
예제 #6
0
파일: dm9000a.c 프로젝트: Mars-Wu/djyos
//----从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;
}
예제 #7
0
파일: dm9000a.c 프로젝트: Mars-Wu/djyos
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;
}
예제 #8
0
// =============================================================================
// 功能: 启动读时序,启动读时序的过程为:器件地址(写)、存储地址(写)、器件地址(读)
//       当器件地址(读)完成时,需打开中断,重新配置寄存器为接收模式,之后将会发生
//       接收数据中断,在中断中将接收到的数据调用IIC_PortWrite写入缓冲,接收到len字
//       节数的数据后,释放信号量iic_semp
// 参数: specific_flag,个性标记,本模块内即IIC寄存器基址
//      dev_addr,器件地址的前7比特,已将内部地址所占的bit位更新,该函数需将该地址左
//               移一位增加增加最后一位读/写比特;
//      mem_addr,存储器内部地址,即发送到总线上的地址,该地址未包含放在器件地址上的
//               比特位;
//      maddr_len,存储器内部地址的长度,字节单位,未包含在器件地址里面的比特位;
//      len,接收的数据总量,接收数据的倒数第一字节,即count-1,停止产生ACK信号,当接
//          收的字节数为count时,产生停止时序,并释放信号量iic_semp;
//      iic_semp,读完成时,驱动需释放的信号量(缓冲区信号量)
// 返回: TRUE,启动读时序成功,FALSE失败
// =============================================================================
static bool_t __IIC_GenerateReadStart(ptu32_t  specific_flag,
                                       u8 dev_addr,
                                       u32 mem_addr,
                                       u8 maddr_len,
                                       u32 length,
                                       struct tagSemaphoreLCB *iic_semp)
{
     volatile tagI2CReg *reg;
      u8 mem_addr_buf[4];
      u32 Recv_Times=0;
      u32 Recv_Index=0;
      u32 i=0;
      u32 Single_Length_Max=0;
      Single_Length_Max=0xFE-maddr_len;
      Recv_Times=(u32)(length/Single_Length_Max);
      Recv_Index=Recv_Times;
      if (length % Single_Length_Max!=0)
      {
        Recv_Times++;
      }

      for(i=0;i<Recv_Index;i++)
  {

      if(specific_flag == CN_IIC_REGISTER_BADDR0)
    {

        if(i!=Recv_Index-1)
        {
        IntParamset0.TransTotalLen = Single_Length_Max;
        IntParamset0.TransCount = 0;
        IntParamset0.pDrvPostSemp = iic_semp;           //iic_bus_semp
        mem_addr=mem_addr+i*Single_Length_Max;
        }
        else
        {
        IntParamset0.TransTotalLen = length-(Recv_Index-1)*Single_Length_Max;
        IntParamset0.TransCount = 0;
        IntParamset0.pDrvPostSemp = iic_semp;           //iic_bus_semp

        }

    }
    else
    {
        return false;
    }


    fill_little_32bit(mem_addr_buf,0,mem_addr);
    reg=(tagI2CReg *)specific_flag;
    _IIC_IntDisable(reg);
    SETBIT(reg->rTWIMITR, TWIEN);                     //generate START

    //step1:首先发送start信号
    SETBIT(reg->rTWIMCTL,TWIMEN);                //MASTER MODE

     //step2:发送器件地址,最低位置0.


     if(__TWI_WaitForTwiFree()>=0)
     {
        //reg->rTWIMADDR = TWI_ADDR_GET(dev_addr);              //device addr
        reg->rTWIMADDR =dev_addr;
        reg->rTWIMCTL = 0xFF<<6;                //clean MCTL reg
     //step3:判断是否收到ACK.
         if(__TWI_WaitForAck(0)==0)
        {
      //step4:若收到从机发的ACK,则开始发存储地址.
            if(__TWI_WriteAddr(reg, mem_addr_buf,maddr_len)==0);
            {
      //step5:若成功发送完存储地址,接着发送一个Repeat Start信号
                SETBIT(reg->rTWIMCTL,TWIRSTART);
      //step6:发送器件地址,最低位置1.
                SETBIT(reg->rTWIMCTL,TWIMDIR);
                reg->rTWIMADDR = TWI_ADDR_GET(dev_addr);
      //step7:开中断
                _IIC_IntEnable(reg);

                if(i!=Recv_Index-1)
                {
                   Lock_SempPend(iic_semp,CN_TIMEOUT_FOREVER);
                }
                else
                {
                   return true;
                }

            }
       }
     }
  }
     return false;
}
예제 #9
0
파일: spibus.c 프로젝트: Mars-Wu/djyos
// =============================================================================
// 功能:数据传送函数,完成数据的发送和接收。该函数完成的功能如下:
//       1.若器件驱动为了避免组包的麻烦,可先发命令再发送数据,分多次调用,多次调用前
//         后被CSActive和CsInactive函数包裹;
//       2.根据Dev查找所属SPI总线;
//       3.若缓冲区大于发送字节数,则直接将数据填入缓冲区;
//       4.若为阻塞发送,则等待总线信号量,若为非阻塞,则等待buf信号量;
//       5.发生超时或错误时,拉高CS并释放信号量
// 参数:Dev,器件指针
//       spidata,SPI数据结构体
//       block_option,阻塞选项,为true时,表明最后一次传输为阻塞方式,否则为非阻塞
//       timeout,超时参数,us
// 返回:返回发送状态,超时或错误或无错误
// =============================================================================
s32 SPI_Transfer(struct tagSPI_Device *Dev,struct tagSPI_DataFrame *spidata,
                u8 block_option,u32 timeout)
{
    struct tagSPI_CB *SPI;
//  struct semaphore_LCB *spi_semp;
    s32 result ;
    u32 written=0;
    u32 base_time = 0,rel_timeout = timeout;

    if(NULL == Dev)
        return CN_SPI_EXIT_PARAM_ERR;

    SPI = (struct tagSPI_CB *)Rsc_GetParent(&Dev->DevNode);//查找该器件属于哪条总线
    if(NULL == SPI)
        return CN_SPI_EXIT_PARAM_ERR;

    base_time = (u32)DjyGetTime();
    //若配置需自动片选,则本函数内部需拉低片选
    if(Dev->AutoCs == true)
    {
        if(false == Lock_SempPend(SPI->SPI_BusSemp,timeout))    //需要等待总线空闲
        {
            result = CN_SPI_EXIT_TIMEOUT;
            goto exit_from_bus_timeout;
        }
        __SPI_AutoCsActive(SPI,Dev);
    }

    Lock_SempPend(SPI->SPI_BlockSemp,0);                        //相当于重置信号量

    //禁止调试或未登记pTransferTxRx,使用轮询方式通信
    if((Djy_QuerySch() == false) || (SPI->pTransferTxRx == NULL)
            || (SPI->Flag & CN_SPI_FLAG_POLL))
    {
        if(SPI->pTransferPoll != NULL)
        {
            SPI->pTransferPoll(SPI->SpecificFlag,spidata->SendBuf,spidata->SendLen,
                spidata->RecvBuf,spidata->RecvLen,spidata->RecvOff);

            if(Dev->AutoCs == true)
                __SPI_AutoCsInactive(SPI,Dev->Cs);
            result = CN_SPI_EXIT_NOERR;
        }
        goto exit_from_no_err;
    }

    if(spidata->RecvLen)
        block_option = true;                            //接收数据自动转为阻塞
    SPI->SPI_Buf.Offset = 0;                            //发送前先清空缓冲区
    SPI->Frame = *spidata;
    SPI->BlockOption = block_option;

    //如果非阻塞方式,且缓冲区够大,则直接写入缓冲区
    //若不是,则先发送调用者提供的缓冲区,直到剩余字节数能够填充到缓冲区
    if((!block_option) && (spidata->SendLen <= SPI->SPI_Buf.MaxLen))
    {
        memcpy(SPI->SPI_Buf.pBuf,spidata->SendBuf,spidata->SendLen);
        written = spidata->SendLen;
    }

    //调用启动时序的回调函数
    if(true == SPI->pTransferTxRx(SPI->SpecificFlag,
                                spidata->SendLen,
                                spidata->RecvLen,
                                spidata->RecvOff
                                ))
    {
        rel_timeout = (u32)DjyGetTime();
        if(rel_timeout - base_time < timeout)
            rel_timeout = timeout - (rel_timeout - base_time);
        else
        {
            result = CN_SPI_EXIT_TIMEOUT;
            goto exit_from_timeout;
        }

        //需要等待的情况:1.阻塞发送;2.数据未全部填到缓冲区
        if((true == block_option) || (written < spidata->SendLen))
        {
            //等待中断函数释放信号量
            if(!Lock_SempPend(SPI->SPI_BlockSemp,rel_timeout))
            {
                result = CN_SPI_EXIT_TIMEOUT;
                goto exit_from_timeout;
            }
        }

        result = CN_SPI_EXIT_NOERR;
        goto exit_from_no_err;
    }else
    {
        result = CN_SPI_EXIT_UNKNOW_ERR;
        goto exit_from_timeout;
    }

exit_from_timeout:
    if(Dev->AutoCs == true)                     //自动片选时,返回前需拉低片选
    {
        __SPI_AutoCsInactive(SPI,Dev->Cs);
    }
exit_from_bus_timeout:
exit_from_no_err:
    return result;
}