打印
[i.MX]

imx6q ECSPI2从模式通过中断接受数据异常

[复制链接]
929|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hwx628|  楼主 | 2019-1-17 14:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
第一次是还是进中断是Rxdata_reg收到是0x00000001;从第二次之后收到的都是0xFFFFFFFF;来源是另外一块MCU,每100ms发我这边32bytes的数据,一次128bit,分两次发给我,每次进中断都正常。时钟是5Mhz。目前只用了ECSPI2来接受东西,每次中断都能进去,

有大佬帮我看看么,困住很久了,代码如下
#define ECSPI_FIFO_SIZE 64
//#define DEBUG
#define SPI_RETRY_TIMES 2
#define BURST_L         8
//master device ECSPI1 for test
uint8_t  tx_buf_ecspi1[ECSPI_FIFO_SIZE*4];
uint8_t  rx_buf_ecspi1[ECSPI_FIFO_SIZE*4];
//slave device ECSPI2 for test
uint8_t  tx_buf_ecspi2[ECSPI_FIFO_SIZE*4];
uint8_t  rx_buf_ecspi2[ECSPI_FIFO_SIZE*4];
//ECSPI device configuration @HWX
param_ecspi_t param[2] = {{1,1,1,0,0,12,0,0},//sschanel=1,master,ECSPI1,5MHz
{0,0,1,1,1,12,0,0}};//sschanel=1,slave,ECSPI2,non-single burst,5MHz

static void ecspi_start_transfer(unsigned instance, uint16_t brs_bts);
static int ecspi_xfer_slv(unsigned instance, const uint8_t * tx_buf, uint8_t * rx_buf, int bytes);
static int ecspi_xfer_mst(unsigned instance, const uint8_t * tx_buf, uint8_t * rx_buf, int bytes);

/*///////////////////////////////////////////////////////////////////////////////
// Code
///////////////////////////////////////////////////////////////////////////////*/

static void ecspi_start_transfer(unsigned instance, uint16_t brs_bts)
{
    // Set burst length
    HW_ECSPI_CONREG(instance).B.BURST_LENGTH = brs_bts - 1;

    // Clear status
    HW_ECSPI_STATREG_WR(instance, BM_ECSPI_STATREG_RO | BM_ECSPI_STATREG_TC);
}

static int ecspi_xfer_slv(unsigned instance, const uint8_t * tx_buf, uint8_t * rx_buf, int bytes)
{

    // new added by @HWX
    /* Configure ECSPI.CONREG   */
    /* Configure ECSPI.CONFIGREG   */
    /* Fill TXFIFO*/
    /* Wait for RXFIFO Interrupt(Ready or Data Request or Full) */
    /* Read Data from RXFIFO*/
    uint32_t val;
    uint32_t idx;

      val = 0;
//            return ERROR_GENERIC;
//        }

    // Read from Rx FIFO

    for (idx = 0; bytes > 0; bytes -= 4, idx += 4)
    {
        val = HW_ECSPI_RXDATA_RD(instance);
        if (rx_buf)
        {
            switch (bytes)
            {
                default:
                    rx_buf[idx + 3] = val >> 24;
//                    rx_buf[idx + 2] = (val >> 16) & 0xFF;
//                    rx_buf[idx + 1] = (val >> 8) & 0xFF;
//                    rx_buf[idx] = val & 0xFF;
                    break;
                case 3:
                    rx_buf[idx + 2] = (val >> 16) & 0xFF;
//                    rx_buf[idx + 1] = (val >> 8) & 0xFF;
//                    rx_buf[idx] = val & 0xFF;
                    break;
                case 2:
                    rx_buf[idx + 1] = (val >> 8) & 0xFF;
//                    rx_buf[idx] = val & 0xFF;
                    break;
                case 1:
                    rx_buf[idx] = val & 0xFF;
                    break;
            }
        }
    }

//#ifdef DEBUG
//            printf("ecspi_xfer_slave: Receive data 0x%x %x %x %x,",rx_buf[0],rx_buf[1],rx_buf[2],rx_buf[3]);
//#endif

    // Clear status,write 1 to clear it
//    HW_ECSPI_STATREG_WR(instance, BM_ECSPI_STATREG_TC);

    return SUCCESS;


}

