to send the CAN frames after recieving ACK in CAPL (using delay/timer in CAPL) - can-bus

I wrote a CAPl code, where it has to send the CAN frames to control the stepper motor step. stepper motor used is TMCM-1311 module.
variables{
message step myMsg1;
message llmmodule myMsg2;
message llmmodule myMg3;
}
on start{
int i=0;
for (i=0:;i<=5000:i++)
{
myMsg1.DLC = 8;
myMsg1.byte(0) = 0x04;
myMsg1.byte(1) = 0x01;
myMsg1.byte(2) = 0x00;
myMsg1.byte(3) = 0x00;
myMsg1.byte(4) = 0x00;
myMsg1.byte(5) = 0x00;
myMsg1.byte(6) = 0x0A;
myMsg1.byte(7) = 0x00;
output(mymsg1);
myMsg2.DLC = 8;
myMsg2.byte(0) = 0x07;
myMsg2.byte(1) = 0x01;
myMsg2.byte(2) = 0x03;
myMsg2.byte(3) = 0x11;
output(mymsg2);
myMsg3.DLC = 8;
myMsg3.byte(0) = 0x07;
myMsg3.byte(1) = 0x03;
myMsg3.byte(2) = 0x01;
myMsg3.byte(3) = 0x00;
output(mymsg3);
}
}
In the for loop of the above code, the CAN frame is continuously sent without waiting for the ACK, the 1st data frame i.e., myMsg1 is sent for rotating the stepper motor to certain step size, so once that frame is sent it takes some time for the stpper motor to rotate to that position, once it is at that position then the other 2 CAN frames i.e., myMsg2 and myMsg3 should be sent. After the ACK recieved for all the 3 data frames sent then i in the for loop should increment and the next iteration should take place. But in the above code the for loop is executing without waiting for the ACK from the CAN frame, so i think timer should be used there to give a delay and to execute the next iterations after the ACK is received. I tried using timers but i could not find a solution as required, so it would be great help if anyone can let me know how it should be executed.

You have to use the on message event for this use case.
variables
{
message step myMsg1;
message llmmodule myMsg2;
message llmmodule myMg3;
}
on start
{
myMsg1.DLC = 8;
myMsg1.byte(0) = 0x04;
myMsg1.byte(1) = 0x01;
myMsg1.byte(2) = 0x00;
myMsg1.byte(3) = 0x00;
myMsg1.byte(4) = 0x00;
myMsg1.byte(5) = 0x00;
myMsg1.byte(6) = 0x0A;
myMsg1.byte(7) = 0x00;
myMsg2.DLC = 8;
myMsg2.byte(0) = 0x07;
myMsg2.byte(1) = 0x01;
myMsg2.byte(2) = 0x03;
myMsg2.byte(3) = 0x11;
myMsg3.DLC = 8;
myMsg3.byte(0) = 0x07;
myMsg3.byte(1) = 0x03;
myMsg3.byte(2) = 0x01;
myMsg3.byte(3) = 0x00;
output(mymsg1);
}
on message ACK_Msg1
{
output(mymsg2);
}
on message ACK_Msg2
{
output(mymsg3);
}
on message ACK_Msg3
{
output(mymsg1);
}
This code will go on until the ack messages stop. So, if you want to do this for a definite amount of times, you might have to use some kind of flags in every event.

Related

Could I Test CAN Tranceiver with External Loopback Mode?

