Why DTBO fails on load and says no symbols in root of device tree.? - linux-device-driver

I am trying to build a DTBO from a dts file.
I have a few questions here.
I get a warning when I build this -
/opt/poky/2.7.3/sysroots/x86_64-pokysdk-linux/usr/bin/dtc -o dtb -o phyDriver.dtbo -# ./phyDriver.dts
(avoid_unnecessary_addr_size): /fragment#1/__overlay__: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property
Here is my phyDriver.dts file from which I have generated the dtbo file.
/dts-v1/;
/plugin/;
/ {
fragment#1 {
target = <&phy0>;
__overlay__ {
#address-cells = <0x1>;
#size-cells = <0x1>;
custom_port_phy {
#address-cells = <1>;
#size-cells = <0>;
compatible = "custom,custom-port-phy";
Dummy_Port_Phy0: dummy_port_phy#0 {
reg = <0>;
speed = <1000>;
};
Dummy_Port_Phy1: dummy_port_phy#1 {
reg = <1>;
speed = <1000>;
};
};
};
};
};
OF: resolver: no symbols in root of device tree.
OF: resolver: overlay phandle fixup failed: -22
create_overlay: Failed to create overlay (err=-22)
Here is my dts file. I am not sure what should be the target value. But, I think the problem is with the target. Here is my root dts file. I see that I have a phy0 entry in my root dts file. Is there anything
I can do to surpass this. My aim is to be able to insert this DTBO so that my phy driver works.
I don't care what target value is.
/dts-v1/;
/ {
#address-cells = <0x1>;
#size-cells = <0x1>;
compatible = "avnet,zynq-microzed", "xlnx,zynq-microzed", "xlnx,zynq-7000";
model = "Avnet MicroZed board";
cpus {
#address-cells = <0x1>;
#size-cells = <0x0>;
cpu#0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0x0>;
clocks = <0x1 0x3>;
clock-latency = <0x3e8>;
cpu0-supply = <0x2>;
operating-points = <0xa2c2b 0xf4240 0x51616 0xf4240>;
};
cpu#1 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0x1>;
clocks = <0x1 0x3>;
};
};
fpga-full {
compatible = "fpga-region";
fpga-mgr = <0x3>;
#address-cells = <0x1>;
#size-cells = <0x1>;
ranges;
};
pmu#f8891000 {
compatible = "arm,cortex-a9-pmu";
interrupts = <0x0 0x5 0x4 0x0 0x6 0x4>;
interrupt-parent = <0x4>;
reg = <0xf8891000 0x1000 0xf8893000 0x1000>;
};
fixedregulator {
compatible = "regulator-fixed";
regulator-name = "VCCPINT";
regulator-min-microvolt = <0xf4240>;
regulator-max-microvolt = <0xf4240>;
regulator-boot-on;
regulator-always-on;
phandle = <0x2>;
};
amba {
u-boot,dm-pre-reloc;
compatible = "simple-bus";
#address-cells = <0x1>;
#size-cells = <0x1>;
interrupt-parent = <0x4>;
ranges;
adc#f8007100 {
compatible = "xlnx,zynq-xadc-1.00.a";
reg = <0xf8007100 0x20>;
interrupts = <0x0 0x7 0x4>;
interrupt-parent = <0x4>;
clocks = <0x1 0xc>;
};
can#e0008000 {
compatible = "xlnx,zynq-can-1.0";
status = "disabled";
clocks = <0x1 0x13 0x1 0x24>;
clock-names = "can_clk", "pclk";
reg = <0xe0008000 0x1000>;
interrupts = <0x0 0x1c 0x4>;
interrupt-parent = <0x4>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
can#e0009000 {
compatible = "xlnx,zynq-can-1.0";
status = "disabled";
clocks = <0x1 0x14 0x1 0x25>;
clock-names = "can_clk", "pclk";
reg = <0xe0009000 0x1000>;
interrupts = <0x0 0x33 0x4>;
interrupt-parent = <0x4>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
gpio#e000a000 {
compatible = "xlnx,zynq-gpio-1.0";
#gpio-cells = <0x2>;
clocks = <0x1 0x2a>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <0x2>;
interrupt-parent = <0x4>;
interrupts = <0x0 0x14 0x4>;
reg = <0xe000a000 0x1000>;
};
i2c#e0004000 {
compatible = "cdns,i2c-r1p10";
status = "disabled";
clocks = <0x1 0x26>;
interrupt-parent = <0x4>;
interrupts = <0x0 0x19 0x4>;
reg = <0xe0004000 0x1000>;
#address-cells = <0x1>;
#size-cells = <0x0>;
};
i2c#e0005000 {
compatible = "cdns,i2c-r1p10";
status = "disabled";
clocks = <0x1 0x27>;
interrupt-parent = <0x4>;
interrupts = <0x0 0x30 0x4>;
reg = <0xe0005000 0x1000>;
#address-cells = <0x1>;
#size-cells = <0x0>;
};
interrupt-controller#f8f01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <0x3>;
interrupt-controller;
reg = <0xf8f01000 0x1000 0xf8f00100 0x100>;
phandle = <0x4>;
};
cache-controller#f8f02000 {
compatible = "arm,pl310-cache";
reg = <0xf8f02000 0x1000>;
interrupts = <0x0 0x2 0x4>;
arm,data-latency = <0x3 0x2 0x2>;
arm,tag-latency = <0x2 0x2 0x2>;
cache-unified;
cache-level = <0x2>;
};
memory-controller#f8006000 {
compatible = "xlnx,zynq-ddrc-a05";
reg = <0xf8006000 0x1000>;
};
ocmc#f800c000 {
compatible = "xlnx,zynq-ocmc-1.0";
interrupt-parent = <0x4>;
interrupts = <0x0 0x3 0x4>;
reg = <0xf800c000 0x1000>;
};
serial#e0000000 {
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
status = "disabled";
clocks = <0x1 0x17 0x1 0x28>;
clock-names = "uart_clk", "pclk";
reg = <0xe0000000 0x1000>;
interrupts = <0x0 0x1b 0x4>;
};
serial#e0001000 {
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
status = "okay";
clocks = <0x1 0x18 0x1 0x29>;
clock-names = "uart_clk", "pclk";
reg = <0xe0001000 0x1000>;
interrupts = <0x0 0x32 0x4>;
};
spi#e0006000 {
compatible = "xlnx,zynq-spi-r1p6";
reg = <0xe0006000 0x1000>;
status = "disabled";
interrupt-parent = <0x4>;
interrupts = <0x0 0x1a 0x4>;
clocks = <0x1 0x19 0x1 0x22>;
clock-names = "ref_clk", "pclk";
#address-cells = <0x1>;
#size-cells = <0x0>;
};
spi#e0007000 {
compatible = "xlnx,zynq-spi-r1p6";
reg = <0xe0007000 0x1000>;
status = "disabled";
interrupt-parent = <0x4>;
interrupts = <0x0 0x31 0x4>;
clocks = <0x1 0x1a 0x1 0x23>;
clock-names = "ref_clk", "pclk";
#address-cells = <0x1>;
#size-cells = <0x0>;
};
spi#e000d000 {
clock-names = "ref_clk", "pclk";
clocks = <0x1 0xa 0x1 0x2b>;
compatible = "xlnx,zynq-qspi-1.0";
status = "disabled";
interrupt-parent = <0x4>;
interrupts = <0x0 0x13 0x4>;
reg = <0xe000d000 0x1000>;
#address-cells = <0x1>;
#size-cells = <0x0>;
};
memory-controller#e000e000 {
#address-cells = <0x1>;
#size-cells = <0x1>;
status = "disabled";
clock-names = "memclk", "apb_pclk";
clocks = <0x1 0xb 0x1 0x2c>;
compatible = "arm,pl353-smc-r2p1", "arm,primecell";
interrupt-parent = <0x4>;
interrupts = <0x0 0x12 0x4>;
ranges;
reg = <0xe000e000 0x1000>;
flash#e1000000 {
status = "disabled";
compatible = "arm,pl353-nand-r2p1";
reg = <0xe1000000 0x1000000>;
#address-cells = <0x1>;
#size-cells = <0x1>;
};
flash#e2000000 {
status = "disabled";
compatible = "cfi-flash";
reg = <0xe2000000 0x2000000>;
#address-cells = <0x1>;
#size-cells = <0x1>;
};
};
ethernet#e000b000 {
compatible = "cdns,zynq-gem", "cdns,gem";
reg = <0xe000b000 0x1000>;
status = "okay";
interrupts = <0x0 0x16 0x4>;
clocks = <0x1 0x1e 0x1 0x1e 0x1 0xd>;
clock-names = "pclk", "hclk", "tx_clk";
#address-cells = <0x1>;
#size-cells = <0x0>;
phy-mode = "rgmii-id";
phy-handle = <0x5>;
ethernet-phy#0 {
reg = <0x0>;
phandle = <0x5>;
};
};
ethernet#e000c000 {
compatible = "cdns,zynq-gem", "cdns,gem";
reg = <0xe000c000 0x1000>;
status = "disabled";
interrupts = <0x0 0x2d 0x4>;
clocks = <0x1 0x1f 0x1 0x1f 0x1 0xe>;
clock-names = "pclk", "hclk", "tx_clk";
#address-cells = <0x1>;
#size-cells = <0x0>;
};
mmc#e0100000 {
compatible = "arasan,sdhci-8.9a";
status = "okay";
clock-names = "clk_xin", "clk_ahb";
clocks = <0x1 0x15 0x1 0x20>;
interrupt-parent = <0x4>;
interrupts = <0x0 0x18 0x4>;
reg = <0xe0100000 0x1000>;
};
mmc#e0101000 {
compatible = "arasan,sdhci-8.9a";
status = "disabled";
clock-names = "clk_xin", "clk_ahb";
clocks = <0x1 0x16 0x1 0x21>;
interrupt-parent = <0x4>;
interrupts = <0x0 0x2f 0x4>;
reg = <0xe0101000 0x1000>;
};
slcr#f8000000 {
u-boot,dm-pre-reloc;
#address-cells = <0x1>;
#size-cells = <0x1>;
compatible = "xlnx,zynq-slcr", "syscon", "simple-mfd";
reg = <0xf8000000 0x1000>;
ranges;
phandle = <0x6>;
clkc#100 {
u-boot,dm-pre-reloc;
#clock-cells = <0x1>;
compatible = "xlnx,ps7-clkc";
fclk-enable = <0xf>;
clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x", "cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x", "dci", "lqspi", "smc", "pcap", "gem0", "gem1", "fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1", "sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1", "dma", "usb0_aper", "usb1_aper", "gem0_aper", "gem1_aper", "sdio0_aper", "sdio1_aper", "spi0_aper", "spi1_aper", "can0_aper", "can1_aper", "i2c0_aper", "i2c1_aper", "uart0_aper", "uart1_aper", "gpio_aper", "lqspi_aper", "smc_aper", "swdt", "dbg_trc", "dbg_apb";
reg = <0x100 0x100>;
ps-clk-frequency = <0x1fca055>;
phandle = <0x1>;
};
rstc#200 {
compatible = "xlnx,zynq-reset";
reg = <0x200 0x48>;
#reset-cells = <0x1>;
syscon = <0x6>;
};
pinctrl#700 {
compatible = "xlnx,pinctrl-zynq";
reg = <0x700 0x200>;
syscon = <0x6>;
usb0-default {
phandle = <0x8>;
mux {
groups = "usb0_0_grp";
function = "usb0";
};
conf {
groups = "usb0_0_grp";
slew-rate = <0x0>;
io-standard = <0x1>;
};
conf-rx {
pins = "MIO29", "MIO31", "MIO36";
bias-high-impedance;
};
conf-tx {
pins = "MIO28", "MIO30", "MIO32", "MIO33", "MIO34", "MIO35", "MIO37", "MIO38", "MIO39";
bias-disable;
};
};
};
};
dmac#f8003000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0xf8003000 0x1000>;
interrupt-parent = <0x4>;
interrupt-names = "abort", "dma0", "dma1", "dma2", "dma3", "dma4", "dma5", "dma6", "dma7";
interrupts = <0x0 0xd 0x4 0x0 0xe 0x4 0x0 0xf 0x4 0x0 0x10 0x4 0x0 0x11 0x4 0x0 0x28 0x4 0x0 0x29 0x4 0x0 0x2a 0x4 0x0 0x2b 0x4>;
#dma-cells = <0x1>;
#dma-channels = <0x8>;
#dma-requests = <0x4>;
clocks = <0x1 0x1b>;
clock-names = "apb_pclk";
};
devcfg#f8007000 {
compatible = "xlnx,zynq-devcfg-1.0";
interrupt-parent = <0x4>;
interrupts = <0x0 0x8 0x4>;
reg = <0xf8007000 0x100>;
clocks = <0x1 0xc 0x1 0xf 0x1 0x10 0x1 0x11 0x1 0x12>;
clock-names = "ref_clk", "fclk0", "fclk1", "fclk2", "fclk3";
syscon = <0x6>;
phandle = <0x3>;
};
efuse#f800d000 {
compatible = "xlnx,zynq-efuse";
reg = <0xf800d000 0x20>;
};
timer#f8f00200 {
compatible = "arm,cortex-a9-global-timer";
reg = <0xf8f00200 0x20>;
interrupts = <0x1 0xb 0x301>;
interrupt-parent = <0x4>;
clocks = <0x1 0x4>;
};
timer#f8001000 {
interrupt-parent = <0x4>;
interrupts = <0x0 0xa 0x4 0x0 0xb 0x4 0x0 0xc 0x4>;
compatible = "cdns,ttc";
clocks = <0x1 0x6>;
reg = <0xf8001000 0x1000>;
};
timer#f8002000 {
interrupt-parent = <0x4>;
interrupts = <0x0 0x25 0x4 0x0 0x26 0x4 0x0 0x27 0x4>;
compatible = "cdns,ttc";
clocks = <0x1 0x6>;
reg = <0xf8002000 0x1000>;
};
timer#f8f00600 {
interrupt-parent = <0x4>;
interrupts = <0x1 0xd 0x301>;
compatible = "arm,cortex-a9-twd-timer";
reg = <0xf8f00600 0x20>;
clocks = <0x1 0x4>;
};
usb#e0002000 {
compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
status = "okay";
clocks = <0x1 0x1c>;
interrupt-parent = <0x4>;
interrupts = <0x0 0x15 0x4>;
reg = <0xe0002000 0x1000>;
phy_type = "ulpi";
dr_mode = "host";
usb-phy = <0x7>;
pinctrl-names = "default";
pinctrl-0 = <0x8>;
};
usb#e0003000 {
compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
status = "disabled";
clocks = <0x1 0x1d>;
interrupt-parent = <0x4>;
interrupts = <0x0 0x2c 0x4>;
reg = <0xe0003000 0x1000>;
phy_type = "ulpi";
};
watchdog#f8005000 {
clocks = <0x1 0x2d>;
compatible = "cdns,wdt-r1p2";
interrupt-parent = <0x4>;
interrupts = <0x0 0x9 0x1>;
reg = <0xf8005000 0x1000>;
timeout-sec = <0xa>;
};
};
aliases {
ethernet0 = "/amba/ethernet#e000b000";
serial0 = "/amba/serial#e0001000";
};
memory#0 {
device_type = "memory";
reg = <0x0 0x40000000>;
};
chosen {
bootargs = "earlycon";
stdout-path = "serial0:115200n8";
};
phy0 {
compatible = "usb-nop-xceiv";
#phy-cells = <0x0>;
phandle = <0x7>;
};
};

