Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for VSI as an input audio source #38

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 84 additions & 23 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ variables:
TARGET: [corstone310, corstone300]
TOOLCHAIN: [ARMCLANG, GNU]
INFERENCE: [ETHOS]
AUDIO: [ROM, VSI]
.pipeline_config_applications_sw: &pipeline_config_applications_sw
TARGET: [corstone310, corstone300]
TOOLCHAIN: [ARMCLANG, GNU]
INFERENCE: [SOFTWARE]
AUDIO: [ROM, VSI]

stages:
- quality-check
Expand Down Expand Up @@ -86,15 +88,16 @@ build-applications:
./tools/scripts/build.sh ${APP} \
--target $TARGET \
--inference $INFERENCE \
--audio $AUDIO \
--toolchain $TOOLCHAIN \
--certificate_path $PWD/certificate.pem \
--private_key_path $PWD/private_key.pem
- |
if [ $APP == "blinky" ];then
tar -czf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_build.tar.gz \
tar -czf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_build.tar.gz \
build/${APP}_merged.elf
else
tar -czf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_build.tar.gz \
tar -czf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_build.tar.gz \
build/${APP}_merged.elf \
build/${APP}-update_signed.bin \
build/update-signature.txt \
Expand All @@ -111,27 +114,60 @@ build-applications:

artifacts:
paths:
- ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_build.tar.gz
- ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_build.tar.gz
expire_in: 1 week

test-applications-output:
extends: .test_job
script:
- tar xf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_build.tar.gz
- tar xf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_build.tar.gz
- export APP_UNDERSCORED=$(echo ${APP} | tr '-' '_')
- |
pytest -s tools/tests/test_application_output.py \
--build-artefacts-path "build" \
--fvp $FVP_BIN \
--merged-elf-name "${APP}_merged.elf" \
--timeout-seconds 900 \
--pass-output-file "applications/${APP_UNDERSCORED}/tests/pass_output.log" \
--fail-output-file "applications/${APP_UNDERSCORED}/tests/fail_output.log"
if [[ $AUDIO == "VSI" ]]; then
apt-get -y update
apt-get -y install make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblzma-dev tk-dev
mkdir /tmp/python_vsi_setup
pushd /tmp/python_vsi_setup
wget https://www.python.org/ftp/python/3.9.18/Python-3.9.18.tgz
tar xzf Python-3.9.18.tgz
cd Python-3.9.18
./configure --prefix=/opt/python/3.9.18/ --enable-optimizations
make -j "$(nproc)"
make altinstall
popd
rm -rf /tmp/python_vsi_setup
pytest -s tools/tests/test_application_output.py \
--audio-file-path "applications/${APP_UNDERSCORED}/resources/test.wav" \
--build-artefacts-path "build" \
--fvp $FVP_BIN \
--merged-elf-name "${APP}_merged.elf" \
--timeout-seconds 900 \
--pass-output-file "applications/${APP_UNDERSCORED}/tests/pass_output.log" \
--fail-output-file "applications/${APP_UNDERSCORED}/tests/fail_output.log" \
--pythonhome-path "/opt/python/3.9.18"
else
pytest -s tools/tests/test_application_output.py \
--build-artefacts-path "build" \
--fvp $FVP_BIN \
--merged-elf-name "${APP}_merged.elf" \
--timeout-seconds 900 \
--pass-output-file "applications/${APP_UNDERSCORED}/tests/pass_output.log" \
--fail-output-file "applications/${APP_UNDERSCORED}/tests/fail_output.log"
fi
parallel:
matrix:
-
<< : *pipeline_config_applications_ethos
APP: [blinky, keyword-detection, speech-recognition]
-
<< : *pipeline_config_applications_sw
APP: [keyword-detection]

artifacts:
paths:
- ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_build.tar.gz
- ${TARGET}_aws-iot-example_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_build.tar.gz
expire_in: 1 week