Hello I am using STM32H753 over a custom PCB.
I have no any CAN Analyzer except oscilloscope, multimeter and logic analyzer.
We have a problem with CAN BUS communication.
I am suspecting of CAN Tranceiver but we couldn't find the root cause yet.
There are external and internal loopback modes in STM32H7 to test CAN, However these modes also allow us to see the messages what we sent on CAN TX.
I have two different product which has different STM32H753 variant. One is working and the other one is not. Their tranceivers are different but almost same pinout and behavior.
My assumption was if I see my messages on CAN TX then I have to see them CAN H and CAN L.
I wrote test code.
I tried both test code in both device.
On working one, I saw messages on CAN Tx and also see messages with in a suppress way which I thought because of no termination resistor at the end.
On the not-working one, I also saw messages at CAN TX and there is no any move at CAN H or CAN L.
My question is my test was is true or still I could miss something or this test does not imply anyhting ?
HAL_Delay(100);
if(HAL_FDCAN_AddMessageToTxBuffer(&hfdcan1, &TxHeader, TxData_Node1_To_Node2, FDCAN_TX_BUFFER0 ) != HAL_OK)
{
Error_Handler();
}
/* Send Tx buffer message */
if(HAL_FDCAN_EnableTxBufferRequest(&hfdcan1, FDCAN_TX_BUFFER0) != HAL_OK)
{
Error_Handler();
}
while(HAL_FDCAN_IsTxBufferMessagePending(&hfdcan1, FDCAN_TX_BUFFER0) == 1);
/* Polling for reception complete on buffer index 0 */
while(HAL_FDCAN_IsRxBufferMessageAvailable(&hfdcan1, FDCAN_RX_BUFFER0) == 0);
/* Retrieve message from Rx buffer 0. Rec msg from Node 2 */
if(HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_BUFFER0, &RxHeader, RxData_From_Node2) != HAL_OK)
{
Error_Handler();
}
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_EXTERNAL_LOOPBACK;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 1;
hfdcan1.Init.NominalSyncJumpWidth = 13;
hfdcan1.Init.NominalTimeSeg1 = 86;
hfdcan1.Init.NominalTimeSeg2 = 13;
hfdcan1.Init.DataPrescaler = 2;
hfdcan1.Init.DataSyncJumpWidth = 12;
hfdcan1.Init.DataTimeSeg1 = 12;
hfdcan1.Init.DataTimeSeg2 = 12;
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 0 ;
hfdcan1.Init.RxFifo0ElmtsNbr = 0;
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxFifo1ElmtsNbr = 0;
hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxBuffersNbr = 1;
hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.TxEventsNbr = 0;
hfdcan1.Init.TxBuffersNbr = 1;
hfdcan1.Init.TxFifoQueueElmtsNbr = 32;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}

ESP32+SN65HVD230 custom baud rate

