Add 2 I2c devices with the same adress in dts - linux-device-driver

I have a 2 different board each with a I2c device, the devices have the same address. I want to build one firmware where I can control both of devices depends on which device is connected to the I2C bus
device1#30 {
compatible = "device1";
reg = <0x30>;
clock-mode = /bits/ 8 <1>;
....
device2#30 {
compatible = "device2";
reg = <0x30>;
clock-mode = /bits/ 8 <1>;
I got an error when trying to read from the register of the second device which says that device 2 that be binded. How can I resolve this problem ?
NB : I have only 1 I2C Bus
I tried to add some detection function in the first and second device ( read ID register ) but it fails because I can't read the reg of the second device.

Related

how to increase spidev bus speed

I want to communicate through SPI from an Up2 6000 and a microcontroller. On the Up2 I am using Ubuntu 20.04 with kernel 5.13 and the PREEMT_RT patch.
Linux up 5.13.0-rt1 #1 SMP PREEMPT_RT Thu Oct 13 12:09:18 CEST 2022 x86_64 x86_64 x86_64 GNU/Linux
Then my program to communicate through SPI sets the speed like this:
int file_desctiptor = open("/dev/spidev1.0", O_RDWR);
if (file_desctiptor < 0) {
return -2;
}
// Set the spi mode
if (ioctl(file_desctiptor, SPI_IOC_WR_MODE, SPI_MODE_1 | SPI_CS_HIGH) < 0) {
close(file_desctiptor);
return -3;
}
// Set the spi speed
uint32_t speed{8000000};
if (ioctl(file_desctiptor, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) {
close(file_desctiptor);
return -4;
}
But on the oscilloscope I can see the speed of the SCLK signal is 1MHz. However, when I change the speed value for less than 1MHz I can notice the difference on the oscilloscope, so it must be a maximum set somewhere.
To enable spidev on the Up2 6000 I use ACPI overloads. I also modified the max speed here:
/*
* This ASL can be used to declare a spidev device on SPI1 CS0
*/
DefinitionBlock ("", "SSDT", 5, "INTEL", "SPIDEV0", 0x00000001)
{
External (_SB.PC00.SPI1, DeviceObj)
Scope (\_SB.PC00.SPI1)
{
Device (TP0)
{
Name (_HID, "SPT0001") // _HID: Hardware ID
Name (_DDN, "SPI test device connected to CS0") // _DDN: DOS Device Name
Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings
{
SpiSerialBusV2 (0x0000, PolarityLow, FourWireMode, 0x08,
ControllerInitiated, 8000000, ClockPolarityLow,
ClockPhaseFirst, "\\_SB.PC00.SPI1",
0x00, ResourceConsumer, , Exclusive,
)
})
}
}
}
But the speed is still 1MHz. Am I missing something else?
Edit:
I have read back the speed using SPI_IOC_RD_MAX_SPEED_HZ and it is 8MHz but still on my logic analyzer I can see 1MHz.
I compiled my kernel with some logs to see what was happening in the drivers and I got this:
Apparently there are two instances of pxa2xx-spi driver, I suppose one is internal and we don't have much access (the first one with frequency 100MHz) and the other one is the one connected to the GPIO (so with frequency maximum limit of 990099 Hz).
Then, the SPT0001 ACPI module tries to modify this frequency to be 8MHz but as it is bigger than the one of the controller the driver does not set it. Finally, I try to open a file descriptor for SPI exchanges at 10MHz and again the driver refuses to open it because the controller has a smaller frequency.
Where is this frequency limit set? I tried compiling the kernel with different configurations but it didn't change. Is it something related to the hardware itself? Or perhaps another ACPI that I am missing?

USB issue SAM3S-EK -> Custom card