# The test-ota job should wait for build-applications job to finish as
# test-ota job uses the output build artifacts from build-applications job.
Expand All @@ -141,22 +177,47 @@ test-applications-output:
test-ota:
extends: .test_job
needs:
- job: build-applications
artifacts: true
- job: test-applications-output
artifacts: true
script:
- tar xf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_build.tar.gz
- tar xf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_build.tar.gz
- export APP_UNDERSCORED=$(echo ${APP} | tr '-' '_')
- |
pytest -s tools/tests/test_ota.py \
--build-artefacts-path "build" \
--fvp $FVP_BIN \
--credentials-path "applications/${APP_UNDERSCORED}/configs/aws_configs" \
--merged-elf-name "${APP}_merged.elf" \
--signed-update-bin-name "${APP}-update_signed.bin" \
--timeout-seconds 1800 \
--pass-ota-output-file "applications/${APP_UNDERSCORED}/tests/pass_ota_output.log" \
--fail-ota-output-file "applications/${APP_UNDERSCORED}/tests/fail_ota_output.log"
if [[ $AUDIO == "VSI" ]]; then
apt-get -y update
apt-get -y install make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblzma-dev tk-dev
mkdir /tmp/python_vsi_setup
pushd /tmp/python_vsi_setup
wget https://www.python.org/ftp/python/3.9.18/Python-3.9.18.tgz
tar xzf Python-3.9.18.tgz
cd Python-3.9.18
./configure --prefix=/opt/python/3.9.18/ --enable-optimizations
make -j "$(nproc)"
make altinstall
popd
rm -rf /tmp/python_vsi_setup
pytest -s tools/tests/test_ota.py \
--audio-file-path "applications/${APP_UNDERSCORED}/resources/test.wav" \
--build-artefacts-path "build" \
--fvp $FVP_BIN \
--credentials-path "applications/${APP_UNDERSCORED}/configs/aws_configs" \
--merged-elf-name "${APP}_merged.elf" \
--signed-update-bin-name "${APP}-update_signed.bin" \
--timeout-seconds 1800 \
--pass-ota-output-file "applications/${APP_UNDERSCORED}/tests/pass_ota_output.log" \
--fail-ota-output-file "applications/${APP_UNDERSCORED}/tests/fail_ota_output.log" \
--pythonhome-path "/opt/python/3.9.18"
else
pytest -s tools/tests/test_ota.py \
--build-artefacts-path "build" \
--fvp $FVP_BIN \
--credentials-path "applications/${APP_UNDERSCORED}/configs/aws_configs" \
--merged-elf-name "${APP}_merged.elf" \
--signed-update-bin-name "${APP}-update_signed.bin" \
--timeout-seconds 1800 \
--pass-ota-output-file "applications/${APP_UNDERSCORED}/tests/pass_ota_output.log" \
--fail-ota-output-file "applications/${APP_UNDERSCORED}/tests/fail_ota_output.log"
fi
parallel:
matrix:
-
Expand Down
7 changes: 6 additions & 1 deletion applications/keyword_detection/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ endif()

set(ML_INFERENCE_ENGINE "ETHOS" CACHE STRING "Machine Learning inference engine (ETHOS | SOFTWARE)")

set(AUDIO_SOURCE "ROM" CACHE STRING "Source of audio data (ROM)")
set(AUDIO_SOURCE "ROM" CACHE STRING "Source of audio data (ROM | VSI)")

# From: ota-for-aws-iot-embedded-sdk/source/include/ota_appversion32.h
# struct version
Expand Down Expand Up @@ -151,6 +151,11 @@ if(${AUDIO_SOURCE} STREQUAL "ROM")
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)
elseif(${AUDIO_SOURCE} STREQUAL "VSI")
target_compile_definitions(keyword-detection
PRIVATE
AUDIO_VSI
)
endif()

if (${ML_INFERENCE_ENGINE} STREQUAL "ETHOS")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
#define appCONFIG_ML_MQTT_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE )
#define appCONFIG_ML_MQTT_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )

#define appCONFIG_VSI_CALLBACK_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE )
#define appCONFIG_VSI_CALLBACK_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )


/** @brief Increase backoff algorithm timeout by 8 seconds when device advisor
* test is active.
Expand Down
52 changes: 52 additions & 0 deletions applications/keyword_detection/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@

#include "FreeRTOSConfig.h"

#ifdef AUDIO_VSI
#include "Driver_SAI.h"
#endif

/*
* Semihosting is a mechanism that enables code running on an ARM target
* to communicate and use the Input/Output facilities of a host computer
Expand All @@ -47,6 +51,15 @@
extern void vStartOtaTask( void );
extern int32_t network_startup( void );

#ifdef AUDIO_VSI
void vVsiCallbackTask( void * arg );
static void prvStartVsiCallbackTask( void );
extern uint32_t ulVsiEvent;
extern void (* pxOnVsiEvent)( void * );
extern void * pvVsiContext;
TaskHandle_t xVsiTaskHandle = NULL;
#endif

psa_key_handle_t xOTACodeVerifyKeyHandle = 0;
QueueHandle_t xMlMqttQueue = NULL;
typedef struct
Expand Down Expand Up @@ -207,6 +220,10 @@ int main( void )

vStartBlinkTask();

#ifdef AUDIO_VSI
prvStartVsiCallbackTask();
#endif

vStartMlTask();

vTaskStartScheduler();
Expand Down Expand Up @@ -277,3 +294,38 @@ int main( void )
*pulTimerTaskStackSize = ( uint32_t ) configTIMER_TASK_STACK_DEPTH;
}
#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */

#ifdef AUDIO_VSI
void vVsiCallbackTask( void * arg )
{
( void ) arg;

while( 1 )
{
( void ) ulTaskNotifyTake( pdTRUE, portMAX_DELAY );

if( ( ulVsiEvent & ARM_SAI_EVENT_RECEIVE_COMPLETE ) && ( pxOnVsiEvent ) )
{
pxOnVsiEvent( pvVsiContext );
}

if( ulVsiEvent & ARM_SAI_EVENT_RX_OVERFLOW )
{
LogError( ( "VSI Receive Overflow Error \r\n" ) );
}
}
}