I am trying to read CAN bus from my car (my car use 95Kbps can speed).
I use this library Link. To add custom CAN baud rate, added this
typedef enum {
CAN_SPEED_100KBPS = 100, /**< \brief CAN Node runs at 100kBit/s. */
CAN_SPEED_125KBPS = 125, /**< \brief CAN Node runs at 125kBit/s. */
CAN_SPEED_200KBPS = 200, /**< \brief CAN Node runs at 250kBit/s. */
CAN_SPEED_250KBPS = 250, /**< \brief CAN Node runs at 250kBit/s. */
CAN_SPEED_500KBPS = 500, /**< \brief CAN Node runs at 500kBit/s. */
CAN_SPEED_800KBPS = 800, /**< \brief CAN Node runs at 800kBit/s. */
CAN_SPEED_1000KBPS = 1000 /**< \brief CAN Node runs at 1000kBit/s. */
CAN_SPEED_95KBPS = 95 /**< \brief CAN Node runs at 95kBit/s. */ //This string I added
} CAN_speed_t;
And I use esp32can_basic.ino with two modifications
Set speed
CAN_cfg.speed = CAN_SPEED_95KBPS;
Delete writing
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
CAN_frame_t tx_frame;
tx_frame.FIR.B.FF = CAN_frame_std;
tx_frame.MsgID = 0x001;
tx_frame.FIR.B.DLC = 8;
tx_frame.data.u8[0] = 0x00;
tx_frame.data.u8[1] = 0x01;
tx_frame.data.u8[2] = 0x02;
tx_frame.data.u8[3] = 0x03;
tx_frame.data.u8[4] = 0x04;
tx_frame.data.u8[5] = 0x05;
tx_frame.data.u8[6] = 0x06;
tx_frame.data.u8[7] = 0x07;
ESP32Can.CANWriteFrame(&tx_frame);
But nothing work :(
My hardware is ESP32-PICO-D4 and SN65HVD230 CAN Board. What have I done wrong?
UPD1 in CAN.c in int CAN_init() there are this strings
switch (CAN_cfg.speed) {
case CAN_SPEED_1000KBPS:
MODULE_CAN->BTR1.B.TSEG1 = 0x4;
__tq = 0.125;
break;
case CAN_SPEED_800KBPS:
MODULE_CAN->BTR1.B.TSEG1 = 0x6;
__tq = 0.125;
break;
case CAN_SPEED_200KBPS:
MODULE_CAN->BTR1.B.TSEG1 = 0xc;
MODULE_CAN->BTR1.B.TSEG2 = 0x5;
__tq = 0.25;
break;
default:
MODULE_CAN->BTR1.B.TSEG1 = 0xc;
__tq = ((float) 1000 / CAN_cfg.speed) / 16;
}
I think this code calculate tq.
"Nothing work" - no CAN codes read. I think I set wrong baud rate.
TQ (Time Quanta) is like the Sampling rate at which this SP is taken, which is also between TSEG1 and TSEG2 First and second Segment.
You need to calculate this values (check here) for more infor and a calculator

Problem reading data from multiple ADC channels with stm32f4-discovery board using DMA

I am trying to read data from channel 0,1,2 and 3 of ADC1. The issue is that when I read from channel 1 and channel 2 and run the code in debug mode it shows the correct valueenter image description heres but when I modified it for doing the same for channel 3 and 4 also,it does not show any value.Following is the code and the screen shot of memory map:
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
uint16_t ADC1ConvertedValue[4] = {0,0,0,0};//Stores converted vals [2] = {0,0}
void DMA_config()
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 ,ENABLE);
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_Channel = DMA_Channel_0;
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t) 0x4001204C;//ADC1's data register
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStruct.DMA_BufferSize = 4;//2
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//Reads 16 bit values _HalfWord
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//Stores 16 bit values _Halfword
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;//_HalfFull
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStruct);
DMA_Cmd(DMA2_Stream0, ENABLE);
}
void ADC_config()
{
/* Configure GPIO pins ******************************************************/
ADC_InitTypeDef ADC_InitStruct;
ADC_CommonInitTypeDef ADC_CommonInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//ADC1 is connected to the APB2 peripheral bus
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;// PA0,PA1,PA3,PA3
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;//The pins are configured in analog mode
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL ;//We don't need any pull up or pull down
GPIO_Init(GPIOA, &GPIO_InitStruct);//Initialize GPIOA pins with the configuration
/* ADC Common Init **********************************************************/
ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStruct);
/* ADC1 Init ****************************************************************/
ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;//Input voltage is converted into a 12bit int (max 4095)
ADC_InitStruct.ADC_ScanConvMode = ENABLE;//The scan is configured in multiple channels
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;//Continuous conversion: input signal is sampled more than once
ADC_InitStruct.ADC_ExternalTrigConv = DISABLE;
ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//Data converted will be shifted to right
ADC_InitStruct.ADC_NbrOfConversion = 4;
ADC_Init(ADC1, &ADC_InitStruct);//Initialize ADC with the configuration
/* Select the channels to be read from **************************************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_144Cycles);//PA0
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_144Cycles);//PA1
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_144Cycles);//PA2
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_144Cycles);//PA3
/* Enable DMA request after last transfer (Single-ADC mode) */
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
}
int main(void)
{
DMA_config();
ADC_config();
while(1)
{
ADC_SoftwareStartConv(ADC1);
//value=ADC_Read();
}
return 0;
}
You shouldn't start the ADC conversion multiple times (in your while(1) loop).
Since you've configured the ADC with .ADC_ContinuousConvMode = ENABLE it should be enough to start it before the loop and do nothing within it.

Portaudio MME device behaviour issue

I am using the multiple-output-device feature provided by paMME host API to output audio through multiple stereo devices. I also need to use a single multichannel input device using MME.
- When I configure just the output device and play internally generated audio, there is no problem.
- However problem starts to occur when I configure both the input device and the mulitple-stereo output devices. The application crashes when I try to use more than two channels on the output. That is, if I try to increment the 'out' pointer for more than 2*frames_per_buffer , it crashes, which indicates that buffer has been allocated only to two output channels.
Can anybody throw some light on what could be the problem. The configuration code is given below:
outputParameters.device = paUseHostApiSpecificDeviceSpecification;
outputParameters.channelCount = 8;
outputParameters.sampleFormat = paInt16;
outputParameters.hostApiSpecificStreamInfo = NULL;
wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);
wmmeStreamInfo.hostApiType = paMME;
wmmeStreamInfo.version = 1;
wmmeStreamInfo.flags = paWinMmeUseMultipleDevices;
wmmeDeviceAndNumChannels[0].device = selectedDeviceIndex[0];
wmmeDeviceAndNumChannels[0].channelCount = 2;
wmmeDeviceAndNumChannels[1].device = selectedDeviceIndex[1];
wmmeDeviceAndNumChannels[1].channelCount = 2;
wmmeDeviceAndNumChannels[2].device = selectedDeviceIndex[2];
wmmeDeviceAndNumChannels[2].channelCount = 2;
wmmeDeviceAndNumChannels[3].device = selectedDeviceIndex[3];
wmmeDeviceAndNumChannels[3].channelCount = 2;
wmmeStreamInfo.devices = wmmeDeviceAndNumChannels;
wmmeStreamInfo.deviceCount = 4;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( selectedDeviceIndex[0] )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;
inputParameters.device = selectedInputDeviceIndex; /* default output device */
inputParameters.channelCount = 8; /* stereo output */
inputParameters.sampleFormat = paInt16; /* 32 bit floating point output */
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
Thanks and regards,
Siddharth Kumar.

