eRPC error handling for SPI transfer

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

eRPC error handling for SPI transfer

1,857 Views
sevi
Contributor II

Hi,

 

I'm using eRPC with the LPC54605 as eRPC-Server (SPI-Slave) and an embedded Linux as eRPC-Client (SPI-Master).

The server is running with erpc_server_run() and this works fine as long as there is no error. If an error accurse the erpc_server_run() function returns. The question is what to do in case of error, what’s the correct way of error handling. If I simply restart the server it immediately returns with kErpcStatus_ReceiveFailed. This is because the eRPC-client hook into SpidevMasterTransport_WaitForSlaveReadyMarker and waiting for ERPC_BOARD_SPI_SLAVE_READY_MARKER1/2 which never send by the server.

 

How to deal with the client hook? Should the server send the two markers to push client out of this loop?

 

Thank you for your assistance

Sebastian

Labels (1)
Tags (1)
0 Kudos
Reply
6 Replies

1,815 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi

Is your project related with any NXP demo code? If yes, SDK demo or refer this link?

https://community.nxp.com/t5/MCUXpresso-SDK-Knowledge-Base/Introducing-eRPC/ta-p/1099139

Please let me know the specific demo code you referred to thus I can look into it directly. 

Thanks

Jun Zhang

0 Kudos
Reply

1,811 Views
sevi
Contributor II

Hi,

 

thank you for your replay.

Unfortunately for the used LPC54605 there is no demo code. My starting point was the LED example from GitHub: https://github.com/EmbeddedRPC/erpc

I try to describe more exactly what I'm doing here:

- principal environment

*---------------*            *-----------------*
|  erpc Client  |     ---->  |  erpc Server    |
*---------------*            *-----------------*
 - Xilinx UltraScale+         - NXP LPC54605
 - petalinux                  - FreeRTOS
 - SPI Master                 - SPI Slave

 

- IDL code

// Define a data type.
const int32 BUFFER_SIZE_1k = 1024;

type TestBuffer1k_t = int8[BUFFER_SIZE_1k];

// Grouping name for test module
@group("Test")

// An interface is a logical grouping of functions.
interface testFunctions {
    writeData1k(in TestBuffer1k_t buffer) -> void
    readData1k(out TestBuffer1k_t buffer) -> void
}

 

- eRPC Server task

erpc_transport_t tTransport;
erpc_mbf_t tBuffer;
erpc_status_t tStatus;

/* MU transport layer initialization */
tTransport = erpc_transport_spi_slave_init(BOARD_SPI0_BM_BASEADDR, 1e6, CLOCK_GetFlexCommClkFreq(kFRO12M_to_FLEXCOMM5));

/* MessageBufferFactory initialization */
tBuffer = erpc_mbf_dynamic_init();

/* eRPC server side initialization */
erpc_server_init(tTransport, tBuffer);

// Add the IO service.
erpc_add_service_to_server(create_testFunctions_service());

/* set SPI client IRQ priority above SYSCALL_INTERRUPT_PIORITY as requested in FreeRTOS */
NVIC_SetPriority(FLEXCOMM5_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);

while (true) {
  // Run the server.
  tStatus = erpc_server_run();
  
  // print error message
  PRINTF("eRPC Server Run quit: %d\n", tStatus);

  // NOT WORKING but solution for erpc client hook because of erpc server exit on e.g. CRC error
  // after error erpc client hook into receiving ERPC_BOARD_SPI_SLAVE_READY_MARKER1 = 0xAB and ERPC_BOARD_SPI_SLAVE_READY_MARKER2 = 0xCD
  //SendSlaveReadyMarker();
} // endless loop

 

- eRPC server function implementation

static TestBuffer1k_t TestBuffer;

void writeData1k(const TestBuffer1k_t buf) {
  memcpy(&TestBuffer[0], &buf[0], sizeof(TestBuffer));
}