static void prvStartVsiCallbackTask( void )
{
if( xTaskCreate( vVsiCallbackTask,
"VSI_CALLBACK_TASK",
appCONFIG_VSI_CALLBACK_TASK_STACK_SIZE,
NULL,
appCONFIG_VSI_CALLBACK_TASK_PRIORITY,
&xVsiTaskHandle ) != pdPASS )
{
LogError( ( "Failed to create Vsi Callback Task\r\n" ) );
}
}
#endif /* ifdef AUDIO_VSI */
38 changes: 18 additions & 20 deletions applications/keyword_detection/ml_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,10 @@ __attribute__((section(".bss.NoInit.vsi_audio_buffer"))) __attribute__((aligned(
int16_t shared_audio_buffer[AUDIO_BUFFER_SIZE / 2];
const int kAudioSampleFrequency = 16000;

/* Audio events definitions */
#define SEND_COMPLETED_Pos 0U /* Event: Send complete bit position */
#define RECEIVE_COMPLETED_Pos 1U /* Event: Receive complete bit position */
#define TX_UNDERFLOW_Pos 2U /* Event: Tx underflow bit position */
#define RX_OVERFLOW_Pos 3U /* Event: Rx overflow bit position */
#define FRAME_ERROR_Pos 4U /* Event: Frame error bit position */
#define SEND_COMPLETE_Msk (1UL << SEND_COMPLETED_Pos) /* Event: Send complete Mask */
#define RECEIVE_COMPLETE_Msk (1UL << RECEIVE_COMPLETED_Pos) /* Event: Receive complete Mask */
#define TX_UNDERFLOW_Msk (1UL << TX_UNDERFLOW_Pos) /* Event: Tx underflow Mask */
#define RX_OVERFLOW_Msk (1UL << RX_OVERFLOW_Pos) /* Event: Rx overflow Mask */
#define FRAME_ERROR_Msk (1UL << FRAME_ERROR_Pos) /* Event: Frame error Mask */

extern ARM_DRIVER_SAI Driver_SAI0;
extern TaskHandle_t xVsiTaskHandle;

uint32_t ulVsiEvent;

#else /* !defined(AUDIO_VSI) */

Expand Down Expand Up @@ -317,8 +308,8 @@ arm::app::ApplicationContext caseContext;

extern "C" {
// Audio driver data
void (*event_fn)(void *);
void *event_ptr = nullptr;
void (*pxOnVsiEvent)(void *);
void *pvVsiContext = nullptr;
}

// Audio driver callback function for event management
Expand All @@ -327,11 +318,18 @@ void *event_ptr = nullptr;
// to use logging calls inside the ISR.
static void prvArmSaiSignalEvent(uint32_t event)
{
if ((event & RECEIVE_COMPLETE_Msk) == ARM_SAI_EVENT_RECEIVE_COMPLETE) {
if (event_fn) {
event_fn(event_ptr);
}
if(xVsiTaskHandle == NULL)
{
LogError( ( "VSI Task is not created\r\n" ) );
return;
}

BaseType_t xHigherPriorityTaskWoken = pdFALSE;
ulVsiEvent = event;

vTaskNotifyGiveFromISR( xVsiTaskHandle, &xHigherPriorityTaskWoken );

portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

static int prvAudioDrvSetup(void (*event_handler)(void *), void *event_handler_ptr)
Expand Down Expand Up @@ -364,8 +362,8 @@ static int prvAudioDrvSetup(void (*event_handler)(void *), void *event_handler_p
return -1;
}

event_fn = event_handler;
event_ptr = event_handler_ptr;
pxOnVsiEvent = event_handler;
pvVsiContext = event_handler_ptr;

return 0;
}
Expand Down
7 changes: 6 additions & 1 deletion applications/speech_recognition/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ endif()

set(ML_INFERENCE_ENGINE "ETHOS" CACHE STRING "Machine Learning inference engine (ETHOS)")

set(AUDIO_SOURCE "ROM" CACHE STRING "Source of audio data (ROM)")
set(AUDIO_SOURCE "ROM" CACHE STRING "Source of audio data (ROM | VSI)")

# From: ota-for-aws-iot-embedded-sdk/source/include/ota_appversion32.h
# struct version
Expand Down Expand Up @@ -164,6 +164,11 @@ if(${AUDIO_SOURCE} STREQUAL "ROM")
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)
elseif(${AUDIO_SOURCE} STREQUAL "VSI")
target_compile_definitions(speech-recognition
PRIVATE
AUDIO_VSI
)
endif()

if (${ML_INFERENCE_ENGINE} STREQUAL "ETHOS")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
#define appCONFIG_BLINK_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE )
#define appCONFIG_BLINK_TASK_PRIORITY ( tskIDLE_PRIORITY )

#define appCONFIG_VSI_CALLBACK_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE )
#define appCONFIG_VSI_CALLBACK_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )


/** @brief Increase backoff algorithm timeout by 8 seconds when device advisor
Expand Down
Loading
Loading