From fb10b29c65d1979510991672660ce02aeb5e53b1 Mon Sep 17 00:00:00 2001 From: Jason Yuan Date: Tue, 7 Mar 2023 14:06:33 -0800 Subject: [PATCH] samples: boards: firmware for Twinkie V2 sample firmware for Twinkie V2 that toggles the LED based on charging status. Signed-off-by: Jason Yuan --- boards/arm/google_twinkie_v2/board.cmake | 8 +- boards/arm/google_twinkie_v2/doc/index.rst | 2 - .../google_twinkie_v2/google_twinkie_v2.dts | 17 ++- .../google_twinkie_v2_pda/CMakeLists.txt | 9 ++ .../boards/google_twinkie_v2_pda/README.rst | 25 +++++ samples/boards/google_twinkie_v2_pda/prj.conf | 4 + .../boards/google_twinkie_v2_pda/sample.yaml | 6 ++ .../boards/google_twinkie_v2_pda/src/meas.c | 102 ++++++++++++++++++ .../boards/google_twinkie_v2_pda/src/meas.h | 36 +++++++ .../boards/google_twinkie_v2_pda/src/view.c | 58 ++++++++++ 10 files changed, 250 insertions(+), 17 deletions(-) create mode 100644 samples/boards/google_twinkie_v2_pda/CMakeLists.txt create mode 100644 samples/boards/google_twinkie_v2_pda/README.rst create mode 100644 samples/boards/google_twinkie_v2_pda/prj.conf create mode 100644 samples/boards/google_twinkie_v2_pda/sample.yaml create mode 100644 samples/boards/google_twinkie_v2_pda/src/meas.c create mode 100644 samples/boards/google_twinkie_v2_pda/src/meas.h create mode 100644 samples/boards/google_twinkie_v2_pda/src/view.c diff --git a/boards/arm/google_twinkie_v2/board.cmake b/boards/arm/google_twinkie_v2/board.cmake index 7ff209ba658d4dc..21a528b2e8e6dc1 100644 --- a/boards/arm/google_twinkie_v2/board.cmake +++ b/boards/arm/google_twinkie_v2/board.cmake @@ -1,13 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 board_runner_args(dfu-util "--pid=0483:df11" "--alt=0" "--dfuse") - -include(${ZEPHYR_BASE}/boards/common/dfu-util.board.cmake) - board_runner_args(stm32cubeprogrammer "--port=swd" "--reset=hw") - -include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) - board_runner_args(jlink "--device=STM32G0B1RE" "--speed=4000") +include(${ZEPHYR_BASE}/boards/common/dfu-util.board.cmake) +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/google_twinkie_v2/doc/index.rst b/boards/arm/google_twinkie_v2/doc/index.rst index accc52012a60cd3..216e5747b7fc087 100644 --- a/boards/arm/google_twinkie_v2/doc/index.rst +++ b/boards/arm/google_twinkie_v2/doc/index.rst @@ -9,8 +9,6 @@ Overview Google Twinkie V2 is a reference board for the google power delivery analyzer (PDA) Twinkie V2. -Zephyr has support for the STM32-based embedded controller (EC) on-board. - Hardware ******** diff --git a/boards/arm/google_twinkie_v2/google_twinkie_v2.dts b/boards/arm/google_twinkie_v2/google_twinkie_v2.dts index b098b59bc8b99af..b41daafbd8448c7 100644 --- a/boards/arm/google_twinkie_v2/google_twinkie_v2.dts +++ b/boards/arm/google_twinkie_v2/google_twinkie_v2.dts @@ -32,6 +32,10 @@ gpio_keys { compatible = "gpio-keys"; + + /* does not go to an actual button in current hardware. + * short TP5 to TP6 to activate. + */ dfu_detect: dfudetect { gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; }; @@ -70,11 +74,7 @@ sense-gain-mult = <25>; }; - aliases { - led0 = &red_led_0; - led1 = &green_led_1; - led2 = &blue_led_2; bootloader-led0 = &blue_led_2; vcc1 = &cc1_buf; vcc2 = &cc2_buf; @@ -84,7 +84,6 @@ }; }; - &adc1 { #address-cells = <1>; #size-cells = <0>; @@ -96,6 +95,9 @@ &adc1_in18_pc5 /* CSA_CC2 */ >; + pinctrl-names = "default"; + status = "okay"; + channel@1 { reg = <1>; zephyr,gain = "ADC_GAIN_1"; @@ -140,9 +142,6 @@ zephyr,acquisition-time = ; zephyr,resolution = <12>; }; - - pinctrl-names = "default"; - status = "okay"; }; &clk_hsi { @@ -175,6 +174,6 @@ psc-ucpdclk = <1>; hbitclkdiv = <27>; - pinctrl-names = "default"; pinctrl-0 = <&ucpd1_cc1_pa8 &ucpd1_cc2_pb15>; + pinctrl-names = "default"; }; diff --git a/samples/boards/google_twinkie_v2_pda/CMakeLists.txt b/samples/boards/google_twinkie_v2_pda/CMakeLists.txt new file mode 100644 index 000000000000000..188407e289eefe0 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(google_twinkie_v2) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/boards/google_twinkie_v2_pda/README.rst b/samples/boards/google_twinkie_v2_pda/README.rst new file mode 100644 index 000000000000000..3d2d1b813c797a9 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/README.rst @@ -0,0 +1,25 @@ +.. _google_twinkie_v2_pda: + +Twinkie Power Delivery +###################### + +Overview +******** + +This provides access to :ref:`Twinkie ` so you can try out +the supported features. + +Building and Running +******************** + +Build and flash Twinkie as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/google_pda + :board: google_twinkie_v2 + :goals: build flash + :compact: + +After flashing, the LED will start red. Putting the Twinkie in between any +usbc connection will cause the LED to turn blue. The LED will turn green instead +if the device is currently charging. diff --git a/samples/boards/google_twinkie_v2_pda/prj.conf b/samples/boards/google_twinkie_v2_pda/prj.conf new file mode 100644 index 000000000000000..3e500a69630af18 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ADC=y +CONFIG_ADC_STM32=y +CONFIG_GPIO=y +CONFIG_LED=y diff --git a/samples/boards/google_twinkie_v2_pda/sample.yaml b/samples/boards/google_twinkie_v2_pda/sample.yaml new file mode 100644 index 000000000000000..8a9a47957547118 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/sample.yaml @@ -0,0 +1,6 @@ +sample: + name: Twinkie V2 usb Vbus snooper +tests: + sample.board.google_twinkie_v2: + platform_allow: google_twinkie_v2 + tags: usb diff --git a/samples/boards/google_twinkie_v2_pda/src/meas.c b/samples/boards/google_twinkie_v2_pda/src/meas.c new file mode 100644 index 000000000000000..5d2ba9c793ccdb1 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/src/meas.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +/* The devicetree node identifier for the adc aliases. */ +#define VBUS_V_MEAS_NODE DT_ALIAS(vbus) +#define VBUS_C_MEAS_NODE DT_ALIAS(cbus) + +static const struct voltage_divider_dt_spec adc_vbus_v = + VOLTAGE_DIVIDER_DT_SPEC_GET(VBUS_V_MEAS_NODE); +static const struct current_sense_amplifier_dt_spec adc_vbus_c = + CURRENT_SENSE_AMPLIFIER_DT_SPEC_GET(VBUS_C_MEAS_NODE); + +int meas_vbus_v(int32_t *v) +{ + int ret; + int32_t sample_buffer = 0; + + /* Structure defining an ADC sampling sequence */ + struct adc_sequence sequence = { + .buffer = &sample_buffer, + /* buffer size in bytes, not number of samples */ + .buffer_size = sizeof(sample_buffer), + .calibrate = true, + }; + adc_sequence_init_dt(&adc_vbus_v.port, &sequence); + + ret = adc_read(adc_vbus_v.port.dev, &sequence); + if (ret != 0) { + return ret; + } + + *v = sample_buffer; + ret = adc_raw_to_millivolts_dt(&adc_vbus_v.port, v); + if (ret != 0) { + return ret; + } + + ret = voltage_divider_scale_dt(&adc_vbus_v, v); + if (ret != 0) { + return ret; + } + + return 0; +} + +int meas_vbus_c(int32_t *c) +{ + int ret; + int32_t sample_buffer = 0; + + /* Structure defining an ADC sampling sequence */ + struct adc_sequence sequence = { + .buffer = &sample_buffer, + /* buffer size in bytes, not number of samples */ + .buffer_size = sizeof(sample_buffer), + .calibrate = true, + }; + adc_sequence_init_dt(&adc_vbus_c.port, &sequence); + + ret = adc_read(adc_vbus_c.port.dev, &sequence); + if (ret != 0) { + return ret; + } + + *c = sample_buffer; + ret = adc_raw_to_millivolts_dt(&adc_vbus_c.port, c); + if (ret != 0) { + return ret; + } + + /* prescaling the voltage offset */ + *c -= adc_vbus_c.port.vref_mv / 2; + current_sense_amplifier_scale_dt(&adc_vbus_c, c); + + return 0; +} + +int meas_init(void) +{ + int ret; + + ret = adc_channel_setup_dt(&adc_vbus_v.port); + if (ret != 0) { + return ret; + } + + ret = adc_channel_setup_dt(&adc_vbus_c.port); + if (ret != 0) { + return ret; + } + + return 0; +} diff --git a/samples/boards/google_twinkie_v2_pda/src/meas.h b/samples/boards/google_twinkie_v2_pda/src/meas.h new file mode 100644 index 000000000000000..5367510b460ee26 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/src/meas.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MEAS_H__ +#define __MEAS_H__ + +/** + * @brief Initializes the measurement module, sets up all the adc channels through the device tree + * binding + * + * @return 0 on success + */ +int meas_init(void); + +/** + * @brief Measure the voltage on VBUS + * + * @param v pointer where VBUS voltage, in millivolts, is stored + * + * @return 0 on success + */ +int meas_vbus_v(int32_t *v); + +/** + * @brief Measure the current on VBUS + * + * @param c pointer where VBUS current, in milliamperes, is stored + * + * @return 0 on success + */ +int meas_vbus_c(int32_t *c); + +#endif diff --git a/samples/boards/google_twinkie_v2_pda/src/view.c b/samples/boards/google_twinkie_v2_pda/src/view.c new file mode 100644 index 000000000000000..d28d4caeb367828 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/src/view.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "meas.h" + +enum led_color_t { + LED_RED, + LED_GREEN, + LED_BLUE, +}; + +static void set_led(const struct device *const led, enum led_color_t led_color) +{ + if (led_color != LED_RED) led_off(led, LED_RED); + if (led_color != LED_GREEN) led_off(led, LED_GREEN); + if (led_color != LED_BLUE) led_off(led, LED_BLUE); + led_on(led, led_color); +} + +#define CHARGING_VOLTAGE 5000 +#define CHARGING_CURRENT 1000 + +void main(void) +{ + meas_init(); + + const struct device *const led = DEVICE_DT_GET_ONE(gpio_leds); + int32_t vbus_v = 0; + int32_t vbus_c = 0; + + if (!device_is_ready(led)) { + return; + } + + while (1) { + meas_vbus_v(&vbus_v); + meas_vbus_c(&vbus_c); + + if (vbus_v > CHARGING_VOLTAGE) { + if (vbus_c > CHARGING_CURRENT) { + set_led(led, LED_GREEN); + } else { + set_led(led, LED_BLUE); + } + } else { + set_led(led, LED_RED); + } + + k_usleep(500); + } +}