kendryte-freertos-sdk/lib/freertos/include/kernel/driver.hpp

471 lines
19 KiB
C++

/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _FREERTOS_DRIVER_H
#define _FREERTOS_DRIVER_H
#include "object.hpp"
#include <gsl/span>
#include <memory>
#define MAKE_ENUM_CLASS_BITMASK_TYPE(enumName) \
static_assert(std::is_enum<enumName>::value, "enumName is not a enum."); \
constexpr enumName operator|(enumName a, enumName b) noexcept \
{ \
typedef std::underlying_type_t<enumName> underlying_type; \
return static_cast<enumName>(static_cast<underlying_type>(a) | static_cast<underlying_type>(b)); \
} \
constexpr enumName operator&(enumName a, enumName b) noexcept \
{ \
typedef std::underlying_type_t<enumName> underlying_type; \
return static_cast<enumName>(static_cast<underlying_type>(a) & static_cast<underlying_type>(b)); \
} \
constexpr enumName operator^(enumName a, enumName b) noexcept \
{ \
typedef std::underlying_type_t<enumName> underlying_type; \
return static_cast<enumName>(static_cast<underlying_type>(a) ^ static_cast<underlying_type>(b)); \
} \
constexpr enumName operator~(enumName a) noexcept \
{ \
typedef std::underlying_type_t<enumName> underlying_type; \
return static_cast<enumName>(~static_cast<underlying_type>(a)); \
} \
constexpr enumName &operator|=(enumName &a, enumName b) noexcept \
{ \
return a = (a | b); \
} \
constexpr enumName &operator&=(enumName &a, enumName b) noexcept \
{ \
return a = (a & b); \
} \
constexpr enumName &operator^=(enumName &a, enumName b) noexcept \
{ \
return a = (a ^ b); \
}
namespace sys
{
MAKE_ENUM_CLASS_BITMASK_TYPE(file_access_t);
MAKE_ENUM_CLASS_BITMASK_TYPE(file_mode_t);
MAKE_ENUM_CLASS_BITMASK_TYPE(socket_message_flag_t);
class errno_exception : public std::runtime_error
{
public:
explicit errno_exception(const char *msg, int code) noexcept
: runtime_error(msg), code_(code)
{
}
int code() const noexcept
{
return code_;
}
private:
int code_;
};
class object_access : public virtual object
{
public:
virtual void open() = 0;
virtual void close() = 0;
};
template <class T>
struct object_accessor
{
public:
object_accessor() = default;
object_accessor(object_accessor &) = delete;
object_accessor &operator=(object_accessor &other) = delete;
template <class U>
object_accessor(object_accessor<U> &&other)
: obj_(std::move(other.obj_))
{
}
explicit object_accessor(object_ptr<T> &&obj) noexcept
: obj_(std::move(obj))
{
}
~object_accessor()
{
if (obj_)
std::move(obj_)->close();
}
operator bool() const noexcept
{
return obj_;
}
object_accessor &operator=(object_accessor &&other) noexcept
{
if (obj_)
obj_->close();
obj_ = std::move(other.obj_);
return *this;
}
T *operator->() const noexcept
{
return obj_.get();
}
template <class U>
bool is() const
{
return obj_.template is<U>();
}
template <class U>
object_accessor<U> move_as()
{
auto obj = obj_.template as<U>();
if (obj_ && !obj)
throw std::bad_cast();
obj_.reset();
return object_accessor<U>(std::move(obj));
}
template <class U>
U *as()
{
auto obj = obj_.template as<U>();
if (obj)
return obj.get();
return nullptr;
}
object_ptr<T> get_object() const noexcept
{
return obj_;
}
void reset() noexcept
{
if (obj_)
std::move(obj_)->close();
}
private:
template <class U>
friend class object_accessor;
object_ptr<T> obj_;
};
template <typename T>
object_accessor<T> make_accessor(object_ptr<T> obj)
{
obj->open();
return object_accessor<T>(std::move(obj));
}
class driver : public virtual object, public virtual object_access
{
public:
virtual void install() = 0;
};
typedef struct tag_driver_registry
{
const char *name;
object_ptr<driver> driver_ptr;
} driver_registry_t;
class uart_driver : public driver
{
public:
virtual void config(uint32_t baud_rate, uint32_t databits, uart_stopbits_t stopbits, uart_parity_t parity) = 0;
virtual int read(gsl::span<uint8_t> buffer) = 0;
virtual int write(gsl::span<const uint8_t> buffer) = 0;
};
class gpio_driver : public driver
{
public:
virtual uint32_t get_pin_count() = 0;
virtual void set_drive_mode(uint32_t pin, gpio_drive_mode_t mode) = 0;
virtual void set_pin_edge(uint32_t pin, gpio_pin_edge_t edge) = 0;
virtual void set_on_changed(uint32_t pin, gpio_on_changed_t callback, void *userdata) = 0;
virtual gpio_pin_value_t get_pin_value(uint32_t pin) = 0;
virtual void set_pin_value(uint32_t pin, gpio_pin_value_t value) = 0;
};
class i2c_device_driver : public driver
{
public:
virtual double set_clock_rate(double clock_rate) = 0;
virtual int read(gsl::span<uint8_t> buffer) = 0;
virtual int write(gsl::span<const uint8_t> buffer) = 0;
virtual int transfer_sequential(gsl::span<const uint8_t> write_buffer, gsl::span<uint8_t> read_buffer) = 0;
};
class i2c_driver : public driver
{
public:
virtual object_ptr<i2c_device_driver> get_device(uint32_t slave_address, uint32_t address_width) = 0;
virtual void config_as_slave(uint32_t slave_address, uint32_t address_width, const i2c_slave_handler_t &handler) = 0;
virtual double slave_set_clock_rate(double clock_rate) = 0;
};
class i2s_driver : public driver
{
public:
virtual void config_as_render(const audio_format_t &format, size_t delay_ms, i2s_align_mode_t align_mode, uint32_t channels_mask) = 0;
virtual void config_as_capture(const audio_format_t &format, size_t delay_ms, i2s_align_mode_t align_mode, uint32_t channels_mask) = 0;
virtual void get_buffer(gsl::span<uint8_t> &buffer, size_t &frames) = 0;
virtual void release_buffer(uint32_t frames) = 0;
virtual void start() = 0;
virtual void stop() = 0;
};
class spi_device_driver : public driver
{
public:
virtual void config_non_standard(uint32_t instruction_length, uint32_t address_length, uint32_t wait_cycles, spi_inst_addr_trans_mode_t trans_mode) = 0;
virtual double set_clock_rate(double clock_rate) = 0;
virtual int read(gsl::span<uint8_t> buffer) = 0;
virtual int write(gsl::span<const uint8_t> buffer) = 0;
virtual int transfer_full_duplex(gsl::span<const uint8_t> write_buffer, gsl::span<uint8_t> read_buffer) = 0;
virtual int transfer_sequential(gsl::span<const uint8_t> write_buffer, gsl::span<uint8_t> read_buffer) = 0;
virtual void fill(uint32_t instruction, uint32_t address, uint32_t value, size_t count) = 0;
};
class spi_driver : public driver
{
public:
virtual object_ptr<spi_device_driver> get_device(spi_mode_t mode, spi_frame_format_t frame_format, uint32_t chip_select_mask, uint32_t data_bit_length) = 0;
virtual void slave_config(uint32_t data_bit_length, const spi_slave_handler_t &handler) = 0;
};
class dvp_driver : public driver
{
public:
virtual uint32_t get_output_num() = 0;
virtual void config(uint32_t width, uint32_t height, bool auto_enable) = 0;
virtual void enable_frame() = 0;
virtual void set_signal(dvp_signal_type_t type, bool value) = 0;
virtual void set_output_enable(uint32_t index, bool enable) = 0;
virtual void set_output_attributes(uint32_t index, video_format_t format, void *output_buffer) = 0;
virtual void set_frame_event_enable(dvp_frame_event_t event, bool enable) = 0;
virtual void set_on_frame_event(dvp_on_frame_event_t callback, void *userdata) = 0;
virtual double xclk_set_clock_rate(double clock_rate) = 0;
};
class sccb_device_driver : public driver
{
public:
virtual uint8_t read_byte(uint16_t reg_address) = 0;
virtual void write_byte(uint16_t reg_address, uint8_t value) = 0;
};
class sccb_driver : public driver
{
public:
virtual object_ptr<sccb_device_driver> get_device(uint32_t slave_address, uint32_t reg_address_width) = 0;
};
class fft_driver : public driver
{
public:
virtual void complex_uint16(uint16_t shift, fft_direction_t direction, const uint64_t *input, size_t point_num, uint64_t *output) = 0;
};
class aes_driver : public driver
{
public:
virtual void aes_ecb128_hard_decrypt(gsl::span<const uint8_t> input_key, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_ecb128_hard_encrypt(gsl::span<const uint8_t> input_key, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_ecb192_hard_decrypt(gsl::span<const uint8_t> input_key, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_ecb192_hard_encrypt(gsl::span<const uint8_t> input_key, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_ecb256_hard_decrypt(gsl::span<const uint8_t> input_key, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_ecb256_hard_encrypt(gsl::span<const uint8_t> input_key, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_cbc128_hard_decrypt(cbc_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_cbc128_hard_encrypt(cbc_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_cbc192_hard_decrypt(cbc_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_cbc192_hard_encrypt(cbc_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_cbc256_hard_decrypt(cbc_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_cbc256_hard_encrypt(cbc_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
virtual void aes_gcm128_hard_decrypt(gcm_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data, gsl::span<uint8_t> gcm_tag) = 0;
virtual void aes_gcm128_hard_encrypt(gcm_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data, gsl::span<uint8_t> gcm_tag) = 0;
virtual void aes_gcm192_hard_decrypt(gcm_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data, gsl::span<uint8_t> gcm_tag) = 0;
virtual void aes_gcm192_hard_encrypt(gcm_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data, gsl::span<uint8_t> gcm_tag) = 0;
virtual void aes_gcm256_hard_decrypt(gcm_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data, gsl::span<uint8_t> gcm_tag) = 0;
virtual void aes_gcm256_hard_encrypt(gcm_context_t &context, gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data, gsl::span<uint8_t> gcm_tag) = 0;
};
class sha256_driver : public driver
{
public:
virtual void sha256_hard_calculate(gsl::span<const uint8_t> input_data, gsl::span<uint8_t> output_data) = 0;
};
class timer_driver : public driver
{
public:
virtual size_t set_interval(size_t nanoseconds) = 0;
virtual void set_on_tick(timer_on_tick_t on_tick, void *userdata) = 0;
virtual void set_enable(bool enable) = 0;
};
class pwm_driver : public driver
{
public:
virtual uint32_t get_pin_count() = 0;
virtual double set_frequency(double frequency) = 0;
virtual double set_active_duty_cycle_percentage(uint32_t pin, double duty_cycle_percentage) = 0;
virtual void set_enable(uint32_t pin, bool enable) = 0;
};
class wdt_driver : public driver
{
public:
virtual void set_response_mode(wdt_response_mode_t mode) = 0;
virtual size_t set_timeout(size_t nanoseconds) = 0;
virtual void set_on_timeout(wdt_on_timeout_t handler, void *userdata) = 0;
virtual void restart_counter() = 0;
virtual void set_enable(bool enable) = 0;
};
class rtc_driver : public driver
{
public:
virtual void get_datetime(struct tm &datetime) = 0;
virtual void set_datetime(const struct tm &datetime) = 0;
};
class custom_driver : public driver
{
public:
virtual int control(uint32_t control_code, gsl::span<const uint8_t> write_buffer, gsl::span<uint8_t> read_buffer) = 0;
};
/* ===== internal drivers ======*/
void kernel_iface_pic_on_irq(uint32_t irq);
class pic_driver : public driver
{
public:
virtual void set_irq_enable(uint32_t irq, bool enable) = 0;
virtual void set_irq_priority(uint32_t irq, uint32_t priority) = 0;
};
class dma_driver : public driver
{
public:
virtual void set_select_request(uint32_t request) = 0;
virtual void config(uint32_t priority) = 0;
virtual void transmit_async(const volatile void *src, volatile void *dest, bool src_inc, bool dest_inc, size_t element_size, size_t count, size_t burst_size, SemaphoreHandle_t completion_event) = 0;
virtual void loop_async(const volatile void **srcs, size_t src_num, volatile void **dests, size_t dest_num, bool src_inc, bool dest_inc, size_t element_size, size_t count, size_t burst_size, dma_stage_completion_handler_t stage_completion_handler, void *stage_completion_handler_data, SemaphoreHandle_t completion_event, int *stop_signal) = 0;
};
class dmac_driver : public driver
{
public:
};
class block_storage_driver : public driver
{
public:
virtual uint32_t get_rw_block_size() = 0;
virtual uint32_t get_blocks_count() = 0;
virtual void read_blocks(uint32_t start_block, uint32_t blocks_count, gsl::span<uint8_t> buffer) = 0;
virtual void write_blocks(uint32_t start_block, uint32_t blocks_count, gsl::span<const uint8_t> buffer) = 0;
};
class filesystem_file : public virtual object_access
{
public:
virtual size_t read(gsl::span<uint8_t> buffer) = 0;
virtual size_t write(gsl::span<const uint8_t> buffer) = 0;
virtual fpos_t get_position() = 0;
virtual void set_position(fpos_t position) = 0;
virtual uint64_t get_size() = 0;
virtual void flush() = 0;
};
class network_adapter_handler
{
public:
virtual void notify_input() = 0;
};
class network_adapter_driver : public driver
{
public:
virtual void set_handler(network_adapter_handler *handler) = 0;
virtual mac_address_t get_mac_address() = 0;
virtual void disable_rx(void) = 0;
virtual void enable_rx(void) = 0;
virtual bool interface_check() = 0;
virtual bool is_packet_available() = 0;
virtual void reset(SemaphoreHandle_t interrupt_event) = 0;
virtual void begin_send(size_t length) = 0;
virtual void send(gsl::span<const uint8_t> buffer) = 0;
virtual void end_send() = 0;
virtual size_t begin_receive() = 0;
virtual void receive(gsl::span<uint8_t> buffer) = 0;
virtual void end_receive() = 0;
};
class network_socket : public virtual custom_driver, public virtual object_access
{
public:
virtual object_accessor<network_socket> accept(socket_address_t *remote_address) = 0;
virtual void bind(const socket_address_t &address) = 0;
virtual void connect(const socket_address_t &address) = 0;
virtual void listen(uint32_t backlog) = 0;
virtual void shutdown(socket_shutdown_t how) = 0;
virtual size_t send(gsl::span<const uint8_t> buffer, socket_message_flag_t flags) = 0;
virtual size_t receive(gsl::span<uint8_t> buffer, socket_message_flag_t flags) = 0;
virtual size_t send_to(gsl::span<const uint8_t> buffer, socket_message_flag_t flags, const socket_address_t &to) = 0;
virtual size_t receive_from(gsl::span<uint8_t> buffer, socket_message_flag_t flags, socket_address_t *from) = 0;
virtual size_t read(gsl::span<uint8_t> buffer) = 0;
virtual size_t write(gsl::span<const uint8_t> buffer) = 0;
virtual int fcntl(int cmd, int val) = 0;
virtual void select(fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout) = 0;
};
extern driver_registry_t g_hal_drivers[];
extern driver_registry_t g_dma_drivers[];
extern driver_registry_t g_system_drivers[];
/**
* @brief Install a driver
* @param[in] name Specify the path to access it later
* @param[in] type The type of driver
*
* @return result
* - NULL Fail
* - other The driver registry
*/
driver_registry_t *system_install_driver(const char *name, object_ptr<driver> driver);
object_accessor<driver> system_open_driver(const char *name);
handle_t system_alloc_handle(object_accessor<object_access> object);
object_accessor<object_access> &system_handle_to_object(handle_t file);
}
#endif /* _FREERTOS_DRIVER_H */