diff --git a/.github/workflows/build-board-custom-fork.yml b/.github/workflows/build-board-custom-fork.yml new file mode 100644 index 00000000000..efd7eb6755d --- /dev/null +++ b/.github/workflows/build-board-custom-fork.yml @@ -0,0 +1,135 @@ +name: Build board (custom) + +on: + workflow_dispatch: + inputs: + board: + description: 'Board: Found in ports/*/boards/[board_id]' + required: true + type: string + version: + description: 'Version: Can be a tag or a commit (>=8.1.0)' + required: false + default: latest + type: string + language: + description: 'Language: Found in locale/[language].po' + required: false + default: en_US + type: string + flags: + description: 'Flags: Build flags (e.g. CIRCUITPY_WIFI=1)' + required: false + type: string + branch: + description: 'Branch (only if Version="latest")' + required: false + default: 'main' + type: string + debug: + description: 'Make a debug build' + required: false + default: false + type: boolean + +run-name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }} + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - name: Set up repository + run: | + git clone --filter=tree:0 "https://github.com/${{ github.repository }}.git" "$GITHUB_WORKSPACE" + - name: Fetch upstream tags + run: | + cd "$GITHUB_WORKSPACE" + git remote add upstream https://github.com/adafruit/circuitpython.git + git fetch upstream --tags + - name: Checkout head / tag + env: + TAG: ${{ inputs.version == 'latest' && 'HEAD' || inputs.version }} + run: | + git checkout "$TAG" + - name: fork compatibility + if: github.repository_owner != 'adafruit' + env: + REPO: ${{ github.repository }} + run: | + git remote add fork "https://github.com/$REPO.git" + git fetch fork --filter=tree:0 + - name: branch compatibility + if: inputs.branch != 'main' && inputs.version == 'latest' && github.repository_owner == 'adafruit' + env: + BRANCH: ${{ inputs.branch }} + run: | + git checkout "$BRANCH" + - name: branch compatibility (fork) + if: inputs.branch != '' && inputs.version == 'latest' && github.repository_owner != 'adafruit' + env: + BRANCH: ${{ inputs.branch }} + run: | + git checkout -b fork-branch "fork/$BRANCH" + - name: Set up identifier + if: inputs.debug || inputs.flags != '' + run: | + > custom-build && git add custom-build + - name: Set up python + uses: actions/setup-python@v6 + with: + python-version: 3.x + - name: Board to port + id: board-to-port + run: | + PORT=$(python tools/board_to_port.py "${{ inputs.board }}") + echo "port=$PORT" >> $GITHUB_OUTPUT + shell: bash + - name: Set up port + id: set-up-port + uses: ./.github/actions/deps/ports + with: + board: ${{ inputs.board }} + port: ${{ steps.board-to-port.outputs.port }} + - name: Set up submodules + id: set-up-submodules + uses: ./.github/actions/deps/submodules + with: + action: cache + target: ${{ inputs.board }} + - name: Set up external + uses: ./.github/actions/deps/external + with: + action: cache + port: ${{ steps.board-to-port.outputs.port }} + - name: Set up mpy-cross + if: steps.set-up-submodules.outputs.frozen == 'True' + uses: ./.github/actions/mpy_cross + with: + cp-version: ${{ steps.set-up-submodules.outputs.version }} + download: false + - name: Versions + run: | + python py/version.py + gcc --version + python3 --version + cmake --version || true + ninja --version || true + aarch64-none-elf-gcc --version || true + arm-none-eabi-gcc --version || true + xtensa-esp32-elf-gcc --version || true + riscv32-esp-elf-gcc --version || true + riscv64-unknown-elf-gcc --version || true + mkfs.fat --version || true + - name: Build board + env: + TRANSLATION: ${{ inputs.language }} + BOARD: ${{ inputs.board }} + FLAGS: ${{ inputs.flags }} + DEBUG: ${{ inputs.debug && '1' || '0' }} + run: make -j4 $FLAGS BOARD="$BOARD" DEBUG=$DEBUG TRANSLATION="$TRANSLATION" + working-directory: ports/${{ steps.board-to-port.outputs.port }} + - name: Upload artifact + uses: actions/upload-artifact@v7 + with: + name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }} + path: ports/${{ steps.board-to-port.outputs.port }}/build-${{ inputs.board }}/firmware.* diff --git a/ports/nordic/common-hal/_bleio/Adapter.c b/ports/nordic/common-hal/_bleio/Adapter.c index 2ca9df89710..c785471df72 100644 --- a/ports/nordic/common-hal/_bleio/Adapter.c +++ b/ports/nordic/common-hal/_bleio/Adapter.c @@ -119,7 +119,7 @@ static uint32_t ble_stack_enable(void) { ble_conf.conn_cfg.params.gap_conn_cfg.conn_count = BLEIO_TOTAL_CONNECTION_COUNT; // Event length here can influence throughput so perhaps make multiple connection profiles // available. - ble_conf.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT; + ble_conf.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_CODED_PHY_MIN; err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_conf, sd_ram_end); if (err_code != NRF_SUCCESS) { return err_code; @@ -296,6 +296,39 @@ static bool adapter_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { break; } + case BLE_GAP_EVT_PHY_UPDATE: { + ble_gap_evt_phy_update_t *phy = + &ble_evt->evt.gap_evt.params.phy_update; + + mp_printf(&mp_plat_print, + "PHY UPDATE: status=%d TX=%d RX=%d\n", + phy->status, + phy->tx_phy, + phy->rx_phy); + + break; + } + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { + ble_gap_phys_t phys = { + .tx_phys = BLE_GAP_PHY_CODED, + .rx_phys = BLE_GAP_PHY_CODED, + }; + + uint32_t err_code = sd_ble_gap_phy_update( + ble_evt->evt.gap_evt.conn_handle, + &phys); + + if (err_code != NRF_SUCCESS) { + mp_raise_bleio_BluetoothError( + MP_ERROR_TEXT("sd_ble_gap_phy_update failed in event handler")); + } + + mp_printf(&mp_plat_print, + "PHY UPDATE REQUEST in event handler returned 0x%04lx, handle=%d\n", + err_code, ble_evt->evt.gap_evt.conn_handle); + + break; + } default: // For debugging. @@ -551,11 +584,11 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t } ble_gap_scan_params_t scan_params = { - .extended = extended, + .extended = true, .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS) + 0.5f, .timeout = nrf_timeout, .window = SEC_TO_UNITS(window, UNIT_0_625_MS) + 0.5f, - .scan_phys = BLE_GAP_PHY_1MBPS, + .scan_phys = BLE_GAP_PHY_CODED, .active = active }; @@ -620,9 +653,10 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre _convert_address(address, &addr); ble_gap_scan_params_t scan_params = { + .extended = true, .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), - .scan_phys = BLE_GAP_PHY_1MBPS, + .scan_phys = BLE_GAP_PHY_CODED, // timeout of 0 means no timeout .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS) + 0.5f, }; @@ -640,6 +674,14 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM); + if (err_code != NRF_SUCCESS) { + mp_raise_bleio_BluetoothError( + MP_ERROR_TEXT("sd_ble_gap_connect failed")); + } + + mp_printf(&mp_plat_print, + "CONNECT returned 0x%04lx\n", err_code); + if (err_code != NRF_SUCCESS) { ble_drv_remove_event_handler(connect_on_ble_evt, &event_info); check_nrf_error(err_code); @@ -670,10 +712,17 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre // Negotiate for better PHY, larger MTU and data lengths since we are the central. // The peer may decline, which is its prerogative. ble_gap_phys_t const phys = { - .rx_phys = BLE_GAP_PHY_AUTO, - .tx_phys = BLE_GAP_PHY_AUTO, + .rx_phys = BLE_GAP_PHY_CODED, + .tx_phys = BLE_GAP_PHY_CODED, }; - sd_ble_gap_phy_update(conn_handle, &phys); + uint32_t update_err_code = sd_ble_gap_phy_update(conn_handle, &phys); + if (update_err_code != NRF_SUCCESS) { + mp_raise_bleio_BluetoothError( + MP_ERROR_TEXT("sd_ble_gap_phy_update failed")); + } + mp_printf(&mp_plat_print, + "PHY UPDATE REQUEST returned 0x%04lx, handle=%d\n", + update_err_code, conn_handle); // The MTU size passed here has to match the value passed in the BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST // event handler in Connection.c, per the SD doc: // "The value must be equal to Server RX MTU size given in @@ -714,7 +763,7 @@ static bool advertising_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { switch (ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: // Connecting also stops an advertisement. // Set the tx_power for the connection higher than the advertisement. - sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, ble_evt->evt.gap_evt.conn_handle, 0); + sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, ble_evt->evt.gap_evt.conn_handle, 3); common_hal_bleio_adapter_stop_advertising(self); return false; break; @@ -754,8 +803,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, timeout = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED; } uint32_t err_code; - bool extended = advertising_data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX || - scan_response_data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX; + bool extended = true; uint8_t adv_type; ble_gap_addr_t *peer = NULL; @@ -816,7 +864,8 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, .properties.type = adv_type, .duration = SEC_TO_UNITS(timeout, UNIT_10_MS), .filter_policy = BLE_GAP_ADV_FP_ANY, - .primary_phy = BLE_GAP_PHY_1MBPS, + .primary_phy = BLE_GAP_PHY_CODED, + .secondary_phy = BLE_GAP_PHY_CODED, .p_peer_addr = peer, }; @@ -841,7 +890,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, ble_drv_add_event_handler_entry(&self->advertising_handler_entry, advertising_on_ble_evt, self); - err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, adv_handle, tx_power); + err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, adv_handle, 3); if (err_code != NRF_SUCCESS) { return err_code; }