I am developing my project with SAM3S-EK demo board. I used USB CDC and MSC Driver with example code and ASF and everything work fine. Now I want to put the code into my custom card (with a SAM3S1B).
But that is my problem. I have assigned the pin and changed the clock config but the device is not recognized by Windows. All of descriptors are equal to zero (according to USBLyser).
Can someone help me ?
That is my clock config file (I have a 16MHz crystal) :
// ===== System Clock (MCK) Source Options
#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLLACK
// ===== System Clock (MCK) Prescaler Options (Fmck = Fsys / (SYSCLK_PRES))
#define CONFIG_SYSCLK_PRES SYSCLK_PRES_4
// ===== PLL0 (A) Options (Fpll = (Fclk * PLL_mul) / PLL_div)
// Use mul and div effective values here.
#define CONFIG_PLL0_SOURCE PLL_SRC_MAINCK_XTAL
#define CONFIG_PLL0_MUL 32
#define CONFIG_PLL0_DIV 2
// ===== PLL1 (B) Options (Fpll = (Fclk * PLL_mul) / PLL_div)
// Use mul and div effective values here.
#define CONFIG_PLL1_SOURCE PLL_SRC_MAINCK_12M_RC
#define CONFIG_PLL1_MUL 16
#define CONFIG_PLL1_DIV 2
// ===== USB Clock Source Options (Fusb = FpllX / USB_div)
// Use div effective value here.
//#define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL0
#define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL1
#define CONFIG_USBCLK_DIV 2
// ===== Target frequency (System clock)
// - XTAL frequency: 16MHz
// - System clock source: PLLA
// - System clock prescaler: 4 (divided by 4)
// - PLLA source: XTAL
// - PLLA output: XTAL * 32 / 3
// - System clock is: 16 * 32 / 4 / 2 = 64MHz
// ===== Target frequency (USB Clock)
// - USB clock source: PLLB
// - USB clock divider: 2 (divided by 2)
// - PLLB output: XTAL * 12 / 2
// - USB clock: 16 * 12 / 2 / 2 = 48MHz
Like all USB devices used under Windows, you need to first install a Windows side USB driver that is specific to the device you are attaching.
When you install Atmel Studio 6.2 or newer, it installs a Windows side USB driver for the Atmel ASF USB driver you are using in your firmware. That Windows driver works with my SAM4E target processor. Be aware that it takes a long time to load the driver in Windows. It will appear to have hung. Just give it time, and it will eventually install the driver. You will probably have to respond to a pop-up warning to permit installation of an unsigned driver.
The Windows driver can also be downloaded and installed separately. Use this link:
https://gallery.atmel.com/Products/Details/6272a8fd-68fe-43d8-a990-741878cfe7b6?
Double check your clock rate. I am using the SAM4L part and it requires the PLL to run off of OSC0 to generate a 48 MHz clock. I had the same problem for a while because my ABDACB used the same clock and changed the rate. As I understand it, the plugging in of a USB device senses the single pull up resistor on the pin DP or DN depending on the speed. That is what tells windows (the host) to attempt to communicate. If the clock rate is wrong, the properties in windows all show 0s.

Intimating new firmware start address to bootloader

Considering a microcontroller(in my case STM32L4 series) once the new firmware image is written into the flash, how the new start address of the application can be intimated to the bootloader?
Normally the bootloader should know the sector where the application has been written. If this is not case then there are two options:
1. When you write the firmware image to a particular sector - record in flash in a known sector the firmware sector i.e in a known sector write a struct bootloaderInfo that records the sector address of the firmware and any other info that is useful for the bootloader e.g a CRC for the firmware image, a firmware version etc. The bootloader can read this struct (its always in a known sector) and from that know where the sector where the firmware is to run.
2. The bootloader could scan flash sectors looking for the firmware image. This is not really recommended but would work. A sector with a valid firmware image will have a. a valid stack pointer and b. a valid reset vector. They could be tested with the following macros:
#define STACK_POINTER_RANGE 0x2FFE0000
#define IS_VALID_STACK_POINTER(address) (((*(volatile uint32_t*)address) & STACK_POINTER_RANGE) == SRAM_BASE)
#define IS_VALID_RESET_VECTOR(sectorAddress) \
(((*(uint32_t*)(sectorAddress+4)) & 0x8FF0000 ) == sectorAddress)
Once the application address in known the bootloader can jump to it in the normal way:
uint32_t JumpAddress = *(__IO uint32_t*)(sector + 4);
pFunction JumpToApplication = (pFunction)JumpAddress;
// Initialize user application's Stack Pointer:
__set_MSP(*(__IO uint32_t*)sector);
JumpToApplication();