Problem 1: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property
Your __overlay__ node has #address-cells and #size-cells, this means you should have a reg property in its subnodes (i.e. custom_port_phy) that set the address and size (or use the ranges property).
Since you need no addressing of subnodes, just remove #address-cells and #size-cells from __overlay__.
On the other hand, the #address-cells and #size-cells in the custom_port_phy are correct, because its subnodes (dummy_port_phy#0 and dummy_port_phy#1) do have a reg property.
The result should be:
/dts-v1/;
/plugin/;
/ {
fragment#1 {
target = <&phy0>;
__overlay__ {
// Remove these (custom_port_phy has no reg)
// #address-cells = <0x1>;
// #size-cells = <0x1>;
custom_port_phy {
// Leave these (dummy_port_phy#X have reg)
#address-cells = <1>;
#size-cells = <0>;
compatible = "custom,custom-port-phy";
Dummy_Port_Phy0: dummy_port_phy#0 {
reg = <0>;
speed = <1000>;
};
Dummy_Port_Phy1: dummy_port_phy#1 {
reg = <1>;
speed = <1000>;
};
};
};
};
};
Problem 2: no symbols in root of device tree
You need to compile the base device tree with the -# flag. This way the base tree will expose its __symbols__ (including the phy0 you need) and it will be found when applying the overlay.
See the kernel code that emits that error.

