Using MQX on a Kinetis K60 how do I change the SPI chip select?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Using MQX on a Kinetis K60 how do I change the SPI chip select?

Jump to solution
2,966 Views
kfranz
Contributor III

I am looking at the example code in Freescale MQX 3.8\mqx\examples\spi\spi.c . I can see how the various SPI control parameters are changed except for the chip select. We have a custom design with SPI devices connected to each of the four chip selects on SPI1 (SPI1_PCS0, SPI1_PCS1, SPI1_PCS2, SPI1_PCS3). It looks like I use ioctl(spifd, IO_IOCTL_SPI_SET_CS, &param) to change the current chip select. Is this correct? If so, what does 'param' get set to for each of the chip selects? If not, how do I change the active chip select?

thanks,

Kevin


Labels (1)
Tags (3)
1 Solution
826 Views
kfranz
Contributor III

Thank you for the information. I understand the code you provided and see how to make the SPI1 port work. After some additional research, I believe one more change is required, that is to enable the chip selects being used as an output. We have a custom board based on the twrk60n512 which uses chip select 0, 2, and 3 on SPI1. At runtime we will be using multiple SPI1 channels.

In Freescale MQX 3.8\mqx\source\bsp\twrk60n512\init_gpio.c , _bsp_dspi_io_init(), you have to add initializing the chip select 2 and 3 as an output pin. Chip select 0 is already in the case statement. To add setting chip select 2 and 3 as an output when using SPI1 the following code needs to be added to case 1:

pctl->PCR[5] = PORT_PCR_MUX(2); /* DSPI1.PCS2   K60, SPI1 chip select 2 as an output */
pctl->PCR[6] = PORT_PCR_MUX(2); /* DSPI1.PCS3   K60, SPI1 chip select 3 as an output */


Thanks for you help,

Kevin

View solution in original post

3 Replies
826 Views
DavidS
NXP Employee
NXP Employee

Hi kfranz,

Good question.

Let me try to answer.

I'm using the TWR-K70F120M tower kit with the TWR-MEM Rev B card to allow accessing serial flash using the SPI2 in polled mode to allow me to use IOCTL commands to change the chip select used by the SPI module.

Also using MQX3.8.1 and the C:\Freescale\Freescale MQX 3.8\mqx\examples\spi project.  "spi.c" source attached.

Doing this I think I uncovered errata that I will pass along to our MQX Development team to review.

The init_spi.c in the BSP has the following:

const DSPI_INIT_STRUCT _bsp_dspi2_init = {

   2,                            /* SPI channel */

   SPI_PUSHR_PCS(1 << 0),        /* Chip Select 0 */  //DES 32-bit value is 0x00010000 (big endian format)

The SPI_PUSHR_PCS is stored to a 32-bit value in the structure.

The spi_pol_dspi.c _dspi_polled_init() function does the following:

Io_info_ptr->CS = DSPI_PUSHR_PCS_GET(dspi_init_ptr->CS);

The macro will basically returns 32-bit result of 0x00000001 (big endian format) so rather than having the variable in the register format, it is now just a chip select value but note that the real chip select value is io_info_ptr->CS - 1 (i.e. value of 1 equals CS 0, value 2 equals CS 1, etc..)

The rest of the SPI driver uses the io_info_ptr->CS value/mask.

I changed the IOCTL calls GET/SET to work with value/mask rather than register format.

My example code is modifying this to allow the example to use the SPI2 CS0 or CS1 and therefore you can just change the TWR-MEM Rev B jumper J14 to test.  J14 pin 1-2 is CS0 and J14 pin 2-3 is CS1.

Now that I have played with this code I think the initialization code and driver code are out of sync and will leave it to the developers to correct.

But the change I did make to the spi_pol_dspi.c is as follows:

        case IO_IOCTL_SPI_GET_CS:

            if (NULL == param_ptr)

            {

                result = SPI_ERROR_INVALID_PARAMETER;

            }

            else

            {

                *param_ptr = (io_info_ptr->CS) - 1;   //DES <-updated

//DES bad format               *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 = (*param_ptr) + 1;   //DES <-updated

//DES bad format               io_info_ptr->CS = DSPI_PUSHR_PCS_GET(*param_ptr);

            }

            break;

In summary:  You can use one fopen() call per SPI module and then use the IOCTL call to change which SPI chip select you want to use for that module.

Regards,

David

0 Kudos
827 Views
kfranz
Contributor III

Thank you for the information. I understand the code you provided and see how to make the SPI1 port work. After some additional research, I believe one more change is required, that is to enable the chip selects being used as an output. We have a custom board based on the twrk60n512 which uses chip select 0, 2, and 3 on SPI1. At runtime we will be using multiple SPI1 channels.

In Freescale MQX 3.8\mqx\source\bsp\twrk60n512\init_gpio.c , _bsp_dspi_io_init(), you have to add initializing the chip select 2 and 3 as an output pin. Chip select 0 is already in the case statement. To add setting chip select 2 and 3 as an output when using SPI1 the following code needs to be added to case 1:

pctl->PCR[5] = PORT_PCR_MUX(2); /* DSPI1.PCS2   K60, SPI1 chip select 2 as an output */
pctl->PCR[6] = PORT_PCR_MUX(2); /* DSPI1.PCS3   K60, SPI1 chip select 3 as an output */


Thanks for you help,

Kevin

828 Views
DavidS
NXP Employee
NXP Employee

Hi Kevin,

I was testing you ;-)

Sorry for the over sight.  Yes I had to update the PCR setting to enable CS1 for the SPI2 module in the init_gpio.c.

For those using the TWR-K70 I did the following:

        case 2:
            /* Configure GPIOD for DSPI2 peripheral function     */
            pctl = (PORT_MemMapPtr)PORTD_BASE_PTR;

            pctl->PCR[15] = PORT_PCR_MUX(2);    /* DSPI2.PCS1   */  //DES <--LINE ADDED TO ENABLE CS1 testing
            pctl->PCR[11] = PORT_PCR_MUX(2);    /* DSPI2.PCS0   */
            pctl->PCR[12] = PORT_PCR_MUX(2);    /* DSPI2.SCK    */
            pctl->PCR[13] = PORT_PCR_MUX(2);    /* DSPI2.SOUT   */
            pctl->PCR[14] = PORT_PCR_MUX(2);    /* DSPI2.SIN    */
            pctl->PCR[15] = PORT_PCR_MUX(2);    /* DSPI2.PCS1   */

Thanks for your input.

Regards,

David

0 Kudos