TI中文支持网
TI专业的中文技术问题搜集分享网站

SPI master 代码转移到 ti-rtos的project zero 里发现,与spi slave 通信不了

原有的spimaster代码:

void *masterThread(void *arg0)
{
SPI_Handle masterSpi;
SPI_Params spiParams;
SPI_Transaction transaction;
uint32_t i;
bool transferOK;
int32_t status;

/*
* Board_SPI_MASTER_READY & Board_SPI_SLAVE_READY are GPIO pins connected
* between the master & slave. These pins are used to synchronize
* the master & slave applications via a small 'handshake'. The pins
* are later used to synchronize transfers & ensure the master will not
* start a transfer until the slave is ready. These pins behave
* differently between spimaster & spislave examples:
*
* spimaster example:
* * Board_SPI_MASTER_READY is configured as an output pin. During the
* 'handshake' this pin is changed from low to high output. This
* notifies the slave the master is ready to run the application.
* Afterwards, the pin is used by the master to notify the slave it
* has opened Board_SPI_MASTER. When Board_SPI_MASTER is opened, this
* pin will be pulled low.
*
* * Board_SPI_SLAVE_READY is configured as an input pin. During the
* 'handshake' this pin is read & a high value will indicate the slave
* ready to run the application. Afterwards, a falling edge interrupt
* will be configured on this pin. When the slave is ready to perform
* a transfer, it will pull this pin low.
*
* Below we set Board_SPI_MASTER_READY & Board_SPI_SLAVE_READY initial
* conditions for the 'handshake'.
*/
GPIO_setConfig(Board_SPI_MASTER_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_INPUT);

/*
* Handshake – Set Board_SPI_MASTER_READY high to indicate master is ready
* to run. Wait Board_SPI_SLAVE_READY to be high.
*/
GPIO_write(Board_SPI_MASTER_READY, 1);
while (GPIO_read(Board_SPI_SLAVE_READY) == 0) {}

/* Handshake complete; now configure interrupt on Board_SPI_SLAVE_READY */
GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
GPIO_setCallback(Board_SPI_SLAVE_READY, slaveReadyFxn);
GPIO_enableInt(Board_SPI_SLAVE_READY);

/*
* Create synchronization semaphore; the master will wait on this semaphore
* until the slave is ready.
*/
status = sem_init(&masterSem, 0, 0);
if (status != 0) {
Display_printf(display, 0, 0, "Error creating masterSem\n");

while(1);
}

/* Open SPI as master (default) */
SPI_Params_init(&spiParams);
spiParams.frameFormat = SPI_POL0_PHA1;
spiParams.bitRate = 4000000;
masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
if (masterSpi == NULL) {
Display_printf(display, 0, 0, "Error initializing master SPI\n");
while (1);
}
else {
Display_printf(display, 0, 0, "Master SPI initialized\n");
}

/*
* Master has opened Board_SPI_MASTER; set Board_SPI_MASTER_READY high to
* inform the slave.
*/
GPIO_write(Board_SPI_MASTER_READY, 0);

/* Copy message to transmit buffer */
strncpy((char *) masterTxBuffer, MASTER_MSG, SPI_MSG_LENGTH);

for (i = 0; i < MAX_LOOP; i++) {
/*
* Wait until slave is ready for transfer; slave will pull
* Board_SPI_SLAVE_READY low.
*/
sem_wait(&masterSem);

/* Initialize master SPI transaction structure */
masterTxBuffer[sizeof(MASTER_MSG) – 1] = (i % 10) + '0';
memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH);
transaction.count = SPI_MSG_LENGTH;
transaction.txBuf = (void *) masterTxBuffer;
transaction.rxBuf = (void *) masterRxBuffer;

/* Toggle user LED, indicating a SPI transfer is in progress */
GPIO_toggle(Board_GPIO_LED1);

/* Perform SPI transfer */
transferOK = SPI_transfer(masterSpi, &transaction);
if (transferOK) {
Display_printf(display, 0, 0, "Master received: %s", masterRxBuffer);
}
else {
Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
}

/* Sleep for a bit before starting the next SPI transfer */
sleep(3);
}