OLED on Zedboard

I am very new to zedboard. I have a zedboard running an Ubuntu image. I am trying to write a driver to run the OLED on the board. On board start-up the OLED on the board shows some display(Xilinx logo), therefore I am assuming it already has a driver. I have the following questions:
a) How is the OLED in the zedboard internally connected, is it through SPI, GPIOs or the PL. If it's through SPI/GPIOs then which pins?
b) Any tutorial or documentation that I can follow to create userspace drivers using SPI/GPIO for the OLED in the zedboard?
c) I have a redhat desktop, is there any SDk I can use to develop userspace drivers for the zedboard from my redhat desktop.
I have seen a lot of materials on the zedboard but none of them talks about how the OLED is internally connected. In one document it shows that it's connected to the PL. If that's the case then how can I write userspace drivers using the PL on the zedboard? I will be coding using C.
Appreciate your help and thanks in advance!
a) How is the OLED in the zedboard internally connected, is it through SPI, GPIOs or the PL. If it's through SPI/GPIOs then which pins?
First or second result for the web search "zedboard oled pdf" - http://zedboard.org/sites/default/files/ZedBoard_HW_UG_v1_1.pdf
then search for "oled" in it (page numbers of the pdf file, not printed in document):
page3: 2.4.4 OLED...... ... ...... 19
page4: 128x32 OLED Display
page5: ZYNQ XC7Z020-CSG484 OLED <- bus_of_5 -> 128x32 OLED
page20: 2.4.4 OLED
An Inteltronic/Wisechip UG-2832HSWEG04 OLED Display is used on the ZedBoard. This
provides a 128x32 pixel, passive-matrix, monochrome display. The display size is 30mm x11.5mm x 1.45mm. Table 11 - OLED Connections ... Interface
oled_pin symb EPP_pin Function
9 RES# U9 Power Reset for Controller and Driver
8 CS# N/C Chip Select – Pulled Down on Board
10 D/C# U10 Data/Command Control
11 SCLK AB12 Serial Clock Input Signal
12 SDIN AA12 Serial Data Input Signal
So, we know model of OLED UG-2832HSWEG04 (datasheet http://www.adafruit.com/datasheets/UG-2832HSWEG04.pdf with low-level details on data interface) and data connection; this is OLED with 1 serial data input and 1 serial clock.
Pinout pdf is http://www.xilinx.com/support/documentation/user_guides/ug865-Zynq-7000-Pkg-Pinout.pdf (too long to read), but there is shorter version of pin list in txt format: http://www.xilinx.com/support/packagefiles/z7packages/xc7z020clg484pkg.txt
Device/Package xc7z020clg484 9/18/2012 10:07:35
Pin Pin Name Memory Byte Group Bank VCCAUX Group Super Logic Region I/O Type
AA12 IO_L7P_T1_13 1 13 NA NA HR
AB12 IO_L7N_T1_13 1 13 NA NA HR
HR means "3.3V-capable high-range (HR) banks", both data pins are from "bank 13". Pin name is IO_* so it "supports both input, as well as output functionality", and is part of "PL Pins" (PL = programmable logic = FPGA). Default Zedboard firmware of FPGA part gives access to this pin to the ARM part of chip with linux kernel (PS = processing system = ARM) by routing it to some internal processing_system GPIO pin via system.ucf file like:
NET processing_system7_0_GPIO_pin[5] LOC = AB12 | IOSTANDARD="LVCMOS25"; # "OLED-SCLK"
NET processing_system7_0_GPIO_pin[6] LOC = AA12 | IOSTANDARD="LVCMOS25"; # "OLED-SDIN"
Then the GPIO pins are registered in devicetree (dts) https://github.com/Digilent/linux-digilent/blob/master/arch/arm/boot/dts/digilent-zed.dts in zed_oled group:
zed_oled {
compatible = "dglnt,pmodoled-gpio";
/* GPIO Pins */
vbat-gpio = <&ps7_gpio_0 55 0>;
vdd-gpio = <&ps7_gpio_0 56 0>;
res-gpio = <&ps7_gpio_0 57 0>;
dc-gpio = <&ps7_gpio_0 58 0>;
/* SPI-GPIOs */
spi-bus-num = <2>;
spi-speed-hz = <4000000>;
spi-sclk-gpio = <&ps7_gpio_0 59 0>;
spi-sdin-gpio = <&ps7_gpio_0 60 0>;
};
b) Any tutorial or documentation that I can follow to create userspace drivers using SPI/GPIO for the OLED in the zedboard?
According to Avnet's Getting Started pdf, "Demo 2 – OLED Display" scetion on page 17 (web searched as "zedboard oled") http://zedboard.org/sites/default/files/documentations/GS-AES-Z7EV-7Z020-G-14.1-V6%5B1%5D.pdf#page=17 there is kernel driver pmodoled-gpio.ko (on screenshot it reported as "pmodoled-gpio-spi"), so OLED is driven with GPIO pins.
There are two helper scripts: unload_oled to remove the kernel module and load_oled to insert it into kernel. Driver will create special device file /dev/zed_oled to work with display from user-space and load_oled also displays the /root/logo.bin file using this zed_oled interface.
Typical usage of zed_oled is like cat yourfile.bin > /dev/zed_oled, for example http://people.mech.kuleuven.be/~lin.zhang/notes/emebedded-linux/zedboard-oled-display.html and better http://zedboard.org/content/zedboard-oled
The .bin file format. ... The screen is written to right to left, top to bottom with each pixel being represented by a bit within one of the bytes within the .bin file. Bits are read-in top down 8 pixels then move over 1 pixel and write the next 8 bits and continue until you are at the end of the row. Then move down 8 pixels and do this again 3 more times.
You can do writes from C application, check code from http://www.cnblogs.com/popo0904/p/3853144.html (you can use online web translation services to read the text)
Documentation on the kernel module PmodOLED used in standard zedboard demo: https://github.com/Digilent/linux-digilent/blob/master/Documentation/pmods/pmodoled.txt
The driver provides a 512 Byte display buffer for the display of PmodOLED.
The Whole screen is divided into four lines, each of them is 128 bits wide
and 8 bits high, as shown in the figure below.
+--------------------------...----------------------------+
+ Line 4 +
+--------------------------...----------------------------+
+ Line 3 +
+--------------------------...----------------------------+
+ Line 2 +
+--------------------------...----------------------------+ MSB (bit 7)
+ Line 1 +
+--------------------------...----------------------------+ LSB (bit 0)
byte 127 byte 0
Users can perform read and write functions to the device node to access the data
inside the display buffer.
And there is source code of the dirver: https://github.com/Digilent/linux-digilent/blob/06b388903e5459687ba2538ae3895ffe29e2e39e/drivers/pmods/pmodoled-gpio.c
c) I have a redhat desktop, is there any SDk I can use to develop userspace drivers for the zedboard from my redhat desktop.
The standard driver is kernel-space for this OLED on ZEDboard, you can use it from precompiled ZEDboard firmware. Or you can build the kernel according to zedboard instructions, all in-kernel drivers will be built too (if enabled in kernel configuration): http://zedboard.org/content/creating-linux-kernel-image-boot-zc702-sd-card-slot

Microphone Device ID

I have three USB microphones plugged up to my Macbook Air via a USB hub. In the Audio MIDI I aggregated the devices and selected the aggregate device as the input for the computer. However, 'audiorecorder' is not picking up the device ID.
audiodevinfo
ans
{1x1 struct}
{1x1 struct}
and it's naming the internal microphone. Is there a way to set a device ID for each individual microphone?
You can determine if you have the correct name for a device using
mic1 = audiodevinfo(1, 0)
mic2 = audiodevinfo(1, 1)
mic3 = audiodevinfo(1, 2)
where the first argument is output/input (0 or 1) and the second argument is the device ID. Then you can address the mics separately, for example by using
audiorecorder(Fs, NBITS, NCHANS, ID)
and replacing ID with 1 for mic2
If you plug any mic in or out of the computer you may need to restart matlab for it to be recognized.