Пример #1
0
/*FUNCTION****************************************************************
*
* Function Name    : _dspi_dma_ioctl
* Returned Value   : MQX error code
* Comments         :
*    This function performs miscellaneous services for
*    the SPI I/O device.
*
*END*********************************************************************/
static _mqx_int _dspi_dma_ioctl
    (
        /* [IN] The address of the device specific information */
        void                          *io_info_ptr,

        /* [IN] SPI transfer parameters */
        SPI_PARAM_STRUCT_PTR           params,

        /* [IN] The command to perform */
        uint32_t                        cmd,

        /* [IN] Parameters for the command */
        uint32_t                    *param_ptr
    )
{
    DSPI_DMA_INFO_STRUCT_PTR           dspi_info_ptr = (DSPI_DMA_INFO_STRUCT_PTR)io_info_ptr;
    uint32_t                            result = SPI_OK;

    BSP_CLOCK_CONFIGURATION clock_config;
    uint32_t clock_speed;

    switch (cmd)
    {
        case IO_IOCTL_SPI_GET_BAUD:
            clock_config = _bsp_get_clock_configuration();
            clock_speed = _bsp_get_clock(clock_config, dspi_info_ptr->CLOCK_SOURCE);
            *((uint32_t *)param_ptr) = _dspi_find_baudrate(clock_speed, *((uint32_t *)param_ptr), NULL);
            break;

        default:
            result = IO_ERROR_INVALID_IOCTL_CMD;
            break;
    }
    return result;
}
Пример #2
0
/*FUNCTION****************************************************************
*
* Function Name    : _dspi_polled_ioctl
* Returned Value   : MQX error code
* Comments         :
*    This function performs miscellaneous services for
*    the SPI I/O device.
*
*END*********************************************************************/
uint_32 _dspi_polled_ioctl
    (
        /* [IN] The address of the device specific information */
        DSPI_INFO_STRUCT_PTR         io_info_ptr,

        /* [IN] The command to perform */
        uint_32                      cmd,

        /* [IN] Parameters for the command */
        uint_32_ptr                  param_ptr,

        /* [IN] Opening flags */
        uint_32                      flags
    )
{
    VDSPI_REG_STRUCT_PTR             dspi_ptr;
    SPI_CS_CALLBACK_STRUCT_PTR       callbacks;
    uint_32                          val, num;
    uint_32                          result = SPI_OK;
    SPI_READ_WRITE_STRUCT_PTR        rw_ptr;

    dspi_ptr = io_info_ptr->DSPI_PTR;

    switch (cmd)
    {
        case IO_IOCTL_SPI_GET_BAUD:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                val = dspi_ptr->CTAR[0];
                val = (BAUDRATE_PRESCALER[DSPI_CTAR_PBR_GET(val)] * BAUDRATE_SCALER[DSPI_CTAR_BR_GET(val)]) >> ((val & DSPI_CTAR_DBR_MASK) != 0);
                *param_ptr = (uint_32)((io_info_ptr->INIT.CLOCK_SPEED) / val);
            }
            break;
        case IO_IOCTL_SPI_SET_BAUD:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else if (0 == (*param_ptr))
            {
                result = SPI_ERROR_BAUD_RATE_INVALID;
            }
            else
            {
                /* Disable SPI module */
                dspi_ptr->MCR |= DSPI_MCR_HALT_MASK;
                /* Read current settings and clear those to be changed */
                val = dspi_ptr->CTAR[0];
                val &= ~(DSPI_CTAR_PBR_MASK | DSPI_CTAR_BR_MASK | DSPI_CTAR_DBR_MASK);
                val &= ~(DSPI_CTAR_PCSSCK_MASK | DSPI_CTAR_CSSCK_MASK);
                val &= ~(DSPI_CTAR_PASC_MASK | DSPI_CTAR_ASC_MASK);
                val &= ~(DSPI_CTAR_PDT_MASK | DSPI_CTAR_DT_MASK);
                /* Calculate dividers */
                val |= _dspi_find_baudrate (io_info_ptr->INIT.CLOCK_SPEED, *param_ptr);
                /* Write settins to register */
                dspi_ptr->CTAR[0] = val;
                /* Re-enable SPI module */
                dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK);
            }
            break;
        case IO_IOCTL_SPI_DEVICE_DISABLE:
            dspi_ptr->MCR |= DSPI_MCR_HALT_MASK;
            break;
        case IO_IOCTL_SPI_DEVICE_ENABLE:
            dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK);
            break;
        case IO_IOCTL_SPI_GET_MODE:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                if (dspi_ptr->CTAR[0] & DSPI_CTAR_CPOL_MASK)
                {
                    if (dspi_ptr->CTAR[0] & DSPI_CTAR_CPHA_MASK)
                    {
                        *param_ptr = SPI_CLK_POL_PHA_MODE3;
                    }
                    else
                    {
                        *param_ptr = SPI_CLK_POL_PHA_MODE2;
                    }
                }
                else
                {
                    if (dspi_ptr->CTAR[0] & DSPI_CTAR_CPHA_MASK)
                    {
                        *param_ptr = SPI_CLK_POL_PHA_MODE1;
                    }
                    else
                    {
                        *param_ptr = SPI_CLK_POL_PHA_MODE0;
                    }
                }
            }
            break;
        case IO_IOCTL_SPI_SET_MODE:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                /* Disable SPI module */
                dspi_ptr->MCR |= DSPI_MCR_HALT_MASK;
                switch (*param_ptr)
                {
                    case (SPI_CLK_POL_PHA_MODE0):
                        /* Inactive state of SPI_CLK = logic 0 */
                        dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPOL_MASK);
                        /* SPI_CLK transitions middle of bit timing */
                        dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPHA_MASK);
                        break;
                    case (SPI_CLK_POL_PHA_MODE1):
                        /* Inactive state of SPI_CLK = logic 0 */
                        dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPOL_MASK);
                        /* SPI_CLK transitions begining of bit timing */
                        dspi_ptr->CTAR[0] |= DSPI_CTAR_CPHA_MASK;
                        break;
                    case (SPI_CLK_POL_PHA_MODE2):
                        /* Inactive state of SPI_CLK = logic 1 */
                        dspi_ptr->CTAR[0] |= DSPI_CTAR_CPOL_MASK;
                        /* SPI_CLK transitions middle of bit timing */
                        dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPHA_MASK);
                        break;
                    case (SPI_CLK_POL_PHA_MODE3):
                        /* Inactive state of SPI_CLK = logic 1 */
                        dspi_ptr->CTAR[0] |= DSPI_CTAR_CPOL_MASK;
                        /* SPI_CLK transitions begining of bit timing */
                        dspi_ptr->CTAR[0] |= DSPI_CTAR_CPHA_MASK;
                        break;
                    default:
                        result = SPI_ERROR_MODE_INVALID;
                        break;
                }
                /* Enable SPI module */
                dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK);
            }
            break;
        case IO_IOCTL_SPI_GET_TRANSFER_MODE:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                if (dspi_ptr->MCR & DSPI_MCR_MSTR_MASK)
                {
                    *param_ptr = SPI_DEVICE_MASTER_MODE;
                }
                else
                {
                    *param_ptr = SPI_DEVICE_SLAVE_MODE;
                }
            }
            break;
        case IO_IOCTL_SPI_SET_TRANSFER_MODE:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                /* Disable SPI module */
                dspi_ptr->MCR |= DSPI_MCR_HALT_MASK;
                /* Set transfer mode */
                if (*param_ptr == SPI_DEVICE_SLAVE_MODE)
                {
                    dspi_ptr->MCR &= (~ DSPI_MCR_MSTR_MASK);
                }
                else if (*param_ptr == SPI_DEVICE_MASTER_MODE)
                {
                    dspi_ptr->MCR |= DSPI_MCR_MSTR_MASK;
                }
                else
                {
                    result = SPI_ERROR_TRANSFER_MODE_INVALID;
                }
                /* Enable SPI module */
                dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK);
            }
            break;
        case IO_IOCTL_SPI_GET_ENDIAN:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else if (dspi_ptr->CTAR[0] & DSPI_CTAR_LSBFE_MASK)
            {
                *param_ptr = SPI_DEVICE_LITTLE_ENDIAN;
            }
            else
            {
                *param_ptr = SPI_DEVICE_BIG_ENDIAN;
            }
            break;
        case IO_IOCTL_SPI_SET_ENDIAN:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else if (! (dspi_ptr->MCR & DSPI_MCR_MSTR_MASK))
            {
                result = SPI_ERROR_ENDIAN_INVALID;
            }
            else if (*param_ptr == SPI_DEVICE_LITTLE_ENDIAN)
            {
                dspi_ptr->CTAR[0] |= DSPI_CTAR_LSBFE_MASK;
            }
            else if (*param_ptr == SPI_DEVICE_BIG_ENDIAN)
            {
                dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_LSBFE_MASK);
            }
            else
            {
                result = SPI_ERROR_ENDIAN_INVALID;
            }
            break;
        case IO_IOCTL_SPI_GET_STATS:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                *((SPI_STATISTICS_STRUCT_PTR)param_ptr) = io_info_ptr->STATS;
            }
            break;
        case IO_IOCTL_SPI_CLEAR_STATS:
            io_info_ptr->STATS.INTERRUPTS   = 0;
            io_info_ptr->STATS.RX_PACKETS   = 0;
            io_info_ptr->STATS.RX_OVERFLOWS = 0;
            io_info_ptr->STATS.TX_PACKETS   = 0;
            io_info_ptr->STATS.TX_ABORTS    = 0;
            io_info_ptr->STATS.TX_UNDERFLOWS= 0;
            break;
        case IO_IOCTL_FLUSH_OUTPUT:
        case IO_IOCTL_SPI_FLUSH_DEASSERT_CS:
            while ((io_info_ptr->RX_COUNT) || (io_info_ptr->TX_COUNT) || (io_info_ptr->DMA_FLAGS))
                {};  // waiting for completion
            if ((0 == (flags & SPI_FLAG_NO_DEASSERT_ON_FLUSH)) || (IO_IOCTL_SPI_FLUSH_DEASSERT_CS == cmd))
            {
                /* Deassert all chip selects */
                if (dspi_ptr->MCR & DSPI_MCR_MSTR_MASK)
                {
                    _dspi_polled_cs(io_info_ptr, 0);
                    dspi_ptr->MCR |= DSPI_MCR_HALT_MASK;
                    dspi_ptr->MCR &= (~ DSPI_MCR_MSTR_MASK);
                    dspi_ptr->MCR |= DSPI_MCR_MSTR_MASK;
                    dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK);
                }
            }
            break;
        case IO_IOCTL_SPI_GET_FRAMESIZE:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                *param_ptr = DSPI_CTAR_FMSZ_GET(dspi_ptr->CTAR[0]) + 1;
            }
            break;
        case IO_IOCTL_SPI_SET_FRAMESIZE:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                /* Disable SPI module */
                dspi_ptr->MCR |= DSPI_MCR_HALT_MASK;
                dspi_ptr->CTAR[0] &= (~ (DSPI_CTAR_FMSZ(0x0F)));
                dspi_ptr->CTAR[0] |= DSPI_CTAR_FMSZ(*param_ptr - 1);
                /* Enable SPI module */
                dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK);
            }
            break;
        case IO_IOCTL_SPI_GET_CS:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                *param_ptr = DSPI_PUSHR_PCS(io_info_ptr->CS);
            }
            break;
        case IO_IOCTL_SPI_SET_CS:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                io_info_ptr->CS = DSPI_PUSHR_PCS_GET(*param_ptr);
            }
            break;
        case IO_IOCTL_SPI_ENABLE_MODF:
            result = MQX_IO_OPERATION_NOT_AVAILABLE;
            break;
        case IO_IOCTL_SPI_DISABLE_MODF:
            break;
        case IO_IOCTL_SPI_SET_CS_CALLBACK:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                callbacks = (SPI_CS_CALLBACK_STRUCT_PTR)(param_ptr);
                for (num = 0; num < DSPI_CS_COUNT; num++)
                {
                    if (0 != (callbacks->MASK & (DSPI_PUSHR_PCS(1 << num))))
                    {
                        io_info_ptr->CS_CALLBACK[num] = callbacks->CALLBACK;
                        io_info_ptr->CS_USERDATA[num] = callbacks->USERDATA;
                    }
                }
            }
            break;
        case IO_IOCTL_SPI_READ_WRITE:
            if (NULL == param_ptr)
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            }
            else
            {
                rw_ptr = (SPI_READ_WRITE_STRUCT_PTR)param_ptr;
                _dspi_polled_tx_rx (io_info_ptr, (uint_8_ptr)(rw_ptr->WRITE_BUFFER), (uint_8_ptr)(rw_ptr->READ_BUFFER), rw_ptr->BUFFER_LENGTH);
            }
            break;
        case IO_IOCTL_SPI_KEEP_QSPI_CS_ACTIVE:
            result = MQX_IO_OPERATION_NOT_AVAILABLE;
            break;
        default:
            result = IO_ERROR_INVALID_IOCTL_CMD;
            break;
    }
    return result;
}
Пример #3
0
/*FUNCTION****************************************************************
*
* Function Name    : _dspi_polled_init
* Returned Value   : MQX error code
* Comments         :
*    This function initializes the SPI module
*
*END*********************************************************************/
uint_32 _dspi_polled_init
    (
        /* [IN] The initialization information for the device being opened */
        DSPI_INIT_STRUCT_PTR          dspi_init_ptr,

        /* [OUT] The address to store device specific information */
        pointer _PTR_                 io_info_ptr_ptr,

        /* [IN] The rest of the name of the device opened */
        char_ptr                      open_name_ptr
    )
{
    VDSPI_REG_STRUCT_PTR              dspi_ptr;
    DSPI_INFO_STRUCT_PTR              io_info_ptr;
    uint_32                           i;

    #if PSP_HAS_DEVICE_PROTECTION
    if (!_bsp_dspi_enable_access(dspi_init_ptr->CHANNEL)) {
        return SPI_ERROR_CHANNEL_INVALID;
    }
    #endif

    // Check channel
    dspi_ptr = _bsp_get_dspi_base_address (dspi_init_ptr->CHANNEL);
    if (NULL == dspi_ptr)
    {
        return SPI_ERROR_CHANNEL_INVALID;
    }

    if (_bsp_dspi_io_init (dspi_init_ptr->CHANNEL) == -1)
    {
        return SPI_ERROR_CHANNEL_INVALID;
    }

    // Disable and clear SPI
    dspi_ptr->MCR &= (~ DSPI_MCR_MDIS_MASK);
    dspi_ptr->MCR = DSPI_MCR_HALT_MASK | DSPI_MCR_CLR_TXF_MASK | DSPI_MCR_CLR_RXF_MASK | DSPI_MCR_DIS_RXF_MASK | DSPI_MCR_DIS_TXF_MASK;

    /* Initialize internal data */
    io_info_ptr = (DSPI_INFO_STRUCT_PTR)_mem_alloc_system_zero((uint_32)sizeof(DSPI_INFO_STRUCT));
    if (io_info_ptr == NULL)
    {
        return MQX_OUT_OF_MEMORY;
    }
    _mem_set_type (io_info_ptr,MEM_TYPE_IO_SPI_INFO_STRUCT);

    *io_info_ptr_ptr = io_info_ptr;

    io_info_ptr->DSPI_PTR           = dspi_ptr;
    io_info_ptr->INIT               = *dspi_init_ptr;
    io_info_ptr->RX_REQUEST         = 0;
    io_info_ptr->RX_BUFFER          = NULL;
    io_info_ptr->RX_IN              = 0;
    io_info_ptr->RX_OUT             = 0;
    io_info_ptr->RX_COUNT           = 0;
    io_info_ptr->RX_DATA            = 0;
    io_info_ptr->TX_BUFFER          = NULL;
    io_info_ptr->TX_IN              = 0;
    io_info_ptr->TX_OUT             = 0;
    io_info_ptr->TX_COUNT           = 0;
    io_info_ptr->TX_DATA            = DSPI_PUSHR_CONT_MASK | DSPI_PUSHR_PCS(0) | DSPI_PUSHR_CTAS(0) | DSPI_PUSHR_TXDATA(0xFFFF);
    io_info_ptr->DMA_FLAGS          = 0;
    io_info_ptr->CS                 = DSPI_PUSHR_PCS_GET(dspi_init_ptr->CS);
    io_info_ptr->CS_ACTIVE          = 0;
    for (i = 0; i < DSPI_CS_COUNT; i++)
    {
        io_info_ptr->CS_CALLBACK[i] = NULL;
        io_info_ptr->CS_USERDATA[i] = NULL;
    }
    io_info_ptr->STATS.INTERRUPTS   = 0;
    io_info_ptr->STATS.RX_PACKETS   = 0;
    io_info_ptr->STATS.RX_OVERFLOWS = 0;
    io_info_ptr->STATS.TX_PACKETS   = 0;
    io_info_ptr->STATS.TX_ABORTS    = 0;
    io_info_ptr->STATS.TX_UNDERFLOWS= 0;

    /* Set the SPI clock baud rate divider */
    dspi_ptr->CTAR[0] = DSPI_CTAR_FMSZ(7);
    dspi_ptr->CTAR[0] |= _dspi_find_baudrate (dspi_init_ptr->CLOCK_SPEED, dspi_init_ptr->BAUD_RATE);

    /* Set up SPI clock polarity and phase */
    switch (dspi_init_ptr->CLOCK_POL_PHASE)
    {
        case (SPI_CLK_POL_PHA_MODE0):
            /* Inactive state of SPI_CLK = logic 0 */
            dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPOL_MASK);
            /* SPI_CLK transitions middle of bit timing */
            dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPHA_MASK);
            break;
        case (SPI_CLK_POL_PHA_MODE1):
            /* Inactive state of SPI_CLK = logic 0 */
            dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPOL_MASK);
            /* SPI_CLK transitions begining of bit timing */
            dspi_ptr->CTAR[0] |= DSPI_CTAR_CPHA_MASK;
            break;
        case (SPI_CLK_POL_PHA_MODE2):
            /* Inactive state of SPI_CLK = logic 1 */
            dspi_ptr->CTAR[0] |= DSPI_CTAR_CPOL_MASK;
            /* SPI_CLK transitions middle of bit timing */
            dspi_ptr->CTAR[0] &= (~ DSPI_CTAR_CPHA_MASK);
            break;
        case (SPI_CLK_POL_PHA_MODE3):
            /* Inactive state of SPI_CLK = logic 1 */
            dspi_ptr->CTAR[0] |= DSPI_CTAR_CPOL_MASK;
            /* SPI_CLK transitions begining of bit timing */
            dspi_ptr->CTAR[0] |= DSPI_CTAR_CPHA_MASK;
            break;
        default:
            _mem_free (*io_info_ptr_ptr);
            *io_info_ptr_ptr = NULL;
            return SPI_ERROR_MODE_INVALID;
    }

    /* Receive FIFO overflow disable */
    dspi_ptr->MCR |= DSPI_MCR_ROOE_MASK;

    /* Set CS0-7 inactive high */
    dspi_ptr->MCR |= DSPI_MCR_PCSIS(0xFF);

    /* Set transfer mode */
    if (dspi_init_ptr->TRANSFER_MODE == SPI_DEVICE_SLAVE_MODE)
    {
        dspi_ptr->MCR &= (~ DSPI_MCR_MSTR_MASK);
    }
    else if (dspi_init_ptr->TRANSFER_MODE == SPI_DEVICE_MASTER_MODE)
    {
        dspi_ptr->MCR |= DSPI_MCR_MSTR_MASK;
    }
    else
    {
        _mem_free (*io_info_ptr_ptr);
        *io_info_ptr_ptr = NULL;
        return SPI_ERROR_TRANSFER_MODE_INVALID;
    }

    /* Disable interrupts */
    dspi_ptr->RSER = 0;

    /* Clear all flags */
    dspi_ptr->SR = ~ DSPI_SR_TFFF_MASK;

    /* Enable SPI */
    dspi_ptr->MCR &= (~ DSPI_MCR_HALT_MASK);

    return SPI_OK;
}
Пример #4
0
/*FUNCTION****************************************************************
*
* Function Name    : _dspi_setparam
* Returned Value   :
* Comments         :
*    Set parameters for following transfers.
*
*END*********************************************************************/
static _mqx_int _dspi_setparam
   (
        /* [IN] Device specific context structure */
        void                          *io_info_ptr,

        /* [IN] Parameters to set */
        SPI_PARAM_STRUCT_PTR           params
   )
{
    DSPI_INFO_STRUCT_PTR               dspi_info_ptr = (DSPI_INFO_STRUCT_PTR)io_info_ptr;
    VDSPI_REG_STRUCT_PTR               dspi_ptr = dspi_info_ptr->DSPI_PTR;

    BSP_CLOCK_CONFIGURATION clock_config;
    uint32_t clock_speed;

    uint32_t ctar;
    uint32_t cpol_invert;

    /* Transfer mode */
    if ((params->ATTR & SPI_ATTR_TRANSFER_MODE_MASK) != SPI_ATTR_MASTER_MODE)
        return SPI_ERROR_TRANSFER_MODE_INVALID;

    /* Set master mode */
    dspi_ptr->MCR |= DSPI_MCR_MSTR_MASK;

    clock_config = _bsp_get_clock_configuration();

    /* Check the parameter against most recent values to avoid time consuming baudrate finding routine */
    if ((dspi_info_ptr->CLOCK_CONFIG != clock_config) || (dspi_info_ptr->BAUDRATE != params->BAUDRATE))
    {
        dspi_info_ptr->CLOCK_CONFIG = clock_config;
        dspi_info_ptr->BAUDRATE = params->BAUDRATE;

        /* Find configuration of prescalers best matching the desired value */
        clock_speed = _bsp_get_clock(dspi_info_ptr->CLOCK_CONFIG, dspi_info_ptr->CLOCK_SOURCE);
        _dspi_find_baudrate(clock_speed, dspi_info_ptr->BAUDRATE, &(dspi_info_ptr->CTAR_TIMING));
    }

    /* Set up prescalers */
    ctar = dspi_info_ptr->CTAR_TIMING;

    /* Set up transfer parameters */
    _dspi_ctar_params(params, &ctar);

    /* Check whether it is necessary to invert idle clock polarity */
    cpol_invert = (dspi_ptr->CTAR[0] ^ ctar) & DSPI_CTAR_CPOL_MASK;

    /* Store to register */
    dspi_ptr->CTAR[0] = ctar;

    dspi_info_ptr->DUMMY_PATTERN = params->DUMMY_PATTERN;
    dspi_info_ptr->ATTR = params->ATTR;

    if (cpol_invert) {
        /* Dummy transfer with inactive CS to invert idle clock polarity */
        dspi_ptr->MCR = (dspi_ptr->MCR & ~(uint32_t)DSPI_MCR_PCSIS_MASK) | DSPI_MCR_PCSIS(0xFF);
        _dspi_tx_rx(io_info_ptr, NULL, NULL, (params->FRAMESIZE+7)/8);
    }

    /* Set CS signals */
    //dspi_ptr->MCR = (dspi_ptr->MCR & ~DSPI_MCR_PCSIS_MASK) | DSPI_MCR_PCSIS(~(params->CS));

    return SPI_OK;
}
Пример #5
0
/*FUNCTION****************************************************************
* 
* Function Name    : _dspi_polled_ioctl
* Returned Value   : MQX error code
* Comments         : 
*    This function performs miscellaneous services for
*    the SPI I/O device.  
*
*END*********************************************************************/
uint_32 _dspi_polled_ioctl
    (
        /* [IN] The address of the device specific information */
        DSPI_INFO_STRUCT_PTR         io_info_ptr,
        
        /* [IN] The command to perform */
        uint_32                      cmd,
        
        /* [IN] Parameters for the command */
        uint_32_ptr                  param_ptr,
        
        /* [IN] Opening flags */
        uint_32                      flags
    )
{
    SPI_MemMapPtr                    dspi_ptr;
    SPI_CS_CALLBACK_STRUCT_PTR       callbacks;
    uint_32                          val, num, size, command;
    uint_32                          result = SPI_OK;
    SPI_READ_WRITE_STRUCT_PTR        rw_ptr;
    uchar_ptr                        input, output;
    
    dspi_ptr = io_info_ptr->DSPI_PTR;
    
    switch (cmd) 
    {
        case IO_IOCTL_SPI_GET_BAUD:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else 
            {
                val = dspi_ptr->CTAR[0];
                val = BAUDRATE_PRESCALER[SPI_CTAR_PBR_GET(val)] * BAUDRATE_SCALER[SPI_CTAR_BR_GET(val)];
                *param_ptr = (uint_32)((io_info_ptr->INIT.CLOCK_SPEED) / val);
            }
            break;
        case IO_IOCTL_SPI_SET_BAUD:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else if (0 == (*param_ptr)) 
            {
                result = SPI_ERROR_BAUD_RATE_INVALID;
            } 
            else 
            {
                val = _dspi_find_baudrate (io_info_ptr->INIT.CLOCK_SPEED, *param_ptr);
                /* Disable SPI module */
                dspi_ptr->MCR |= SPI_MCR_HALT_MASK;
                /* Set the frequency divider */
                dspi_ptr->CTAR[0] &= (~ (SPI_CTAR_PBR(0x0F) | SPI_CTAR_BR(0x0F)));
                dspi_ptr->CTAR[0] |= val;
                /* Enable SPI module */
                dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK);
            }
            break;
        case IO_IOCTL_SPI_DEVICE_DISABLE:
            dspi_ptr->MCR |= SPI_MCR_HALT_MASK;
            break;
        case IO_IOCTL_SPI_DEVICE_ENABLE:
            dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK);
            break;
        case IO_IOCTL_SPI_GET_MODE:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else
            {
                if (dspi_ptr->CTAR[0] & SPI_CTAR_CPOL_MASK)
                {
                    if (dspi_ptr->CTAR[0] & SPI_CTAR_CPHA_MASK)
                    {
                        *param_ptr = SPI_CLK_POL_PHA_MODE3;
                    }
                    else
                    {
                        *param_ptr = SPI_CLK_POL_PHA_MODE2;
                    }
                }
                else
                {
                    if (dspi_ptr->CTAR[0] & SPI_CTAR_CPHA_MASK)
                    {
                        *param_ptr = SPI_CLK_POL_PHA_MODE1;
                    }
                    else
                    {
                        *param_ptr = SPI_CLK_POL_PHA_MODE0;
                    }
                }
            }
            break;
        case IO_IOCTL_SPI_SET_MODE:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else
            {       
                /* Disable SPI module */
                dspi_ptr->MCR |= SPI_MCR_HALT_MASK;
                switch (*param_ptr)
                {
                    case (SPI_CLK_POL_PHA_MODE0):
                        /* Inactive state of SPI_CLK = logic 0 */
                        dspi_ptr->CTAR[0] &= (~ SPI_CTAR_CPOL_MASK);
                        /* SPI_CLK transitions middle of bit timing */
                        dspi_ptr->CTAR[0] &= (~ SPI_CTAR_CPHA_MASK);
                        break;
                    case (SPI_CLK_POL_PHA_MODE1):
                        /* Inactive state of SPI_CLK = logic 0 */
                        dspi_ptr->CTAR[0] &= (~ SPI_CTAR_CPOL_MASK);
                        /* SPI_CLK transitions begining of bit timing */
                        dspi_ptr->CTAR[0] |= SPI_CTAR_CPHA_MASK;
                        break;
                    case (SPI_CLK_POL_PHA_MODE2):
                        /* Inactive state of SPI_CLK = logic 1 */
                        dspi_ptr->CTAR[0] |= SPI_CTAR_CPOL_MASK;
                        /* SPI_CLK transitions middle of bit timing */
                        dspi_ptr->CTAR[0] &= (~ SPI_CTAR_CPHA_MASK);
                        break;
                    case (SPI_CLK_POL_PHA_MODE3):
                        /* Inactive state of SPI_CLK = logic 1 */
                        dspi_ptr->CTAR[0] |= SPI_CTAR_CPOL_MASK;
                        /* SPI_CLK transitions begining of bit timing */
                        dspi_ptr->CTAR[0] |= SPI_CTAR_CPHA_MASK;
                        break;
                    default:
                        result = SPI_ERROR_MODE_INVALID;
                        break;
                }
                /* Enable SPI module */
                dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK);
            }
            break;
        case IO_IOCTL_SPI_GET_TRANSFER_MODE:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else
            {
                if (dspi_ptr->MCR & SPI_MCR_MSTR_MASK) 
                {
                    *param_ptr = SPI_DEVICE_MASTER_MODE;
                }
                else 
                {
                    *param_ptr = SPI_DEVICE_SLAVE_MODE;
                }
            }
            break;
        case IO_IOCTL_SPI_SET_TRANSFER_MODE:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else
            {
                /* Disable SPI module */
                dspi_ptr->MCR |= SPI_MCR_HALT_MASK;
                /* Set transfer mode */
                if (*param_ptr == SPI_DEVICE_SLAVE_MODE)
                {
                    dspi_ptr->MCR &= (~ SPI_MCR_MSTR_MASK);
                }
                else if (*param_ptr == SPI_DEVICE_MASTER_MODE)
                {
                    dspi_ptr->MCR |= SPI_MCR_MSTR_MASK;
                }
                else
                {
                    result = SPI_ERROR_TRANSFER_MODE_INVALID;
                }
                /* Enable SPI module */
                dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK);
            }
            break;
        case IO_IOCTL_SPI_GET_ENDIAN:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else if (dspi_ptr->CTAR[0] & SPI_CTAR_LSBFE_MASK)
            {
                *param_ptr = SPI_DEVICE_LITTLE_ENDIAN;   
            }
            else
            {
                *param_ptr = SPI_DEVICE_BIG_ENDIAN; 
            }
            break;
        case IO_IOCTL_SPI_SET_ENDIAN:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else if (! (dspi_ptr->MCR & SPI_MCR_MSTR_MASK)) 
            {
                result = SPI_ERROR_ENDIAN_INVALID;
            }
            else if (*param_ptr == SPI_DEVICE_LITTLE_ENDIAN)
            {
                dspi_ptr->CTAR[0] |= SPI_CTAR_LSBFE_MASK;
            }
            else if (*param_ptr == SPI_DEVICE_BIG_ENDIAN)
            {
                dspi_ptr->CTAR[0] &= (~ SPI_CTAR_LSBFE_MASK);
            }
            else
            {
                result = SPI_ERROR_ENDIAN_INVALID;
            }
            break;
        case IO_IOCTL_SPI_GET_STATS:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else 
            {
                *((SPI_STATISTICS_STRUCT_PTR)param_ptr) = io_info_ptr->STATS;
            }
            break;
        case IO_IOCTL_SPI_CLEAR_STATS:
            io_info_ptr->STATS.INTERRUPTS   = 0;
            io_info_ptr->STATS.RX_PACKETS   = 0;
            io_info_ptr->STATS.RX_OVERFLOWS = 0;
            io_info_ptr->STATS.TX_PACKETS   = 0;
            io_info_ptr->STATS.TX_ABORTS    = 0;
            io_info_ptr->STATS.TX_UNDERFLOWS= 0;
            break;
        case IO_IOCTL_FLUSH_OUTPUT:
        case IO_IOCTL_SPI_FLUSH_DEASSERT_CS:
            while ((0 != io_info_ptr->RECEIVING) || (0 != io_info_ptr->ONTHEWAY) || (dspi_ptr->RSER & SPI_RSER_TFFF_RE_MASK)) 
               {};  // waiting for completion
            if ((0 == (flags & SPI_FLAG_NO_DEASSERT_ON_FLUSH)) || (IO_IOCTL_SPI_FLUSH_DEASSERT_CS == cmd))
            {
                /* Deassert all chip selects */
                if (dspi_ptr->MCR & SPI_MCR_MSTR_MASK) 
                {
                    for (num = 0; num < DSPI_CS_COUNT; num++)
                    {
                        if ((NULL != io_info_ptr->CS_CALLBACK[num]) && (0 != (io_info_ptr->CS_ACTIVE & (1 << num))))
                        {
                            io_info_ptr->CS_CALLBACK[num] (SPI_PUSHR_PCS(1 << num), 1, io_info_ptr->CS_USERDATA[num]);
                        }                
                    }
                    io_info_ptr->CS_ACTIVE = 0;
                    dspi_ptr->RSER &= (~ SPI_RSER_RFDF_RE_MASK);
                    val = (uint_32)-1;
                    _dspi_polled_tx_rx (io_info_ptr, (uchar_ptr)&val, TRUE, 0);
                    dspi_ptr->RSER |= SPI_RSER_RFDF_RE_MASK;
                }
            }
            break;
        case IO_IOCTL_SPI_GET_FRAMESIZE:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else 
            {
                *param_ptr = SPI_CTAR_FMSZ_GET(dspi_ptr->CTAR[0]) + 1;
            }
            break;
        case IO_IOCTL_SPI_SET_FRAMESIZE:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else 
            {
                /* Disable SPI module */
                dspi_ptr->MCR |= SPI_MCR_HALT_MASK;
                dspi_ptr->CTAR[0] &= (~ (SPI_CTAR_FMSZ(0x0F)));
                dspi_ptr->CTAR[0] |= SPI_CTAR_FMSZ(*param_ptr - 1);
                /* Enable SPI module */
                dspi_ptr->MCR &= (~ SPI_MCR_HALT_MASK);
            }
            break;
        case IO_IOCTL_SPI_GET_CS:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else 
            {
                *param_ptr = SPI_PUSHR_PCS(io_info_ptr->CS);
            }
            break;
        case IO_IOCTL_SPI_SET_CS:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else 
            {
                io_info_ptr->CS = SPI_PUSHR_PCS_GET(*param_ptr);
            }
            break;
        case IO_IOCTL_SPI_ENABLE_MODF:
            result = MQX_IO_OPERATION_NOT_AVAILABLE;
            break;
        case IO_IOCTL_SPI_DISABLE_MODF:
            break;
        case IO_IOCTL_SPI_SET_CS_CALLBACK:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else 
            {
                callbacks = (SPI_CS_CALLBACK_STRUCT_PTR)(param_ptr);
                for (num = 0; num < DSPI_CS_COUNT; num++)
                {
                    if (0 != (callbacks->MASK & (SPI_PUSHR_PCS(1 << num))))
                    {
                        io_info_ptr->CS_CALLBACK[num] = callbacks->CALLBACK;
                        io_info_ptr->CS_USERDATA[num] = callbacks->USERDATA;
                    }                
                }
            }
            break;
        case IO_IOCTL_SPI_READ_WRITE:
            if (NULL == param_ptr) 
            {
                result = SPI_ERROR_INVALID_PARAMETER;
            } 
            else 
            {
                rw_ptr = (SPI_READ_WRITE_STRUCT_PTR)param_ptr;
                command = SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS(io_info_ptr->CS);
                size = rw_ptr->BUFFER_LENGTH;
                input = (uchar_ptr)rw_ptr->WRITE_BUFFER;
                output = (uchar_ptr)rw_ptr->READ_BUFFER;
                for (num = 0; num < size; num++)
                {
                    val = _dspi_polled_tx_rx (io_info_ptr, input, TRUE, command);
                    if (SPI_CTAR_FMSZ_GET(dspi_ptr->CTAR[0]) > 7)
                    {
                        output[0] = (uint_8)(val >> 8);
                        output++;
                        input++;
                    }
                    output[0] = (uint_8)val;
                    output++;
                    input++;
                    io_info_ptr->STATS.RX_PACKETS++;
                    io_info_ptr->STATS.TX_PACKETS++;
                }
            }
            break;
        case IO_IOCTL_SPI_KEEP_QSPI_CS_ACTIVE:
            result = MQX_IO_OPERATION_NOT_AVAILABLE;
            break;
        default:
            result = IO_ERROR_INVALID_IOCTL_CMD;
            break;
    }