SPI_close(masterSpi);

/* Example complete – set pins to a known state */
GPIO_disableInt(Board_SPI_SLAVE_READY);
GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
GPIO_write(Board_SPI_MASTER_READY, 0);

Display_printf(display, 0, 0, "\nDone");
Display_printf(display, 0, 0, "count= %d", count);

return (NULL);
}

/*
* ======== mainThread ========
*/
void *mainThread(void *arg0)
{
pthread_t thread0;
pthread_attr_t attrs;
struct sched_param priParam;
int retc;
int detachState;

/* Call driver init functions. */
Display_init();
GPIO_init();
SPI_init();

/* Configure the LED pins */
GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

/* Open the display for output */
display = Display_open(Display_Type_UART, NULL);
if (display == NULL) {
/* Failed to open display driver */
while (1);
}

/* Turn on user LED */
GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);

Display_printf(display, 0, 0, "Starting the SPI master example");
Display_printf(display, 0, 0, "This example requires external wires to be "
"connected to the header pins. Please see the Board.html for details.\n");

/* Create application threads */
pthread_attr_init(&attrs);

detachState = PTHREAD_CREATE_DETACHED;
/* Set priority and stack size attributes */
retc = pthread_attr_setdetachstate(&attrs, detachState);
if (retc != 0) {
/* pthread_attr_setdetachstate() failed */
while (1);
}

retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
if (retc != 0) {
/* pthread_attr_setstacksize() failed */
while (1);
}

/* Create master thread */
priParam.sched_priority = 1;
pthread_attr_setschedparam(&attrs, &priParam);

retc = pthread_create(&thread0, &attrs, masterThread, NULL);
if (retc != 0) {
/* pthread_create() failed */
while (1);
}

return (NULL);
}

/***********************************************************************************/

转移到project zero 里的代码

static void Spimaster_taskFxn(UArg a0, UArg a1)
{

SPI_Handle masterSpi;
SPI_Params spiParams;
SPI_Transaction transaction;
uint32_t i;
bool transferOK;
int32_t status;

bool isSuccessful;

/*
* Board_SPI_MASTER_READY & Board_SPI_SLAVE_READY are GPIO pins connected
* between the master & slave. These pins are used to synchronize
* the master & slave applications via a small 'handshake'. The pins
* are later used to synchronize transfers & ensure the master will not
* start a transfer until the slave is ready. These pins behave
* differently between spimaster & spislave examples:
*
* spimaster example:
* * Board_SPI_MASTER_READY is configured as an output pin. During the
* 'handshake' this pin is changed from low to high output. This
* notifies the slave the master is ready to run the application.
* Afterwards, the pin is used by the master to notify the slave it
* has opened Board_SPI_MASTER. When Board_SPI_MASTER is opened, this
* pin will be pulled low.
*
* * Board_SPI_SLAVE_READY is configured as an input pin. During the
* 'handshake' this pin is read & a high value will indicate the slave
* ready to run the application. Afterwards, a falling edge interrupt
* will be configured on this pin. When the slave is ready to perform
* a transfer, it will pull this pin low.
*
* Below we set Board_SPI_MASTER_READY & Board_SPI_SLAVE_READY initial
* conditions for the 'handshake'.
*/

GPIO_init();
SPI_init();

GPIO_setConfig(Board_SPI_MASTER_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_INPUT);

/*
* Handshake – Set Board_SPI_MASTER_READY high to indicate master is ready
* to run. Wait Board_SPI_SLAVE_READY to be high.
*/
GPIO_write(Board_SPI_MASTER_READY, 1);
Log_info0("Board_SPI_MASTER_READY\n");
while (GPIO_read(Board_SPI_SLAVE_READY) == 0) { Log_info0("wait Board_SPI_SLAVE_READY\n");}

/* Handshake complete; now configure interrupt on Board_SPI_SLAVE_READY */
GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
GPIO_setCallback(Board_SPI_SLAVE_READY, slaveReadyFxn);
GPIO_enableInt(Board_SPI_SLAVE_READY);

/*
* Create synchronization semaphore; the master will wait on this semaphore
* until the slave is ready.
*/

/* Open SPI as master (default) */

Semaphore_Params_init(&semParams);
sem = Semaphore_create(0, &semParams, NULL); // 内存在这里分配

if (sem == NULL) // 检查返回的句柄是否有效
{
Log_info0("Error creating masterSem\n");

// System_abort("Semaphore could not be created");
}

spiParams.frameFormat = SPI_POL0_PHA1;
spiParams.bitRate = 4000000;
masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
if (masterSpi == NULL) {
Log_info0("Error initializing master SPI\n");
//Display_printf(display, 0, 0, "Error initializing master SPI\n");
while (1);
}
else {
Log_info0("Master SPI initialized\n");
//Display_printf(display, 0, 0, "Master SPI initialized\n");
}

/*
* Master has opened Board_SPI_MASTER; set Board_SPI_MASTER_READY high to
* inform the slave.
*/
GPIO_write(Board_SPI_MASTER_READY, 0);

/* Copy message to transmit buffer */
strncpy((char *) masterTxBuffer, MASTER_MSG, SPI_MSG_LENGTH);

/*
* Wait until slave is ready for transfer; slave will pull
* Board_SPI_SLAVE_READY low.
*/

/*
if (isSuccessful)
{
//System_printf("Semaphore was posted");
Log_info0("Semaphore was posted\n");

}
else{
// System_printf("Semaphore timed out");
Log_info0("Semaphore timed out\n");

}
*/

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

// while (GPIO_read(Board_SPI_SLAVE_READY) == 1) { Log_info0("wait Board_SPI_SLAVE\n");}

Semaphore_pend(sem, BIOS_WAIT_FOREVER);

/* Initialize master SPI transaction structure */
masterTxBuffer[sizeof(MASTER_MSG) – 1] = (i % 10) + '0';
memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH);
transaction.count = SPI_MSG_LENGTH;
transaction.txBuf = (void *) masterTxBuffer;
transaction.rxBuf = (void *) masterRxBuffer;