Related

PWM input capture and repeat. STM32F4

guys.
I generated PWM signal with timer TIM1.
I want get this PWM from TIM1 with timer TIM2 and repeat it on the some GPIO pin.
I used Standart Peripheral Library.
PWM has generated on pin PA8 with timer TIM1 successfully, but i can't receive this PWM signal from PA0 pin with TIM2.
(PA8 и PA0 i connected with cable.)
Help me, please.
type here
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_tim.h"
#include "misc.h"
#include <stdio.h>
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM1_TimeBaseStruct;
TIM_OCInitTypeDef TIM1_OCInitStruct;
TIM_ICInitTypeDef TIM_ICInitStruct;
volatile uint16_t capture1 = 0, capture2 = 0;
volatile uint8_t capture_is_first = 1, capture_is_ready = 0;
const uint32_t myPeriod = 61538 - 1;
const uint32_t myPrescaler = 1 - 1;
const uint32_t myPulse = 5000;
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// Generate PWM on PA8
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// Input capture PWM on PA0
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
TIM1_TimeBaseStruct.TIM_Period = myPeriod;
TIM1_TimeBaseStruct.TIM_Prescaler = myPrescaler;
TIM1_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseStruct);
TIM1_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM1_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM1_OCInitStruct.TIM_Pulse = myPulse;
TIM1_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM1_OCInitStruct.TIM_OCNPolarity = TIM_OutputState_Disable;
TIM1_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM1, &TIM1_OCInitStruct);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
TIM_TimeBaseInitTypeDef timer_base;
TIM_TimeBaseStructInit(&timer_base);
timer_base.TIM_Prescaler = 24000 - 1;
TIM_ICInitTypeDef timer_ic;
timer_ic.TIM_Channel = TIM_Channel_1;
timer_ic.TIM_ICPolarity = TIM_ICPolarity_Rising;
timer_ic.TIM_ICSelection = TIM_ICSelection_DirectTI;
timer_ic.TIM_ICPrescaler = TIM_ICPSC_DIV1;
timer_ic.TIM_ICFilter = 0;
TIM_ICInit(TIM2, &timer_ic);
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
NVIC_EnableIRQ(TIM2_IRQn);
/* Включаем таймер */
TIM_Cmd(TIM2, ENABLE);
while (1)
{
}
} // main
void TIM2_IRQHandler(void)
{
int i = 0;
i++;
printf("I'm TIM2 IRQ Handler.");
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
capture1 = capture2;
capture2 = TIM_GetCapture1(TIM2);
if (!capture_is_first)
capture_is_ready = 1;
capture_is_first = 0;
if (TIM_GetFlagStatus(TIM2, TIM_FLAG_CC1OF) != RESET)
{
TIM_ClearFlag(TIM2, TIM_FLAG_CC1OF);
// ...
}
}
}
I wrote the receive (input capture) PWM signal code using examples from the Internet, but i can't debug this. Help please. I'm new to embedded dev.

