Linux Kernel 5.10 verifier rejects eBPF XDP program that is fine for kernel 5.13 - linux

I am writing some eBPF programs in Rust using redBPF and I've encountered some issue with the verifier that only appears on some kernels.
This is a minimal reproducer XDP probe that shows the issue:
#[xdp]
unsafe fn xdp_test(ctx: XdpContext) -> XdpResult {
let data = ctx.data()?;
let start = ctx.data_start();
let off = data.offset();
let end = ctx.data_end();
/* Ensuring an upper bound for off doesn't make any difference
if off > 50 {
return XdpResult::Err(OutOfBounds);
}
*/
let mut address = start + off;
for i in 0..500 {
address = start + off + i;
if address <= start || address >= end {
break;
}
// This line (packet access) fails on kernel 5.10, but works fine on 5.13
let byte = *(address as *const u8);
// Just so the packet read above doesn't get optimized away
printk!("%u", byte as u32);
}
Ok(XdpAction::Pass)
}
Compiling this into eBPF bytecode and loading it into an Ubuntu 5.13 kernel (5.13.0-48-generic #54~20.04.1-Ubuntu SMP Thu Jun 2 23:37:17 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux) works without issues. The verifier accepts the program.
However, trying to load the exact same bytecode into an Android emulator kernel 5.10.66-android12-9-00041-gfa9c9074531e-ab7914766 #1 SMP PREEMPT Fri Nov 12 11:36:25 UTC 2021 x86_64 the verifier rejects the program. This is the full error log from the verifier:
ret=-1 os error=Permission denied (os error 13): 0: (61) r6 = *(u32 *)(r1 +4)
1: (61) r7 = *(u32 *)(r1 +0)
2: (bf) r1 = r7
3: (07) r1 += 14
4: (2d) if r1 > r6 goto pc+43
R1_w=pkt(id=0,off=14,r=14,imm=0) R6_w=pkt_end(id=0,off=0,imm=0) R7_w=pkt(id=0,off=0,r=14,imm=0) R10=fp0
5: (71) r2 = *(u8 *)(r7 +13)
6: (67) r2 <<= 8
7: (71) r3 = *(u8 *)(r7 +12)
8: (4f) r2 |= r3
9: (55) if r2 != 0x8 goto pc+38
R1_w=pkt(id=0,off=14,r=14,imm=0) R2_w=inv8 R3_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R6_w=pkt_end(id=0,off=0,imm=0) R7_w=pkt(id=0,off=0,r=14,imm=0) R10=fp0
10: (bf) r2 = r7
11: (07) r2 += 34
12: (2d) if r2 > r6 goto pc+35
R1=pkt(id=0,off=14,r=34,imm=0) R2=pkt(id=0,off=34,r=34,imm=0) R3=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R10=fp0
13: (71) r3 = *(u8 *)(r1 +0)
14: (67) r3 <<= 2
15: (57) r3 &= 60
16: (71) r2 = *(u8 *)(r1 +9)
17: (0f) r1 += r3
last_idx 17 first_idx 12
regs=8 stack=0 before 16: (71) r2 = *(u8 *)(r1 +9)
regs=8 stack=0 before 15: (57) r3 &= 60
regs=8 stack=0 before 14: (67) r3 <<= 2
regs=8 stack=0 before 13: (71) r3 = *(u8 *)(r1 +0)
18: (15) if r2 == 0x11 goto pc+31
R1_w=pkt(id=1,off=14,r=0,umax_value=60,var_off=(0x0; 0x3c)) R2_w=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R3_w=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R10=fp0
19: (55) if r2 != 0x6 goto pc+28
R1_w=pkt(id=1,off=14,r=0,umax_value=60,var_off=(0x0; 0x3c)) R2_w=inv6 R3_w=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R10=fp0
20: (2d) if r7 > r1 goto pc+27
R1=pkt(id=1,off=14,r=0,umax_value=60,var_off=(0x0; 0x3c)) R2=inv6 R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R10=fp0
21: (bf) r2 = r1
22: (07) r2 += 20
23: (2d) if r2 > r6 goto pc+24
R1=pkt(id=1,off=14,r=34,umax_value=60,var_off=(0x0; 0x3c)) R2_w=pkt(id=1,off=34,r=34,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R10=fp0
24: (71) r2 = *(u8 *)(r1 +12)
25: (77) r2 >>= 2
26: (57) r2 &= 60
27: (0f) r1 += r2
last_idx 27 first_idx 20
regs=4 stack=0 before 26: (57) r2 &= 60
regs=4 stack=0 before 25: (77) r2 >>= 2
regs=4 stack=0 before 24: (71) r2 = *(u8 *)(r1 +12)
28: (2d) if r7 > r1 goto pc+19
R1=pkt(id=2,off=14,r=0,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R2=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R10=fp0
29: (bf) r8 = r1
30: (3d) if r1 >= r6 goto pc+17
R1=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R2=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R8_w=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R10=fp0
31: (bf) r1 = r8
32: (1f) r1 -= r7
33: (25) if r1 > 0x32 goto pc+14
R1_w=inv(id=0,umax_value=50,var_off=(0x0; 0xffffffff)) R2=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R8_w=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R10=fp0
34: (b7) r9 = 0
35: (bf) r1 = r8
36: (0f) r1 += r9
last_idx 36 first_idx 28
regs=200 stack=0 before 35: (bf) r1 = r8
regs=200 stack=0 before 34: (b7) r9 = 0
37: (3d) if r7 >= r1 goto pc+10
R1=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R2=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R8=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R9=invP0 R10=fp0
38: (3d) if r1 >= r6 goto pc+9
R1=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R2=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R8=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R9=invP0 R10=fp0
39: (71) r3 = *(u8 *)(r1 +0)
invalid access to packet, off=14 size=1, R1(id=2,off=14,r=13)
R1 offset is outside of the packet
processed 40 insns (limit 1000000) max_states_per_insn 0 total_states 4 peak_states 4 mark_read 2
As I understand the issue, the verifier of the 5.10 kernel rejects the dereferencing of the packet pointer, claiming that we don't have validated that it is always within bounds (reading at offset 14 while r is 13). We do in fact check this just above.
Interestingly, if I oversize the bounds check above to something like this, both the 5.10 and 5.13 kernel verifiers accept the program:
[snip]
for i in 0..500 {
address = start + off + i;
// Checking 2 bytes ahead makes 5.10 verifier happy
if address <= start || (address + 2) >= end {
break;
}
// Works on both 5.10 and 5.13
let byte = *(address as *const u8);
// Just so the packet read above doesn't get optimized away
printk!("%u", byte as u32);
}
Ok(XdpAction::Pass)
}
But the above is not what I want, because this causes the bounded loop to abort too early - I want the loop to run fully, if the packet is large enough. I have tried the usual tricks I do when I run into verifier issues, but so far to no avail. I don't quite understand why the 5.10 verifier is unhappy with the first example. Usually this is related to some unbounded registers, but as far as I can see all bounds should be satisfied.
I have tried looking at a diff of the kernel verifier between the two versions, but couldn't see any obvious change that causes this.

TL;DR. You are missing bug fix 2fa7d94afc1a for the BPF verifier. It was backported to the v5.13 kernel you are using as commit e7a61f15beea, but not to the v5.10 kernel.
You might want to try a newer Android kernel if possible, or to ask them to carry the bugfix if they don't on v5.10.
Verifier Error Explanation
I removed parts of the output that were irrelevant here.
R1=pkt(id=2,off=14,r=0,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R2=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R10=fp0
29: (bf) r8 = r1
30: (3d) if r1 >= r6 goto pc+17
R1=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R2=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R8_w=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R10=fp0
[...]
34: (b7) r9 = 0
35: (bf) r1 = r8
36: (0f) r1 += r9
37: (3d) if r7 >= r1 goto pc+10
R1=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R2=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R8=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R9=invP0 R10=fp0
38: (3d) if r1 >= r6 goto pc+9
R1=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R2=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R3=invP(id=0,umax_value=60,var_off=(0x0; 0x3c)) R6=pkt_end(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=34,imm=0) R8=pkt(id=2,off=14,r=13,umax_value=120,var_off=(0x0; 0x7c),s32_max_value=124,u32_max_value=124) R9=invP0 R10=fp0
39: (71) r3 = *(u8 *)(r1 +0)
invalid access to packet, off=14 size=1, R1(id=2,off=14,r=13)
R1 offset is outside of the packet
The verifier tells us that we are trying to access the packet at offset 14 (off=14) with an access size of 1 byte when the packet is only known to be at least 13 bytes long (r=13). The known packet length here is incorrect somehow because you checked that address >= end.
Going up, we can check where that packet range (r=13) is coming from. It is assigned from R8 at instruction 35, itself assigned from R1 at instruction 29.
At instruction 30, we find the address >= end check in its bytecode form. We see that both R1 and R8's ranges are updated from r=0 to r=13 after this check. That is however incorrect and should be updated to off+1, hence r=15.
Checking the Verifier Sources
In the verifier, this update of the range is implemented in find_good_pkt_pointers. The update logic looks fine and shouldn't cause this issue.
But if we git blame those lines, we can see they were changed in commit 2fa7d94afc1a. The commit describes the off-by-two error you are hitting:
This commit fixes the off-by-two error by adjusting new_range in the
right direction and fixes the tests by changing the range into the
one that should actually fail.
This commit was released upstream in v5.16. Checking the Ubuntu sources for Ubuntu-hwe-5.13-5.13.0-48.54_20.04.1, we find this same commit backported as e7a61f15beea, which explains why it works on your v5.13 kernel.

Related

Trying to simulate JK-FF with gate level code

I've been trying to simulate a JK-FF with gate level code, but it's not working. Any help is appreciated.
Circuit code:
module circuit1_3_c(j,k,r,cp,q,q1);
input j,k,r,cp;
output q,q1;
wire t1,t2,t3,t4;
nand(t1,t2,q);
nand(t2,t1,j,cp,t3);
nand(t3,cp,k,t4);
nand(t4,t3,t1);
nand(q,q1,t2);
nand(q1,q,t3,r);
endmodule
Testbench code:
module circuit1_3_ctest;
parameter STEP=10;
parameter HALF_STEP=5;
reg j,k,r,cp;
wire q,q1;
circuit1_3_c circ(j,k,r,cp,q,q1);
initial begin
$dumpfile("circuit1_3_c.vcd");
$dumpvars(0,circuit1_3_ctest);
$monitor("\%t: J=%b, K=%b, R=%b, Cp=%b, Q=%b, Qbar=%b", $time, j,k,r,cp,q,q1);
r<=1'b1;
cp<=1'b0;
j<=1'b0; k<=1'b0; r<=1'b1;
#STEP;
j<=1'b0; k<=1'b1; r<=1'b1;
#STEP;
j<=1'b1; k<=1'b0; r<=1'b1;
#STEP;
j<=1'b1; k<=1'b1; r<=1'b1;
#STEP;
j<=1'b0; k<=1'b0; r<=1'b1;
#STEP;
j<=1'b0; k<=1'b1; r<=1'b1;
#STEP;
j<=1'b1; k<=1'b0; r<=1'b1;
#STEP;
j<=1'b1; k<=1'b1; r<=1'b1;
#HALF_STEP
$finish;
end
always #HALF_STEP cp=~cp;
endmodule
Output. As you can see, q and q1 are always unknown (x):
[1
You need to reset your logic properly. One way is to drive r as 0 at time 0.
Change:
r<=1'b1;
cp<=1'b0;
j<=1'b0; k<=1'b0; r<=1'b1;
to:
cp<=1'b0;
j<=1'b0; k<=1'b0; r<=1'b0;
Output:
0: J=0, K=0, R=0, Cp=0, Q=0, Qbar=1
5: J=0, K=0, R=0, Cp=1, Q=0, Qbar=1
10: J=0, K=1, R=1, Cp=0, Q=0, Qbar=1
15: J=0, K=1, R=1, Cp=1, Q=0, Qbar=1
20: J=1, K=0, R=1, Cp=0, Q=0, Qbar=1
25: J=1, K=0, R=1, Cp=1, Q=1, Qbar=0
30: J=1, K=1, R=1, Cp=0, Q=1, Qbar=0
35: J=1, K=1, R=1, Cp=1, Q=0, Qbar=1
40: J=0, K=0, R=1, Cp=0, Q=0, Qbar=1
45: J=0, K=0, R=1, Cp=1, Q=0, Qbar=1
50: J=0, K=1, R=1, Cp=0, Q=0, Qbar=1
55: J=0, K=1, R=1, Cp=1, Q=0, Qbar=1
60: J=1, K=0, R=1, Cp=0, Q=0, Qbar=1
65: J=1, K=0, R=1, Cp=1, Q=1, Qbar=0
70: J=1, K=1, R=1, Cp=0, Q=1, Qbar=0

PyVista error trying to cast a shadow onto a gridded plane

PyVista is great, and let's me do lots of cool things very conveniently. I would like to cast the shadow of a 3D object onto a plane with grid lines. Here's what I would like, minus the shadows, shadows=False, gridlines=True
I can enable shadows without the grid lines: gridlines=False, shadows=True
but when I try to do both gridlines=True, shadows=True I get a massive error trace as per below and a result just like above, shadows but no grid lines.
QUESTION: is what I am trying to possible? Am I misunderstanding grids and shadows, have I coded it wrong, or is this a bug. My bigger program, with more graphical entities will segfault. I am running PyVista 0.29.0, Python 3.8.5 on MacOS 10.15.7. Similar problems arise if I try to cast the shadow on to a StructuredGrid.
Below is my minimal code example
import pyvista as pv
import vtk
import numpy as np
# change these values
gridlines = True
shadows = False
plotter = pv.Plotter(polygon_smoothing=True, window_size=(2000,2000))
plotter.disable_parallel_projection()
sphere = pv.Sphere(radius=0.3, center=(0,0,1))
plotter.add_mesh(sphere, ambient=0.2, diffuse=0.5, specular=0.8, specular_power=30,
smooth_shading=True, color='dodgerblue')
# add the grid
grid = pv.Plane(i_size=5, j_size=5)
plotter.add_mesh(grid, show_edges=gridlines, ambient=0, diffuse=0.5, specular=0.8, color='red', edge_color='white')
if shadows:
# do the shadows
shadows = vtk.vtkShadowMapPass()
seq = vtk.vtkSequencePass()
passes = vtk.vtkRenderPassCollection()
passes.AddItem(shadows.GetShadowMapBakerPass())
passes.AddItem(shadows)
seq.SetPasses(passes)
# Tell the renderer to use our render pass pipeline
cameraP = vtk.vtkCameraPass()
cameraP.SetDelegatePass(seq)
plotter.renderer.SetPass(cameraP)
plotter.set_background('white')
plotter.show()
Error trace:
(dev) [233 ~...code/RVC3-python/tools] % /Users/corkep/opt/miniconda3/envs/dev/bin/python /Users/corkep/Dropbox/code/RVC3-python/chapter8/pvbug.py
2021-03-11 19:57:38.908 ( 0.621s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b5f90): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:38.908 ( 0.622s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b6840): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:38.908 ( 0.622s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b7120): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:38.908 ( 0.622s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b7a00): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:38.908 ( 0.622s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b82e0): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:38.990 ( 0.704s) [ 84DF2C] vtkShaderProgram.cxx:452 ERR| vtkShaderProgram (0x7fee29ba49b0): 1: #version 150
2: #ifdef GL_ES
3: #ifdef GL_FRAGMENT_PRECISION_HIGH
4: precision highp float;
5: precision highp sampler2D;
6: precision highp sampler3D;
7: #else
8: precision mediump float;
9: precision mediump sampler2D;
10: precision mediump sampler3D;
11: #endif
12: #define texelFetchBuffer texelFetch
13: #define texture1D texture
14: #define texture2D texture
15: #define texture3D texture
16: #else // GL_ES
17: #define highp
18: #define mediump
19: #define lowp
20: #if __VERSION__ == 150
21: #define texelFetchBuffer texelFetch
22: #define texture1D texture
23: #define texture2D texture
24: #define texture3D texture
25: #endif
26: #endif // GL_ES
27: #define varying in
28:
29:
30: /*=========================================================================
31:
32: Program: Visualization Toolkit
33: Module: vtkPolyDataFS.glsl
34:
35: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
36: All rights reserved.
37: See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
38:
39: This software is distributed WITHOUT ANY WARRANTY; without even
40: the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
41: PURPOSE. See the above copyright notice for more information.
42:
43: =========================================================================*/
44: // Template for the polydata mappers fragment shader
45:
46: uniform int PrimitiveIDOffset;
47:
48:
49:
50: // VC position of this fragment
51: //VTK::PositionVC::Dec
52:
53: // Camera prop
54: uniform int cameraParallel;
55:
56:
57: // optional color passed in from the vertex shader, vertexColor
58: uniform float ambientIntensity; // the material ambient
59: uniform float diffuseIntensity; // the material diffuse
60: uniform float opacityUniform; // the fragment opacity
61: uniform vec3 ambientColorUniform; // ambient color
62: uniform vec3 diffuseColorUniform; // diffuse color
63:
64:
65: // optional surface normal declaration
66: //VTK::Normal::Dec
67:
68: // extra lighting parameters
69: uniform vec3 lightColor0;
70: uniform vec3 lightDirectionVC0; // normalized
71: uniform vec3 lightColor1;
72: uniform vec3 lightDirectionVC1; // normalized
73: uniform vec3 lightColor2;
74: uniform vec3 lightDirectionVC2; // normalized
75: uniform vec3 lightColor3;
76: uniform vec3 lightDirectionVC3; // normalized
77: uniform vec3 lightColor4;
78: uniform vec3 lightDirectionVC4; // normalized
79:
80: uniform float depthC;
81: vec2 calcShadow(in vec4 vert,
82: in sampler2D shadowMap,
83: in mat4 shadowTransform,
84: in float attenuation,
85: in int shadowParallel,
86: in float sNearZ, in float sFarZ)
87: {
88: vec4 shadowCoord = shadowTransform*vert;
89: float expFactor = 8.0;
90: float thickness = 0.0;
91: if(shadowCoord.w > 0.0)
92: {
93: vec2 projected = shadowCoord.xy/shadowCoord.w;
94: if(projected.x >= 0.0 && projected.x <= 1.0
95: && projected.y >= 0.0 && projected.y <= 1.0)
96: {
97: float ldepth = shadowCoord.z;
98: if (shadowParallel == 0) { ldepth = (shadowCoord.w - sNearZ)/(sFarZ - sNearZ); }
99: float depthCExpActual = exp(- depthC*ldepth);
100: float depthCExpBlured = texture2D(shadowMap,projected).r;
101: expFactor = depthCExpBlured * depthCExpActual;
102: float depth = log(depthCExpBlured)/depthC;
103: thickness = clamp(ldepth - depth, 0.0, 1.0)*(sFarZ - sNearZ);
104: if (expFactor > 1.0) { expFactor = 1.0; }
105: }
106: }
107: return vec2(1.0 - attenuation + attenuation*expFactor, thickness);
108: }
109: uniform int shadowParallel0;
110: uniform float shadowNearZ0;
111: uniform float shadowFarZ0;
112: uniform float shadowAttenuation0;
113: uniform sampler2D shadowMap0;
114: uniform mat4 shadowTransform0;
115: uniform int shadowParallel1;
116: uniform float shadowNearZ1;
117: uniform float shadowFarZ1;
118: uniform float shadowAttenuation1;
119: uniform sampler2D shadowMap1;
120: uniform mat4 shadowTransform1;
121: uniform int shadowParallel2;
122: uniform float shadowNearZ2;
123: uniform float shadowFarZ2;
124: uniform float shadowAttenuation2;
125: uniform sampler2D shadowMap2;
126: uniform mat4 shadowTransform2;
127: uniform int shadowParallel3;
128: uniform float shadowNearZ3;
129: uniform float shadowFarZ3;
130: uniform float shadowAttenuation3;
131: uniform sampler2D shadowMap3;
132: uniform mat4 shadowTransform3;
133:
134:
135: // Texture maps
136: //VTK::TMap::Dec
137:
138: // Texture coordinates
139: //VTK::TCoord::Dec
140:
141: // picking support
142: //VTK::Picking::Dec
143:
144: // Depth Peeling Support
145: //VTK::DepthPeeling::Dec
146:
147: // clipping plane vars
148: //VTK::Clip::Dec
149:
150: // the output of this shader
151: out vec4 fragOutput0;
152:
153:
154: // Apple Bug
155: //VTK::PrimID::Dec
156:
157: // handle coincident offsets
158: uniform float cCValue;
159: uniform float cSValue;
160: uniform float cDValue;
161:
162: // Value raster
163: //VTK::ValuePass::Dec
164:
165: void main()
166: {
167: // VC position of this fragment. This should not branch/return/discard.
168: //VTK::PositionVC::Impl
169:
170: // Place any calls that require uniform flow (e.g. dFdx) here.
171: //VTK::UniformFlow::Impl
172:
173: // Set gl_FragDepth here (gl_FragCoord.z by default)
174: float Zdc = gl_FragCoord.z*2.0 - 1.0;
175: float Z2 = -1.0*cDValue/(Zdc + cCValue) + cSValue;
176: float Zdc2 = -1.0*cCValue - cDValue/Z2;
177: gl_FragDepth = Zdc2*0.5 + 0.5;
178:
179:
180: // Early depth peeling abort:
181: //VTK::DepthPeeling::PreColor
182:
183: // Apple Bug
184: //VTK::PrimID::Impl
185:
186: //VTK::Clip::Impl
187:
188: //VTK::ValuePass::Impl
189:
190: vec3 ambientColor = ambientIntensity * ambientColorUniform;
191: vec3 diffuseColor = diffuseIntensity * diffuseColorUniform;
192: float opacity = opacityUniform;
193:
194:
195: // Generate the normal if we are not passed in one
196: //VTK::Normal::Impl
197:
198: vec2 factor0 = vec2(1.0);
199: vec2 factor1 = calcShadow(vertexVC, shadowMap0, shadowTransform0, shadowAttenuation0, shadowParallel0, shadowNearZ0, shadowFarZ0);
200: vec2 factor2 = calcShadow(vertexVC, shadowMap1, shadowTransform1, shadowAttenuation1, shadowParallel1, shadowNearZ1, shadowFarZ1);
201: vec2 factor3 = calcShadow(vertexVC, shadowMap2, shadowTransform2, shadowAttenuation2, shadowParallel2, shadowNearZ2, shadowFarZ2);
202: vec2 factor4 = calcShadow(vertexVC, shadowMap3, shadowTransform3, shadowAttenuation3, shadowParallel3, shadowNearZ3, shadowFarZ3);
203: fragOutput0 = vec4(ambientColor + diffuseColor, opacity);
204: //VTK::Light::Impl
205:
206:
207:
208: //VTK::TCoord::Impl
209:
210: if (fragOutput0.a <= 0.0)
211: {
212: discard;
213: }
214:
215: //VTK::DepthPeeling::Impl
216:
217: //VTK::Picking::Impl
218:
219: // handle coincident offsets
220: //VTK::Coincident::Impl
221: }
ERROR:root:1: #version 150
2021-03-11 19:57:38.991 ( 0.705s) [ 84DF2C] vtkShaderProgram.cxx:453 ERR| vtkShaderProgram (0x7fee29ba49b0): ERROR: 0:199: Use of undeclared identifier 'vertexVC'
ERROR: 0:200: Use of undeclared identifier 'vertexVC'
ERROR: 0:201: Use of undeclared identifier 'vertexVC'
ERROR: 0:202: Use of undeclared identifier 'vertexVC'
ERROR:root:ERROR: 0:199: Use of undeclared identifier 'vertexVC'
2021-03-11 19:57:39.023 ( 0.737s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b5f90): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.023 ( 0.737s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b6840): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.023 ( 0.737s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b7120): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.023 ( 0.737s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b7a00): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.023 ( 0.737s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b82e0): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.024 ( 0.738s) [ 84DF2C] vtkShaderProgram.cxx:437 ERR| vtkShaderProgram (0x7fee29ba49b0): 1: #version 150
2: #ifndef GL_ES
3: #define highp
4: #define mediump
5: #define lowp
6: #endif // GL_ES
7: #define attribute in
8: #define varying out
9:
10:
11: /*=========================================================================
12:
13: Program: Visualization Toolkit
14: Module: vtkPolyDataVS.glsl
15:
16: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
17: All rights reserved.
18: See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
19:
20: This software is distributed WITHOUT ANY WARRANTY; without even
21: the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
22: PURPOSE. See the above copyright notice for more information.
23:
24: =========================================================================*/
25:
26: in vec4 vertexMC;
27:
28:
29:
30: // frag position in VC
31: //VTK::PositionVC::Dec
32:
33: // optional normal declaration
34: //VTK::Normal::Dec
35:
36: // extra lighting parameters
37: //VTK::Light::Dec
38:
39: // Texture coordinates
40: //VTK::TCoord::Dec
41:
42: // material property values
43: //VTK::Color::Dec
44:
45: // clipping plane vars
46: //VTK::Clip::Dec
47:
48: // camera and actor matrix values
49: uniform mat4 MCDCMatrix;
50:
51: // Apple Bug
52: //VTK::PrimID::Dec
53:
54: // Value raster
55: //VTK::ValuePass::Dec
56:
57: // picking support
58: //VTK::Picking::Dec
59:
60: void main()
61: {
62: //VTK::Color::Impl
63:
64: //VTK::Normal::Impl
65:
66: //VTK::TCoord::Impl
67:
68: //VTK::Clip::Impl
69:
70: //VTK::PrimID::Impl
71:
72: gl_Position = MCDCMatrix * vertexMC;
73:
74:
75: //VTK::ValuePass::Impl
76:
77: //VTK::Light::Impl
78:
79: //VTK::Picking::Impl
80: }
ERROR:root:1: #version 150
2021-03-11 19:57:39.025 ( 0.739s) [ 84DF2C] vtkShaderProgram.cxx:438 ERR| vtkShaderProgram (0x7fee29ba49b0):
WARNING:root:ERROR: In /Users/tjcorona/Development/vtk/source/Rendering/OpenGL2/vtkShaderProgram.cxx, line 438
vtkShaderProgram (0x7fee29ba49b0):
2021-03-11 19:57:39.292 ( 1.006s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b5f90): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.292 ( 1.006s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b6840): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.292 ( 1.006s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b7120): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.292 ( 1.006s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b7a00): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.292 ( 1.006s) [ 84DF2C] vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b82e0): not a spotlight.
ERROR:root:not a spotlight.
2021-03-11 19:57:39.293 ( 1.007s) [ 84DF2C] vtkShaderProgram.cxx:437 ERR| vtkShaderProgram (0x7fee29ba49b0): 1: #version 150
2: #ifndef GL_ES
3: #define highp
4: #define mediump
5: #define lowp
6: #endif // GL_ES
7: #define attribute in
8: #define varying out
9:
10:
11: /*=========================================================================
12:
13: Program: Visualization Toolkit
14: Module: vtkPolyDataVS.glsl
15:
16: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
17: All rights reserved.
18: See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
19:
20: This software is distributed WITHOUT ANY WARRANTY; without even
21: the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
22: PURPOSE. See the above copyright notice for more information.
23:
24: =========================================================================*/
25:
26: in vec4 vertexMC;
27:
28:
29:
30: // frag position in VC
31: //VTK::PositionVC::Dec
32:
33: // optional normal declaration
34: //VTK::Normal::Dec
35:
36: // extra lighting parameters
37: //VTK::Light::Dec
38:
39: // Texture coordinates
40: //VTK::TCoord::Dec
41:
42: // material property values
43: //VTK::Color::Dec
44:
45: // clipping plane vars
46: //VTK::Clip::Dec
47:
48: // camera and actor matrix values
49: uniform mat4 MCDCMatrix;
50:
51: // Apple Bug
52: //VTK::PrimID::Dec
53:
54: // Value raster
55: //VTK::ValuePass::Dec
56:
57: // picking support
58: //VTK::Picking::Dec
59:
60: void main()
61: {
62: //VTK::Color::Impl
63:
64: //VTK::Normal::Impl
65:
66: //VTK::TCoord::Impl
67:
68: //VTK::Clip::Impl
69:
70: //VTK::PrimID::Impl
71:
72: gl_Position = MCDCMatrix * vertexMC;
73:
74:
75: //VTK::ValuePass::Impl
76:
77: //VTK::Light::Impl
78:
79: //VTK::Picking::Impl
80: }
ERROR:root:1: #version 150
2021-03-11 19:57:39.294 ( 1.008s) [ 84DF2C] vtkShaderProgram.cxx:438 ERR| vtkShaderProgram (0x7fee29ba49b0):
WARNING:root:ERROR: In /Users/tjcorona/Development/vtk/source/Rendering/OpenGL2/vtkShaderProgram.cxx, line 438
vtkShaderProgram (0x7fee29ba49b0):
Shadowing is currently not implemented in PyVista, and I don't know how reliable it is in vtk (or how to make it work reliably).
Quoting from this comment:
As for the shadows, it works 100% of the time 60% of the time. We should add as an option and then users can play around with it. I'm sure at some point real time ray tracing is going to be a hardware feature even down to integrated GPUs, so it's a matter of time until this becomes a well tested/supported feature.
For instance on my laptop with an integrated GPU shadow rendering is a mess.
With window size (1000, 1000):
With window size (2000, 1000):
In any case I can more or less reproduce the errors you're seeing. The first error comes partly from PyVista:
vtkLightActor.cxx:285 ERR| vtkLightActor (0x7fee299b5f90): not a spotlight.
ERROR:root:not a spotlight.
This is because PyVista Light objects have a vtkLightActor attached to them, but these should be hidden (i.e. never rendered) unless the light is a spotlight (the only case where a vtkLightActor makes sense). As I noted on the aforementioned issue the error shouldn't arise and it makes little sense that shadowing affects this. If this ended up staying a problem we could try mitigating it in PyVista, but it would be a lot of complexity for questionable gain.
The second error from the shader is very much VTK and I don't know what exactly it's about. Considering how this is not a supported feature of PyVista and you're using vtk directly, it probably makes more sense to raise the issue with vtk. (Although I don't know if there might be something we could put in on the PyVista side to make it work more reliably.)
For what it's worth you might be able to swap your if shadows block with just this:
plotter.renderer.SetUseShadows(shadows)
At least I see the same behaviour if I use that. So in cases where your code works for you, it might be a simpler alternative.

Cortex-M3 SysTick double interrupt

I'm creating a rtos system, with system tick (1ms) for real-time and trigger pendsv-which used for switch task. Priority of systick and pendsv same as 0 (group = 16; <SCB.AIRCR.PRIGROUP = 0b011>). PendSv also trigger by <SCB.ICSR.PENDSVSET = 1> when current task is sleep.
Sometime, PendSV and SysTick occurs at the same time, and SysTick is executed first, then PendSv. But after PendSV executed, SysTick occurs again.
I was tried by change priority, and clear <SCB.ICSR.PENDSTCLR = 1> in system tick handle, nothing changed.
Do you know why, and how to fix that?
logic_analyzer
asm code:
//#define USING_PUSH_POP
EXTERN GPIOA_BITBAND
EXTERN RTOS_GetCurrentCPU //CPU_TypeDef* RTOS_GetCurrentCPU();
EXTERN RTOS_GetNextCPU //CPU_TypeDef* RTOS_GetNextCPU();
PUBLIC PendSV_Handler
PUBLIC RTOS_ASM_Begin //void RTOS_ASM_ASM_Begin(CPU_TypeDef* CPU);
SECTION rtos_function:CODE
PendSV_Handler:
//PUSH in SP when interrupt
//Here - R0 - R1 - R2 - R3 - R12 - BACK_LR - BACK_PC - EAPSR
PUSH {LR}
LDR.W R0, =GPIOA_BITBAND //(1)
MOV R1, #1
STR R1, [R0, #0x180]
BL RTOS_GetCurrentCPU
CMP R0, #0
BEQ BREAK //if (NULL): back to current task
BL RTOS_ASM_SaveCurrentCPU
BL RTOS_GetNextCPU
CMP R0, #0
BEQ BREAK //if (NULL): back to current task
B RTOS_ASM_SwitchNextCPU
BREAK:
POP {PC}
//===================================
RTOS_ASM_Begin: //R0: CPU_TypeDef* MainCPU
PUSH {R1, LR}
STR LR , [R0, #28]
STR R1 , [R0, #24]
ADDS R1 , R0, #24
MOV SP , R1
BL RTOS_ASM_SaveCurrentCPU
POP {R1, PC}
//===================================
RTOS_ASM_SaveCurrentCPU: //R0: CPU_TypeDef* CurrentCPU
#ifdef USING_PUSH_POP
MOVS R1 , SP
STR SP , [R0, #(4 * 16)]
ADDS R0 , R0, #(4 * 16)
MOVS SP , R0
PUSH {R4-R11}
MOVS SP , R1
#else
STR R4 , [R0, #(4 * 8 )]
STR R5 , [R0, #(4 * 9 )]
STR R6 , [R0, #(4 * 10)]
STR R7 , [R0, #(4 * 11)]
STR R8 , [R0, #(4 * 12)]
STR R9 , [R0, #(4 * 13)]
STR R10, [R0, #(4 * 14)]
STR R11, [R0, #(4 * 15)]
STR SP , [R0, #(4 * 16)]
#endif
BX LR
//===================================
RTOS_ASM_SwitchNextCPU: //R0: CPU_TypeDef* NextCPU
#ifdef USING_PUSH_POP
ADDS R1 , R0, #(4 * 8)
MOVS SP , R1
POP {R4-R11}
LDR SP , [R0, #(4 * 16)]
#else
LDR R4 , [R0, #(4 * 8 )]
LDR R5 , [R0, #(4 * 9 )]
LDR R6 , [R0, #(4 * 10)]
LDR R7 , [R0, #(4 * 11)]
LDR R8 , [R0, #(4 * 12)]
LDR R9 , [R0, #(4 * 13)]
LDR R10, [R0, #(4 * 14)]
LDR R11, [R0, #(4 * 15)]
LDR SP , [R0, #(4 * 16)]
#endif
LDR.W R0, =GPIOA_BITBAND //(2)
MOV R1, #0
STR R1, [R0, #0x180]
POP {PC}
//===================================
END
system tick handle:
void SysTick_Handler()
{
GPIOB_BITBAND.ODR._10 ^= 1; //(3)
System.MsTick++;
if (TaskManager.Running)
RTOS_SWITCH_TRIGGER();
//SCB.ICSR.REG = BIT25;
SCB.ICSR.BITS.PENDSTCLR = 1;
}
My solution now is using SVC instead of PendSV

How to reduce the palette of PNG image in Python/Pillow to the colors being really used?

After processing a previously optimized indexed color PNG image with transparency (see here for some background, since this question refers to the same image file), using the following code, the PLTE chunk seems to be expanded with more colors than those effectively being used.
Mu current code:
#!/usr/bin/env/python3
import os
from PIL import Image
source_file = os.path.expanduser("~/Desktop/prob.png")
dest_file = os.path.expanduser("~/Desktop/processed_img.png")
img = Image.open(source_file)
# Convert all colors in the palette to grayscale and save the new palette
pal = img.getpalette()
for i in range(len(pal) // 3):
# Using ITU-R 601-2 luma transform
g = (pal[3*i] * 299 + pal[3*i+1] * 587 + pal[3*i+2] * 114) // 1000
pal[3*i: 3*i+3] = [g, g, g]
img.putpalette(pal)
try:
img.save(dest_file, optimize=True, format="PNG")
except IOError:
ImageFile.MAXBLOCK = img.size[0] * img.size[1]
img.save(dest_file, optimize=True, format="PNG")
Using pngcheck I get a small 16 colors palette for the original file:
$ pngcheck -tc7pv ~/Desktop/prob.png
File: /Users/victor/Desktop/prob.png (12562 bytes)
chunk IHDR at offset 0x0000c, length 13
825 x 825 image, 8-bit palette, non-interlaced
chunk PLTE at offset 0x00025, length 48: 16 palette entries
0: ( 0, 0, 0) = (0x00,0x00,0x00)
1: (230,230,230) = (0xe6,0xe6,0xe6)
2: (215,215,215) = (0xd7,0xd7,0xd7)
3: (199,199,199) = (0xc7,0xc7,0xc7)
4: (175,175,175) = (0xaf,0xaf,0xaf)
5: (143,143,143) = (0x8f,0x8f,0x8f)
6: (111,111,111) = (0x6f,0x6f,0x6f)
7: ( 79, 79, 79) = (0x4f,0x4f,0x4f)
8: ( 22, 22, 22) = (0x16,0x16,0x16)
9: ( 0, 0, 0) = (0x00,0x00,0x00)
10: ( 47, 47, 47) = (0x2f,0x2f,0x2f)
11: (254,254,254) = (0xfe,0xfe,0xfe)
12: (115, 89, 0) = (0x73,0x59,0x00)
13: (225,176, 0) = (0xe1,0xb0,0x00)
14: (255,211, 0) = (0xff,0xd3,0x00)
15: (254,204, 0) = (0xfe,0xcc,0x00)
chunk tRNS at offset 0x00061, length 1: 1 transparency entry
0: 0 = 0x00
chunk IDAT at offset 0x0006e, length 12432
zlib: deflated, 32K window, maximum compression
chunk IEND at offset 0x0310a, length 0
No errors detected in /Users/victor/Desktop/prob.png (5 chunks, 98.2% compression).
Then, after processing the image using the code sample above, pngcheck displays a much bigger PLTE chunk, filled with lots of (probably unused) color values:
$ pngcheck -tc7pv ~/Desktop/processed_img.png
File: /Users/victor/Desktop/processed_img.png (14680 bytes)
chunk IHDR at offset 0x0000c, length 13
825 x 825 image, 8-bit palette, non-interlaced
chunk PLTE at offset 0x00025, length 768: 256 palette entries
0: ( 0, 0, 0) = (0x00,0x00,0x00)
1: (230,230,230) = (0xe6,0xe6,0xe6)
2: (215,215,215) = (0xd7,0xd7,0xd7)
3: (199,199,199) = (0xc7,0xc7,0xc7)
4: (175,175,175) = (0xaf,0xaf,0xaf)
5: (143,143,143) = (0x8f,0x8f,0x8f)
6: (111,111,111) = (0x6f,0x6f,0x6f)
7: ( 79, 79, 79) = (0x4f,0x4f,0x4f)
8: ( 22, 22, 22) = (0x16,0x16,0x16)
9: ( 0, 0, 0) = (0x00,0x00,0x00)
10: ( 47, 47, 47) = (0x2f,0x2f,0x2f)
11: (254,254,254) = (0xfe,0xfe,0xfe)
12: ( 86, 86, 86) = (0x56,0x56,0x56)
13: (170,170,170) = (0xaa,0xaa,0xaa)
14: (200,200,200) = (0xc8,0xc8,0xc8)
15: (195,195,195) = (0xc3,0xc3,0xc3)
16: ( 16, 16, 16) = (0x10,0x10,0x10)
17: ( 17, 17, 17) = (0x11,0x11,0x11)
18: ( 18, 18, 18) = (0x12,0x12,0x12)
19: ( 19, 19, 19) = (0x13,0x13,0x13)
20: ( 20, 20, 20) = (0x14,0x14,0x14)
(...) --- and it goes on listing all values up to 255:
254: (254,254,254) = (0xfe,0xfe,0xfe)
255: (255,255,255) = (0xff,0xff,0xff)
chunk tRNS at offset 0x00331, length 1: 1 transparency entry
0: 0 = 0x00
chunk IDAT at offset 0x0033e, length 13830
zlib: deflated, 32K window, maximum compression
chunk IEND at offset 0x03950, length 0
No errors detected in /Users/victor/Desktop/processed_img.png (5 chunks, 97.8% compression).
Is this behavior normal on Pillow? Is there any way to save a shorter PLTE chunk, similar to the original file (I am trying to optimize for smaller file sizes)?
If Pillow can't do it, is there any other simple way to do it? Preferably using pure Python, but it could also be with numpy or some additional pure Python package, like PyPNG or PurePNG, if that helps.
I ran your code on the bee png with Pillow 9.2.0 and the output png had the same number colors in its palette as the original. Additionally, Image.convert() has the args palette and colors that can be used to control the output colors. For example, to keep the same number of colors as the input image:
from PIL import Image
img = Image.open('bee.png')
num_pixels = img.size[0]*img.size[1]
num_colors = len(img.getcolors(num_pixels))
# Max palette size = 256
if num_colors > 256:
num_colors = 256
img = img.convert(mode='P', palette=1, colors=num_colors)
img.save('bee2.png', optimize=True, format="PNG")
Alternatively, if you're interested in reducing/managing image size I'd recommend compressing the image using the quality arg in Image.save() or utilizing another tool such as ExifTool to eliminate unnecessary metadata (These will likely have a limited effect on the bee png).
For more info on image modes in Pillow see Mark Setchell's answer: What is the difference between images in 'P' and 'L' mode in PIL?
Answers discussing file size reduction with Pillow: How to reduce the image file size using PIL

MCP23017 GPIO Interrupt Handling (RPi)

I have connected a MCP23017 I2C GPIO Expander chip to RPi. I use the this device driver and the mcp23017.dtbo overlay file.
I am trying to check the interrupt handling with the gpio pins. I did the following to connect the pins to interrupt(496 is the base which is GPA0 of MCP23017):
echo "496" > /sys/class/gpio/export
echo "both" > /sys/class/gpio/gpio496/edge
and then to trigger:
cat gpio496/value
But when i check /proc/interrupts it always shows 0 interrupts:
root#raspberrypi:/sys/class/gpio# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
16: 0 0 0 0 bcm2836-timer 0 Edge arch_timer
17: 41827 52799 8260 86838 bcm2836-timer 1 Edge arch_timer
23: 67 0 0 0 ARMCTRL-level 1 Edge 3f00b880.mailbox
24: 248 0 0 0 ARMCTRL-level 2 Edge VCHIQ doorbell
46: 0 0 0 0 ARMCTRL-level 48 Edge bcm2708_fb dma
48: 4125 0 0 0 ARMCTRL-level 50 Edge DMA IRQ
50: 0 0 0 0 ARMCTRL-level 52 Edge DMA IRQ
62: 415706 0 0 0 ARMCTRL-level 64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1
79: 0 0 0 0 ARMCTRL-level 81 Edge 3f200000.gpio:bank0
80: 0 0 0 0 ARMCTRL-level 82 Edge 3f200000.gpio:bank1
83: 945 0 0 0 ARMCTRL-level 85 Edge 3f804000.i2c
86: 502 0 0 0 ARMCTRL-level 88 Edge mmc0
87: 5032 0 0 0 ARMCTRL-level 89 Edge uart-pl011
92: 6828 0 0 0 ARMCTRL-level 94 Edge mmc1
170: 0 0 0 0 pinctrl-bcm2835 4 Edge 1-0020, 1-0021, 1-0022, 1-0023
220: 0 0 0 0 gpio-mcp23xxx 0 Edge gpiolib
Also, when the overlay is loaded, the probe funtion is called and i get the following message:
genirq: irq 170 uses trigger mode 8; requested 2
I could not figure out the problem. I am not sure if there is something wrong in the overlay file. Below is the .dts overlay file:
// Definitions for MCP23017 Gpio Extender from Microchip Semiconductor
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
fragment#0 {
target = <&i2c1>;
__overlay__ {
status = "okay";
};
};
fragment#1 {
target = <&gpio>;
__overlay__ {
mcp23017_pins: mcp23017_pins {
brcm,pins = <4>;
brcm,function = <0>;
};
};
};
fragment#2 {
target = <&i2c1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
mcp20:mcp23017#20 {
compatible = "microchip,mcp23017";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&gpio>;
interrupts = <4 2>;
interrupt-controller;
#interrupt-cells=<2>;
microchip,irq-mirror;
status = "okay";
};
};
};
__overrides__ {
gpiopin = <&mcp23017_pins>,"brcm,pins:0",
<&mcp20>,"interrupts:0";
addr = <&mcp20>,"reg:0";
};
};

Resources