/* Toggle user LED, indicating a SPI transfer is in progress */
GPIO_toggle(Board_GPIO_LED1);

/* Perform SPI transfer */
transferOK = SPI_transfer(masterSpi, &transaction);
if (transferOK) {

Log_info1( "Master received: %s", masterRxBuffer);
}
else {
Log_info0( "Unsuccessful master SPI transfer");
}

/* Sleep for a bit before starting the next SPI transfer */
// sleep(3);
Task_sleep(3000);

}

SPI_close(masterSpi);

/* Example complete – set pins to a known state */
GPIO_disableInt(Board_SPI_SLAVE_READY);
GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
GPIO_write(Board_SPI_MASTER_READY, 0);

Log_info0("\nDone");

return ;

}

主要是更改的sem函数改为ti-rtos的Semaphore函数

Viki Shi:

可以参考一下SDK中的文档:file:///C:/ti/simplelink_cc2640r2_sdk_3_10_00_15/docs/tidrivers/doxygen/html/_s_p_i_8h.html

user5999760:

回复 Viki Shi:

还是没有明白怎么转移到ti_rtos的project zero的工程里来

user5999760:

回复 Viki Shi:

你好,卡在这里好几天了,能帮我分析一下吗,我描述一下我的问题吧,关于spi的使用,我用例程spimaster和spislave分别在两块板子上跑,两者通信是没问题的。Board_SPI_SLAVE_READY和Board_SPI_MASTER_READY这两个引脚应该是两者同步用的。所以打算把spimaster的程序转移到project_zero工程里,目前我工程里只跑了这一个任务,但是通信不了,唯一的改变就是原来spimaster用的是posix,project-zero里用的tirtos,信号量接口改成Semaphore_create,Semaphore_pend,Semaphore_post而已。现在就是project这边收不到也发不出去spi数据

/***main.c:*********/
ProjectZero_createTask();

/*********project.zero.c*********/
void ProjectZero_createTask(void)
{Task_Params taskParams;
// Configure taskTask_Params_init(&taskParams);taskParams.stack = przTaskStack;taskParams.stackSize = PRZ_TASK_STACK_SIZE;taskParams.priority = PRZ_TASK_PRIORITY;
Task_construct(&przTask, Spimaster_taskFxn, &taskParams, NULL);
}