void readData1k(TestBuffer1k_t buf) {
  memcpy(&buf[0], &TestBuffer[0], sizeof(TestBuffer));
}

 

- eRPC client code

TestBuffer1k_t txBuf;
TestBuffer1k_t rxBuf;

/* Init eRPC client environment */
/* spiDev transport layer initialization */
erpc_transport_t transport = erpc_transport_spidev_master_init("/dev/spidev0.0", 1e6);

/* MessageBufferFactory initialization */
erpc_mbf_t message_buffer_factory = erpc_mbf_dynamic_init();

/* eRPC client side initialization */
erpc_client_init(transport, message_buffer_factory);
erpc_client_set_error_handler(error_handler);

/* eRPC test loop */
while (true) {
  /* fill buffer with random data */
  for (i = 0; i < BUFFER_SIZE_1k; i++) {
    txBuf[i] = (int8_t) random();
  }

  /* send data to erpc Server */
  writeData1k(&txBuf[0]);

  /* receive previosly send data again */
  readData1k(&rxBuf[0]);

  /* check for data consistency */
  for (i = 0; i < BUFFER_SIZE_1k; i++) {
    if (txBuf[i] != rxBuf[i]) {
      m_print.out(DL_None, "Failed_1k 0x%08X != 0x%08X\n", txBuf[i], rxBuf[i]);
    }
  }
}

 

- eRPC client error handler

void error_handler(erpc_status_t err, uint32_t functionID) {
  if (err != 0) {
    // error accured sleep 1s to allow MCU to restart eRPC server
    printf("err_%d - fucId: %d\n", err, functionID);
    sleep(1);
  } else {
    // sleep after RPC was sucessfull to avoid MCU SPI overload
    usleep(4);
  }
}

 

Hopefully this is understandable, feel free to ask if there are any questions or you need more information.

 

This code works fine for a certain time but in a disturbed environment a CRC could accure. For this CRC error I dont know how to handle correctly.

After CRC error accures the eRPC client stuck into the endless loop waiting for the ERPC_BOARD_SPI_SLAVE_READY_MARKER1 and ERPC_BOARD_SPI_SLAVE_READY_MARKER2 as defined in "erpc_spi_master_transport.cpp". To release the loop the eRPC server has to send this two markers. If I do this manually the SPI erpc server initialisation interferes with the manual way so this couldn't be the solution.

 

Thank you and best regards

Sebastian

0 Kudos
Reply

1,797 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi 

When there is an issue on the erpc server side and the erpc_server_run() returns an error then it is up to the application to handle that situation. One possible solution would be to notify the client side (any additional communication channel between the server and the client core/task – it could be via MessagingUnit or Mailbox module in case of dual-core SoCs or via a dedicated GPIO pin in case of the communication between two SoCs) that the server is restarting. Then the erpc server can be restarted and the erpc client can also give up sending the actual erpc request and re-init it once the erpc server is back and running again. I am afraid this is application specific and the erpc library does not provide such an functionality.

Besides, if you have further question on Github code  https://github.com/EmbeddedRPC/erpc , I suggest you ask it directly to this site, The code owner could be able to answer you there.

 

Have a nice day

Jun Zhang

0 Kudos
Reply

1,793 Views
sevi
Contributor II

Hi,

 

thank you for the answer.

You are right in saying it is part of application code to handle the error and setup the erpc server again. But if the erpc client stuck into endless loop within erpc lib waiting for the markers and the erpc server do not release this on restart it is hard to get them out there.

 

For me I also tried to use GPIO pin instead of SPI Markers for signaling erpc server is ready. This works much better and I'll get a better opportunity to get erpc client out of the endless loop.

 

Nevertheless I'll go on with my question on GitHub: https://github.com/EmbeddedRPC/erpc/issues/209

 

Thank you for your support.

0 Kudos
Reply

1,759 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Thank you!

0 Kudos
Reply

1,791 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

You are welcome!

0 Kudos
Reply