SPI MISO value 255

i am trying to move my program to hal and my SPI is receiving only 255. What did i forget to set?
Function for reading:
uint8_t addressMsb[1] = { READ_ADDRESS | RTD_MSB_ADDRESS };
uint8_t addressLsb[1] = { READ_ADDRESS | RTD_LSB_ADDRESS };
uint8_t Temp_Msb[1];
uint8_t Temp_Lsb[1];
...
PT_CS1_LOW;
HAL_SPI_Transmit(&hspi1, (uint8_t*) addressMsb, 1, 10);
HAL_SPI_Receive(&hspi1, (uint8_t*) Temp_Msb, 1, 10);
PT_CS1_HIGH;
for(int i = 0; i<10;i++);
PT_CS1_LOW;
HAL_SPI_Transmit(&hspi1, (uint8_t*) addressLsb, 1, 10);
HAL_SPI_Receive(&hspi1, (uint8_t*) Temp_Lsb, 1, 10);
PT_CS1_HIGH;
...
Settings:
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_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
...
__HAL_RCC_SPI1_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
I know that it isnt a HW fail because a selfmade function on this board works. (frequency and settings are the same)
the old function:
if (!((SPI1)->CR1 & SPI_CR1_SPE)){
while(((SPI1)->SR & (SPI_SR_TXE | SPI_SR_RXNE)) == 0 || (SPI1)->SR & SPI_SR_BSY))SPI_WAIT(SPIx);
SPI1->DR = data;
while(((SPI1)->SR & (SPI_SR_TXE | SPI_SR_RXNE)) == 0 || ((SPI1)->SR & SPI_SR_BSY))SPI_WAIT(SPIx);
return SPI1->DR;
}
Sry guys my mistake,
if someone needs a working example for MAX31865 you can take the code up there... I powered down my computer and my HW for 5 minutes and now is everthink working even with HAL. It is suspicious that it did work with the old program and with HAL dont and after restart are both working... but now i know the HAL code is from principle is not wrong.
READ_ADDRESS = 0x00
RTD_MSB_ADDRESS = 0x01
RTD_LSB_ADDRESS = 0x02