Data appearing as Ethernet Trailer in self made SKB

Im trying to make a custom skb in a linux kernel module and then send it over the network.
I succeed in making a SKB but when I send it over the network it does not reach the destination.
If I run wireshark on the local machine that is sending my SBK over the network, it shows my packet. However if I examine the contents of my packet, it shows that the data is being placed as 'Ethernet Trailer'
Also, if I remove all data from my SKB and only send a Header-only SKB, it still does not reach its destination
Here is the code:
u_int32_t local_ip;
u_int32_t remote_ip;
struct udphdr *udph;
struct iphdr *iph;
struct ethhdr *eth;
unsigned short udp_len;
char remote_mac[6];
char local_mac[6];
Allocate a skb:
int header_len = sizeof(*iph) + sizeof(*udph) + sizeof(*eth);
skb = sock_wmalloc(sock->sk, /*payload len*/ len + header_len + LL_RESERVED_SPACE(pfr->ring_netdev->dev), 0, GFP_KERNEL);
Since I am using skb_push, I move down data and tail all the way down:
skb_reserve(skb,
len + header_len + LL_RESERVED_SPACE(pfr->ring_netdev->dev));
Push UDP header:
skb_push(skb, sizeof(*udph));
Reset the transport_pointer accordingly:
skb_reset_transport_header(skb);
Set and populate udp header:
udph = udp_hdr(skb);
udph->source = htons(5123);
udph->dest = htons(5123);
udp_len = 14;
udph->len = htons(udp_len);
udph->check = 0;
local_ip = htonl(0xCB873F2A); /*203.135.63.42*/
remote_ip = htonl(0xCB873F29); /*203.135.61.41*/
udph->check = csum_tcpudp_magic(local_ip,
remote_ip,
udp_len, IPPROTO_UDP,
csum_partial(udph, udp_len, 0));
if (udph->check == 0) {
printk("mangled checksum\n");
udph->check = CSUM_MANGLED_0;
}
Now to push IP header:
skb_push(skb, sizeof(*iph));
Reset the network_pointer:
skb_reset_network_header(skb);
Set and populate the network header:
iph = ip_hdr(skb);
put_unaligned(0x45, (unsigned char *)iph);
iph->tos = 0;
ip_len = 40;
put_unaligned(htons(ip_len), &(iph->tot_len));
//iph->id = htons(atomic_inc_return(&ip_ident));
iph->frag_off = 0;
iph->ttl = 64;
iph->protocol = IPPROTO_UDP;
iph->check = 0;
put_unaligned(local_ip /*"\xC0\xA8\x00\x01"*/, &(iph->saddr));
put_unaligned(remote_ip /*"\xC0\xA8\x00\x01"*/, &(iph->daddr));
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
Push the Ethernet Header:
eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
Reset the mac_pointer accordingly:
skb_reset_mac_header(skb);
set and populate the mac_header:
skb->protocol = eth->h_proto = htons(ETH_P_IP);
remote_mac[0] = 0x4C;
remote_mac[1] = 0x72;
remote_mac[2] = 0xB9;
remote_mac[3] = 0x24;
remote_mac[4] = 0x14;
remote_mac[5] = 0x1E;
local_mac[0] = 0x00;
local_mac[1] = 0x1E;
local_mac[2] = 0xE3;
local_mac[3] = 0xED;
local_mac[4] = 0xD4;
local_mac[5] = 0xA9;
memcpy(eth->h_source, remote_mac, ETH_ALEN);
memcpy(eth->h_dest, remote_mac, ETH_ALEN);
Set device and protocol:
skb->protocol = htons(ETH_P_IP);
skb->dev = pfr->ring_netdev->dev;
skb->priority = sock->sk->sk_priority;
if(!err)
goto out_free;
Now send it
if (dev_queue_xmit(skb) != NETDEV_TX_OK) {
err = -ENETDOWN; /* Probably we need a better error here */
goto out;
}

Resources