I am using the S32K3X4EVB-T172 eval board. I have configured both LIN1 and LIN2 as master. Currently, I am using LIN1 and sending a master diagnostic request to a PLIN-View Pro configured as a slave device (with address set as 0x1).
However, I have observed the following:
I am not really sure that I have configured the LIN peripheral properly. I have repurposed the FreeRTOS toggle LED example and configured a UART to serve as console and the UART5 and UART9 to LIN1 and LIN0 periperals.
I am attaching both the code (zipped) and the ldf file for a slave.
Please let me know what I might have missed.
Hi,
have you tried to measure LIN bus signal by scope or analyzer to know it is really send?
There is TimeoutValue decrementing in waiting for TX, but it does not seem you have set it finally from default zero.
A S32DS examples use below value
#define T_LIN_TIME_OUT (400000U)
/* Wait for the transmission done */
TimeoutValue = 4*T_LIN_TIME_OUT;
BR, Petr
Hi Peter,
I have tried to scope at different points along the communication between Master and Slave. My slave is a simple RGB Led slave from Skpang Electronics, https://copperhilltech.com/lin-bus-slave-rgb-led-breakout-board/
At this time, I see the following:
// Go to sleep first, then send wakeup
Lpuart_Lin_Ip_GoToSleepMode(LIN_INSTANCE_1);
delay_ms(10); // allow idle to complete
printf("After sleep: LIN1 Node state: %d\n", Lpuart_Lin_Ip_Sa_pHwConfigPB_1.StateStruct->CurrentNodeState);
if (Lpuart_Lin_Ip_SendWakeupSignal(LIN_INSTANCE_1) != LPUART_LIN_IP_STATUS_SUCCESS) {
printf("LIN1 wakeup failed\n");
}
delay_ms(10); // allow wakeup pulse to propagate
printf("LIN1 After wakeup: Node state: %d\n", Lpuart_Lin_Ip_Sa_pHwConfigPB_1.StateStruct->CurrentNodeState);
//Important: Move to IDLE so you can transmit
Lpuart_Lin_Ip_GoToIdleState(LIN_INSTANCE_1);
printf("LIN1 After idle: Node state: %d\n", Lpuart_Lin_Ip_Sa_pHwConfigPB_1.StateStruct->CurrentNodeState);
// Let's poll for idle to complete.
if (lin_wait_for_idle(LIN_INSTANCE_1, LIN_IDLE_TIMEOUT_MS) != 0) {
printf("LIN1 Timeout waiting for node to reach IDLE state\n");
} else {
printf("LIN1 Node is now IDLE\n");
}
status = Lpuart_Lin_Ip_GetStatus(LIN_INSTANCE_1, &dummy_rx_ptr);
if (status == LPUART_LIN_IP_STATUS_SLEEP) {
// wake up the node
Lpuart_Lin_Ip_SendWakeupSignal(LIN_INSTANCE_1);
vTaskDelay(pdMS_TO_TICKS(10)); // Allow slave to wake up
Lpuart_Lin_Ip_GoToIdleState(LIN_INSTANCE_1); // forces node into idle mode
vTaskDelay(pdMS_TO_TICKS(10));
}
while (Lpuart_Lin_Ip_Sa_pHwConfigPB_0.StateStruct->CurrentNodeState != LPUART_LIN_IP_NODE_STATE_IDLE);
printf("before calling SendFrame: State: %d, Busy: %d\n",
Lpuart_Lin_Ip_Sa_pHwConfigPB_0.StateStruct->CurrentNodeState,
Lpuart_Lin_Ip_Sa_pHwConfigPB_0.StateStruct->IsBusBusy);
Lpuart_Lin_Ip_Sa_pHwConfigPB_0.StateStruct->IsBusBusy = false;
printf("[LIN_TX] Forcing IsBusBusy = 0 before SendFrame\n");
printf("before calling SendFrame but after forcing isBusBusy: State: %d, Busy: %d\n",
Lpuart_Lin_Ip_Sa_pHwConfigPB_0.StateStruct->CurrentNodeState,
Lpuart_Lin_Ip_Sa_pHwConfigPB_0.StateStruct->IsBusBusy);
uint8_t pid = calculate_pid(msg.pid);
uint8_t check = Lin_Ip_ProcessParity(pid, LIN_IP_CHECK_PARITY);
printf("[DEBUG] PID: 0x%02X, Check result: 0x%02X\n", pid, check);
printf("[DEBUG] CheckSleepMode: %d, CheckDl: %d, CheckPid: %d\n",
(Lpuart_Lin_Ip_Sa_pHwConfigPB_0.StateStruct->CurrentNodeState == LPUART_LIN_IP_NODE_STATE_SLEEP_MODE),
(msg.len == 0 || msg.len > 8),
(Lin_Ip_ProcessParity(pid, LIN_IP_CHECK_PARITY) == 0xFF));
(void)Lpuart_Lin_Ip_SendFrame(LIN_INSTANCE_1, &pdu);
// Wait until the frame transmission completes or times out
timeout = LIN_TIMEOUT_MS;
do {
status = Lpuart_Lin_Ip_GetStatus(LIN_INSTANCE_1, (const uint8 **)&dummy_rx_ptr);
vTaskDelay(pdMS_TO_TICKS(1));
} while ((LPUART_LIN_IP_STATUS_TX_OK != status) && (timeout-- > 1));
if (timeout == 0 || status != LPUART_LIN_IP_STATUS_TX_OK) {
printf("[LIN_TX] Frame send timeout or error, status = %d\n", status);
}
}
Lpuart_Lin_Ip_Sa_pHwConfigPB_0.StateStruct->IsBusBusy = false;
Since I have code in our proprietary repo, I will update the FreeRTOS ToggleLed example and send it to you, if you need it. Please let me know.
Some scope captures ...
These ones are with LPUART9/5/1 acting as UART.
In particular, Channel 1 & 13 are with LPUART1 out through PTC7 and I am bitbanging the break and sync character.
Channel 10/11 - LIN1_SLP and LIN2_SLP are always high, which is good.
Next I will attach captures where one of the UARTs 5/9 are configured as LIN and we will try to transmit some command.
Hi,
check if driver's interrupt are properly assigned. You can follow demo examples. Consider interrupts priorities. Also try to first test without printing.
BR, Petr