Adding a 3x3 Shield button board to nRF5340 DK

I have acquired a basic 3x3 matrix scanning type button board that drops onto the Shield interface of the nRF5340.  I am running the "peripheral_hids_keyboard" sample project with Zephyr.  The button board is the "Ibridge lite 3×3 keypad shield" from https://www.electrokit.com/en/product/ibridge-lite-3x3-keypad-shield-with-lcd-interface/.

What would be the recommend way to add a scanning keyboard driver to this sample project?  I am just getting familiar with this environment and would like to avoid wasting time by re-inventing the wheel if i can avoid it.

I did enable the CONFIG_KSCAN option in the .config file but I don't know how to go any further at this moment.

Thanks!

Parents
  • Hello

    The kscan driver in Zephyr does seem like a good place to start.

    You can find info on the driver here:

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/hardware/peripherals/kscan.html

    And there is also a sample available:

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/samples/drivers/kscan/README.html

    Let me know if you have trouble getting it up and running!

    -Einar

  • Einar,

    I have tried to run the KSCAN sample project and am getting a build error.  I do not know how to declare/define the actual keyboard so I think the build error is related to that issue.  Attached is a screenshot of my error.

    Thanks,
    Peter

  • I will also tack on that it appears that I'm missing the definition for "kscan0".

  • DT_ALIAS is looking for kscan0 in the devicetree, which I would assume it won't find if you haven't added it since the documentation says "key values are defined by a keymap provided by the keyboard manufacturer".

    During the build process a devicetree file is generated in build/zephyr/zephyr.dts, you could check if there's anything there related to kscan or if you'll have to add everything yourself. In the latter case I would recommend checking out the Devicetree documentation.

    -Einar

  • I attached my zephyr.dts and yes kscan0 is not declared in it.  I am somewhat lost because I assumed an example project would target real hardware and I could then have an example that I could modify instead of having to invent a new driver.

    main.c seems to reference a "Fujitsu keyboard model N860-7401-TOO1" cap sense touch screen so I would assume there would be a device free for that but somehow it is vaporized by Nordic's plugins creating a build configuration that targets the nRF5340 DK?

    Part of my trouble is that I haven't been given much time from management to learn this platform so I'm seeking a little bit of hand-holding to get something working quickly.

    My problem is even more complex in that this is a Shield device that is using a bunch of GPIO pins so common sense tells me I need to do some mapping of those GPIO pins to the "keyboard" device.

    /dts-v1/;
    
    / {
    	#address-cells = < 0x1 >;
    	#size-cells = < 0x1 >;
    	model = "Nordic nRF5340 Audio DK NRF5340 Application";
    	compatible = "nordic,nrf5340-audio-dk-nrf5340-cpuapp";
    	chosen {
    		zephyr,entropy = &cryptocell_sw;
    		zephyr,flash-controller = &flash_controller;
    		zephyr,console = &uart0;
    		zephyr,shell-uart = &uart0;
    		zephyr,uart-mcumgr = &uart0;
    		zephyr,bt-mon-uart = &uart0;
    		zephyr,bt-c2h-uart = &uart0;
    		zephyr,ipc_shm = &sram0_shared;
    		zephyr,sram = &sram0_ns;
    		zephyr,flash = &flash0;
    		zephyr,code-partition = &slot0_ns_partition;
    	};
    	aliases {
    		led0 = &rgb1_red;
    		led1 = &rgb1_green;
    		led2 = &rgb1_blue;
    		led3 = &rgb2_red;
    		led4 = &rgb2_green;
    		led5 = &rgb2_blue;
    		led6 = &led1_blue;
    		led7 = &led2_green;
    		led8 = &led3_green;
    		sw0 = &button_1_vol_dn;
    		sw1 = &button_2_vol_up;
    		sw2 = &button3;
    		sw3 = &button4;
    		sw4 = &button5;
    	};
    	soc {
    		#address-cells = < 0x1 >;
    		#size-cells = < 0x1 >;
    		compatible = "nordic,nRF5340-CPUAPP-QKAA", "nordic,nRF5340-CPUAPP", "nordic,nRF53", "simple-bus";
    		interrupt-parent = < &nvic >;
    		ranges;
    		nvic: interrupt-controller@e000e100 {
    			#address-cells = < 0x1 >;
    			compatible = "arm,v8m-nvic";
    			reg = < 0xe000e100 0xc00 >;
    			interrupt-controller;
    			#interrupt-cells = < 0x2 >;
    			arm,num-irq-priority-bits = < 0x3 >;
    			phandle = < 0x1 >;
    		};
    		systick: timer@e000e010 {
    			compatible = "arm,armv8m-systick";
    			reg = < 0xe000e010 0x10 >;
    			status = "disabled";
    		};
    		sram0: memory@20000000 {
    			compatible = "mmio-sram";
    			reg = < 0x20000000 0x80000 >;
    		};
    		peripheral@40000000 {
    			#address-cells = < 0x1 >;
    			#size-cells = < 0x1 >;
    			ranges = < 0x0 0x40000000 0x10000000 >;
    			dcnf: dcnf@0 {
    				compatible = "nordic,nrf-dcnf";
    				reg = < 0x0 0x1000 >;
    				status = "okay";
    			};
    			oscillators: oscillator@4000 {
    				compatible = "nordic,nrf-oscillators";
    				reg = < 0x4000 0x1000 >;
    				status = "okay";
    			};
    			regulators: regulator@4000 {
    				compatible = "nordic,nrf-regulators";
    				reg = < 0x4000 0x1000 >;
    				status = "okay";
    			};
    			clock: clock@5000 {
    				compatible = "nordic,nrf-clock";
    				reg = < 0x5000 0x1000 >;
    				interrupts = < 0x5 0x1 >;
    				status = "okay";
    				label = "CLOCK";
    			};
    			power: power@5000 {
    				compatible = "nordic,nrf-power";
    				reg = < 0x5000 0x1000 >;
    				interrupts = < 0x5 0x1 >;
    				status = "okay";
    			};
    			reset: reset-controller@5000 {
    				compatible = "nordic,nrf-reset";
    				reg = < 0x5000 0x1000 >;
    				status = "okay";
    			};
    			ctrlap: ctrlap@6000 {
    				compatible = "nordic,nrf-ctrlapperi";
    				reg = < 0x6000 0x1000 >;
    				status = "okay";
    			};
    			i2c0: i2c@8000 {
    				compatible = "nordic,nrf-twim";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0x8000 0x1000 >;
    				clock-frequency = < 0x186a0 >;
    				interrupts = < 0x8 0x1 >;
    				status = "disabled";
    				label = "I2C_0";
    			};
    			spi0: spi@8000 {
    				compatible = "nordic,nrf-spim";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0x8000 0x1000 >;
    				interrupts = < 0x8 0x1 >;
    				status = "disabled";
    				label = "SPI_0";
    			};
    			uart0: uart@8000 {
    				compatible = "nordic,nrf-uarte";
    				reg = < 0x8000 0x1000 >;
    				interrupts = < 0x8 0x1 >;
    				status = "okay";
    				label = "UART_0";
    				current-speed = < 0x1c200 >;
    				pinctrl-0 = < &uart0_default >;
    				pinctrl-1 = < &uart0_sleep >;
    				pinctrl-names = "default", "sleep";
    			};
    			i2c1: i2c@9000 {
    				compatible = "nordic,nrf-twim";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0x9000 0x1000 >;
    				clock-frequency = < 0x186a0 >;
    				interrupts = < 0x9 0x1 >;
    				status = "okay";
    				label = "I2C_1";
    				pinctrl-0 = < &i2c1_default >;
    				pinctrl-1 = < &i2c1_sleep >;
    				pinctrl-names = "default", "sleep";
    			};
    			spi1: spi@9000 {
    				compatible = "nordic,nrf-spim";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0x9000 0x1000 >;
    				interrupts = < 0x9 0x1 >;
    				status = "disabled";
    				label = "SPI_1";
    			};
    			uart1: uart@9000 {
    				compatible = "nordic,nrf-uarte";
    				reg = < 0x9000 0x1000 >;
    				interrupts = < 0x9 0x1 >;
    				status = "disabled";
    				label = "UART_1";
    			};
    			spi4: spi@a000 {
    				compatible = "nordic,nrf-spim";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0xa000 0x1000 >;
    				interrupts = < 0xa 0x1 >;
    				status = "okay";
    				label = "SPI_4";
    				cs-gpios = < &gpio0 0xb 0x1 >, < &gpio0 0x11 0x1 >;
    				pinctrl-0 = < &spi4_default >;
    				pinctrl-1 = < &spi4_sleep >;
    				pinctrl-names = "default", "sleep";
    				sdhc0: sdhc@0 {
    					compatible = "zephyr,mmc-spi-slot";
    					reg = < 0x0 >;
    					status = "okay";
    					label = "SDHC0";
    					spi-max-frequency = < 0x7a1200 >;
    				};
    				cs47l63: cs47l63@1 {
    					reg = < 0x1 >;
    					label = "CS47L63";
    				};
    			};
    			i2c2: i2c@b000 {
    				compatible = "nordic,nrf-twim";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0xb000 0x1000 >;
    				clock-frequency = < 0x186a0 >;
    				interrupts = < 0xb 0x1 >;
    				status = "disabled";
    				label = "I2C_2";
    			};
    			spi2: spi@b000 {
    				compatible = "nordic,nrf-spim";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0xb000 0x1000 >;
    				interrupts = < 0xb 0x1 >;
    				status = "disabled";
    				label = "SPI_2";
    			};
    			uart2: uart@b000 {
    				compatible = "nordic,nrf-uarte";
    				reg = < 0xb000 0x1000 >;
    				interrupts = < 0xb 0x1 >;
    				status = "disabled";
    				label = "UART_2";
    			};
    			i2c3: i2c@c000 {
    				compatible = "nordic,nrf-twim";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0xc000 0x1000 >;
    				clock-frequency = < 0x186a0 >;
    				interrupts = < 0xc 0x1 >;
    				status = "disabled";
    				label = "I2C_3";
    			};
    			spi3: spi@c000 {
    				compatible = "nordic,nrf-spim";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0xc000 0x1000 >;
    				interrupts = < 0xc 0x1 >;
    				status = "disabled";
    				label = "SPI_3";
    			};
    			uart3: uart@c000 {
    				compatible = "nordic,nrf-uarte";
    				reg = < 0xc000 0x1000 >;
    				interrupts = < 0xc 0x1 >;
    				status = "disabled";
    				label = "UART_3";
    			};
    			adc: adc@e000 {
    				compatible = "nordic,nrf-saadc";
    				reg = < 0xe000 0x1000 >;
    				interrupts = < 0xe 0x1 >;
    				status = "okay";
    				label = "ADC_0";
    				#io-channel-cells = < 0x1 >;
    			};
    			timer0: timer@f000 {
    				compatible = "nordic,nrf-timer";
    				status = "okay";
    				reg = < 0xf000 0x1000 >;
    				cc-num = < 0x6 >;
    				interrupts = < 0xf 0x1 >;
    				prescaler = < 0x0 >;
    				label = "TIMER_0";
    			};
    			timer1: timer@10000 {
    				compatible = "nordic,nrf-timer";
    				status = "okay";
    				reg = < 0x10000 0x1000 >;
    				cc-num = < 0x6 >;
    				interrupts = < 0x10 0x1 >;
    				prescaler = < 0x0 >;
    				label = "TIMER_1";
    			};
    			timer2: timer@11000 {
    				compatible = "nordic,nrf-timer";
    				status = "okay";
    				reg = < 0x11000 0x1000 >;
    				cc-num = < 0x6 >;
    				interrupts = < 0x11 0x1 >;
    				prescaler = < 0x0 >;
    				label = "TIMER_2";
    			};
    			rtc0: rtc@14000 {
    				compatible = "nordic,nrf-rtc";
    				reg = < 0x14000 0x1000 >;
    				cc-num = < 0x4 >;
    				interrupts = < 0x14 0x1 >;
    				status = "okay";
    				clock-frequency = < 0x8000 >;
    				prescaler = < 0x1 >;
    				label = "RTC_0";
    			};
    			rtc1: rtc@15000 {
    				compatible = "nordic,nrf-rtc";
    				reg = < 0x15000 0x1000 >;
    				cc-num = < 0x4 >;
    				interrupts = < 0x15 0x1 >;
    				status = "okay";
    				clock-frequency = < 0x8000 >;
    				prescaler = < 0x1 >;
    				label = "RTC_1";
    			};
    			dppic: dppic@17000 {
    				compatible = "nordic,nrf-dppic";
    				reg = < 0x17000 0x1000 >;
    				status = "okay";
    				label = "DPPIC";
    			};
    			wdt: wdt0: watchdog@18000 {
    				compatible = "nordic,nrf-wdt";
    				reg = < 0x18000 0x1000 >;
    				interrupts = < 0x18 0x1 >;
    				status = "okay";
    				label = "WDT";
    			};
    			wdt1: watchdog@19000 {
    				compatible = "nordic,nrf-wdt";
    				reg = < 0x19000 0x1000 >;
    				interrupts = < 0x19 0x1 >;
    				status = "disabled";
    				label = "WDT_1";
    			};
    			comp: comparator@1a000 {
    				compatible = "nordic,nrf-comp";
    				reg = < 0x1a000 0x1000 >;
    				interrupts = < 0x1a 0x1 >;
    				status = "disabled";
    				#io-channel-cells = < 0x1 >;
    			};
    			egu0: egu@1b000 {
    				compatible = "nordic,nrf-egu";
    				reg = < 0x1b000 0x1000 >;
    				interrupts = < 0x1b 0x1 >;
    				status = "okay";
    			};
    			egu1: egu@1c000 {
    				compatible = "nordic,nrf-egu";
    				reg = < 0x1c000 0x1000 >;
    				interrupts = < 0x1c 0x1 >;
    				status = "okay";
    			};
    			egu2: egu@1d000 {
    				compatible = "nordic,nrf-egu";
    				reg = < 0x1d000 0x1000 >;
    				interrupts = < 0x1d 0x1 >;
    				status = "okay";
    			};
    			egu3: egu@1e000 {
    				compatible = "nordic,nrf-egu";
    				reg = < 0x1e000 0x1000 >;
    				interrupts = < 0x1e 0x1 >;
    				status = "okay";
    			};
    			egu4: egu@1f000 {
    				compatible = "nordic,nrf-egu";
    				reg = < 0x1f000 0x1000 >;
    				interrupts = < 0x1f 0x1 >;
    				status = "okay";
    			};
    			egu5: egu@20000 {
    				compatible = "nordic,nrf-egu";
    				reg = < 0x20000 0x1000 >;
    				interrupts = < 0x20 0x1 >;
    				status = "okay";
    			};
    			pwm0: pwm@21000 {
    				compatible = "nordic,nrf-pwm";
    				reg = < 0x21000 0x1000 >;
    				interrupts = < 0x21 0x1 >;
    				status = "okay";
    				label = "PWM_0";
    				#pwm-cells = < 0x3 >;
    			};
    			pwm1: pwm@22000 {
    				compatible = "nordic,nrf-pwm";
    				reg = < 0x22000 0x1000 >;
    				interrupts = < 0x22 0x1 >;
    				status = "disabled";
    				label = "PWM_1";
    				#pwm-cells = < 0x3 >;
    			};
    			pwm2: pwm@23000 {
    				compatible = "nordic,nrf-pwm";
    				reg = < 0x23000 0x1000 >;
    				interrupts = < 0x23 0x1 >;
    				status = "disabled";
    				label = "PWM_2";
    				#pwm-cells = < 0x3 >;
    			};
    			pwm3: pwm@24000 {
    				compatible = "nordic,nrf-pwm";
    				reg = < 0x24000 0x1000 >;
    				interrupts = < 0x24 0x1 >;
    				status = "disabled";
    				label = "PWM_3";
    				#pwm-cells = < 0x3 >;
    			};
    			pdm0: pdm@26000 {
    				compatible = "nordic,nrf-pdm";
    				reg = < 0x26000 0x1000 >;
    				interrupts = < 0x26 0x1 >;
    				status = "disabled";
    				label = "PDM_0";
    			};
    			i2s0: i2s@28000 {
    				compatible = "nordic,nrf-i2s";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0x28000 0x1000 >;
    				interrupts = < 0x28 0x1 >;
    				status = "okay";
    				label = "I2S_0";
    				pinctrl-0 = < &i2s0_default >;
    				pinctrl-names = "default";
    			};
    			mbox: ipc: mbox@2a000 {
    				compatible = "nordic,mbox-nrf-ipc", "nordic,nrf-ipc";
    				reg = < 0x2a000 0x1000 >;
    				tx-mask = < 0xffff >;
    				rx-mask = < 0xffff >;
    				interrupts = < 0x2a 0x1 >;
    				#mbox-cells = < 0x1 >;
    				status = "okay";
    				phandle = < 0xb >;
    			};
    			qspi: qspi@2b000 {
    				compatible = "nordic,nrf-qspi";
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x0 >;
    				reg = < 0x2b000 0x1000 >, < 0x10000000 0x10000000 >;
    				reg-names = "qspi", "qspi_mm";
    				interrupts = < 0x2b 0x1 >;
    				status = "disabled";
    				label = "QSPI";
    			};
    			nfct: nfct@2d000 {
    				compatible = "nordic,nrf-nfct";
    				reg = < 0x2d000 0x1000 >;
    				interrupts = < 0x2d 0x1 >;
    				status = "disabled";
    			};
    			mutex: mutex@30000 {
    				compatible = "nordic,nrf-mutex";
    				reg = < 0x30000 0x1000 >;
    				status = "okay";
    			};
    			qdec0: qdec@33000 {
    				compatible = "nordic,nrf-qdec";
    				reg = < 0x33000 0x1000 >;
    				interrupts = < 0x33 0x1 >;
    				status = "disabled";
    				label = "QDEC_0";
    			};
    			qdec1: qdec@34000 {
    				compatible = "nordic,nrf-qdec";
    				reg = < 0x34000 0x1000 >;
    				interrupts = < 0x34 0x1 >;
    				status = "disabled";
    				label = "QDEC_1";
    			};
    			usbd: zephyr_udc0: usbd@36000 {
    				compatible = "nordic,nrf-usbd";
    				reg = < 0x36000 0x1000 >;
    				interrupts = < 0x36 0x1 >;
    				num-bidir-endpoints = < 0x1 >;
    				num-in-endpoints = < 0x7 >;
    				num-out-endpoints = < 0x7 >;
    				num-isoin-endpoints = < 0x1 >;
    				num-isoout-endpoints = < 0x1 >;
    				status = "okay";
    				label = "USBD";
    				hs_0 {
    					label = "HEADSET";
    					compatible = "usb-audio-hs";
    					mic-feature-mute;
    					mic-channel-l;
    					mic-channel-r;
    					hp-feature-mute;
    					hp-channel-l;
    					hp-channel-r;
    				};
    			};
    			usbreg: regulator@37000 {
    				compatible = "nordic,nrf-usbreg";
    				reg = < 0x37000 0x1000 >;
    				interrupts = < 0x37 0x1 >;
    				status = "okay";
    			};
    			flash_controller: flash-controller@39000 {
    				compatible = "nordic,nrf53-flash-controller";
    				reg = < 0x39000 0x1000 >;
    				partial-erase;
    				#address-cells = < 0x1 >;
    				#size-cells = < 0x1 >;
    				label = "NRF_FLASH_DRV_NAME";
    				flash0: flash@0 {
    					compatible = "soc-nv-flash";
    					label = "NRF_FLASH";
    					erase-block-size = < 0x1000 >;
    					write-block-size = < 0x4 >;
    					reg = < 0x0 0x100000 >;
    					partitions {
    						compatible = "fixed-partitions";
    						#address-cells = < 0x1 >;
    						#size-cells = < 0x1 >;
    						boot_partition: partition@0 {
    							label = "mcuboot";
    							reg = < 0x0 0x10000 >;
    						};
    						slot0_partition: partition@10000 {
    							label = "image-0";
    							reg = < 0x10000 0x40000 >;
    						};
    						slot0_ns_partition: partition@50000 {
    							label = "image-0-nonsecure";
    							reg = < 0x50000 0x30000 >;
    						};
    						slot1_partition: partition@80000 {
    							label = "image-1";
    							reg = < 0x80000 0x40000 >;
    						};
    						slot1_ns_partition: partition@c0000 {
    							label = "image-1-nonsecure";
    							reg = < 0xc0000 0x30000 >;
    						};
    						scratch_partition: partition@f0000 {
    							label = "image-scratch";
    							reg = < 0xf0000 0xa000 >;
    						};
    						storage_partition: partition@fa000 {
    							label = "storage";
    							reg = < 0xfa000 0x6000 >;
    						};
    					};
    				};
    			};
    			kmu: kmu@39000 {
    				compatible = "nordic,nrf-kmu";
    				reg = < 0x39000 0x1000 >;
    				interrupts = < 0x39 0x1 >;
    				status = "okay";
    			};
    			vmc: vmc@81000 {
    				compatible = "nordic,nrf-vmc";
    				reg = < 0x81000 0x1000 >;
    				status = "okay";
    			};
    			gpio0: gpio@842500 {
    				compatible = "nordic,nrf-gpio";
    				gpio-controller;
    				reg = < 0x842500 0x300 >;
    				#gpio-cells = < 0x2 >;
    				label = "GPIO_0";
    				status = "okay";
    				port = < 0x0 >;
    				phandle = < 0x6 >;
    			};
    			gpio1: gpio@842800 {
    				compatible = "nordic,nrf-gpio";
    				gpio-controller;
    				reg = < 0x842800 0x300 >;
    				#gpio-cells = < 0x2 >;
    				ngpios = < 0x10 >;
    				label = "GPIO_1";
    				status = "okay";
    				port = < 0x1 >;
    				phandle = < 0xc >;
    			};
    		};
    		gpiote1: gpiote: gpiote@4002f000 {
    			compatible = "nordic,nrf-gpiote";
    			reg = < 0x4002f000 0x1000 >;
    			interrupts = < 0x2f 0x5 >;
    			status = "okay";
    			label = "GPIOTE_1";
    		};
    	};
    	pinctrl: pin-controller {
    		compatible = "nordic,nrf-pinctrl";
    		i2s0_default: i2s0_default {
    			phandle = < 0x9 >;
    			group1 {
    				psels = < 0x13000c >;
    				nordic,drive-mode = < 0x3 >;
    			};
    			group2 {
    				psels = < 0xd000e >, < 0xf0010 >, < 0x12000d >, < 0x11000f >;
    			};
    		};
    		i2s0_sleep: i2s0_sleep {
    			group1 {
    				psels = < 0x13000c >, < 0xd000e >, < 0xf0010 >, < 0x12000d >, < 0x11000f >;
    				low-power-enable;
    			};
    		};
    		uart0_default: uart0_default {
    			phandle = < 0x2 >;
    			group1 {
    				psels = < 0x25 >, < 0x20027 >;
    			};
    			group2 {
    				psels = < 0x10024 >, < 0x30026 >;
    				bias-pull-up;
    			};
    		};
    		uart0_sleep: uart0_sleep {
    			phandle = < 0x3 >;
    			group1 {
    				psels = < 0x25 >, < 0x10024 >, < 0x20027 >, < 0x30026 >;
    				low-power-enable;
    			};
    		};
    		i2c1_default: i2c1_default {
    			phandle = < 0x4 >;
    			group1 {
    				psels = < 0xc0022 >, < 0xb0023 >;
    			};
    		};
    		i2c1_sleep: i2c1_sleep {
    			phandle = < 0x5 >;
    			group1 {
    				psels = < 0xc0022 >, < 0xb0023 >;
    				low-power-enable;
    			};
    		};
    		spi4_default: spi4_default {
    			phandle = < 0x7 >;
    			group1 {
    				psels = < 0x40008 >, < 0x50009 >;
    				nordic,drive-mode = < 0x3 >;
    			};
    			group2 {
    				psels = < 0x6000a >;
    			};
    		};
    		spi4_sleep: spi4_sleep {
    			phandle = < 0x8 >;
    			group1 {
    				psels = < 0x40008 >, < 0x6000a >, < 0x50009 >;
    				low-power-enable;
    			};
    		};
    	};
    	rng_hci: entropy_bt_hci {
    		compatible = "zephyr,bt-hci-entropy";
    		label = "bt_hci_entropy";
    		status = "okay";
    	};
    	cpus {
    		#address-cells = < 0x1 >;
    		#size-cells = < 0x0 >;
    		cpu@0 {
    			device_type = "cpu";
    			compatible = "arm,cortex-m33f";
    			reg = < 0x0 >;
    			#address-cells = < 0x1 >;
    			#size-cells = < 0x1 >;
    			mpu: mpu@e000ed90 {
    				compatible = "arm,armv8m-mpu";
    				reg = < 0xe000ed90 0x40 >;
    				arm,num-mpu-regions = < 0x8 >;
    			};
    		};
    	};
    	cryptocell_sw: cryptocell-sw {
    		compatible = "nordic,nrf-cc312-sw";
    		#address-cells = < 0x0 >;
    		label = "CRYPTOCELL_SW";
    		status = "okay";
    	};
    	ipc {
    		ipc0: ipc0 {
    			compatible = "zephyr,ipc-openamp-static-vrings";
    			memory-region = < &sram0_shared >;
    			mboxes = < &mbox 0x0 >, < &mbox 0x1 >;
    			mbox-names = "tx", "rx";
    			role = "host";
    			status = "okay";
    		};
    	};
    	gpio_fwd: nrf-gpio-forwarder {
    		compatible = "nordic,nrf-gpio-forwarder";
    		status = "okay";
    		uart {
    			gpios = < &gpio1 0x9 0x0 >, < &gpio1 0x8 0x0 >, < &gpio1 0xb 0x0 >, < &gpio1 0xa 0x0 >;
    		};
    	};
    	reserved-memory {
    		#address-cells = < 0x1 >;
    		#size-cells = < 0x1 >;
    		ranges;
    		sram0_image: image@20000000 {
    			reg = < 0x20000000 0x70000 >;
    		};
    		sram0_s: image_s@20000000 {
    			reg = < 0x20000000 0x40000 >;
    		};
    		sram0_ns: image_ns@20040000 {
    			reg = < 0x20040000 0x30000 >;
    		};
    		sram0_shared: memory@20070000 {
    			reg = < 0x20070000 0x10000 >;
    			phandle = < 0xa >;
    		};
    	};
    	leds: leds {
    		compatible = "gpio-leds";
    		rgb1_red: led_0 {
    			gpios = < &gpio0 0x7 0x0 >;
    			label = "0 LED_RGB_RED CORE_APP";
    		};
    		rgb1_green: led_1 {
    			gpios = < &gpio0 0x19 0x0 >;
    			label = "0 LED_RGB_GREEN CORE_APP";
    		};
    		rgb1_blue: led_2 {
    			gpios = < &gpio0 0x1a 0x0 >;
    			label = "0 LED_RGB_BLUE CORE_APP";
    		};
    		rgb2_red: led_3 {
    			gpios = < &gpio0 0x1c 0x0 >;
    			label = "1 LED_RGB_RED CORE_NET";
    		};
    		rgb2_green: led_4 {
    			gpios = < &gpio0 0x1d 0x0 >;
    			label = "1 LED_RGB_GREEN CORE_NET";
    		};
    		rgb2_blue: led_5 {
    			gpios = < &gpio0 0x1e 0x0 >;
    			label = "1 LED_RGB_BLUE CORE_NET";
    		};
    		led1_blue: led_6 {
    			gpios = < &gpio0 0x1f 0x0 >;
    			label = "2 LED_MONO_BLUE CORE_APP";
    		};
    		led2_green: led_7 {
    			gpios = < &gpio1 0x0 0x0 >;
    			label = "3 LED_MONO_GREEN CORE_APP";
    		};
    		led3_green: led_8 {
    			gpios = < &gpio1 0x1 0x0 >;
    			label = "4 LED_MONO_GREEN CORE_APP";
    		};
    	};
    	buttons {
    		compatible = "gpio-keys";
    		button_1_vol_dn: button_1_vol_dn {
    			gpios = < &gpio0 0x2 0x11 >;
    			label = "Push button 1";
    		};
    		button_2_vol_up: button_2_vol_up {
    			gpios = < &gpio0 0x3 0x11 >;
    			label = "Push button 2";
    		};
    		button3: button_3 {
    			gpios = < &gpio0 0x4 0x11 >;
    			label = "Push button 3";
    		};
    		button4: button_4 {
    			gpios = < &gpio0 0x6 0x11 >;
    			label = "Push button 4";
    		};
    		button5: button_5 {
    			gpios = < &gpio0 0x5 0x11 >;
    			label = "Push button 5";
    		};
    	};
    	nrf5340_audio_dk {
    		compatible = "gpio-keys";
    		hw_codec_gpio_in: hw_codec_gpio_in {
    			gpios = < &gpio0 0x14 0x1 >;
    			label = "GPIO from HW codec";
    		};
    		hw_codec_irq_in: hw_codec_irq_in {
    			gpios = < &gpio0 0x13 0x1 >;
    			label = "Interrupt from HW codec";
    		};
    		hw_codec_reset_out: hw_codec_reset_out {
    			gpios = < &gpio0 0x12 0x1 >;
    			label = "Reset HW codec";
    		};
    		hw_codec_sel_out: hw_codec_sel_out {
    			gpios = < &gpio0 0x15 0x1 >;
    			label = "HW codec selector. Low selects OB HW codec, high \t\t\t\t selects external HW codec";
    		};
    		spi_sel_in: spi_sel_in {
    			gpios = < &gpio0 0x16 0x1 >;
    			label = "SPI select in. High = nRF SPI to HW codec. \t\t\t\t Low = FTDI to HW codec";
    		};
    		pmic_iset_out: pmic_iset_out {
    			gpios = < &gpio0 0x17 0x0 >;
    			label = "PMIC ISET";
    		};
    		board_id_en_out: board_id_en_out {
    			gpios = < &gpio0 0x18 0x0 >;
    			label = "Board revision readback enable";
    		};
    		board_id_in: board_id_in {
    			gpios = < &gpio0 0x1b 0x0 >;
    			label = "Board revision analog readback";
    		};
    		curr_mon_alert_in: curr_mon_alert_in {
    			gpios = < &gpio1 0xf 0x1 >;
    			label = "Curr mon alert in from INA231";
    		};
    	};
    };
    

  • It looks to me like the Fujitsu keyboard stuff in the example is there just to show you how keyboard mapping is done, so you can replace it with your own layout.

    These GPIO mappings you're talking about is exactly what's missing from the devicetree. In the datasheet of the shield you linked to you can see what pins on your shield are the different keyboard scan pins, and you'll have to map these to the GPIO pins on your DK that they are connected to.

    If you have a look at the overlay example code here, I believe your overlay should look very similar to this, but without the zmk bits, and for DT_ALIAS to work you'll have to add something like this:

    aliases {
        kscan0 = &kscan0;
    };

    Hope that helps!

    -Einar

  • I seem to be getting a little further along with this "overlay" concept but I am not all the way there.

    I have modified my CMakeLists.txt as follows:

    # SPDX-License-Identifier: Apache-2.0
    
    set(DTC_OVERLAY_FILE nrf5340_audio_dk_nrf5340_cpuapp_ns.overlay;iBridges-Lite_3x3_keypad.overlay)
    
    cmake_minimum_required(VERSION 3.20.0)
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(kscan)
    
    FILE(GLOB app_sources src/*.c)
    target_sources(app PRIVATE ${app_sources})

    Note the first set() command.  If I want to use my own custom overlay do I have to manually declare the defacto project overlay and then my custom overlay?  Does using a single custom overlay force me to do this and ditch the automatic finding of overlays or can I just let the automatic system do it's thing and declare a custom overlay after?

    Here is my custom overlay "\kscan\iBridges-Lite_3x3_keypad.overlay":

    / {
        chosen {
            kscan = &kscan0;
        };
    
        kscan0: kscan_0 {
            compatible = "kscan-gpio-matrix";
            label = "KSCAN";
            diode-direction = "col2row";
    
            col-gpios
                = <&gpio0 16 GPIO_ACTIVE_HIGH>
                , <&gpio0 17 GPIO_ACTIVE_HIGH>
                , <&gpio0 18 GPIO_ACTIVE_HIGH>
                ;
    
            row-gpios
                = <&gpio0 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
                , <&gpio0 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
                , <&gpio0 15 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
                ;
        };
    
        aliases {
            kscan0 = &kscan0;
        };
    };

    Now my build is still failing at the following:

    FAILED: zephyr/zephyr_pre0.elf zephyr/zephyr_pre0.map
    cmd.exe /C "cd . && C:\Users\PeterTomich\ncs\toolchains\v2.0.0\opt\zephyr-sdk\arm-zephyr-eabi\bin\arm-zephyr-eabi-gcc.exe zephyr/CMakeFiles/zephyr_pre0.dir/misc/empty_file.c.obj -o zephyr\zephyr_pre0.elf -Wl,-T zephyr/linker_zephyr_pre0.cmd -Wl,-Map=C:/Nordic/Scanning_Keyboard/kscan/build/zephyr/zephyr_pre0.map -Wl,--whole-archive app/libapp.a zephyr/libzephyr.a zephyr/arch/common/libarch__common.a zephyr/arch/arch/arm/core/aarch32/libarch__arm__core__aarch32.a zephyr/arch/arch/arm/core/aarch32/cortex_m/libarch__arm__core__aarch32__cortex_m.a zephyr/arch/arch/arm/core/aarch32/cortex_m/cmse/libarch__arm__core__aarch32__cortex_m__cmse.a zephyr/arch/arch/arm/core/aarch32/mpu/libarch__arm__core__aarch32__mpu.a zephyr/lib/libc/minimal/liblib__libc__minimal.a zephyr/lib/posix/liblib__posix.a zephyr/soc/arm/common/cortex_m/libsoc__arm__common__cortex_m.a zephyr/subsys/random/libsubsys__random.a zephyr/drivers/clock_control/libdrivers__clock_control.a zephyr/drivers/gpio/libdrivers__gpio.a zephyr/drivers/entropy/libdrivers__entropy.a zephyr/drivers/timer/libdrivers__timer.a zephyr/drivers/pinctrl/libdrivers__pinctrl.a modules/nrf/lib/fatal_error/lib..__nrf__lib__fatal_error.a modules/trusted-firmware-m/libtfm_api.a modules/hal_nordic/nrfx/libmodules__hal_nordic__nrfx.a modules/nrfxlib/nrfxlib/nrf_security/src/zephyr/libmbedtls_zephyr.a -Wl,--no-whole-archive zephyr/kernel/libkernel.a zephyr/CMakeFiles/offsets.dir/./arch/arm/core/offsets/offsets.c.obj -L"c:/users/petertomich/ncs/toolchains/v2.0.0/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/10.3.0/thumb/v8-m.main/nofp" -LC:/Nordic/Scanning_Keyboard/kscan/build/zephyr -lgcc zephyr/arch/common/libisr_tables.a tfm/platform/libplatform_ns.a tfm/app/libtfm_api_ns.a tfm/secure_fw/s_veneers.o -no-pie -Wl,--gc-sections -Wl,--build-id=none -Wl,--sort-common=descending -Wl,--sort-section=alignment -Wl,-u,_OffsetAbsSyms -Wl,-u,_ConfigAbsSyms -nostdlib -static -Wl,-X -Wl,-N -Wl,--orphan-handling=warn modules/nrfxlib/nrfxlib/nrf_security/src/libmbedcrypto.a C:/Users/PeterTomich/ncs/v2.0.0/nrfxlib/crypto/nrf_oberon/lib/cortex-m33/soft-float/liboberon_mbedtls_3.0.11.a modules/nrfxlib/nrfxlib/nrf_security/src/libmbedcrypto_base.a -mcpu=cortex-m33 -mthumb -mabi=aapcs -mfp16-format=ieee C:/Users/PeterTomich/ncs/v2.0.0/nrfxlib/crypto/nrf_oberon/lib/cortex-m33/soft-float/liboberon_3.0.11.a && cmd.exe /C "cd /D C:\Nordic\Scanning_Keyboard\kscan\build\zephyr && C:\Users\PeterTomich\ncs\toolchains\v2.0.0\opt\bin\cmake.exe -E echo ""
    c:/users/petertomich/ncs/toolchains/v2.0.0/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/10.3.0/../../../../arm-zephyr-eabi/bin/ld.exe: app/libapp.a(main.c.obj):C:\Nordic\Scanning_Keyboard\kscan\src\main.c:20: undefined reference to `__device_dts_ord_5'
    collect2.exe: error: ld returned 1 exit status
    ninja: build stopped: subcommand failed.
    FATAL ERROR: command exited with status 1: 'c:\Users\PeterTomich\ncs\toolchains\v2.0.0\opt\bin\cmake.EXE' --build 'c:\Nordic\Scanning_Keyboard\kscan\build'

    * The terminal process terminated with exit code: 1.
    * Terminal will be reused by tasks, press any key to close it.

    The problem appears to be this: undefined reference to `__device_dts_ord_5'

    Thanks for your help on this!

Reply
  • I seem to be getting a little further along with this "overlay" concept but I am not all the way there.

    I have modified my CMakeLists.txt as follows:

    # SPDX-License-Identifier: Apache-2.0
    
    set(DTC_OVERLAY_FILE nrf5340_audio_dk_nrf5340_cpuapp_ns.overlay;iBridges-Lite_3x3_keypad.overlay)
    
    cmake_minimum_required(VERSION 3.20.0)
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(kscan)
    
    FILE(GLOB app_sources src/*.c)
    target_sources(app PRIVATE ${app_sources})

    Note the first set() command.  If I want to use my own custom overlay do I have to manually declare the defacto project overlay and then my custom overlay?  Does using a single custom overlay force me to do this and ditch the automatic finding of overlays or can I just let the automatic system do it's thing and declare a custom overlay after?

    Here is my custom overlay "\kscan\iBridges-Lite_3x3_keypad.overlay":

    / {
        chosen {
            kscan = &kscan0;
        };
    
        kscan0: kscan_0 {
            compatible = "kscan-gpio-matrix";
            label = "KSCAN";
            diode-direction = "col2row";
    
            col-gpios
                = <&gpio0 16 GPIO_ACTIVE_HIGH>
                , <&gpio0 17 GPIO_ACTIVE_HIGH>
                , <&gpio0 18 GPIO_ACTIVE_HIGH>
                ;
    
            row-gpios
                = <&gpio0 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
                , <&gpio0 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
                , <&gpio0 15 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
                ;
        };
    
        aliases {
            kscan0 = &kscan0;
        };
    };

    Now my build is still failing at the following:

    FAILED: zephyr/zephyr_pre0.elf zephyr/zephyr_pre0.map
    cmd.exe /C "cd . && C:\Users\PeterTomich\ncs\toolchains\v2.0.0\opt\zephyr-sdk\arm-zephyr-eabi\bin\arm-zephyr-eabi-gcc.exe zephyr/CMakeFiles/zephyr_pre0.dir/misc/empty_file.c.obj -o zephyr\zephyr_pre0.elf -Wl,-T zephyr/linker_zephyr_pre0.cmd -Wl,-Map=C:/Nordic/Scanning_Keyboard/kscan/build/zephyr/zephyr_pre0.map -Wl,--whole-archive app/libapp.a zephyr/libzephyr.a zephyr/arch/common/libarch__common.a zephyr/arch/arch/arm/core/aarch32/libarch__arm__core__aarch32.a zephyr/arch/arch/arm/core/aarch32/cortex_m/libarch__arm__core__aarch32__cortex_m.a zephyr/arch/arch/arm/core/aarch32/cortex_m/cmse/libarch__arm__core__aarch32__cortex_m__cmse.a zephyr/arch/arch/arm/core/aarch32/mpu/libarch__arm__core__aarch32__mpu.a zephyr/lib/libc/minimal/liblib__libc__minimal.a zephyr/lib/posix/liblib__posix.a zephyr/soc/arm/common/cortex_m/libsoc__arm__common__cortex_m.a zephyr/subsys/random/libsubsys__random.a zephyr/drivers/clock_control/libdrivers__clock_control.a zephyr/drivers/gpio/libdrivers__gpio.a zephyr/drivers/entropy/libdrivers__entropy.a zephyr/drivers/timer/libdrivers__timer.a zephyr/drivers/pinctrl/libdrivers__pinctrl.a modules/nrf/lib/fatal_error/lib..__nrf__lib__fatal_error.a modules/trusted-firmware-m/libtfm_api.a modules/hal_nordic/nrfx/libmodules__hal_nordic__nrfx.a modules/nrfxlib/nrfxlib/nrf_security/src/zephyr/libmbedtls_zephyr.a -Wl,--no-whole-archive zephyr/kernel/libkernel.a zephyr/CMakeFiles/offsets.dir/./arch/arm/core/offsets/offsets.c.obj -L"c:/users/petertomich/ncs/toolchains/v2.0.0/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/10.3.0/thumb/v8-m.main/nofp" -LC:/Nordic/Scanning_Keyboard/kscan/build/zephyr -lgcc zephyr/arch/common/libisr_tables.a tfm/platform/libplatform_ns.a tfm/app/libtfm_api_ns.a tfm/secure_fw/s_veneers.o -no-pie -Wl,--gc-sections -Wl,--build-id=none -Wl,--sort-common=descending -Wl,--sort-section=alignment -Wl,-u,_OffsetAbsSyms -Wl,-u,_ConfigAbsSyms -nostdlib -static -Wl,-X -Wl,-N -Wl,--orphan-handling=warn modules/nrfxlib/nrfxlib/nrf_security/src/libmbedcrypto.a C:/Users/PeterTomich/ncs/v2.0.0/nrfxlib/crypto/nrf_oberon/lib/cortex-m33/soft-float/liboberon_mbedtls_3.0.11.a modules/nrfxlib/nrfxlib/nrf_security/src/libmbedcrypto_base.a -mcpu=cortex-m33 -mthumb -mabi=aapcs -mfp16-format=ieee C:/Users/PeterTomich/ncs/v2.0.0/nrfxlib/crypto/nrf_oberon/lib/cortex-m33/soft-float/liboberon_3.0.11.a && cmd.exe /C "cd /D C:\Nordic\Scanning_Keyboard\kscan\build\zephyr && C:\Users\PeterTomich\ncs\toolchains\v2.0.0\opt\bin\cmake.exe -E echo ""
    c:/users/petertomich/ncs/toolchains/v2.0.0/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/10.3.0/../../../../arm-zephyr-eabi/bin/ld.exe: app/libapp.a(main.c.obj):C:\Nordic\Scanning_Keyboard\kscan\src\main.c:20: undefined reference to `__device_dts_ord_5'
    collect2.exe: error: ld returned 1 exit status
    ninja: build stopped: subcommand failed.
    FATAL ERROR: command exited with status 1: 'c:\Users\PeterTomich\ncs\toolchains\v2.0.0\opt\bin\cmake.EXE' --build 'c:\Nordic\Scanning_Keyboard\kscan\build'

    * The terminal process terminated with exit code: 1.
    * Terminal will be reused by tasks, press any key to close it.

    The problem appears to be this: undefined reference to `__device_dts_ord_5'

    Thanks for your help on this!

Children
No Data
Related