SPI fails to read first 6 bytes - stm32

I'm having a lot of issues with SPI module on my STM32F051 MCU. I've got it configured as a master to drive a slave flash memory module (that doesn't really matter).
I'm trying to read 8 bytes from memory, this is how the 'read data' message is structured:
First 4 bytes of the message are transmitted, next 8 are received.
First byte is 'read data' opcode, three following are data address and equal 0 in this case.
Code:
memset(out, 0x00, 256);
memset(in, 0x00, 256);
out[0] = OPCODE_READ;
out[1] = 0x00;
out[2] = 0x00;
out[3] = 0x00;
uint32_t len = 4 + size; // size == 8
spi_select(M25P80);
HAL_SPI_TransmitReceive(&hspi1, out, in, len, TIMEOUT);
delay_ms(BYTE_SPEED_MS * 5); // Needed because ^ finishes before physically
// transmitting the data. Nevermind the 5, it
// was picked experimentally
spi_deselect(M25P80);
Signal (yellow - clock, red - miso):
At 488 bits/s transmitting 4 bytes takes 4 * 1E3 / (488 / 8) = 65.5 ms. Then the reception starts. Memory starts transmitting [0xFF...0xFF] right away, but contents of the 'in' buffer are:
[0x00 0x00 0x00 0x00] [0x00 0x00 0x00 0x00 0x00] 0xFF 0xFF 0x00...0x00
^ zero because this ^ should be 0xFF ^ correct data
is the part where
data was being sent
to the memory
So first six bytes of data are just lost. Am I the only one who's having such a hard time with STM's SPI module?
EDIT:
I've gotten myself a different eval board with a slightly different MCU (STM32F030) and it gets even weirder:
[0x02 0x02 0x02 0x02]
0x00 0x02 0x00 0x00 0xFF 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00...0x00
Although I must mention that I'm using a different compiler with this MCU.
EDIT 2:
The way I partially got it to work is using 16-bit mode with SPI. This fixed this particular bug, but there are more similar oddities with STM32's SPI.
EDIT 3:
SPI initialisation code:
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLED;
HAL_SPI_Init(&hspi1);
}

Are you sure that the initialization of SPI is right?
Maybe your Clock polarity or phase settings does not match between Master and Slave?
Take a watch to ClockSettings.
Please show your SPI-Initialization-Code!

Related

In device tree, can't understand 'ranges' property of PCIe root complex node

For example in linux-5.15.68's arch/arm64/boot/dts/ti/k3-am64-main.dtsi,
&cbass_main {
... skip ...
pcie0_rc: pcie#f102000 {
compatible = "ti,am64-pcie-host", "ti,j721e-pcie-host";
reg = <0x00 0x0f102000 0x00 0x1000>,
<0x00 0x0f100000 0x00 0x400>,
<0x00 0x0d000000 0x00 0x00800000>,
<0x00 0x68000000 0x00 0x00001000>;
reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
... skip ...
#address-cells = <3>;
#size-cells = <2>;
...skip ...
msi-map = <0x0 &gic_its 0x0 0x10000>;
ranges = <0x01000000 0x00 0x68001000 0x00 0x68001000 0x00 0x0010000>,
<0x02000000 0x00 0x68011000 0x00 0x68011000 0x00 0x7fef000>;
dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x00000010 0x0>;
};
};
the 'ranges' property says
IO space starting at address 0x68001000 with size 64KiB is mapped to the parent bus address 0x68001000.
a 32 bit memory address space starting with address 0x68011000 and size 0x7fef000 is mapped to parent bus address 0x68011000.
The device tree document says these addresses are all physical.
What I can't understand is :
I know the BIOS will set the BAR addresses during the enumeration process. This is allocating the endpoint's function to a certain PCIe bus address and I guess setting BAR can be done without this 'ranges' information(it will assign free address range for that device according to the device's need). By the time linux kernel later reads this 'ranges' property, the BIOS (or bootloader) has already assigned different PCIe address to that device. Then, how is this 'ranges' property used by the kernel?

