Deciphering HCI event from BLUEnrg-ms bluetooth device - stm32

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

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?

STM32 HID Keyboard

I am trying to use and STM32F0-disco as a keyboard for a Windows PC. I'm having a problem with the characters that are being printed.
The code below waits until the onboard button is pressed then should print the three characters once.
/* USER CODE BEGIN 2 */
USBDelay = USBD_HID_GetPollingInterval(&hUsbDeviceFS);
while (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 0);
if (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1) {
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
buff[0] = 0x00;
buff[2] = 0x04;
buff[3] = 0x05;
buff[4] = 0x06;
USBD_HID_SendReport(&hUsbDeviceFS, buff, 8);
HAL_Delay(USBDelay);
buff[0] = 0x00;
buff[2] = 0x00;
buff[3] = 0x00;
buff[4] = 0x00;
USBD_HID_SendReport(&hUsbDeviceFS, buff, 8);
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
HAL_Delay(1000);
}
while (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1);
/* USER CODE END 2 */
The problem I'm having is that the only the characters in the first two key positions of the buffer (which would be the third and fourth elements of the array since element one is the modifier and the second element is reserved). Also, instead of printing once, the characters print continuously without stopping.
Based on the LED's I've added for testing purposes, the characters that I want to print don't print until the second USB_SendReport, which should be sending blank characters to stop the printing.
I've made the necessary changes to usbd_hid.c and usbd_hid.h, as well as the Clock configuration and enabling USB and such. I've put my keyboard descriptor below.
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
Any ideas?
The USB HID protocol works differently than you assume. If the input report contains multiple pressed keys, the host (your Windows PC) assumes that they have been pressed at the same time. So they can be inserted in any order. And it might also be the reason the third key is not inserted.
So you need to send a separate output report for each key. And after the last report you need to send another empty one (with all 0s) to indicate the keys have been released (as you are already doing). Such an additional report is also needed between two presses of the same key.
The reason the keys are inserted continuously indicates the empty report was not received. Even though the function uses the term send (USBD_HID_SendReport()), the USB protocol works such that the host needs to pick up the input report. And since it is an USB interrupt endpoint, this only happens ever so often. If a report hasn't been picked up yet, USBD_HID_SendReport() does nothing. It not even returns an error.
While querying to polling interval (USBD_HID_GetPollingInterval()) looks ok at first, it's the polling interval declared in the USB endpoint descriptor. However, Windows only supports a few interval values and rounds up to the next supported value. So you have to increase the value.

Where is the specific address definition of the GPIO IDR register by STM32Cube resulting files?

I have read through the explanation of the STM32 project produced by the STM32Cube as in this website.
From this website, I have learned that:
In the stm32f0xx.h file, for example, the origianl address of GPIOA is already declared by
"#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000U)"
then all the corresponding registers for GPIOA is declared by
"#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)"
By the information above, this head file has already defined the original adress of GPIOA, and declared the existance of the corresponding registers for GPIOA (like, IDR, MODER, ODR, etc).
But these codes have not defined clearly the address of these GPIOA corresponding registers. For example, GPIOA_IDR address should be defined as 0x40020000 + 0x10 = 0x40020010, but I haven't seen such definitions in the head file.
Where can one find the codes, which define the register addresses of the GOIP corresponding registers?
It is clearly defined. The GPIO registers are defined in the struct aliased to the GPIO_TypeDef type.
The definition from your question just defines the pointer to the struct of type GPIO_TypeDef with address defined by the integer constant GPIOA_BASE. When you dereference this pointer by accessing the structure members the compiler knows where in the memory this particular member is.
typedef struct
{
__IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
__IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
__IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
__IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
__IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
__IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
__IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x1A */
__IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
__IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
__IO uint32_t BRR; /*!< GPIO bit reset register, Address offset: 0x28 */
}GPIO_TypeDef;
so for example if you derefernce the pointer accessing the OSPEEDR register GPIOA -> OSPEEDR = 0x4567; the compiler knows that this member of the struct is at the offset 8 (in bytes - but machine code uses only byte addresses) from the beginning of the struct

SPI fails to read first 6 bytes

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!

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?