How do I use the STM32CUBEF4 HAL library to read out the sensor data with i2c?

I want to use the latest HAL library instead of Standard Peripheral Library.
And i want to readout the BMA250E G-sensor's chip_id, but it doesn't work.
Value of aRxBuffer always keep at 0x00. But it should be 0xf9!
What's wrong in my code?
‪#‎include‬ "stm32f4xx_hal.h"
#define I2Cx_SDA_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2Cx_SDA_PIN GPIO_PIN_9
#define I2Cx_SDA_GPIO_PORT GPIOB
#define I2Cx_SDA_AF GPIO_AF4_I2C1
#define I2Cx_SCL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2Cx_SCL_PIN GPIO_PIN_6
#define I2Cx_SCL_GPIO_PORT GPIOB
#define I2Cx_SCL_AF GPIO_AF4_I2C1
#define I2Cx_CLK_ENABLE() __HAL_RCC_I2C1_CLK_ENABLE()
#define I2Cx_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
#define I2Cx_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()
‪#‎define‬ I2C_ADDRESS 0x18
static void SystemClock_Config(void);
uint8_t aTxBuffer[2],aRxBuffer;
int main()
{
HAL_Init();
SystemClock_Config();
I2C_HandleTypeDef I2cHandle;
I2cHandle.Instance = I2C1;
I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2cHandle.Init.ClockSpeed = 400000;
I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
I2cHandle.Init.OwnAddress1 = 0;
I2cHandle.Init.OwnAddress2 = 0;
HAL_I2C_Init(&I2cHandle);
aTxBuffer[0]=0x00;
HAL_I2C_Master_Transmit(&I2cHandle, I2C_ADDRESS,aTxBuffer, 1, 10000);
HAL_I2C_Master_Receive(&I2cHandle,I2C_ADDRESS|0x01 ,&aRxBuffer, 1, 10000);
HAL_Delay(1000);
}
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 360;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType =
(RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
I2Cx_SCL_GPIO_CLK_ENABLE();
I2Cx_SDA_GPIO_CLK_ENABLE();
GPIO_InitStruct.Pin = I2Cx_SCL_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Alternate = I2Cx_SCL_AF;
HAL_GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = I2Cx_SDA_PIN;
GPIO_InitStruct.Alternate = I2Cx_SDA_AF;
HAL_GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct);
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c)
{
I2Cx_FORCE_RESET();
I2Cx_RELEASE_RESET();
HAL_GPIO_DeInit(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN);
HAL_GPIO_DeInit(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_PIN);
}
First, I would advise you to use STMCube. It will set up the clock and the I2C bus for you.
It is very good practice to check what the HAL functions return. If you don't have HAL_OK, something went wrong.
Try at 100KHz first, and then increase to 400KHz.
The I2C address of the device is 0x18 (if SDO is grounded, which I assume it is). But in the HAL driver, you have to define:
#‎define‬ I2C_ADDRESS (0x18<<1)
What you want to do is to read a register, so don't use HAL_I2C_Master_Receive or HAL_I2C_Master_Transmit, but HAL_I2C_Mem_Read or HAL_I2C_Mem_Write, like this:
#define REG_CHIP_ID 0x00
HAL_I2C_Mem_Read(&I2cHandle, I2C_ADDRESS, REG_CHIP_ID, I2C_MEMADD_SIZE_8BIT, &aRxBuffer, 1, 10000);
Also, note that the HAL takes care of the R/W bit of the address, so you don't need to do:
I2C_ADDRESS|0x01