Trinamic TMC2209 STM32 UART not reading from device

I've been struggling for ages, finally caved and asking for help now.
There are very little resources on STM32 for this driver that I have seen.
I can use the device with the STEP/DIR interface but I want to be able to do the more advanced things now with only the single UART line and not the STEP/DIR lines.
I am trying to control a TMC2209 in the most basic form to understand how it all works, without libraries and such.
I want to get basic controls working so I can understand it and build up my own code from there, right now the goal is to just talk to the thing and get it to spin.
I am using a STM32F103, I have setup the USART3 line (PC10) in signal wire half duplex mode and using the following code to try read from the CHOPCONF register.
Sync = 0x05; // sync byte to start the Tx
Address = 0x00; // MS1 and MS2 are pulled low so the device address is 0
RegAddress = 0x6C; // Trying for a basic read from the CHOPCONF Reg
motor_CRC = 0xCA; // CRC that has been worked out
HAL_UART_Transmit(&huart3,&Sync,sizeof(Sync),20);
HAL_UART_Transmit(&huart3,&Address,sizeof(Address),20);
HAL_UART_Transmit(&huart3,&RegAddress,sizeof(RegAddress),20);
HAL_UART_Transmit(&huart3,&motor_CRC,sizeof(motor_CRC),20);
// Receive the data from the TMC2209
HAL_UART_Receive(&huart3, &ReplySync, sizeof(ReplySync), 200);
HAL_UART_Receive(&huart3, &ReplyMasterAddr, sizeof(ReplyMaster), 20);
HAL_UART_Receive(&huart3, &ReplyAddr, sizeof(ReplyAddr), 20);
HAL_UART_Receive(&huart3, &Reply1, sizeof(Reply1), 20);
HAL_UART_Receive(&huart3, &Reply2, sizeof(Reply2), 20);
HAL_UART_Receive(&huart3, &Reply3, sizeof(Reply3), 20);
HAL_UART_Receive(&huart3, &Reply4, sizeof(Reply4), 20);
HAL_UART_Receive(&huart3, &ReplyCRC, sizeof(ReplyCRC), 20);
HAL_Delay(1000);
I expect the following : ( according to the Datasheet that is,,, )
ReplySync >>> 0x05
ReplyMasterAddr>>> 0xFF
ReplyAddr >>> 0xCA
Reply1 >>> 0x53
Reply2 >>> 0x00
Reply3 >>> 0x00
Reply4 >>> 0x10
ReplyCRC >>> I dont know this one yet,,,,
But I am getting this :
ReplySync >>> 0x05
ReplyMasterAddr>>> 0x00
ReplyAddr >>> 0x5D
Reply1 >>> 0x09
Reply2 >>> 0x08
Reply3 >>> 0x00
Reply4 >>> 0x02
ReplyCRC >>> 0x09
I am not sure if I am transmitting these in the correct order or maybe the HAL function should not be used for this at all ?
Any help or pointers in the right direction would be greatly appreciated.

sending null with HAL_UART_Transmit