//! [url=home.php?mod=space&uid=247401]@brief[/url] Perform a SPI master transfer.
//!
//! @param instance ECSPI module instance number starting at 1.
//! @param tx_buf
//! @param rx_buf
//! @param bytes Number of bytes to transfer.
//!
//! [url=home.php?mod=space&uid=2539868]@Todo[/url] Use interrupts to get notification of transfer completion instead of
//!     polling the ECSPI STATREG and pausing 500 碌s.
static int ecspi_xfer_mst(unsigned instance, const uint8_t * tx_buf, uint8_t * rx_buf, int bytes)
{
    uint32_t val;
    uint32_t idx;
//
//    // Start burst
//    HW_ECSPI_CONREG_SET(instance, BM_ECSPI_CONREG_SMC);
//
//    // Write to Tx FIFO
//    val = 0;
//
//    for (idx = 0; idx < bytes; idx += 4)
//    {
//        // Only read from the buffer if it is not NULL. If a tx_buf is not provided,
//        // then transfer 0 bytes.
//        if (tx_buf)
//        {
//            val = tx_buf[idx] + (tx_buf[idx + 1] << 8) + (tx_buf[idx + 2] << 16) + (tx_buf[idx + 3] << 24);
//        }
//
//        HW_ECSPI_TXDATA_WR(instance, val);
//    }
//    // write 1 to start burst immediately
////     HW_ECSPI_CONREG_SET(instance, BM_ECSPI_CONREG_XCH);
//    //poll the value of XCH BIT,if XCH = 0, transfer process is over already.
////     while(BG_ECSPI_CONREG_XCH(HW_ECSPI_CONREG_ADDR(instance)) == 0)
////     {
////
////     }
//    // Wait for transfer complete
//    val = SPI_RETRY_TIMES;
//    while (!HW_ECSPI_STATREG(instance).B.TC)
//    {
//        val--;
//        if (val == 0)
//        {
////#ifdef DEBUG
////            printf("ecspi_xfer: Transfer timeout.\n");
////#endif
//            return ERROR_GENERIC;
//        }
//
////        hal_delay_us(500);  //delay module not added now @HWX
//    }


//    if(HW_ECSPI_STATREG(instance).B.RR)
//    {
        for (idx = 0; bytes > 0; bytes -= 4, idx += 4)
        {
            val = HW_ECSPI_RXDATA_RD(instance);
            if (rx_buf)
            {
                switch (bytes)
                {
                    default:
                        rx_buf[idx + 3] = val >> 24;
//                        rx_buf[idx + 2] = (val >> 16) & 0xFF;
//                        rx_buf[idx + 1] = (val >> 8) & 0xFF;
//                        rx_buf[idx] = val & 0xFF;
                        break;
                    case 3:
                        rx_buf[idx + 2] = (val >> 16) & 0xFF;
//                        rx_buf[idx + 1] = (val >> 8) & 0xFF;
//                        rx_buf[idx] = val & 0xFF;
                        break;
                    case 2:
                        rx_buf[idx + 1] = (val >> 8) & 0xFF;
//                        rx_buf[idx] = val & 0xFF;
                        break;
                    case 1:
                        rx_buf[idx] = val & 0xFF;
                        break;
                }
            }
        }
//    }
    // Clear status
    HW_ECSPI_STATREG_WR(instance, BM_ECSPI_STATREG_TC);

    return SUCCESS;
}

int ecspi_configure(dev_ecspi_e instance, const param_ecspi_t * param)
{
    // Reset eCSPI controller
    HW_ECSPI_CONREG(instance).B.EN = 1;

    // Setup chip select
    HW_ECSPI_CONREG(instance).B.CHANNEL_SELECT = param->channel;

    // Setup mode
    uint32_t channelMask = 1 << param->channel;
    uint32_t value = HW_ECSPI_CONREG(instance).B.CHANNEL_MODE;
    BW_ECSPI_CONREG_CHANNEL_MODE(instance, param->mode ? (value | channelMask) : (value & ~channelMask));

    // Setup pre & post clock divider
    HW_ECSPI_CONREG(instance).B.PRE_DIVIDER = (param->pre_div == 0) ? 0 : (param->pre_div - 1);
    HW_ECSPI_CONREG(instance).B.POST_DIVIDER = param->post_div;

    // Enable eCSPI
    HW_ECSPI_CONREG(instance).B.EN = 1;

    // Setup SCLK_PHA, SCLK_POL, SS_POL
    value = HW_ECSPI_CONFIGREG(instance).B.SCLK_PHA;
    HW_ECSPI_CONFIGREG(instance).B.SCLK_PHA = param->sclk_pha ? (value | channelMask) : (value & ~channelMask);

    value = HW_ECSPI_CONFIGREG(instance).B.SCLK_POL;
    HW_ECSPI_CONFIGREG(instance).B.SCLK_POL = param->sclk_pol ? (value | channelMask) : (value & ~channelMask);

    value = HW_ECSPI_CONFIGREG(instance).B.SS_POL;
    HW_ECSPI_CONFIGREG(instance).B.SS_POL = param->ss_pol ? (value | channelMask) : (value & ~channelMask);

    HW_ECSPI_CONFIGREG(instance).B.SS_CTL |= channelMask;
//    HW_ECSPI_CONFIGREG(instance).B.SS_CTL = 0x0;
//    HW_ECSPI_PERIODREG(instance).B.SAMPLE_PERIOD = 0x10;

    //Configure the Rx_threshold
    HW_ECSPI_DMAREG(instance).B.RX_THRESHOLD = 0x1; //unit = one word(32 bits)
    //Enable  RDR interrupt
//    HW_ECSPI_INTREG(instance).B.TCEN =0x01;
    HW_ECSPI_INTREG(instance).B.RDREN =1;

    return SUCCESS;
}