static void Spimaster_taskFxn(UArg a0, UArg a1)
{SPI_HandlemasterSpi;SPI_ParamsspiParams;SPI_Transaction transaction;uint32_ti;booltransferOK;int32_tstatus;
GPIO_init();SPI_init();
GPIO_setConfig(Board_SPI_MASTER_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_INPUT);

GPIO_write(Board_SPI_MASTER_READY, 1);Log_info0("Board_SPI_MASTER_READY\n");while (GPIO_read(Board_SPI_SLAVE_READY) == 0) { Log_info0("wait Board_SPI_SLAVE_READY\n");}
/* Handshake complete; now configure interrupt on Board_SPI_SLAVE_READY */GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);GPIO_setCallback(Board_SPI_SLAVE_READY, slaveReadyFxn);GPIO_enableInt(Board_SPI_SLAVE_READY);
/** Create synchronization semaphore; the master will wait on this semaphore* until the slave is ready.*/

/* Open SPI as master (default) */
//Semaphore_Params_init(&semParams);sem = Semaphore_create(0, NULL, Error_IGNORE);// 内存在这里分配
if (sem == NULL)// 检查返回的句柄是否有效{Log_info0("Error creating masterSem\n");
// System_abort("Semaphore could not be created");}

spiParams.frameFormat = SPI_POL0_PHA1;spiParams.bitRate = 4000000;masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);if (masterSpi == NULL) {Log_info0("Error initializing master SPI\n");//Display_printf(display, 0, 0, "Error initializing master SPI\n");while (1);}else {Log_info0("Master SPI initialized\n");//Display_printf(display, 0, 0, "Master SPI initialized\n");}
/** Master has opened Board_SPI_MASTER; set Board_SPI_MASTER_READY high to* inform the slave.*/GPIO_write(Board_SPI_MASTER_READY, 0);
/* Copy message to transmit buffer */strncpy((char *) masterTxBuffer, MASTER_MSG, SPI_MSG_LENGTH);

/** Wait until slave is ready for transfer; slave will pull* Board_SPI_SLAVE_READY low.*/

/*if (isSuccessful){//System_printf("Semaphore was posted");Log_info0("Semaphore was posted\n");
}else{// System_printf("Semaphore timed out");Log_info0("Semaphore timed out\n");
}*/
for (i = 0; i < MAX_LOOP; i++) {

// while (GPIO_read(Board_SPI_SLAVE_READY) == 1) { Log_info0("wait Board_SPI_SLAVE\n");}

Semaphore_pend(sem, BIOS_WAIT_FOREVER);
/* Initialize master SPI transaction structure */masterTxBuffer[sizeof(MASTER_MSG) – 1] = (i % 10) + '0';memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH);transaction.count = SPI_MSG_LENGTH;transaction.txBuf = (void *) masterTxBuffer;transaction.rxBuf = (void *) masterRxBuffer;
/* Toggle user LED, indicating a SPI transfer is in progress */GPIO_toggle(Board_GPIO_LED1);
/* Perform SPI transfer */transferOK = SPI_transfer(masterSpi, &transaction);if (transferOK) {
Log_info1( "Master received: %s", masterRxBuffer);}else {Log_info0( "Unsuccessful master SPI transfer");}
/* Sleep for a bit before starting the next SPI transfer*/// sleep(3);Task_sleep(3000);
}
SPI_close(masterSpi);
/* Example complete – set pins to a known state */GPIO_disableInt(Board_SPI_SLAVE_READY);GPIO_setConfig(Board_SPI_SLAVE_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);GPIO_write(Board_SPI_MASTER_READY, 0);
Log_info0("\nDone");
return ;

}

Viki Shi:

回复 user5999760:

把代码发给实验室的同事了,看能不能测一下,后续有回复会第一时间更新

Alvin Chen:

回复 Viki Shi:

为何在乎那个信号量?

The masterThread performs the following actions:

Before performing transfers, we must make sure both, spimaster & spislave applications are synchronized with each other. The master will set Board_SPI_MASTER_READY to 1 to notify the slave it is ready to synchronize. The master will then wait for the slave to pull Board_SPI_SLAVE_READY high in acknowledgment.

