I'm working with the CAN Module from the STM32F446RE board which has the MCU mentioned in the title. I'm trying to transmit some data on the UART via Tera Term terminal and take this data and send it via Loopback mode and read it back. For starters I have generated the configuration from CubeMx and written some code to transmit a numerical value which the user enters to the can 'network' and when that happens I want to go into an can completed transmission ISR and print some message on the UART from there to indicate that the transfer was completed.
In the CubeMx I have configured the CAN interrupts like this:
CAN1 TX interrupt enabled
CAN1 RX interrupt enabled(because I will also want to trigger the receive interrupt after I fix this issue)
This is the part of the code(I cannot copy paste all as this is the post will become too long just ask me if I need to provide more of my code):
while (1)
{
/*keep getting what the user enters on the UART untill enter is pressed*/
while(received_data != '\r')
{
HAL_UART_Receive(&huart2,&received_data,1,HAL_MAX_DELAY);
recvd_buffer[buf_indx] = received_data;
buf_indx++;
if(buf_indx > 1)
{
buf_indx = 0;
}
}
if( recvd_buffer[0] == '1' || recvd_buffer[0] == '0')
{
received_data = 0;
buf_indx = 0;
user_data = "\n\rOK. Starting CAN transmission in interrupt mode\n\r";
len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
//CAN will start sending data in non-blocking mode
CAN_Tx(recvd_buffer[0]);
recvd_buffer[0] = 0;
recvd_buffer[1] = 1;
}
else
{
recvd_buffer[0] = 0;
recvd_buffer[1] = 1;
received_data = 0;
user_data = "\n\rInvalid value. Please enter either 1 or 2\n\r";
len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
}
}
}
Below I have also implemented the 3 Tx mailbox transmit complete callback functions:
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
{
uint16_t user_data = "\n\rTransmission completed mailbox_0\n\r";
uint16_t len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
}
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan)
{
user_data = "\n\rTransmission completed mailbox_1\n\r";
uint16_t len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
}
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan)
{
user_data = "\n\rTransmission completed mailbox_2\n\r";
uint16_t len_of_data = strlen(user_data);
HAL_UART_Transmit( &huart2, (uint8_t*)user_data, len_of_data, HAL_MAX_DELAY );
}
This is the CAN_Tx function that makes use of the CAN hal driver to send the data:
void CAN_Tx(uint8_t value)
{
uint8_t mailbox_no;
CAN_TxHeaderTypeDef can_header;
can_header.StdId = 0;
can_header.ExtId = 0;
can_header.IDE = CAN_ID_STD;
can_header.RTR = CAN_RTR_DATA;
can_header.DLC = 1;
can_header.TransmitGlobalTime = DISABLE;
HAL_CAN_AddTxMessage(&hcan1, &can_header, value, &mailbox_no);
}
I have debugged the code in main and it seems to work fine. I got no error in the Can_Tx function it returns with success. From my understanding from the datasheet of the microcontroller(secttion 30.8 - bxCAN interrupts) if the timer1 transmit interrupt is enabled than depending on which mailbox was used for transmission one of those callbacks should get executed. However that does not happen the code inside them won't get executed. Please help me understand what I'm doing wrong. Thank you!
Related
I have a custom ZYNQ7000-based board. I want to insert an AXI GPIO that directly generate an interrupt. I want to handle the interrupt in a kernel module. All things sound to be correct but it does not work.
My Toolset:
Petalinux 2021.2 installed on Ubuntu 20.04.03
Vivado 2021.2
I have only one interrupt that I connect it to the processor interrupt input.
I connect a push button to AXI GPIO 1 and configure it to generate interrupt.
Based on my pl-DTS file
/ {
amba_pl: amba_pl {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges ;
axi_gpio_0: gpio#41200000 {
#gpio-cells = <3>;
clock-names = "s_axi_aclk";
clocks = <&clkc 15>;
compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
gpio-controller ;
reg = <0x41200000 0x10000>;
xlnx,all-inputs = <0x0>;
xlnx,all-inputs-2 = <0x0>;
xlnx,all-outputs = <0x1>;
xlnx,all-outputs-2 = <0x0>;
xlnx,dout-default = <0x00000000>;
xlnx,dout-default-2 = <0x00000000>;
xlnx,gpio-width = <0x4>;
xlnx,gpio2-width = <0x20>;
xlnx,interrupt-present = <0x0>;
xlnx,is-dual = <0x0>;
xlnx,tri-default = <0xFFFFFFFF>;
xlnx,tri-default-2 = <0xFFFFFFFF>;
};
axi_gpio_1: gpio#41210000 {
#gpio-cells = <3>;
#interrupt-cells = <2>;
clock-names = "s_axi_aclk";
clocks = <&clkc 15>;
compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
gpio-controller;
interrupt-controller;
interrupt-names = "ip2intc_irpt";
interrupt-parent = <&intc>;
interrupts = <0 29 4>;
reg = <0x41210000 0x10000>;
xlnx,all-inputs = <0x1>;
xlnx,all-inputs-2 = <0x0>;
xlnx,all-outputs = <0x0>;
xlnx,all-outputs-2 = <0x0>;
xlnx,dout-default = <0x00000000>;
xlnx,dout-default-2 = <0x00000000>;
xlnx,gpio-width = <0x1>;
xlnx,gpio2-width = <0x20>;
xlnx,interrupt-present = <0x1>;
xlnx,is-dual = <0x0>;
xlnx,tri-default = <0xFFFFFFFF>;
xlnx,tri-default-2 = <0xFFFFFFFF>;
};
};
};
The interrupt should be at 61 (29 + 32 = 61): interrupts = <0 29 4>;.
I enable the interrupt enable register and global interrupt register.
I want to write a kernel module and register the axi-gpio interrupt in that and register a ISR to handle it. the main part of my code is as follows:
if (request_irq(IRQ_NUM, isr, 0, DEVICE_NAME, NULL)) {
printk(KERN_ERR "my_init: Cannot register IRQ %d\n", IRQ_NUM);
return -EIO;
} else {
printk(KERN_INFO "my_init: Registered IRQ %d\n", IRQ_NUM);
}
printk(KERN_INFO "my_init: Initialize Module \"%s\"\n", DEVICE_NAME);
pdev = platform_device_register_simple(DEVICE_NAME, 0, NULL, 0);
if (pdev == NULL) {
printk(KERN_WARNING "my_init: Adding platform device \"%s\" failed\n", DEVICE_NAME);
kfree(pdev);
return -ENODEV;
}
PROBLEMS:
Interrupt 61 could not be registered.
In fact, I found "all free interrupts" and tried "all" with my axi-gpio. None of them works correctly.
I do not want to use GPIO-keys or UIO because they need a blocking read BUT I want to write a kernel module and register the axi-gpio interrupt in that by interrupt request function (request_irq()) and register a ISR for it.
I searched and read all previous problems in the Xilinx and other venders. I tried all solutions but I cannot find anything.
BTW:
The connection between push button and processor is okay because I could activate it by the GPIO-keys. GPIO-keys interrupt catches the push button actions.
I am developing client-server application which transfers data via UDP.
I am facing the problem of dropped packets. I added socket buffer checking to detect potential overflow. Also my app checks sequence of received numbers in packets. Packets have fixed size. If free space of socket buffer is less than threshold (size of 3 packets for example) then "Critical level of buffer" message is logged. If number of packet is skipped in sequence then corresponding message is logged. There is code:
UdpServer::UdpServer(asio::io_service& io, uint16_t port, uint32_t packetSize) : CommunicationBase(io, port),
m_socket(io, asio::ip::udp::endpoint(asio::ip::address_v6::any(), m_port))
{
m_buffer = new uint8_t[packetSize];
m_packetSize = packetSize;
m_socketBufferSize = m_packetSize * 32;
m_criticalLevel = 5 * m_packetSize;
asio::ip::udp::socket::receive_buffer_size recieveBuffSize(m_socketBufferSize);
m_socket.set_option(recieveBuffSize);
}
UdpServer::~UdpServer()
{
std::free(m_buffer);
}
void UdpServer::StartReceive(std::function<void(uint8_t* buffer, uint32_t bytesCount)> receiveHandler)
{
m_onReceive = receiveHandler;
Receive();
}
inline void UdpServer::Receive()
{
m_socket.async_receive(asio::null_buffers(), [=](const boost::system::error_code& error, size_t bytesCount)
{
OnReceive(bytesCount, error);
});
}
void UdpServer::OnReceive(size_t bytesCount, const boost::system::error_code& error)
{
static uint16_t lastSendNum = 65535;
uint16_t currentNum = 0;
uint16_t diff = 0;
if (error)
{
if (error == asio::error::operation_aborted)
{
logtrace << "UDP socket reports operation aborted, terminating";
return;
}
logerror << "UDP socket error (ignoring): " << error.message();
}
else
{
asio::ip::udp::endpoint from;
boost::system::error_code receiveError;
size_t bytesRead = 0;
size_t bytesAvailable = m_socket.available();
while (bytesAvailable > 0)
{
if (m_socketBufferSize - bytesAvailable < m_criticalLevel)
{
logwarning << "Critical buffer level!";
}
bytesRead = m_socket.receive(asio::buffer(m_buffer, m_packetSize), 0, receiveError);
if (receiveError)
{
logerror << "UDP socket error: " << receiveError.message();
break;
}
currentNum = *reinterpret_cast<uint16_t*>(m_buffer);
diff = currentNum - lastSendNum;
if (diff != 1)
{
logdebug << "Chunk skipped: " << diff << ". Last " << lastSendNum << " next " << currentNum;
}
lastSendNum = currentNum;
if (m_onReceive)
{
m_onReceive(m_buffer, bytesRead);
}
bytesAvailable = m_socket.available();
}
}
Receive();
}
Even if checking of buffer status and packet processing m_onReceive are disabled and bytesAvailable > 0 replaced with true, udp packets are dropped. Speed rate is ~71 Mb/s via 1Gb Ethernet.
Windows 10 is used. Also I checked netstat -s result: no reassembly failures. Socket buffer is never being overflowed.
Quoting form this online kernel doc
SO_TIMESTAMPING
Generates timestamps on reception, transmission or both. Supports
multiple timestamp sources, including hardware. Supports generating
timestamps for stream sockets.
Linux supports TCP timestamping, and I tried to write some demo code to get any timestamp for TCP packet.
The server code as below:
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);
client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
// Note: I am trying to get software timestamp only here..
int oval = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
int olen = sizeof( oval );
if ( setsockopt( client_sock, SOL_SOCKET, SO_TIMESTAMPING, &oval, olen ) < 0 )
{ perror( "setsockopt TIMESTAMP"); exit(1); }
puts("Connection accepted");
char buf[] = "----------------------------------------";
int len = strlen( buf );
struct iovec myiov[1] = { {buf, len } };
unsigned char cbuf[ 40 ] = { 0 };
int clen = sizeof( cbuf );
struct msghdr mymsghdr = { 0 };
mymsghdr.msg_name = NULL;
mymsghdr.msg_namelen = 0;
mymsghdr.msg_iov = myiov;
mymsghdr.msg_iovlen = 1;
mymsghdr.msg_control = cbuf;
mymsghdr.msg_controllen = clen;
mymsghdr.msg_flags = 0;
int read_size = recvmsg( client_sock, &mymsghdr, 0);
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
else
{
struct msghdr *msgp = &mymsghdr;
printf("msg received: %s \n",(char*)msgp->msg_iov[0].iov_base);// This line is successfully hit.
// Additional info: print msgp->msg_controllen inside gdb is 0.
struct cmsghdr *cmsg;
for ( cmsg = CMSG_FIRSTHDR( msgp );
cmsg != NULL;
cmsg = CMSG_NXTHDR( msgp, cmsg ) )
{
printf("Time GOT!\n"); // <-- This line is not hit.
if (( cmsg->cmsg_level == SOL_SOCKET )
&&( cmsg->cmsg_type == SO_TIMESTAMPING ))
printf("TIME GOT2\n");// <-- of course , this line is not hit
}
}
Any ideas why no timestamping is available here ? Thanks
Solution
I am able to get the software timestamp along with hardware timestamp using onload with solarflare NIC.
Still no idea how to get software timestamp alone.
The link you gave, in the comments at the end, says:
I've discovered why it doesn't work. SIOCGSTAMP only works for UDP
packets or RAW sockets, but does not work for TCP. – Gio Mar 17 '16 at 9:331
it doesn't make sense to ask for timestamps for TCP, because there's
no direct correlation between arriving packets and data becoming
available. If you really want timestamps for TCP you'll have to use
RAW sockets and implement your own TCP stack (or use a userspace TCP
library). – ecatmur Jul 4 '16 at 10:39
We are using libmodbus library to read register values from energy meter EM6400 which supports Modbus over RTU. We are facing the following two issues.
1) We are facing an issue with modbus_read_registers API, this API returns -1 and the error message is:
ERROR Connection timed out: select.
After debugging the library, we found this issue is due to the echo of request bytes in the response message.
read() API call in _modbus_rtu_recv returns request bytes first followed by response bytes. As a result, length_to_read is calculated in compute_data_length_after_meta() based on the request bytes instead of response bytes (which contains the number of bytes read) and connection timed out issue occurs.
We tried to use both 3.0.6 and 3.1.2 libmodbus versions but same issue occurs in both the versions.
2) modbus_rtu_set_serial_mode (ctx, MODBUS_RTU_RS485) returns "BAD file descriptor".
Please confirm if there is any API call missing or any parameter is not set correctly.
Our sample code to read register value is as follows.
int main()
{
modbus_t *ctx;
uint16_t tab_reg[2] = {0,0};
float avgVLL = -1;;
int res = 0;
int rc;
int i;
struct timeval response_timeout;
uint32_t tv_sec = 0;
uint32_t tv_usec = 0;
response_timeout.tv_sec = 5;
response_timeout.tv_usec = 0;
ctx = modbus_new_rtu("/dev/ttyUSB0", 19200, 'E', 8, 1);
if (NULL == ctx)
{
printf("Unable to create libmodbus context\n");
res = 1;
}
else
{
printf("created libmodbus context\n");
modbus_set_debug(ctx, TRUE);
//modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK |MODBUS_ERROR_RECOVERY_PROTOCOL);
rc = modbus_set_slave(ctx, 1);
printf("modbus_set_slave return: %d\n",rc);
if (rc != 0)
{
printf("modbus_set_slave: %s \n",modbus_strerror(errno));
}
/* Commented - Giving 'Bad File Descriptor' issue
rc = modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
printf("modbus_rtu_set_serial_mode: %d \n",rc);
if (rc != 0)
{
printf("modbus_rtu_set_serial_mode: %s \n",modbus_strerror(errno));
}
*/
// This code is for version 3.0.6
modbus_get_response_timeout(ctx, &response_timeout);
printf("Default response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );
response_timeout.tv_sec = 60;
response_timeout.tv_usec = 0;
modbus_set_response_timeout(ctx, &response_timeout);
modbus_get_response_timeout(ctx, &response_timeout);
printf("Set response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );
/* This code is for version 3.1.2
modbus_get_response_timeout(ctx, &tv_sec, &tv_usec);
printf("Default response timeout:%d sec %d usec \n",tv_sec,tv_usec );
tv_sec = 60;
tv_usec = 0;
modbus_set_response_timeout(ctx, tv_sec,tv_usec);
modbus_get_response_timeout(ctx, &tv_sec, &tv_usec);
printf("Set response timeout:%d sec %d usec \n",tv_sec,tv_usec );
*/
rc = modbus_connect(ctx);
printf("modbus_connect: %d \n",rc);
if (rc == -1) {
printf("Connection failed: %s\n", modbus_strerror(errno));
res = 1;
}
rc = modbus_read_registers(ctx, 3908, 2, tab_reg);
printf("modbus_read_registers: %d \n",rc);
if (rc == -1) {
printf("Read registers failed: %s\n", modbus_strerror(errno));
res = 1;
}
for (i=0; i < 2; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
avgVLL = modbus_get_float(tab_reg);
printf("Average Line to Line Voltage = %f\n", avgVLL);
modbus_close(ctx);
modbus_free(ctx);
}
}
Output of this sample is as follows:
created libmodbus context
modbus_set_slave return: 0
modbus_rtu_set_serial_mode: -1
modbus_rtu_set_serial_mode: Bad file descriptor
Default response timeout:0 sec 500000 usec
Set response timeout:60 sec 0 usec
Opening /dev/ttyUSB0 at 19200 bauds (E, 8, 1)
modbus_connect: 0
[01][03][0F][44][00][02][87][0A]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><03><0F><44><00><02><87><0A><01><03><04><C4><5F><43><D4><C6><7E>modbus_read_registers: -1
Read registers failed: Connection timed out
reg[0]=0 (0x0)
reg[1]=0 (0x0)
Average Line to Line Voltage = 0.000000
Issue 1) is probably a hardware issue, with "local echo" enabled in your RS-485 adapter. Local echo is sometimes used to confirm sending of data bytes on the bus. You need to disable it, or find another RS-485 adapter.
I have written about this in the documentation of my MinimalModbus Python library: Local Echo
It lists a few common ways to disable local echo in RS-485 adapters.
I was able to use the code below to init the SPI and read the values from accelerometer
SPI_InitTypeDef SPI_InitTypeDefStruct;
GPIO_InitTypeDef GPIO_InitTypeDefStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE , ENABLE);
SPI_InitTypeDefStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitTypeDefStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitTypeDefStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitTypeDefStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitTypeDefStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitTypeDefStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //seems like it was here causing trouble
SPI_InitTypeDefStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI1, &SPI_InitTypeDefStruct);
GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_6;
GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitTypeDefStruct);
GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOE, &GPIO_InitTypeDefStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
SPI_Cmd(SPI1, ENABLE);
SPI_send(0x23, 0xc9); // resetting the accelerometer internal circuit
//SPI_send(0x20, 0x67); // 100Hz data update rate, block data update disable, x/y/z enabled
SPI_send(0x20, 0x97);
//SPI_send(0x24, 0x20); // Anti aliasing filter bandwidth 800Hz, 16G (very sensitive), no self-test, 4-wire interface
SPI_send(0x24, 0x00); // Anti aliasing filter bandwidth 800Hz, 2G ( sensitive ??), no self-test, 4-wire interface
SPI_send(0x10, 0x00); // Output(X) = Measurement(X) - OFFSET(X) * 32;
SPI_send(0x11, 0x00); // Output(Y) = Measurement(Y) - OFFSET(Y) * 32;
SPI_send(0x12, 0x00); // Output(Z) = Measurement(Z) - OFFSET(Z) * 32;
void SPI_send(uint8_t address, uint8_t data)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_3);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, address);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, data);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
}
uint8_t SPI_read(uint8_t address)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_3);
address = 0x80 | address; // 0b10 - reading and clearing status
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, address);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, 0x00);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
return SPI_I2S_ReceiveData(SPI1);
}
Then I combined these code with my project which has an 500Hz interrupt.
It always work at first but if i unplug the board then plug it in again, SPI will only read zeros, even though the LIS3DSH still have readings(i used oscilloscope checked it). I had to download the shorter version of the project code( taking out most of the code in the interrupt) to get SPI to work properly again.
I am using the Kickstart, size-limited IAR ewarm I thought it was because my code exceed the limit. But I did not get warning and my code was not more than 32kb.
I am just confused since it works until I unplug it. Could someone give me some suggestions?
Thanks
I decided just to add the SPI_DeInit(...) before SPI_Init(...). This seems to solve the problem. I still dont understand why it wont reset itself though.