STM32 F3 Discovery ADC with DMA and Nvic

I have to use 4 ADC channels in my stm32f3 Discovery, so I've decided to use DMA with Nvic. Values sent by USART are correct, however, the DMA1 Channel1 interrupt is called only once after downloading code to flash. I need a continuous conversion, is there something wrong with ADC/DMA/Nvic configuration?
#include"stm32f30x.h"
#include"stm32f30x_gpio.h"
#include"stm32f30x_rcc.h"
#include"stm32f30x_usart.h"
#include"stm32f30x_misc.h"
#include"stm32f30x_adc.h"
#include"stm32f30x_tim.h"
#include"stm32f30x_dma.h"
#define ADC1_DR ((uint32_t)0x4001244C)
__IO uint16_t calibration_value = 0;
__IO uint32_t TimingDelay = 0;
__IO uint16_t ADC_Values[4];
uint16_t tmp[4];
volatile uint32_t dmaFlag = 0;
volatile char rxData[100];
volatile long int rxIndex=0, rxFlag=0;
void USART_puts( USART_TypeDef* USARTx, char *str )
{
while(*str)
{
while( USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET );
USART_SendData(USARTx, *str);
*str++;
}
}
void adc_init(void);
int main(void)
{
int8_t dmaIndex;
int k;
usart_init();
USART_puts(USART1,"ok");
adc_init();
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_RDY));
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_StartConversion(ADC1);
//
while(1)
{
while(!dmaFlag);
usart_num(tmp[0]);
usart_num(tmp[1]);
usart_num(tmp[2]);
usart_num(tmp[3]);
for(k=0;k<10000000;k++);
dmaFlag= 0;
}
}
void adc_init(void)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure1;
GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure1.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure1);
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_Circular;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
ADC_InitStructure.ADC_NbrOfRegChannel = 4;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_StructInit(&ADC_InitStructure);
ADC_VoltageRegulatorCmd(ADC1, ENABLE);
ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1) != RESET );
calibration_value = ADC_GetCalibrationValue(ADC1);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 3, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 4, ADC_SampleTime_7Cycles5);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Values;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 4;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16 bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 16 bit
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
}
void DMA1_Channel1_IRQHandler(void)
{
USART_puts(USART1,"fsfr");
if (DMA_GetITStatus(DMA1_IT_TC1))
{
int dmaIndex;
for(dmaIndex=0; dmaIndex<4; dmaIndex++)
{
tmp[dmaIndex]=ADC_Values[dmaIndex]/4;
}
DMA_ClearITPendingBit(DMA1_IT_TC1);
dmaFlag= 1;
}
}
void usart_init( void )
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init( GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig( USART1, USART_IT_RXNE, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd( USART1, ENABLE);
}
void USART1_IRQHandler( void )
{
if( USART_GetITStatus( USART1, USART_IT_RXNE) )
{
rxData[rxIndex] = USART_ReceiveData(USART1);
// USART_ClearITPendingBit(USART1,USART_IT_RXNE);
while( !(rxData[rxIndex] == 'e') )
{
if( USART_GetITStatus( USART1, USART_IT_RXNE) )
{
rxIndex++;
rxData[rxIndex] = USART_ReceiveData(USART1);
if( rxData[rxIndex] == ' ')
rxData[rxIndex] = '0';
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
rxFlag = 1;
}
///USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
void rxDataClear( void )
{
int i=0;
while( rxData[i] )
{
rxData[i] = 0;
i++;
}
rxIndex = 0;
}
void usart_float( float liczba )
{
float tmp;
char dane[7];
tmp = liczba;
dane[0]=(((int)tmp %1000) /100)+0x30;
dane[1]=(((int)tmp %100) /10)+0x30;
dane[2]=(((int)tmp %10))+0x30;
dane[3]='.';
dane[4]=((int)(tmp*10) %10)+0x30;
dane[5]=((int)(tmp*100) %10)+0x30;
dane[6]=((int)(tmp*1000) %10)+0x30;
dane[7]='\0';
USART_puts(USART1,dane);
}
void usart_num(signed int liczba)
{
int i, length=0,znak=0;
char liczba_str[10] = {0};
if( liczba < 0 )
{
znak = 1;
liczba = - liczba;
}
for( i = 1; (i <= liczba) && (length <= 10); i*=10 )
{
if( (liczba/i) > 0 )
length++;
}
if(length == 0)
length = 1;
i = 1;
while(length)
{
liczba_str[length-1]=liczba%(10*i)/i+48;
length--;
i*= 10;
}
if(znak)
USART_puts(USART1,"-");
else
USART_puts(USART1," ");
USART_puts(USART1, liczba_str );
}
Try this to continuous conversion,change this:
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
to :
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
and replace this:
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
by:
ADC_DMAConfig( ADC1, ADC_DMAMode_Circular );
/* Enable ADC1 DMA */
ADC_DMACmd( ADC1, ENABLE );
/* Enable ADC1 */
ADC_Cmd( ADC1, ENABLE );
/* Wait for ADC1 ready */
i = 0xFFFFF;
while(!ADC_GetFlagStatus( ADC1, ADC_FLAG_RDY ) && i) i--;
/* Enable the DMA1 channel1 */
DMA_Cmd( DMA1_Channel1, ENABLE );
/* Start ADC1 Software Conversion */
ADC_StartConversion( ADC1);`

stm32 pulse count up mode with reset, why not reset? (two signal reset count and steps)

I make this easy example, with count pulse input TI1 and reset pulse input TI2
when enable reset trigger counter give random numbers!
stm32 driver https://github.com/mbedmicro/mbed/blob/9b7d23d47153c298a6d24de9a415202705889d11/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32L4/stm32l4xx_hal_tim.h
function is like this:
/* Select the TIM_SMCR_TS_1 signal as Input trigger for the TIM */
htim->Instance->SMCR &= ~TIM_SMCR_TS;
htim->Instance->SMCR |= TIM_SMCR_TS_1;
Use the TIM_SMCR_TS_1 to reset the TIM counter each edge detection */
htim->Instance->SMCR &= ~TIM_SMCR_SMS;
htim->Instance->SMCR |= TIM_SLAVEMODE_RESET;
code:
#include "mbed.h"
#include "stm32f4xx.h"
#include "stm32f4xx_hal_tim_ex.h"
//direction to PA_9 -- step pulse to PA_8
uint16_t count1;
void pulsecount(void)
{
TIM_HandleTypeDef timer;
TIM_IC_InitTypeDef ICconfiginit;
TIM_ClockConfigTypeDef counter;
TIM_SlaveConfigTypeDef SlaveModeselect;
GPIO_InitTypeDef GPIO_InitStruct;
__TIM1_CLK_ENABLE();
__GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
timer.Instance = TIM1;
timer.Init.Period = 0xffff;
timer.Init.Prescaler = 0;
timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
timer.Init.CounterMode = TIM_COUNTERMODE_UP;
ICconfiginit.ICFilter = 0x0f;
ICconfiginit.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
ICconfiginit.ICPrescaler = TIM_ICPSC_DIV1;
ICconfiginit.ICSelection = TIM_ICSELECTION_DIRECTTI;
counter.ClockSource = TIM_CLOCKSOURCE_TI1;
counter.ClockFilter = 0x0f;
SlaveModeselect.SlaveMode = TIM_SLAVEMODE_RESET;
SlaveModeselect.InputTrigger = TIM_TS_TI2FP2;
HAL_TIM_IC_Init(&timer);
HAL_TIM_IC_ConfigChannel(&timer, &ICconfiginit, TIM_CHANNEL_1);
HAL_TIM_ConfigClockSource(&timer, &counter);
HAL_TIM_SlaveConfigSynchronization(&timer, &SlaveModeselect); ///<<< not reset
HAL_TIM_IC_Start(&timer, TIM_CHANNEL_1);
TIM1->EGR = 1; // Generate an update event
TIM1->CR1 = 1; // Enable the counter
}
int main()
{
pulsecount();
while (1) {
count1=TIM1->CNT;
printf("%d\r\n", count1);
wait(1.0);
};
}