Opens Board_SPI_MASTER & sets Board_SPI_MASTER_READY to 0. Setting Board_SPI_MASTER_READY will notify the slave Board_SPI_MASTER has been opened.

Waits for the slave to be ready for the SPI transfer. The slave will pull Board_SPI_SLAVE_READY low when ready for a transfer.

Creates a SPI transaction structure and sets txBuffer to Hello from master, msg# n, where n is the iteration number.

Toggles Board_GPIO_LED1.

Transfers the message. If the transfer is successful, the message received from the slave SPI is printed. Otherwise, an error message is printed.

Sleeps for 3 seconds.

Repeats from step 3 for MAX_LOOP iterations.

Closes the SPI driver object and terminates execution.

说白了就是Board_SPI_MASTER_READY和Board_SPI_SLAVE_READY  就是说明对方总线配置好可以发送了是为了避免发送对面还没准备接收,并不会导致发送方有问题。

配置好总线即可发送:

/* Open SPI as master (default) */SPI_Params_init(&spiParams);spiParams.frameFormat = SPI_POL0_PHA1;spiParams.bitRate = 4000000;masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);if (masterSpi == NULL) {Display_printf(display, 0, 0, "Error initializing master SPI\n");while (1);}else {Display_printf(display, 0, 0, "Master SPI initialized\n");}
masterTxBuffer[sizeof(MASTER_MSG) - 1] = (i % 10) + '0';memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH);transaction.count = SPI_MSG_LENGTH;transaction.txBuf = (void *) masterTxBuffer;transaction.rxBuf = (void *) masterRxBuffer;transferOK = SPI_transfer(masterSpi, &transaction);
user5999760:

回复 Alvin Chen:

了解你说的意思, 刚开始我也是这么理解的,可是就像我上面描述的,现在就是收不到,在线debug从机代码(spislave未改过),发现如果是spimaster的代码就能收到,是我上述project-zero里的代码就收不到,spislave里的sem_wait一直在等,不往下执行,我也是新研究TI的产品,找不出哪里自己有问题

Alvin Chen:

回复 user5999760:

你master 初始化之后给一个电平Board_SPI_MASTER_READY为低则会让slave 知道master 已经准备好,
slave 初始化之后则应该Board_SPI_SLAVE_READY拉个告诉master slave准备好,就可以通信了。
其实简单的方法自己在master发送之前判断Board_SPI_SLAVE_READY电平。

user5999760:

回复 Alvin Chen:

关于Board_SPI_MASTER_READY和Board_SPI_SLAVE_READY这边是没有问题的,现在的问题我觉得应该是在SPI_transfer之后,既没有收到数据也没有发出数据

Alvin Chen:

回复 user5999760:

你SPI_transfer返回是transferOK ?你bebug到SPI_transfer看一下是否返回transferOK,如果返回去用示波器抓一下

我在你的程序没有看到Board_SPI_SLAVE_READY触发中断post信号量的过程
*======== slaveReadyFxn ========*Callback function for the GPIO interrupt on Board_SPI_SLAVE_READY.*/
void slaveReadyFxn(uint_least8_t index)
{sem_post(&masterSem);
}

user5999760:

回复 Alvin Chen:

我debug第一次是ok,但是rxbuffer里全是0

我就是把函数转移过来的,除了semwait改成了Semaphore_pend等,就是更改了一下project_zero里的CC2640R2_LAUNCHXL.h

把#define CC2640R2_LAUNCHXL_SPI0_CSN          PIN_UNASSIGNED改成和spimaster一样的    

#define CC2640R2_LAUNCHXL_SPI0_CSN              IOID_11

就是片选信号吧

void slaveReadyFxn(uint_least8_t index)

{

   Semaphore_post(sem);

   count++;

}

如果有条件,你们能不能试一下看看会不会出现我说的问题

赞(0)
未经允许不得转载:TI中文支持网 » SPI master 代码转移到 ti-rtos的project zero 里发现,与spi slave 通信不了
分享到: 更多 (0)