mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-23 08:15:30 +03:00
Adding RP2350 SDK and target framework (#13988)
* Adding RP2350 SDK and target framework * Spacing * Removing board definitions
This commit is contained in:
parent
462cb05930
commit
2dd6f95aad
576 changed files with 435012 additions and 0 deletions
150
lib/main/pico-sdk/rp2_common/pico_sha256/include/pico/sha256.h
Normal file
150
lib/main/pico-sdk/rp2_common/pico_sha256/include/pico/sha256.h
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _PICO_SHA256_H
|
||||
#define _PICO_SHA256_H
|
||||
|
||||
#include "pico/time.h"
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/sha256.h"
|
||||
|
||||
/** \file pico/sha256.h
|
||||
* \defgroup pico_sha256 pico_sha256
|
||||
*
|
||||
* \brief SHA-256 Hardware Accelerated implementation
|
||||
*
|
||||
* RP2350 is equipped with a hardware accelerated implementation of the SHA-256 hash algorithm.
|
||||
* This should be much quicker than performing a SHA-256 checksum in software.
|
||||
*
|
||||
* \code
|
||||
* pico_sha256_state_t state;
|
||||
* if (pico_sha256_try_start(&state, SHA256_BIG_ENDIAN, true) == PICO_OK) {
|
||||
* sha256_result_t result;
|
||||
* pico_sha256_update(&state, some_data, sizeof(some_data));
|
||||
* pico_sha256_update(&state, some_more_data, sizeof(some_more_data));
|
||||
* pico_sha256_finish(&state, &result);
|
||||
* for (int i = 0; i < SHA256_RESULT_BYTES; i++) {
|
||||
* printf("%02x", result.bytes[i]);
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \subsection sha256_example Example
|
||||
* \addtogroup pico_sha256
|
||||
*
|
||||
* \include hello_sha256.c
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \brief SHA-256 state used by the API
|
||||
* \ingroup pico_sha256
|
||||
*/
|
||||
typedef struct pico_sha256_state {
|
||||
enum sha256_endianness endianness;
|
||||
int8_t channel;
|
||||
bool locked;
|
||||
uint8_t cache_used;
|
||||
union {
|
||||
uint32_t word;
|
||||
uint8_t bytes[4];
|
||||
} cache;
|
||||
dma_channel_config config;
|
||||
size_t total_data_size;
|
||||
} pico_sha256_state_t;
|
||||
|
||||
/*! \brief Start a SHA-256 calculation returning immediately with an error if the SHA-256 hardware is not available
|
||||
* \ingroup pico_sha256
|
||||
*
|
||||
* Initialises the hardware and state ready to start a new SHA-256 calculation.
|
||||
* Only one instance can be started at any time.
|
||||
*
|
||||
* @param state A pointer to a pico_sha256_state_t instance
|
||||
* @param endianness SHA256_BIG_ENDIAN or SHA256_LITTLE_ENDIAN for data in and data out
|
||||
* @param use_dma Set to true to use DMA internally to copy data to hardware. This is quicker at the expense of hardware DMA resources.
|
||||
* @return Returns PICO_OK if the hardware was available for use and the sha256 calculation could be started, otherwise an error is returned
|
||||
*/
|
||||
int pico_sha256_try_start(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma);
|
||||
|
||||
/*! \brief Start a SHA-256 calculation waiting for a defined period for the SHA-256 hardware to be available
|
||||
* \ingroup pico_sha256
|
||||
*
|
||||
* Initialises the hardware and state ready to start a new SHA-256 calculation.
|
||||
* Only one instance can be started at any time.
|
||||
*
|
||||
* @param state A pointer to a pico_sha256_state_t instance
|
||||
* @param endianness SHA256_BIG_ENDIAN or SHA256_LITTLE_ENDIAN for data in and data out
|
||||
* @param use_dma Set to true to use DMA internally to copy data to hardware. This is quicker at the expense of hardware DMA resources.
|
||||
* @param until How long to wait for the SHA hardware to be available
|
||||
* @return Returns PICO_OK if the hardware was available for use and the sha256 calculation could be started in time, otherwise an error is returned
|
||||
*/
|
||||
int pico_sha256_start_blocking_until(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma, absolute_time_t until);
|
||||
|
||||
/*! \brief Start a SHA-256 calculation, blocking forever waiting until the SHA-256 hardware is available
|
||||
* \ingroup pico_sha256
|
||||
*
|
||||
* Initialises the hardware and state ready to start a new SHA-256 calculation.
|
||||
* Only one instance can be started at any time.
|
||||
*
|
||||
* @param state A pointer to a pico_sha256_state_t instance
|
||||
* @param endianness SHA256_BIG_ENDIAN or SHA256_LITTLE_ENDIAN for data in and data out
|
||||
* @param use_dma Set to true to use DMA internally to copy data to hardware. This is quicker at the expense of hardware DMA resources.
|
||||
* @return Returns PICO_OK if the hardware was available for use and the sha256 calculation could be started, otherwise an error is returned
|
||||
*/
|
||||
static inline int pico_sha256_start_blocking(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma) {
|
||||
return pico_sha256_start_blocking_until(state, endianness, use_dma, at_the_end_of_time);
|
||||
}
|
||||
|
||||
/*! \brief Add byte data to be SHA-256 calculation
|
||||
* \ingroup pico_sha256
|
||||
*
|
||||
* Add byte data to be SHA-256 calculation
|
||||
* You may call this as many times as required to add all the data needed.
|
||||
* You must have called pico_sha256_try_start (or equivalent) already.
|
||||
*
|
||||
* @param state A pointer to a pico_sha256_state_t instance
|
||||
* @param data Pointer to the data to be added to the calculation
|
||||
* @param data_size_bytes Amount of data to add
|
||||
*
|
||||
* @note This function may return before the copy has completed in which case the data passed to the function must remain valid and
|
||||
* unchanged until a further call to pico_sha256_update or pico_sha256_finish. If this is not done, corrupt data may be used for the
|
||||
* SHA-256 calculation giving an unexpected result.
|
||||
*/
|
||||
void pico_sha256_update(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes);
|
||||
|
||||
/*! \brief Add byte data to be SHA-256 calculation
|
||||
* \ingroup pico_sha256
|
||||
*
|
||||
* Add byte data to be SHA-256 calculation
|
||||
* You may call this as many times as required to add all the data needed.
|
||||
* You must have called pico_sha256_try_start already.
|
||||
*
|
||||
* @param state A pointer to a pico_sha256_state_t instance
|
||||
* @param data Pointer to the data to be added to the calculation
|
||||
* @param data_size_bytes Amount of data to add
|
||||
*
|
||||
* @note This function will only return when the data passed in is no longer required, so it can be freed or changed on return.
|
||||
*/
|
||||
void pico_sha256_update_blocking(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes);
|
||||
|
||||
/*! \brief Finish the SHA-256 calculation and return the result
|
||||
* \ingroup pico_sha256
|
||||
*
|
||||
* Ends the SHA-256 calculation freeing the hardware for use by another caller.
|
||||
* You must have called pico_sha256_try_start already.
|
||||
*
|
||||
* @param state A pointer to a pico_sha256_state_t instance
|
||||
* @param out The SHA-256 checksum
|
||||
*/
|
||||
void pico_sha256_finish(pico_sha256_state_t *state, sha256_result_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
185
lib/main/pico-sdk/rp2_common/pico_sha256/sha256.c
Normal file
185
lib/main/pico-sdk/rp2_common/pico_sha256/sha256.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "hardware/sha256.h"
|
||||
#include "pico/bootrom/lock.h"
|
||||
#include "pico/sha256.h"
|
||||
#include "pico/time.h"
|
||||
|
||||
// We add one 0x80 byte, then 8 bytes for the size
|
||||
#define SHA256_PADDING_DATA_BYTES 9
|
||||
#define SHA256_BLOCK_SIZE_BYTES 64
|
||||
|
||||
bool __weak pico_sha256_lock(pico_sha256_state_t *state) {
|
||||
if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256))
|
||||
return false;
|
||||
state->locked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void __weak pico_sha256_unlock(pico_sha256_state_t *state) {
|
||||
assert(state->locked);
|
||||
bootrom_release_lock(BOOTROM_LOCK_SHA_256);
|
||||
state->locked = false;
|
||||
}
|
||||
|
||||
int pico_sha256_try_start(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma) {
|
||||
memset(state, 0, sizeof(*state));
|
||||
if (!pico_sha256_lock(state)) return PICO_ERROR_RESOURCE_IN_USE;
|
||||
state->endianness = endianness;
|
||||
if (use_dma) {
|
||||
state->channel = (int8_t)dma_claim_unused_channel(false);
|
||||
if (state->channel < 0) {
|
||||
pico_sha256_unlock(state);
|
||||
return PICO_ERROR_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
state->config = dma_channel_get_default_config(state->channel);
|
||||
channel_config_set_transfer_data_size(&state->config, DMA_SIZE_8);
|
||||
channel_config_set_read_increment(&state->config, true);
|
||||
channel_config_set_write_increment(&state->config, false);
|
||||
channel_config_set_dreq(&state->config, DREQ_SHA256);
|
||||
sha256_set_dma_size(1);
|
||||
} else {
|
||||
state->channel = -1;
|
||||
}
|
||||
sha256_err_not_ready_clear();
|
||||
sha256_set_bswap(endianness == SHA256_BIG_ENDIAN);
|
||||
sha256_start();
|
||||
state->total_data_size = 0;
|
||||
return PICO_OK;
|
||||
}
|
||||
|
||||
int pico_sha256_start_blocking_until(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma, absolute_time_t until) {
|
||||
int rc;
|
||||
do {
|
||||
rc = pico_sha256_try_start(state, endianness, use_dma);
|
||||
if (rc != PICO_ERROR_RESOURCE_IN_USE) break;
|
||||
if (time_reached(until)) {
|
||||
rc = PICO_ERROR_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void write_to_hardware(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes) {
|
||||
if (state->channel >= 0) {
|
||||
dma_channel_wait_for_finish_blocking(state->channel);
|
||||
assert(!sha256_err_not_ready());
|
||||
sha256_wait_ready_blocking();
|
||||
dma_channel_configure(
|
||||
state->channel,
|
||||
&state->config,
|
||||
sha256_get_write_addr(),
|
||||
data,
|
||||
data_size_bytes,
|
||||
true
|
||||
);
|
||||
} else {
|
||||
if (!state->cache_used && !(((uintptr_t)data)&3u)) {
|
||||
GCC_Like_Pragma("GCC diagnostic ignored \"-Wcast-align\"")
|
||||
const uint32_t *data32 = (const uint32_t *)data;
|
||||
// aligned writes
|
||||
while (data_size_bytes >= 4) {
|
||||
// write a whole word
|
||||
sha256_wait_ready_blocking();
|
||||
sha256_put_word(*data32++);
|
||||
data_size_bytes -= 4;
|
||||
}
|
||||
data = (const uint8_t *)data32;
|
||||
}
|
||||
while (data_size_bytes--) {
|
||||
state->cache.bytes[state->cache_used++] = *data++;
|
||||
if (state->cache_used == 4) {
|
||||
state->cache_used = 0;
|
||||
sha256_wait_ready_blocking();
|
||||
sha256_put_word(state->cache.word);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_internal(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes) {
|
||||
assert(state->locked);
|
||||
// must finish off the last 64 byte block first or else sha256_err_not_ready will be true
|
||||
size_t bytes_left = ((state->total_data_size + (SHA256_BLOCK_SIZE_BYTES - 1)) & ~(SHA256_BLOCK_SIZE_BYTES - 1)) - state->total_data_size;
|
||||
if (bytes_left > data_size_bytes) bytes_left = data_size_bytes;
|
||||
if (bytes_left > 0) {
|
||||
write_to_hardware(state, data, bytes_left);
|
||||
state->total_data_size += bytes_left;
|
||||
data_size_bytes -= bytes_left;
|
||||
data += bytes_left;
|
||||
}
|
||||
// Write the rest of the data
|
||||
if (data_size_bytes > 0) {
|
||||
write_to_hardware(state, data, data_size_bytes);
|
||||
state->total_data_size += data_size_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void add_zero_bytes(pico_sha256_state_t *state, size_t data_size_bytes) {
|
||||
uint32_t zero = 0;
|
||||
// todo: can be done a bit more efficiently with dma?
|
||||
assert(data_size_bytes < INT32_MAX);
|
||||
while((int32_t)data_size_bytes > 0) {
|
||||
update_internal(state, (uint8_t *)&zero, MIN(4, data_size_bytes));
|
||||
data_size_bytes -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
void pico_sha256_update(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes) {
|
||||
update_internal(state, data, data_size_bytes);
|
||||
}
|
||||
|
||||
void pico_sha256_update_blocking(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes) {
|
||||
update_internal(state, data, data_size_bytes);
|
||||
if (state->channel >= 0) {
|
||||
dma_channel_wait_for_finish_blocking(state->channel);
|
||||
}
|
||||
}
|
||||
|
||||
// write the SHA-256 padding to hardware
|
||||
static void write_padding(pico_sha256_state_t *state) {
|
||||
// Has to be a multiple of 64 bytes
|
||||
uint64_t size = (state->total_data_size + SHA256_PADDING_DATA_BYTES + (SHA256_BLOCK_SIZE_BYTES - 1)) & ~(SHA256_BLOCK_SIZE_BYTES - 1);
|
||||
const size_t user_data_size = state->total_data_size;
|
||||
const size_t padding_size_bytes = size - state->total_data_size;
|
||||
|
||||
// append a single '1' bit
|
||||
const uint8_t one_bit = 0x80;
|
||||
update_internal(state, &one_bit, 1);
|
||||
|
||||
// Zero unused padding
|
||||
add_zero_bytes(state, padding_size_bytes - SHA256_PADDING_DATA_BYTES);
|
||||
|
||||
// Add size in bits, big endian
|
||||
size = __builtin_bswap64(user_data_size * 8);
|
||||
update_internal(state, (uint8_t*)&size, sizeof(uint64_t)); // last write
|
||||
}
|
||||
|
||||
void pico_sha256_finish(pico_sha256_state_t *state, sha256_result_t *out) {
|
||||
assert(state->locked);
|
||||
// pass NULL to abandon the current hash in case of an error
|
||||
if (out) {
|
||||
write_padding(state);
|
||||
if (state->channel >= 0) {
|
||||
dma_channel_wait_for_finish_blocking(state->channel);
|
||||
assert(!sha256_err_not_ready());
|
||||
}
|
||||
sha256_wait_valid_blocking();
|
||||
sha256_get_result(out, state->endianness);
|
||||
}
|
||||
if (state->channel >= 0) {
|
||||
dma_channel_cleanup(state->channel);
|
||||
dma_channel_unclaim(state->channel);
|
||||
state->channel = -1;
|
||||
}
|
||||
pico_sha256_unlock(state);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue