stm32 spi full-duplex slave mode - stm32

I'm working on spi communicate between stm32f0308-discovery and jetson tx2. Jetson is master and stm32 should be slave. (idk how but if it is possible stm32 may be master too.) My problem is I'm new for stm32 and I don't know how an I make stm32 to slave. Can someone show me a way for stm32 spi slave ? Thanks in advance.

You can start by reading the reference manual of your product family. Then, you can find examples of SPI peripheral configuration source code in STM32Cube software packages.
If you are new to STM32 and new to the microcontroller ecosystem, I'm afraid you will need some training. But there are plenty of resources online.

You can select SPI mode when configuring the SPI_InitTypeDef structure. You need to set the SPI_Mode to Slave as follows:
SPI_InitDef.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitDef.SPI_Mode = SPI_Mode_Slave; // <-- This is it
SPI_InitDef.SPI_DataSize = SPI_DataSize_8b; // 8-bit transactions
SPI_InitDef.SPI_FirstBit = SPI_FirstBit_MSB; // set it to match Master conf
SPI_InitDef.SPI_CPOL = SPI_CPOL_Low; // set it to match Master conf
SPI_InitDef.SPI_CPHA = SPI_CPHA_2Edge; // set it to match Master conf
SPI_InitDef.SPI_NSS = SPI_NSS_Hard; // use hardware SS
An example tutorial using blue pill boards can be found here

Yes. You can make STM32 as the slave. The only thing you need to do is CLEAR the MSTR Bit in The Control Register on the peripheral. You perhaps then can load some values in the SPI Data Register & then can read them from your other board.

Related

Cache configuration for DMA device access on ARM Cortex-A72

I am writing an operating system for the raspberry pi.
I have a problem with the sdcard driver for the custom sdhost controller (emmc2)
of the raspberry-pi 4 (Cortex-A72, ARMv8-A, bcm2711 chipset).
Without using sdma everything works. With sdma, read works, but after writing sectors, the data on the sdcard sometimes contains invalid data.
For the sdma data transfer, I use a transfer buffer with a device type memory attribute (nGnRnE). When I use a fresh data buffer for the dma write transfer, the data on the sdcard is correct. But when I reuse the same buffer for the next write, then the sector on the sdcard partially contains data from the previous buffer content.
Maybe this is a cache coherency problem. I have enabled all caches (I and D). In the ARM manuals there is a talk of the SCU (snoop control unit) and I don't know whether I have do bother about the SCU.
My questions are:
Is it necessary to enable the SCU on a Cortex-A72 and how can this be done ?
What other things have to be kept in mind when using dma for device access ?
I found the solution for my problem:
On the raspberry pi 4 (bcm2711 chip), the physical addresses that are written into the registers of a dma engine must be legacy master addresses. The legacy master addresses are in the range 0xC0000000-0xFFFFFFFF. So I have to add 0xC0000000 to the values of the physical addresses that are written into the registers of the sdhci controller.
The documentation can be found here:
https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
1.2. Address map
1.2.4. Legacy master addresses
The answer to the other SCU question is: it is not necessary to enable the SCU on the Raspberry Pi 4 when the caches are enabled.

Can't receive from USB bulk endpoint despite Windows enumerates and libusb reads descriptor of STM32 custom device class

For a fast ADC sampling USB device, I am using the USB 2.0 High Speed capable STM32F733 with the embedded USB-HS PHY. In USBView, I can see that the device is enumerated, the libusb code opens the device and claims interface, but when I try to receive data with libusb_bulk_transfer, the operation times out (return code -12). Things I have tried: I have confirmed than when I request data with libusb_bulk_transfer, the device is interrupted. Note: I have DMA enabled in my class configuration C file and it is not clear to me how that is triggered. I have verified that the transfersize and packet count registers are being set correctly by the LL library function, and that when I request data from
Any tips on debugging such problems will be much appreciated - this board is my undergrad thesis due in under two months!
Desktop sequence:
libusb_get_device_list, libusb_get_device_descriptor, libusb_open, libusb_get_string_descriptor_ascii, libusb_free_device_list, libusb_bulk_transfer(devh, fat_EPIN_ADDR, inframe, fat_EPIN_SIZE, &gotBytes, 100). Where gotBytes is integer, and inframe is a large array.
Device firmware:
MX_USB_DEVICE_Init();
uint8_t txBuffer[10*fat_EPIN_SIZE];
while (1)
{
USBD_LL_Transmit(&hUsbDeviceHS, Custom_fat_EPIN_ADDR, txBuffer, Custom_fat_EPIN_SIZE);
HAL_Delay(1);
}
Custom_fat_EPIN_SIZE is 0x200 and the endpoint address is 0x81 (EP IN 1)
Installed driver for device is WinUSB (verified in Device Manger to be winusb.sys), and I am linking libusb-1.0 into my desktop program. You can find my source code at https://gitlab.com/tywonemi-school-stuff/silicon-radar-fun, the firmware is My SW/v1 and the desktop software is a Qt Creator project in My SW/Viewer, of note is usb.cpp. You can also compare with testing project/HIDTest, which is code that I tested with STM32F303 nucleo dev board where I was able to read an array through IN bulk endpoint with the Viewer application. However, F3 has the USB peripheral, while F7 has OTG_USB, and I am now attempting USB 2.0 compliant HS so there may be more protocol-based pitfalls. You can also find the output of the device descriptor etc from USBView in my SW/USBView_broken.txt
EDIT 1: I have found finally some concrete error in the STM32 behavior. The DMAADDR is set for EPIN 0x81, and never increments, despite the DMA being enabled. I have went through literally every occurrence of the word "DMA" in the USB_OTG periphery.
I thought it might be that my linker script makes my array be stored in DTCM or similar, and the OTG DMA can't access it, but the address of txBuffer is 0x2003EBEC which is in SRAM2. The AHB matrix in the reference manual clearly shows, that the USB OTG HS DMA is master for a bus that SRAM2 is a slave of. And DTCM is connected too. I will look for application notes for USB OTG HS DMA - it just seems to be refusing to copy data!
I have fixed my issue by disabling the DMA setting. I have re-read the relevant portions of the reference manual and still don't know how exactly the values propagate into the Tx FIFOs. It is possible that DMA-less operation will be a major bottleneck in my project, I might return to this later.

Beagle Bone Black I2C2 Issues

I am having troubles using an I2C sensor with the Beagle Bone Black (BBB). The BBB is running a newly flashed 18.04 Ubuntu image specifically for the BBB.
I wired the sensor (VIN, GND, SCL, SDA) to the corresponding I2C2 pins (4, 2, 19, 20) on the BBB using the below pinout.
The sensor is supposed to be using address 0x40, but scanning I2C2 (using i2cdetect -r 2) does not show the sensor.
I have tested this with two separate sensors as I thought at first I may have fried the original sensor somehow, but the results are the same. In fact, running the I2C2 scan command yields the exact same results when nothing is connected at all.
I have read in many places that I2C2 may not be enabled by default, but I assume it is enabled in my case as I can scan I2C2 without getting an error. Is this assumption incorrect? Again, this is a freshly flashed BBB, and I have not enabled/disabled anything - it should be in the default state.
I have also verified the connectivity of my wires between the sensor and BBB. The voltage between VIN and GND on the chip is 3.3V, so it is definitely being powered.
Why can't I connect to my I2C sensors using the BBB?
it could be that the source you are using is outdated or not a viable entry for i2c.
Also, you could use this command to make sure i2c2 pins are available:
config-pin p9.21 i2c
config-pin p9.22 i2c
This may work, also. If this does not work, please reply with your entire source.
Seth
P.S. Also, if you have time, you may want to get an i2c library to use if your software falls short of setting up your own i2c library. They have smbus2 you can install with pip and other i2c libraries out there still.
Here are a few things you should check (in random order).
List all I2C buses wich i2cdetect -l and try them all. Depending on the platform, the i2c bus number in Linux may be different from the peripheral number used in the datasheet and pinout. E.g. "I2C2" might be bus i2c-1 or i2c-3 in Linux).
Use an oscilloscope or logical analyzer to see if the SCL and SDA lines are being driven. If they aren't check the bus number as above. If they are, then check whether the device gives an ACK; if it doesn't, anything else will never work: double-check the chip slave address. There are cheap logical analyzers that you can buy and user with pulseview.
Simply load the Linux driver for your chip (see the kernel docs on how to do it from userspace for a quick test). Then see check if the device appears or use dmesg to see any kernel error messages while probing.

max732x.c I2C IO Expander + GPIO Keys w/ Linux Device Tree not working

I'm working with a Freescale MX6 and a 3.10.31 Freescale modified kernel. I have a Maxim MAX7325 used as an IO expander, which has pushbuttons attached to P0-P2. The interrupt line from the 7325 is attached to the GPIO_3 pad (which I believe is GPIO1_3...)
I set up the 7325 and gpio-keys in the device tree like this:
max7325_reset: max7325-reset {
compatible = "gpio-reset";
reset-gpios = <&gpio5 16 GPIO_ACTIVE_LOW>;
reset-delay-us = <1>;
#reset-cells = <0>;
};
gpio-keys {
compatible = "gpio-keys";
sw2 {
gpios = <&max7325 2 GPIO_ACTIVE_LOW>;
linux,code = <30>; //a
gpio-key,wakeup;
};
};
and
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1_2>;
status = "okay";
max7325: gpio#68 {
compatible = "maxim,max7325";
reg = <0x68>;
gpio-controller;
#gpio-cells = <2>;
resets = <&max7325_reset>;
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
interrupt-parent = <&gpio1>;
interrupts = <3 2>;
};
};
What appears to happen is when probe for the MAX7325 driver is called, client->dev.platform_data is NULL. Because of this, when max732x_irq_setup is called later, it doesn't set up the chip->gpio_chip.to_irq pointer to point at max732x_gpio_to_irq function (presumably because it doesn't have the right info for this to work.) Later, when gpio_keys
tries to config the first input, it fails when it tries to set up the interrupt and none of the other keys get set up.
gpio-keys gpio-keys.20: Unable to get irq number for GPIO 242, error -6
I did determine using the /sys interface that P0 maps to GPIO 240, so yeah, GPIO 242 is the sw2 GPIO-KEY I was trying to set up.
I'm wondering, does this driver not work with a device tree? I don't see it trying to get any device tree properties, but other IO expander drivers I looked at didn't either, so I thought maybe the I2C core is reading the device tree and supposed to fill in the platform_data from there somehow before it calls the driver's probe function (?)
I'm fairly new at this, so any help would be appreciated. =) I did read a few of the Device Tree docs online, but I'm thinking this is something fairly specific that I'm not doing correctly, which they don't cover... (?)
I do have CONFIG_GPIO_MAX732X_IRQ configured in the kernel... and I did at one point try setting the interrupt-controller property for the max7325 I2c1 node, but I wasn't sure that was needed (?)
MAX732x device tree support
Driver you are using won't work with data from device tree. I have added device tree support to this driver and sent it to kernel mailing lists for review, but they are not merged yet. See this thread (total 4 patches):
You can either apply those patches to your branch or wait for them to get into upstream kernel and then cherry-pick them from there (into your branch).
Bindings documentation (see patches above) shows how to create device tree declaration for MAX732x. In your case it may look like this:
&i2c1 {
expander: max7325#68 {
compatible = "maxim,max7325";
reg = <0x68>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&gpio1>;
interrupts = <3 2>;
};
};
Another way for you to use this driver (without patches above) is to specify platform data in board file for your board. I believe it should be one of next files:
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-imx6sl.c
arch/arm/mach-imx/mach-imx6sx.c
You can find an example how to do so here: arch/arm/mach-pxa/littleton.c, line 394.
But it may be not reliable way: I tried to do so and had some issues with i2c buses numbers (didn't look too much in that way though). It also looks bad to scatter devices' definitions between board file and dts file. So I strongly recommend you to use patches above.
Answers to questions
What appears to happen is when probe for the MAX7325 driver is called, client->dev.platform_data is NULL.
It happens because driver was binded with device declaration from device tree file rather than from board file. In that case driver should use client->dev.of_node instead of client->dev.platform_data. Just see how it's done in my patch above.
You can read more about how binding/matching/instantiating happens in kernel documentation here:
Documentation/i2c/instantiating-devices
Documentation/devicetree/usage-model.txt
I thought maybe the I2C core is reading the device tree and supposed to fill in the platform_data from there somehow before it calls the driver's probe function (?)
No. When binding is happening, client->irq being automatically populated in I2C core (before driver's probe function being called). Properties like gpio_base and irq_base -- you don't need them in case when data came from device tree.
I did at one point try setting the interrupt-controller property for the max7325 I2c1 node, but I wasn't sure that was needed (?)
MAX7325 issues interrupt to your SoC when it detects changes on input lines (more specifically, on open-drain I/O ports configured as inputs).
So if you want your driver to generate separate interrupts for each input I/O line (so that other drivers can consume them), you should specify "interrupt-controller" and "#interrupt-cells" properties. But for this you need all patches mentioned above to be applied.
Patches status
Now all mentioned patches were merged into upstream kernel (v4.0 and later):
gpio: max732x: Add device tree support
gpio: max732x: Rewrite IRQ code to use irq_domain API
gpio: max732x: Fix possible deadlock
gpio: max732x: Add DT binding documentation
Also notice that there are some new patches were made on top of my patches. You can watch them here.

Bluetooth low energy (BLE 112 ) Difference between BGAPI and BGScript

What is the Difference between BGAPI and BGScript ?
And if we write any code for BG profile than how can we burn it in BLE 112?
The BGAPI interface defines the protocol used to talk to the module over USB or serial link.
BGScript is something which runs on the module processor itself, when the USB or serial link is not used.
I have the dongle, BLED112, which is the same thing as BLE112 with a USB connector on it, and the code is "burned" to it using standard USB DFU interface.
The downloading of the code to BLE112 can be done using several methods:
(1) Bring out the DD, DC debug interface pins from your module and use the CC-Debugger (digikey part 296-30207-ND, $55). This works every time. If you have the DKBLE112 kit, the CC-Debugger fits on the 10-pin .050 connector in lower right corner. You can "burn" any firmware and any stack this way. Works awesome.
(2) Hope that the current firmware on the CC2540 has serial bootloader, and load the new firmware (hopefully also containing serial bootloader) using UART. TI has the tools, but it sure seems quite convoluted to me, and I did not try it.