//! @todo Validate [url=home.php?mod=space&uid=18481]@a[/url] dev value for the chip, since not all chips will have all 5 instances.
int ecspi_open(dev_ecspi_e dev, const param_ecspi_t * param)
{
    // Configure IO signals
    ecspi_iomux_config(dev);

    // Ungate the module clock.
    clock_gating_config(REGS_ECSPI_BASE(dev), CLOCK_ON);

    // Configure eCSPI registers
    ecspi_configure(dev, param);

    return SUCCESS;
}

int ecspi_close(dev_ecspi_e dev)
{
    // Disable controller
    HW_ECSPI_CONREG(dev).B.EN = 0;

    // Gate the module clock.
    clock_gating_config(REGS_ECSPI_BASE(dev), CLOCK_OFF);

    return SUCCESS;
}

//! @todo Handle tranfers larger than the FIFO length!
int ecspi_xfer(dev_ecspi_e dev, const uint8_t * tx_buf, uint8_t * rx_buf, uint16_t brs_bts)
{
    uint32_t retv = SUCCESS;

    // Set bytes for burst
    int bytes = brs_bts >> 3;

    // Handle non-byte-aligned bits
    if ((brs_bts & 0x7) != 0)
    {
        bytes++;
    }

    // Check burst length
    if (bytes > ECSPI_FIFO_SIZE * 4)
    {
#ifdef DEBUG
        printf("ecspi_xfer: Burst out of length.\n");
#endif
        retv = ERROR_GENERIC;
    }

    if (retv == SUCCESS)
    {
        // Prepare transfer
        ecspi_start_transfer(dev, brs_bts);

        // Initiate transfer
        uint32_t channel = HW_ECSPI_CONREG(dev).B.CHANNEL_SELECT;

        // Handle different mode transfer
        if ((HW_ECSPI_CONREG(dev).B.CHANNEL_MODE & (1 << channel)) == 0)
        {
            retv = ecspi_xfer_slv(dev, tx_buf, rx_buf, bytes);
        }
        else
        {
            retv = ecspi_xfer_mst(dev, tx_buf, rx_buf, bytes);
        }
    }

    return retv;
}

//static void Ecspi1_txIsr(void){
//        static int i = 0;
//        ecspi_xfer(DEV_ECSPI1, &tx_buf_ecspi1[i], &rx_buf_ecspi1[i], BURST_L);
//        if(i < ECSPI_FIFO_SIZE*4)
//        {
//                i++;
//        }
//        else{
//                i = 0;
//        }
//}
static int i = 0;
static void Ecspi2_rxIsr(void){

        ecspi_xfer(DEV_ECSPI2, &tx_buf_ecspi2[i], &rx_buf_ecspi2[i], BURST_L);
        if(i < (ECSPI_FIFO_SIZE*4-16))
        {
                i += 1;
        }
        else{
                i = 0;
        }
}

//spi module initialize @HWX
void Spi_Init(void){
//    ecspi_open(DEV_ECSPI1, &param[0]); //Enable ECSPI1
    ecspi_open(DEV_ECSPI2, &param[1]); //Enable ECSPI2
    // bind the ECSPI1 TDR ISR in GIC
//        GIC_SpiIntInstall(Ecspi1_txIsr, IAR_INT_eCSPI1, 0x54, 0);
//        GIC_IntEnable(IAR_INT_eCSPI1, 1);
    // bind the ECSPI2 RDR ISR in GIC
        GIC_SpiIntInstall(Ecspi2_rxIsr, IAR_INT_eCSPI2, 0x55, 0);
        GIC_IntEnable(IAR_INT_eCSPI2, 1);
        //for ecspi1,datas need to be wrote into norflash

}

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