I'm using HAL driver for STM32103F in Keil IDE. I need to transmit a code to an ESP which is connected to my STM32 via serial port. this code makes ESP publish whatever is in the command (CMD2) to the broker that I'm using, but the problem occurs when the command (CMD2) contains 0x00 (NULL), so the ESP does not publish anything to the broker. this is the code that I'm using:
char Appendix[8] = "\",0,0\r\n";
// DataLength = the length of the data stored in CMD2
// CMD2 might contain 0x00 in it
for(int i = 0; i < 7; i++) CMD2[DataLength+i] = Appendix[i];
CMD2[DataLength+7] = 0x00;
sprintf(PubTopic, "AT+MQTTPUB=0,\"Data/%s\",\"", SerialNumber);
SizeOfPub = strlen(PubTopic);
for(int i = SizeOfPub; i < SizeOfPub+DataLength+8; i++) PubTopic[i] = CMD2[i-SizeOfPub];
HAL_UART_Transmit(huart, (uint8_t *) PubTopic, SizeOfPub+DataLength+7, 10);
when my command (CMD2) contains 0x00 (NULL), ESP does not act correctly to the last line, but this code works fine when there is no 0x00 (NULL) in the command(CMD2). for example:
1)CMD2 = 0x45 0x55 0x53
2)CMD2 = 0x45 0x00 0x53
in the first case, there is no problem with the code, but in the second case, ESP does not publish anything.
Thanks to codo, I figured out that I have followed the wrong path. The best way of publishing a code using AT+COMMAND that may contain the NULL character is to use AT+MQTTPUBRAW. this is my code:
sprintf(PubTopic, "AT+MQTTPUBRAW=0,\"Data/%s\",%d,0,0", SerialNumber, DataLength);
StrPrintln(&huart1, PubTopic);
HAL_Delay(50);
/*
* SendCommand is a uint8_t variable that contains commands
* that need to be published
*/
HAL_UART_Transmit(&huart1, SendCommand, DataLength, 10);

Deciphering HCI event from BLUEnrg-ms bluetooth device

I am successfully able to communicate with my IDB05A1 from my nucleo-64 board.
I make it discoverable and pair my phone to it. However immediately after pairing, the device disconnects from my phone.
Before it disconnects I receive a HCI event i cannot decipher:
0x04 0xff 0x0b 0x01 0x0c 0x01 0x08 0x04 0x00 0x02 0x00 0x00 0x02 0x00
please help me decipher this. datasheet with commands and events
0x04 //HCI event
0xff //Vendor specific
0x0b //Contains 0b(12) bytes
0x01, 0x0c //BLUEnrg event code
0x......
What event is this?
This event looks not related to the problem.
It indicates the modified value of some attribute.
HCI event packet:
0x04 //HCI event
0xff //Vendor specific
0x0b //Contains 0b(11) bytes
0x01 0x0c 0x01 0x08 0x04 0x00 0x02 0x00 0x00 0x02 0x00 //Event data
Event data:
0x0c01 //ACI_GATT_ATTRIBUTE_MODIFIED_EVENT
0x0801 //The connection handle which modified the attribute
0x0004 //Handle of the attribute that was modified
0x0002 //Length of the attribute data
0x00 //Offset
0x0002 //The modified value

How to set sockaddr_in6::sin6_addr byte order to network byte order?

I developing a network application and using socket APIs.
I want to set sin6_addr byte order of sockaddr_in6 structure.
For 16 bits or 32 bits variables, it is simple: Using htons or htonl:
// IPv4
sockaddr_in addr;
addr.sin_port = htons(123);
addr.sin_addr.s_addr = htonl(123456);
But for 128 bits variables, I dont know how to set byte order to network byte order:
// IPv6
sockaddr_in6 addr;
addr.sin6_port = htons(123);
addr.sin6_addr.s6_addr = ??? // 16 bytes with network byte order but how to set?
Some answers may be using htons for 8 times (2 * 8 = 16 bytes), or using htonl for 4 times (4 * 4 = 16 bytes), but I don't know which way is correct.
Thanks.
The s6_addr member of struct in6_addr is defined as:
uint8_t s6_addr[16];
Since it is an array of uint8_t, rather than being a single 128-bit integer type, the issue of endianness does not arise: you simply copy from your source uint8_t [16] array to the destination. For example, to copy in the address 2001:888:0:2:0:0:0:2 you would use:
static const uint8_t myaddr[16] = { 0x20, 0x01, 0x08, 0x88, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
memcpy(addr.sin6_addr.s6_addr, myaddr, sizeof myaddr);
The usual thing would be to use one of the hostname lookup routines and use the result of that, which is already in network byte order. How come you're dealing with hardcoded numeric IP addresses at all?