Compare commits
	
		
			3 Commits
		
	
	
		
			feat/buzze
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | eefa769bc8 | ||
|   | a0a6586752 | ||
|   | 1084643b2b | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -3,6 +3,7 @@ | ||||
| picotool | ||||
| sdk | ||||
| freertos* | ||||
| tinyusb | ||||
| 
 | ||||
| build | ||||
| toolchain | ||||
|  | ||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -42,7 +42,7 @@ format: .check-name | ||||
| 
 | ||||
| run-debug: format | ||||
| 	@rm -f  ${name}/${name}.debug | ||||
| 	@gcc -DLOG_LEVEL=TRACE -std=c99 -o2 ${name}/*.c  -lm -o ${name}/${name}.debug && ./${name}/${name}.debug | ||||
| 	@gcc -DLOG_LEVEL=DEBUG -std=c99 -o2 ${name}/*.c  -lm -o ${name}/${name}.debug && ./${name}/${name}.debug | ||||
| 
 | ||||
| compile: format | ||||
| 	@rm -f ${name}/build/CMakeCache.txt | ||||
|  | ||||
							
								
								
									
										29
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								README.md
									
									
									
									
									
								
							| @ -90,3 +90,32 @@ Metadata Block 1 | ||||
|  image type:             ARM Secure | ||||
| ``` | ||||
| 
 | ||||
| ## Show program outputs via USB serial mode | ||||
| In order to show logs from your program running on the microcontroller, you have to integrate [TinyUSB](https://github.com/raspberrypi/tinyusb/tree/pico) in the Pico C SDK. | ||||
| 
 | ||||
| ### Installation | ||||
| To do it, simply launch the following command: | ||||
| ```bash | ||||
| ./scripts/install_tiny_usb.bash <version> | ||||
| # for the 0.17.0 version | ||||
| ./scripts/install_tiny_usb.bash 0.17.0 | ||||
| ``` | ||||
| 
 | ||||
| It will download TinyUSB sources and create a symbolic link in the Pico C SDK for integration at compilation. | ||||
| 
 | ||||
| **NOTE**: If the SDK is located in specific directory, set the **INSTALL_PATH** variable pointing to the directory of the SDK before to launch the script. | ||||
| 
 | ||||
| ### Display output on terminal | ||||
| Recompile and push your program on the microcontroller. Then to display the program outputs, you have to use `minicom`. | ||||
| 
 | ||||
| ```bash | ||||
| sudo apt install minicom | ||||
| ``` | ||||
| 
 | ||||
| **NOTE**: if you have the habit to use another tool then, use it ! | ||||
| 
 | ||||
| After the installation, the microcontroller plug into the USB port, you can launch the command to visualize the program outputs: | ||||
| 
 | ||||
| ```bash | ||||
| sudo minicom -b 115200 -o -D /dev/ttyACM0 | ||||
| ``` | ||||
|  | ||||
| @ -52,6 +52,7 @@ set(FREERTOS_PORT_FILES | ||||
| 
 | ||||
| add_executable(buzzer main.c log.c gpio.c jobs.c utils.c ${FREERTOS_SOURCES} ${FREERTOS_PORT_FILES}) | ||||
| add_definitions(-DPICO) | ||||
| add_definitions(-DLOG_LEVEL=INFO) | ||||
| 
 | ||||
| pico_set_program_name(buzzer "buzzer") | ||||
| pico_set_program_version(buzzer "0.1") | ||||
| @ -62,7 +63,7 @@ pico_enable_stdio_usb(buzzer 1) | ||||
| 
 | ||||
| # Add the standard library to the build | ||||
| target_link_libraries(buzzer | ||||
|         pico_stdlib hardware_pwm pico_multicore hardware_exception) | ||||
|         pico_stdlib hardware_pwm pico_multicore hardware_exception hardware_adc) | ||||
| 
 | ||||
| # Add the standard include files to the build | ||||
| target_include_directories(buzzer PRIVATE | ||||
|  | ||||
							
								
								
									
										39
									
								
								buzzer/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								buzzer/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| # buzzer | ||||
| 
 | ||||
| 
 | ||||
| A program to run alarm on button pushed. | ||||
| 
 | ||||
| To activate the alarm, push the button. Same for desactivation. | ||||
| The alarm is launched in a separate task and controlled by | ||||
| the main task (which holds the push button logic). | ||||
| 
 | ||||
| You can run the application in "DEBUG" mode using: | ||||
| `make run-debug name=buzzer` | ||||
| The FreeRTOS engine is replaced by threads.  | ||||
| 
 | ||||
| ## Hardware | ||||
| 
 | ||||
| ### Variant 1 | ||||
| 
 | ||||
| * 1x Passive Buzzer | ||||
| * 1x Push button | ||||
| * 1 NPN transistor for signal amplification | ||||
| * 1x 1k ohm resistor (NPN collector) | ||||
| * 2x 10k ohm resistor | ||||
| 
 | ||||
| <div align="center"> | ||||
| <img src="circuit.jpg" style="transform:rotate(-90deg); margin:-100px;" width="300" /> | ||||
| </div> | ||||
| 
 | ||||
| ### Variant 2 | ||||
| You can play with the frequency [1500; 2000] hz thanks to the potentiometer. | ||||
| 
 | ||||
| * Variant 1 | ||||
| * 1x Rotary potentiometer | ||||
| * 1x blue LED | ||||
| 
 | ||||
| <div align="center"> | ||||
| <img src="circuit_variant.jpg" style="transform:rotate(-90deg); margin:-90px;" width="300" /> | ||||
| </div> | ||||
| 
 | ||||
| Enjoy ! 😉 | ||||
							
								
								
									
										
											BIN
										
									
								
								buzzer/circuit_variant.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								buzzer/circuit_variant.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.9 MiB | 
| @ -4,8 +4,7 @@ | ||||
| #include <pico/printf.h> | ||||
| #include <pico/stdlib.h> | ||||
| #include <hardware/pwm.h> | ||||
| 
 | ||||
| #define DEFAULT_WRAP_LEVEL 20 | ||||
| #include <hardware/adc.h> | ||||
| #else | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| @ -37,6 +36,21 @@ void _sleep_us(size_t value) { | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns a ratio of the ADC value input. | ||||
|  * | ||||
|  * The range of the ADC on Raspberry Pico 2 is 10 bits so the resolution is 1024 (2^10). | ||||
|  * | ||||
|  */ | ||||
| double gpio_get_adc() { | ||||
| #ifdef PICO | ||||
|     return adc_read() / 1023.0 ; // 2^10 - 1
 | ||||
| #else | ||||
|     trace("<GPIO.get_adc (input=0) (value=?)"); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void gpio_set_level(gpio *g, uint16_t level) { | ||||
|     if (g->has_pwm && g->direction == GPIO_OUT) { | ||||
|         g->level = level; | ||||
| @ -44,7 +58,7 @@ void gpio_set_level(gpio *g, uint16_t level) { | ||||
| #ifdef PICO | ||||
|         pwm_set_gpio_level(g->pin, level); | ||||
| #else | ||||
|         debug("<GPIO.set_level (pin=%ld) (level=%d)>", g->pin, level); | ||||
|         trace("<GPIO.set_level (pin=%ld) (level=%d)>", g->pin, level); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
| @ -70,7 +84,7 @@ bool gpio_get_input(gpio* g) { | ||||
|         } | ||||
|         g->state = GPIO_INPUT_MOCK_COUNTER++ % value == 0; | ||||
| #endif | ||||
|         trace("<GPIO.get_input (pin=%ld) (level=%d)>", g->pin, g->state); | ||||
|         trace("<GPIO.get_input (pin=%ld) (state=%d)>", g->pin, g->state); | ||||
|         return g->state; | ||||
|     } | ||||
|     return false; | ||||
| @ -91,12 +105,15 @@ void gpio_onoff(gpio* g, uint32_t delay_ms, size_t times) { | ||||
| void init_gpio(void) { | ||||
| #ifdef PICO | ||||
|     stdio_init_all(); | ||||
|     adc_init(); | ||||
|     adc_select_input(0); // pin: 26
 | ||||
|     for (size_t i = 0; i < NB_GPIO; i++) { | ||||
|         gpio_init(GPIOS[i]->pin); | ||||
|         gpio_set_dir(GPIOS[i]->pin, GPIOS[i]->direction); | ||||
| 
 | ||||
|         if (GPIOS[i]->has_pwm) { | ||||
|             uint slice_num = pwm_gpio_to_slice_num(GPIOS[i]->pin); | ||||
|             gpio_set_function(GPIOS[i]->pin, GPIO_FUNC_PWM); | ||||
|             pwm_set_enabled(slice_num, true); | ||||
|             pwm_set_wrap(slice_num, DEFAULT_WRAP_LEVEL); | ||||
|         } | ||||
|  | ||||
| @ -22,7 +22,8 @@ | ||||
| #define GPIO_IN 0 | ||||
| #endif | ||||
| 
 | ||||
| #define NB_GPIO 3 | ||||
| #define NB_GPIO 5 | ||||
| #define DEFAULT_WRAP_LEVEL 20 | ||||
| 
 | ||||
| typedef struct gpio gpio; | ||||
| struct gpio { | ||||
| @ -45,11 +46,20 @@ static gpio GPIO_BUZZER = (gpio) { | ||||
|     .pin = 15, .direction = GPIO_OUT, .has_pwm = false, .level = 0, .state = false | ||||
| }; | ||||
| 
 | ||||
| static gpio* GPIOS[NB_GPIO] = {&GPIO_DEFAULT_LED, &GPIO_BUTTON, &GPIO_BUZZER}; | ||||
| static gpio GPIO_ADC = (gpio) { | ||||
|     .pin = 26, .direction = GPIO_IN, .has_pwm = false, .level = 0, .state = false | ||||
| }; | ||||
| 
 | ||||
| static gpio GPIO_LED = (gpio) { | ||||
|     .pin = 20, .direction = GPIO_OUT, .has_pwm = true, .level = 0, .state = false | ||||
| }; | ||||
| 
 | ||||
| static gpio* GPIOS[NB_GPIO] = {&GPIO_DEFAULT_LED, &GPIO_BUTTON, &GPIO_BUZZER, &GPIO_ADC, &GPIO_LED}; | ||||
| 
 | ||||
| void gpio_set_level(gpio *g, uint16_t level); | ||||
| void gpio_set_state(gpio *g, bool state); | ||||
| bool gpio_get_input(gpio* g); | ||||
| double gpio_get_adc(void); | ||||
| void gpio_onoff(gpio* g, uint32_t delay_ms, size_t times); | ||||
| 
 | ||||
| void init_gpio(void); | ||||
|  | ||||
| @ -29,6 +29,7 @@ int init_app_state(AppState *s) { | ||||
|         return -1; | ||||
|     } | ||||
| #endif | ||||
|     s->freq_multiplicator = 0; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| @ -60,6 +61,7 @@ int cancel_task(AppState *s) { | ||||
|         vTaskDelete(*s->task); | ||||
|         free(s->task); | ||||
|         gpio_set_state(GPIOS[2], false); | ||||
|         gpio_set_level(GPIOS[4],0); | ||||
|         return 0; | ||||
|     } | ||||
| #else | ||||
| @ -76,6 +78,7 @@ int cancel_task(AppState *s) { | ||||
|         free(s->task); | ||||
|         s->task = NULL; | ||||
|     } | ||||
|     gpio_set_level(GPIOS[4],0); | ||||
|     return 0; | ||||
| #endif | ||||
| } | ||||
| @ -91,8 +94,8 @@ int launch_task(AppState *s, FnJob f) { | ||||
|     } | ||||
| 
 | ||||
|     BaseType_t res = | ||||
|         xTaskCreate(f, "task", configMINIMAL_STACK_SIZE, | ||||
|                     NULL, configMAX_PRIORITIES - 1U, task); | ||||
|         xTaskCreateAffinitySet(f, "task", configMINIMAL_STACK_SIZE, | ||||
|                                s, configMAX_PRIORITIES - 1U, 1 << 1,task); | ||||
| 
 | ||||
|     if (res != pdPASS) { | ||||
|         error("unable to launch run alarm task task, code error: %d", | ||||
| @ -117,6 +120,37 @@ int launch_task(AppState *s, FnJob f) { | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * | ||||
|  */ | ||||
| void check_acd_value(void* args) { | ||||
|     AppState* s = (AppState*) args; | ||||
|     uint16_t current_freq_multiplicator = 0; | ||||
| 
 | ||||
|     for (;;) { | ||||
|         double freq_mul = gpio_get_adc(); | ||||
|         if (freq_mul != current_freq_multiplicator) { | ||||
| #ifdef PICO | ||||
|             gpio_set_level(GPIOS[4], current_freq_multiplicator * DEFAULT_WRAP_LEVEL); | ||||
| #endif | ||||
| 
 | ||||
|             if (lock(s) != 0) | ||||
|                 fatal(stop_app_fallback, "unable to lock app mutex"); | ||||
| 
 | ||||
|             s->freq_multiplicator = freq_mul; | ||||
|             current_freq_multiplicator = freq_mul; | ||||
| 
 | ||||
|             if (release(s) != 0) | ||||
|                 fatal(stop_app_fallback, "unable to release app mutex"); | ||||
| 
 | ||||
|             debug("freq multiplicator updated: %d\n", current_freq_multiplicator); | ||||
|         } | ||||
| #ifdef PICO | ||||
|         gpio_set_level(GPIOS[4], current_freq_multiplicator * DEFAULT_WRAP_LEVEL); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Main app loop. | ||||
|  * | ||||
|  | ||||
| @ -17,6 +17,7 @@ enum ACTION {STOP, START}; | ||||
| typedef struct AppState AppState; | ||||
| struct AppState { | ||||
|     Action action; | ||||
|     double freq_multiplicator; | ||||
|      | ||||
|     #ifdef PICO | ||||
|         TaskHandle_t* task; | ||||
| @ -38,6 +39,7 @@ struct TaskParam { | ||||
| int init_app_state(AppState *s); | ||||
| 
 | ||||
| void check_btn_state(void* args); | ||||
| void check_acd_value(void* args); | ||||
| 
 | ||||
| int lock(AppState *s); | ||||
| int release(AppState *s); | ||||
|  | ||||
| @ -24,8 +24,8 @@ | ||||
| #include "gpio.h" | ||||
| #include "utils.h" | ||||
| 
 | ||||
| #define ALARM_BASE_FREQ 2000 // auditive frequency human range: [20; 20000] hertz
 | ||||
| #define ALARM_PERIOD_MS 500 | ||||
| #define ALARM_BASE_FREQ 1500 // auditive frequency human range: [20; 20000] hertz
 | ||||
| #define ALARM_PERIOD_MS 200 | ||||
| #define PI 3.14 | ||||
| 
 | ||||
| /**
 | ||||
| @ -35,7 +35,8 @@ | ||||
|  * | ||||
|  * NOTE: `sleep_us` method does not impact FreeRTOS engine | ||||
|  * since, the scheduler started on two cores (RP2350). The behavior may differs | ||||
|  * on one core. Update the FreeRTOS tick freq and implement `pdUS_TO_TICKS` if needed. | ||||
|  * on one core. Update the FreeRTOS tick freq and implement `pdUS_TO_TICKS` if needed or, | ||||
|  * run the alarm in dedicated core see: `xTaskCreateAffinitySet`. | ||||
|  */ | ||||
| void gen_freq(gpio* g, size_t freq_hz, size_t duration_ms) { | ||||
|     if (!freq_hz) { | ||||
| @ -59,7 +60,22 @@ void gen_freq(gpio* g, size_t freq_hz, size_t duration_ms) { | ||||
| } | ||||
| 
 | ||||
| void run_alarm(void *const params) { | ||||
|     AppState* as = (AppState* ) params; | ||||
| 
 | ||||
|     for(;;) { | ||||
|         if (lock(as) != 0) | ||||
|             fatal(stop_app_fallback, "unable to lock the app state"); | ||||
| 
 | ||||
|         uint16_t freq = as->freq_multiplicator * 500 + ALARM_BASE_FREQ; | ||||
| 
 | ||||
|         if (release(as) != 0) | ||||
|             fatal(stop_app_fallback, "unable to release the app state"); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef PICO | ||||
|         gpio_set_level(GPIOS[4], as->freq_multiplicator * DEFAULT_WRAP_LEVEL); | ||||
| #endif | ||||
| 
 | ||||
|         debug("running alarm..."); | ||||
|         float sin_val; | ||||
|         int tone_val; | ||||
| @ -68,18 +84,37 @@ void run_alarm(void *const params) { | ||||
| 
 | ||||
|         for (size_t i = 0; i < 360; i+=10) { | ||||
|             sin_val = sinf(i * (PI / 180)); | ||||
|             tone_val = ALARM_BASE_FREQ + sin_val * (ALARM_BASE_FREQ / 10); | ||||
|             tone_val = freq  + sin_val * (freq / 10); | ||||
|             gen_freq(GPIOS[2], tone_val, duration_ms); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int init_check_adc_value(AppState* as) { | ||||
| #ifdef PICO | ||||
|     BaseType_t res = | ||||
|         xTaskCreateAffinitySet(check_acd_value, "check_adc_value", configMINIMAL_STACK_SIZE, | ||||
|                                (void *const)as, configMAX_PRIORITIES - 1U, 1 << 0, NULL); | ||||
| 
 | ||||
|     if (res != pdPASS) | ||||
|         return -1; | ||||
| 
 | ||||
|     return 0; | ||||
| #else | ||||
|     pthread_t task; | ||||
|     if (pthread_create(&task, NULL, check_acd_value, as) != 0) { | ||||
|         return -1; | ||||
|     } | ||||
|     return 0; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Initialize the main FreeRTOS task.
 | ||||
| int init_rtos_main(TaskParam *params) { | ||||
| #ifdef PICO | ||||
|     BaseType_t res = | ||||
|         xTaskCreate(check_btn_state, "main", configMINIMAL_STACK_SIZE, | ||||
|                     (void *const)params, configMAX_PRIORITIES - 1U, NULL); | ||||
|         xTaskCreateAffinitySet(check_btn_state, "main", configMINIMAL_STACK_SIZE, | ||||
|                                (void *const)params, configMAX_PRIORITIES - 1U, 1 << 0, NULL); | ||||
| 
 | ||||
|     if (res != pdPASS) | ||||
|         return -1; | ||||
| @ -105,9 +140,14 @@ int init_rtos_main(TaskParam *params) { | ||||
|  * You can run the application in "DEBUG" mode using: | ||||
|  * `make run-debug name=buzzer` | ||||
|  * The FreeRTOS engine is replaced by threads. | ||||
|  * | ||||
|  * A variant to play with the frequency can be done adding a | ||||
|  * potentiometer and set `check_adc` to true. See README.md for details. | ||||
|  * | ||||
|  */ | ||||
| int main() { | ||||
|     init_gpio(); | ||||
|     bool check_adc = false; | ||||
| 
 | ||||
|     AppState as; | ||||
|     if (init_app_state(&as)  != 0) | ||||
| @ -118,6 +158,11 @@ int main() { | ||||
|         .f = run_alarm, | ||||
|     }; | ||||
| 
 | ||||
|     // launch the check of the ADC value reveived by the potentiometer
 | ||||
|     if (check_adc) | ||||
|         if (init_check_adc_value(&as) != 0) | ||||
|             fatal(stop_app_fallback, "unable to launch check adc value task"); | ||||
| 
 | ||||
| #ifdef PICO | ||||
|     if (init_rtos_main(¶ms) != 0) | ||||
|         fatal(stop_app_fallback, "unable to launch to FreeRTOS main task"); | ||||
|  | ||||
							
								
								
									
										67
									
								
								scripts/install_tiny_usb.bash
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										67
									
								
								scripts/install_tiny_usb.bash
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,67 @@ | ||||
| #!/bin/bash | ||||
| 
 | ||||
| ############################################### | ||||
| # | ||||
| # Download and install Tiny USB. | ||||
| # src: https://github.com/hathach/tinyusb | ||||
| # | ||||
| # ex: ./install_tiny_usb.bash 0.17.0 | ||||
| # | ||||
| ############################################### | ||||
| 
 | ||||
| TINY_USB_VERSION=$1 | ||||
| REGEX_VERSION="^[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}$" | ||||
| 
 | ||||
| if [[ -z ${INSTALL_PATH} ]] | ||||
| then | ||||
|     INSTALL_PATH=${PWD} | ||||
| fi | ||||
| 
 | ||||
| usage() { | ||||
|     echo "usage:" | ||||
|     echo "./install_tiny_usb.bash <version> (ex: ./install_tiny_usb.bash 2.1.0)" | ||||
| } | ||||
| 
 | ||||
| if [[ ! "${TINY_USB_VERSION}" =~ ${REGEX_VERSION} ]] | ||||
| then | ||||
|     echo "error: unable to parse the version: '${TINY_USB_VERSION}'" | ||||
|     usage | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| if [[ ! -d ${INSTALL_PATH}/tinyusb/${TINY_USB_VERSION} ]] | ||||
| then | ||||
|     echo "installing Tiny USB ${TINY_USB_VERSION}" | ||||
| 
 | ||||
|     tar_file="${TINY_USB_VERSION}.tar.gz" | ||||
|     wget https://github.com/hathach/tinyusb/archive/refs/tags/${TINY_USB_VERSION}.tar.gz -P ${INSTALL_PATH} | ||||
|     if [[ $? != 0 ]] | ||||
|     then | ||||
|         echo "error: unable to get tiny USB VERSION: ${TINY_USB_VERSION}" | ||||
|         exit 1 | ||||
|     fi | ||||
| 
 | ||||
|     mkdir -p ${INSTALL_PATH}/tinyusb | ||||
|     tar xzvf ${INSTALL_PATH}/${tar_file} -C ${INSTALL_PATH}/tinyusb | ||||
|     rm ${INSTALL_PATH}/${tar_file} | ||||
| 
 | ||||
|     mv ${INSTALL_PATH}/tinyusb/tinyusb-${TINY_USB_VERSION} ${INSTALL_PATH}/tinyusb/${TINY_USB_VERSION} | ||||
| 
 | ||||
|     echo "find Pico SDK to add TinyUSB support on compilation..." | ||||
|     tiny_usb_dir=$(find ${INSTALL_PATH}/sdk -name tinyusb -type d | grep lib | head -1) | ||||
|     if [[ ! -z ${tiny_usb_dir} ]] | ||||
|     then | ||||
|         cd ${tiny_usb_dir}/.. | ||||
|         lib_dir=${PWD} | ||||
| 
 | ||||
|         rmdir ${tiny_usb_dir} | ||||
|         ln -s ${INSTALL_PATH}/tinyusb/${TINY_USB_VERSION} tinyusb | ||||
| 
 | ||||
|         echo "Tiny USB soft link added to Pico SDK: $(ls -lrt ${lib_dir}/tinyusb)" | ||||
|     fi | ||||
| 
 | ||||
|     echo "Tiny USB installed successfully: ${INSTALL_PATH}/tinyusb/${TINY_USB_VERSION}" | ||||
|     exit 0 | ||||
| fi | ||||
| 
 | ||||
| echo "Tiny USB already exists: ${INSTALL_PATH}/tinyusb/${TINY_USB_VERSION}" | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user