diff --git a/docs/html/API/sys/cronalarms.html b/docs/html/API/sys/cronalarms.html deleted file mode 100644 index 0cb66c90a..000000000 --- a/docs/html/API/sys/cronalarms.html +++ /dev/null @@ -1,266 +0,0 @@ - - - - -
- - - - -GAP支持的角色:Peripheral与Central,Observer与Broadcaster
GATT支持的角色:Server与Client
支持配对包括蓝牙4.2中的安全连接特性
支持永久存储蓝牙特定的设置和数据
支持Relay, Friend Node, Low-Power Node (LPN) and GATT Proxy角色
支持两种Provisioning bearers(PB-ADV & PB-GATT)
--- --
Host:这一层位于应用程序之下,由多个(非实时)网络和传输协议组成,使应用程序能够以标准和互操作的方式与对等设备通信。
Controller:控制器实现了链路层(LE LL),这是一种低层次的实时协议,它与无线电硬件一起提供了空中通信的标准互操作。LL处理包的接收和传输,保证数据的传递,并处理所有LL控制程序。
Radio Hardware:实现所需的模拟和数字基带功能块,允许链路层固件在频谱的2.4GHz波段发送和接收。
--- --
HCI:Host与controller接口
L2CAP:逻辑链路控制和适应协议
GATT:通用属性配置层(Generic Attribute Profile)
GAP:通用访问配置层(Generic Access Profile)
SMP:安全管理器配置层(Security Manager Specification)
相关硬件和基础服务初始化
设置广播参数:广播数据,广播间隔,扫描回应等参数或者数据
设置Profile:添加从机服务、特征值,还有设置回调函数用于接收主机数据等
设置配对参数(可选)
启动广播,开始运行
等待相关事件,及事件处理,例如收到主机发来的数据,被链接等等
相关硬件和基础服务初始化
设置扫描参数
设置连接参数
设置配对参数(可选)
启动协议栈,开始运行
等待相关事件,及事件处理,例如扫描事件,从机的Notify事件等等。
API介绍
void ble_controller_init(uint8_t task_priority)
/**
-* function controller层初始化
-* @param[in] task_priority: 任务优先级
-* @return 空
-*/
-
int hci_driver_init(void)
/**
-* function HCI接口驱动初始化
-* @param[in] 空
-* @return 0:成功,!=0:失败
-*/
-
int bt_enable(bt_ready_cb_t cb)
/**
-* function Ble使能
-* @param[in] cb:如果成功调用回调函数
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_adv_start(const struct bt_le_adv_param *param,const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len)
/**
-* function 开启BLE广播
-*
-* @param[in] param: 指向广播配置参数指针
-* @param[in] ad: 指向广播包中数据指针
-* @param[in] ad_len: 广播包中数据的长度
-* @param[in] sd: 指向扫描响应包数据指针
-* @param[in] sd_len: 扫描响应包数据的长度
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_adv_update_data(const struct bt_data *ad, size_t ad_len,const struct bt_data *sd, size_t sd_len)
/**
-* function 更新BLE广播数据
-* @param[in] ad: 指向广播包中数据指针
-* @param[in] ad_len: 广播包中数据的长度
-* @param[in] sd: 指向扫描响应包数据指针
-* @param[in] sd_len: 扫描响应包数据的长度
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_adv_stop(void)
/**
-* function 停止BLE广播
-* @param[in] 空
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb)
/**
-* function 开启BLE扫描
-* @param[in] param: 指向扫描参数的指针
-* @param[in] cb: 扫描回调函数
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_scan_stop(void)
/**
-* function 停止BLE扫描
-* @param[in] 空
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_whitelist_add(const bt_addr_le_t *addr)
/**
-* function 通过地址添加设备到白名单列表中
-* @param[in] addr:指向需要添加设备地址的指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_whitelist_rem(const bt_addr_le_t *addr)
/**
-* function 从白名单列表中移除设备
-* @param[in] addr:指向需要移除设备地址的指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_whitelist_clear(void)
/**
-* function 清除白名单列表
-* @param[in] 空
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_set_chan_map(u8_t chan_map[5])
/**
-* function 设置(LE)通道映射
-* @param[in] chan_map:通道数组
-* @return 0:成功,!=0:失败
-*/
-
int bt_unpair(u8_t id, const bt_addr_le_t *addr)
/**
-* function 清除配对信息
-* @param[in] id: 本地标识(大多只是默认的BT ID)
-* @param[in] addr: 远端设备地址,NULL或者BT_ADDR_LE_ANY清除所有远端设备
-* @return 0:成功,!=0:失败
-*/
-
int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info)
/**
-* function 获取当前连接设备的信息
-* @param[in] conn: 指向当前连接的指针
-* @param[in] info: 指向当前连接设备信息的指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_conn_get_remote_dev_info(struct bt_conn_info *info)
/**
-* function 获取已连接设备的信息
-* @param[in] info: 指向当前连接设备信息的指针
-* @return 已连接设备的个数
-*/
-
int bt_conn_le_param_update(struct bt_conn *conn,const struct bt_le_conn_param *param)
/**
-* function 更新连接参数
-* @param[in] conn: 指向当前连接的指针
-* @param[in] param: 指向连接参数的指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_conn_disconnect(struct bt_conn *conn, u8_t reason)
/**
-* function 断开当前连接
-* @param[in] conn: 指向当前连接的指针
-* @param[in] reason:断开当前连接的原因
-* @return 0:成功,!=0:失败
-*/
-
struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer,const struct bt_le_conn_param *param)
/**
-* function 创建连接
-* @param[in] peer: 需要连接设备地址的指针
-* @param[in] param: 指向连接参数指针
-* @return 成功:有效的连接对象,否则失败
-*/
-
int bt_conn_create_auto_le(const struct bt_le_conn_param *param)
/**
-* function 自动创建连接白名单列表中的设备
-* @param[in] param: 指向连接参数指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_conn_create_auto_stop(void)
/**
-* function 停止自动创建连接白名单列表中的设备
-* @param[in] 空
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_set_auto_conn(const bt_addr_le_t *addr,const struct bt_le_conn_param *param)
/**
-* function 自动创建连接远端设备
-* @param[in] addr: 远端设备地址指针
-* @param[in] param: 指向连接参数指针
-* @return 0:成功,!=0:失败
-*/
-
struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer,const struct bt_le_adv_param *param)
/**
-* function 发起定向的广播包给远端设备
-* @param[in] peer: 远端设备地址指针
-* @param[in] param: 指向广播参数的指针
-* @return 成功:有效的连接对象,否则失败
-*/
-
int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec)
/**
-* function 设置连接安全等级
-* @param[in] conn: 指向连接对象的指针
-* @param[in] sec: 安全等级
-* @return 0:成功,!=0:失败
-*/
-
bt_security_t bt_conn_get_security(struct bt_conn *conn)
/**
-* function 获取当前连接的安全等级
-* @param[in] conn: 指向连接对象的指针
-* @return 安全级别
-*/
-
u8_t bt_conn_enc_key_size(struct bt_conn *conn)
/**
-* function 获取当前连接的加密key的大小
-* @param[in] conn: 指向连接对象的指针
-* @return 加密key的大小
-*/
-
void bt_conn_cb_register(struct bt_conn_cb *cb)
/**
-* function 注册连接回调函数
-* @param[in] cb: 连接回调函数
-* @return 空
-*/
-
void bt_set_bondable(bool enable)
/**
-* function 设置/清除SMP配对请求/响应数据认证需求中的绑定标志
-* @param[in] enable: 1,使能,0:不使能
-* @return 空
-*/
-
int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb)
/**
-* function 注册认证回调函数
-* @param[in] cb: 回调函数指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey)
/**
-* function 用密钥回复对方
-* @param[in] conn: 连接对象指针
-* @param[in] passkey: 输入的密钥
-* @return 0:成功,!=0:失败
-*/
-
int bt_conn_auth_cancel(struct bt_conn *conn)
/**
-* function 取消认证过程
-* @param[in] conn: 连接对象指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_conn_auth_passkey_confirm(struct bt_conn *conn)
/**
-* function 如果密码匹配,回复对方
-* @param[in] conn: 连接对象的指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin)
/**
-* function 用PIN码进行回复对方
-* @param[in] conn: 连接对象的指针
-* @param[in] pin: PIN码的指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_le_read_rssi(u16_t handle,int8_t *rssi)
/**
-* function 读取对方RSSI值
-* @param[in] handle:连接的句柄值
-* @param[in] rssi: rssi的指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_get_local_address(bt_addr_le_t *adv_addr)
/**
-* function 读取本机的地址
-* @param[in] adv_addr: 指向地址的指针
-* @return 0:成功,!=0:失败
-*/
-
int bt_set_tx_pwr(int8_t power)
/**
-* function 设置本机发射功率
-* @param[in] power: 功率值
-* @return 0:成功,!=0:失败
-*/
-
bt_le_adv_param
数据结构:
/** LE Advertising Parameters. */
-struct bt_le_adv_param {
- /** Local identity */
- u8_t id;
-
- /** Bit-field of advertising options */
- u8_t options;
-
- /** Minimum Advertising Interval (N * 0.625) */
- u16_t interval_min;
-
- /** Maximum Advertising Interval (N * 0.625) */
- u16_t interval_max;
-
- #if defined(CONFIG_BT_STACK_PTS)
- u8_t addr_type;
- #endif
-};
-
此数据结构用来配置广播参数,包括本地识别id、广播选项位域、广播间隙等,其中广播选项位域有如下枚举类型参数可选:
-enum {
- /** Convenience value when no options are specified. */
- BT_LE_ADV_OPT_NONE = 0,
-
- /** Advertise as connectable. Type of advertising is determined by
- * providing SCAN_RSP data and/or enabling local privacy support.
- */
- BT_LE_ADV_OPT_CONNECTABLE = BIT(0),
-
- /** Don't try to resume connectable advertising after a connection.
- * This option is only meaningful when used together with
- * BT_LE_ADV_OPT_CONNECTABLE. If set the advertising will be stopped
- * when bt_le_adv_stop() is called or when an incoming (slave)
- * connection happens. If this option is not set the stack will
- * take care of keeping advertising enabled even as connections
- * occur.
- */
- BT_LE_ADV_OPT_ONE_TIME = BIT(1),
-
- /** Advertise using the identity address as the own address.
- * @warning This will compromise the privacy of the device, so care
- * must be taken when using this option.
- */
- BT_LE_ADV_OPT_USE_IDENTITY = BIT(2),
-
- /** Advertise using GAP device name */
- BT_LE_ADV_OPT_USE_NAME = BIT(3),
-
- /** Use low duty directed advertising mode, otherwise high duty mode
- * will be used. This option is only effective when used with
- * bt_conn_create_slave_le().
- */
- BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY = BIT(4),
-
- /** Enable use of Resolvable Private Address (RPA) as the target address
- * in directed advertisements when CONFIG_BT_PRIVACY is not enabled.
- * This is required if the remote device is privacy-enabled and
- * supports address resolution of the target address in directed
- * advertisement.
- * It is the responsibility of the application to check that the remote
- * device supports address resolution of directed advertisements by
- * reading its Central Address Resolution characteristic.
- */
- BT_LE_ADV_OPT_DIR_ADDR_RPA = BIT(5),
-
- /** Use whitelist to filter devices that can request scan response
- * data.
- */
- BT_LE_ADV_OPT_FILTER_SCAN_REQ = BIT(6),
-
- /** Use whitelist to filter devices that can connect. */
- BT_LE_ADV_OPT_FILTER_CONN = BIT(7),
-};
-
如果需要发送一个广播包,配置可以如下:
-param.id = 0;
-param.options = (BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_USE_NAME | BT_LE_ADV_OPT_ONE_TIME);
-param.interval_min = 0x00a0;
-param.interval_max = 0x00f0;
-
bt_data
数据结构:
struct bt_data {
- u8_t type;
- u8_t data_len;
- const u8_t *data;
-};
-
此数据结构用来填充广播包中的数据,具体的数据包类型可以参考如下:
-Service UUID
-Local Name
-Flags
-Manufacturer Specific Data
-TX Power Level
-Secure Simple Pairing OOB
-Security Manager OOB
-Security Manager TK Value
-Slave Connection Interval Range
-Service Solicitation
-Service Data
-Appearance
-Public Target Address
-Random Target Address
-Advertising Interval
-LE Bluetooth Device Address
-LE Role
-Uniform Resource Identifier
-LE Supported Features
-Channel Map Update Indication
-
用该数据结构配置一个广播包数据,如下所示:
-struct bt_data ad_discov[] = {
- BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
- BT_DATA(BT_DATA_NAME_COMPLETE, "BL602-BLE-DEV", 13),
-};
-
bt_le_scan_param
数据结构:
/** LE scan parameters */
-struct bt_le_scan_param {
- /** Scan type (BT_LE_SCAN_TYPE_ACTIVE or BT_LE_SCAN_TYPE_PASSIVE) */
- u8_t type;
-
- /** Bit-field of scanning filter options. */
- u8_t filter_dup;
-
- /** Scan interval (N * 0.625 ms) */
- u16_t interval;
-
- /** Scan window (N * 0.625 ms) */
- u16_t window;
-};
-
此数据结构用来填充扫描参数, -type:为扫描类型有2种类型BT_LE_SCAN_TYPE_ACTIVE(0x01)、BT_LE_SCAN_TYPE_PASSIVE(0x00)。 -filter_dup:0x00,除定向广告外,接受所有广播和扫描响应,0x01,只接收白名单列表中设备的广播和扫描响应。 -interval:扫描间隙。 -window:扫描窗口。
-如果开启扫描请求,可以配置如下:
-scan_param.type = BT_LE_SCAN_TYPE_PASSIVE
-scan_param.filter_dup = 0x00
-interval=BT_GAP_SCAN_SLOW_INTERVAL_1
-window=BT_GAP_SCAN_SLOW_WINDOW_1
-
bt_le_conn_param
数据结构:
/** Connection parameters for LE connections */
-struct bt_le_conn_param {
- u16_t interval_min;
- u16_t interval_max;
- u16_t latency;
- u16_t timeout;
-
- #if defined(CONFIG_BT_STACK_PTS)
- u8_t own_address_type;
- #endif
-};
-
此数据结构用来填充连接参数,interval_min:连接间隙最少值(0x0018),interval_max:连接间隙最大值(0x0028), -latency:指定为连接事件数的连接允许的最大从延迟。 -timeout:连接超时时间。
-配置该数据结构,如下:
-interval_min=BT_GAP_INIT_CONN_INT_MIN(0x0018)
-interval_max=BT_GAP_INIT_CONN_INT_MAX(0x0028)
-latency=0
-timeout=400
-
bt_conn
数据结构:
struct bt_conn {
- u16_t handle;
- u8_t type;
- u8_t role;
-
- ATOMIC_DEFINE(flags, BT_CONN_NUM_FLAGS);
-
- /* Which local identity address this connection uses */
- u8_t id;
-
-#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
- bt_security_t sec_level;
- bt_security_t required_sec_level;
- u8_t encrypt;
-#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
-
- /* Connection error or reason for disconnect */
- u8_t err;
-
- bt_conn_state_t state;
-
- u16_t rx_len;
- struct net_buf *rx;
-
- /* Sent but not acknowledged TX packets with a callback */
- sys_slist_t tx_pending;
- /* Sent but not acknowledged TX packets without a callback before
- * the next packet (if any) in tx_pending.
- */
- u32_t pending_no_cb;
-
- /* Completed TX for which we need to call the callback */
- sys_slist_t tx_complete;
- struct k_work tx_complete_work;
-
-
- /* Queue for outgoing ACL data */
- struct k_fifo tx_queue;
-
- /* Active L2CAP channels */
- sys_slist_t channels;
-
- atomic_t ref;
-
- /* Delayed work for connection update and other deferred tasks */
- struct k_delayed_work update_work;
-
- union {
- struct bt_conn_le le;
-#if defined(CONFIG_BT_BREDR)
- struct bt_conn_br br;
- struct bt_conn_sco sco;
-#endif
- };
-
-#if defined(CONFIG_BT_REMOTE_VERSION)
- struct bt_conn_rv {
- u8_t version;
- u16_t manufacturer;
- u16_t subversion;
- } rv;
-#endif
-};
-
此数据结构为当前连接数据结构,其中包括BLE蓝牙连接相关的参数,连接成功后该数据结构可以被用户调用。
-linux下有强大的shell工具,可以让用户和片上系统进行交互,而在传统的单片机系统中,用户往往需要自行实现一套类似的交互工具。AliOS-Things原生带有一套名为cli(command-line -interface)的命令行交互工具,在提供基本的系统交互命令的基础上,也支持用户自定义命令。我们已经将其移植到我们到系统中, -同时对其做出了很多完善, 下面将介绍如何使用cli命令并执行
-用户在只需在程序中调用test_cli_init()
接口之后,就可以在shell中test
,就可以打印hello world.
如下图所示
#
-#
-# test
-hello world.
-#
-#
-
还有很多常用命令,请参考`常用命令<../helper/helper.html>`_
-static void cmd_test_func(char *buf, int len, int argc, char **argv)
-{
- printf("hello world.\r\n");
- return;
-}
-
-const static struct cli_command cmds_user[] = {
- {"test", "it's test func ", cmd_test_func}
-};
-
-int test_cli_init(void)
-{
- return aos_cli_register_commands(cmds_user, sizeof(cmds_user)/sizeof(cmds_user[0]));
-}
-
这里主要介绍现阶段支持到部分命令,包括系统命令和用户命令,当然有的命令板子不一定支持,可以通过help
查看其支持到命令,更多的命令请参考源码或者自行添加
系统命令
name |
-help |
-
---|---|
help |
-print this |
-
p |
-print memory |
-
m |
-modify memory |
-
cho |
-echo for command |
-
xit |
-close CLI |
-
evname |
-print device name |
-
ysver |
-system version |
-
eboot |
-reboot system |
-
oweroff |
-poweroff system |
-
ime |
-system time |
-
ta |
-system ota |
-
s |
-thread dump |
-
用户命令
name |
-help |
-
---|---|
test_trng |
-Test TRNG |
-
tcpc |
-create a tcpc for in a new task |
-
ipc |
-iperf TCP client |
-
ips |
-iperf TCP server |
-
ipu |
-iperf UDP client |
-
psm_set |
-psm set |
-
psm_unset |
-psm unset |
-
psm_get |
-psm get |
-
psm_dump |
-psm dump |
-
psm_erase |
-psm dump |
-
amr |
-amr encode test |
-
test_sdh |
-test SDH based on fatfs |
-
http |
-http client download test |
-
mjpeg_start |
-start mjpeg tasks |
-
msg_set |
-message set |
-
msg_get |
-message get |
-
msg_dump |
-message dump |
-
msg_reset |
-erase all message regions |
-
msg_set_t1 |
-message set test 1 |
-
rf_dump |
-rf dump |
-
wifi_ap_start |
-start AP mode |
-
wifi_scan |
-wifi scan |
-
wifi_mon |
-wifi monitor |
-
wifi_raw_send: wifi |
-raw send test |
-
wifi_sta_disconnect |
-wifi station disconnect |
-
wifi_sta_connect |
-wifi station connect |
-
airkiss |
-airkiss |
-
rc_fix_en |
-wifi rate control fixed rate enable |
-
rc_fix_dis |
-wifi rate control fixed rate diable |
-
wifi_capcode |
-capcode utils, wifi_capcode [cap_in] [cap_out] |
-
blfdt |
-blfdt |
-
tc_uart |
-bl test uart |
-
audio_play_ram |
-play sound fm ram |
-
audio_config_es8311 |
-config ES831 |
-
audio_mp3 |
-play sou mp3 |
-
audio_test |
-play test |
-
audio_play |
-audio play |
-
查看支持的所有命令
-可以通过按键TAB
查看,或者命令输入help
如下:
# help
配置wifi的临时ssid和passwd(重启恢复使用默认值)
-例如配置wifi:bl_wifi_005
和密码:123456789
-命令行输入如下命令:
# wifi_sta_connect bl_wifi_005 123456789
配置wifi的默认ssid和passwd
-例如配置wifi:bl_wifi_005
和密码:123456789
-命令行输入如下命令:
# psm_set conf_ap_ssid bl_wifi_005
# psm_set conf_ap_psk 123456789
启动AP
-使用wifi_ap_start
命令可以启动AP,但使用前需要使用psm_erase
擦除STA相关配置信息并重启。启动的AP
-SSID为BL60X_uAP_
加上MAC地址的后3三个字节的HEX串,密码为bouffalolab
系统重启
-# reboot
播音与录音
-该模块需要硬件有SD卡支持,暂时仅支持 pcm 格式文件,其他格式待更新
-配置音频的采样频率
-# audio_config 11p025
-如果没有参数,默认使用16Khz,支持 -8k、16k、24k、32k、48k、11p025、22p05、44p1 -采样频率(11.025khz用11p025表示,其他类似),例如这里配置采样频率为 -11.025Khz
-录音
-# audio_record test.pcm
-如果没有参数,默认录音放在sd卡根目录中,录音文件名record.pcm,这里配置文件名test.pcm,即存放在在根目录test.pcm文件中,同时默认录音10S左右
-放音
-# audio_play test.pcm
-如果没有参数,默认使用sd卡根目录中,录音文件名record.pcm,这里配置文件名test.pcm,即播放SD卡中的test.pcm音频
-图传
-使用mjpeg_start
命令可以启动图传的相关任务
保存图片至SD卡
-该模块需要硬件有SD卡支持,暂时仅支持 jpeg 格式文件,其他格式待更新
-配置mjpeg图片的quality
-# mjpegsd_config 50
-暂时支持6种 quality 5、10、25、50、75、100
-启动保存图片
-# mjpegsd_start
-启动保存图片,默认保存50帧数据
-注意
-如上,示例命令,会在SD卡根目录保存50张 -0.jpeg、1.jpeg...49.jpeg图片
保存AVI至SD卡
-该模块需要硬件有SD卡支持,暂时仅支持 AIV 格式文件,其他格式待更新
-配置mjpeg图片的quality
-# avisd_config 50 bl_avi_q50.avi
-暂时支持6种 quality 5、10、25、50、75、100
-启动保存avi
-# avisd_start
-启动保存avi,默认保存750帧图片
-注意
-如上,示例命令,会在SD卡根目录保存一个"bl_avi_q50.avi"文件
内存卡建议格式化为分配单元64KB,文件系统FAT32
avisd_start之后,如果想修改quality,需重启一下开发板
该模块需要有psram、camera支持,需要开启使能PSRAM、camera相关开关
二维码配网
-该模块是通过手机分享热点的二维码连接WiFi
-启动命令
-qrcode_connect_wifi
输入命令后摄像头会初始化然后开始循环识别二维码
-注意
-成功识别的到二维码后,会先打印二维码信息,如果不是分享热点的二维码会继续扫描
支持SSID为中文,但是要求unicode编码规则为UTF-8
支持开放热点
该模块需要psram、camera支持,需要开启使能PSRAM、camera相关开关
调试平台
-ubuntu18.04
device tree 调试工具
-sudo sudo apt-get install device-tree-compiler
dts 转 dtb
-dtc -I dts -O dtb -o *.dtb *.dts
dtb 转 dts
-dtc -I dtb -O dts *.dtb -o *.dts
dtb 转数组到数组 *.c
-xxd -i *.dtb ./*.c
*.dts 文件开头必须采用如下所示开头
-/dts-v1/; // version: 17 // last_comp_version: 16 // boot_cpuid_phys: 0x0
16进制数组表示方法如下(注:字节间必须有一个空格,且暂时不支持换行)
-mac {
- sta_mac_addr = [C8 43 57 82 73 40];
- ap_mac_addr = [C8 43 57 82 73 02];
- };
-
字符串或者字符串数据表示方法如下
-model = "bl bl602 AVB board";
-compatible = "bl,bl602-sample", "bl,bl602-common";
-
32bit数据表示方法(可以使用16进制ox方式,也可使用10进制方式,字节间必须有一个空格,且暂时不支持换行)
-pwr_table = <0x4 0x64>
-pwr_table = <4 100>
-
串口暂时仅支持配置以下功能
-
使能串口
-status = "okay";
关闭串口
-关闭串口时,余下其他引脚、波特率等配置均无效,不会初始化相关硬件
-status = "disable";
-
配置引脚
-暂时不支持配置cts和rts相关功能,故暂时feature
中rts和cts均为disable
。如果使用了串的tx和rx,feature
中到tx和rx需要配置为okay
,pin
中的tx和rx需要选择相关引脚。
pin {
- rx = <7>;
- tx = <16>;
-};
-feature {
- rts = "disable";
- cts = "disable";
- rx = "okay";
- tx = "okay";
-};
-
配置波特率
-配置波特率参考如下,最大支持 2000000 bps
这里以9600
为例
baudrate = <9600>;
-
配置id号
-配置id参考如下,这里以<0>
为例
id = <0>;
-
配置设备名
-目前串口设备名为/dev/ttyS,至于为当前串口id号,目前调试口使用 -/dev/ttyS0
-pin {
- rx = <7>;
- tx = <16>;
- };
-feature {
- rts = "disable";
- cts = "disable";
- rx = "okay";
- tx = "okay";
-};
-path = "/dev/ttyS0";
-
blog 是一款超轻量级的日志组件,非常适合对资源敏感的软件项目.
-blog -将log简化成3类,分别是组件、文件、私有log,且分别支持软件动态修改、宏彻底关闭方案(不占用rom)。下文统称动态修改为软开关,宏彻底关闭方案为静态开关。
-组件log管理 该log优先级最高,如下的文件log和私有log均受此开关的束缚
文件log管理 -该log优先级中,如下的私有log均受此开关的束缚,且文件log受到组件log的管理。
私有log管理 该log优先级最低,受组件log和文件log管理
按照等级高低分别如下,其中all最低,即所有log均输出
-all : 所有log均输出,其实等同于all
-debug : debug及以上
-info : info及以上
-warn : warn及以上
-error : error及以上
-assert : assert及以上
-never: 所有log均不输出,其实等同于assert
-
包含必要的头文件
-#include <blog.h>
然后分别设置组件log、文件log、私有log。
#include <blog.h>
-BLOG_DECLARE(blog_testc2);
-
-void func(void)
-{
- blog_debug("blog_testc2 debug\r\n");
- blog_info("blog_testc2 info\r\n");
- blog_warn("blog_testc2 warn\r\n");
- blog_error("blog_testc2 error\r\n");
- blog_assert("blog_testc2 assert\r\n");
-
- blog_debug_user(blog_testc2,"blog_testc2 debug user\r\n");
- blog_info_user(blog_testc2,"blog_testc2 info user\r\n");
- blog_warn_user(blog_testc2,"blog_testc2 warn user\r\n");
- blog_error_user(blog_testc2,"blog_testc2 error user\r\n");
- blog_assert_user(blog_testc2,"blog_testc2 assert user\r\n");
-}
-
组件log开关
-静态开关 在相应的 proj_config.mk
-文件目录下,LOG_ENABLED_COMPONENTS配置上增加对应组件的名字
-例如这里需要增加blog_testa blog_testb
-blog_testc组件静态开关,其他组件默认关闭
-LOG_ENABLED_COMPONENTS:=blog_testa blog_testb blog_testc
软件开关 通过输入如下命令来使能log输出等级 形如,logset level
-component_name例如: blogset assert blog_testc
文件log管理
-静态开关
-在对应的*.c文件中,加入此行代码,注意,不管是开或者关,必须选择一种。
-默认就是开
#define BLOG_HARD_DECLARE_DISABLE 1 // 关
软件开关 通过输入如下命令来使能log输出等级 形如,logset level
-component_name.file_name例如:
-blogset info blog_testc.blog_testc2_full
私有log管理
-静态开关 使用就增加BLOG_DECLARE(...),不用直接不增加此行即可。
-BLOG_DECLARE(blog_testc2); // 打开,其中 "blog_testc2"为用户自定义
软件开关 通过输入如下命令来使能log输出等级 形如,logset level
-component_name.file_name.pri_name例如:
-blogset debug blog_testc.blog_testc2_full.blog_testc2
VFS存在的意义,屏蔽掉底层文件系统的差异,为应用层提供标准的系统调用接口。
-基本通用的UNIX接口都已经实现了。之所以具有前缀aos_
。是因为这些都是对外的接口,在AliOS
-Things的代码命名规则中规定:所有的对外接口都需要加上前缀aos_
aos_open
-aos_close
-aos_read
-aos_write
-aos_ioctl
-aos_poll
-aos_fcnt
-aos_lseek
-aos_sync
-aos_stat
-aos_unlink
-aos_rename
-aos_opendir
-aos_closedir
-aos_readdir
-aos_mkdir
-inode_t
数据结构
/* this structure represents inode for driver and fs*/
-typedef struct {
- union inode_ops_t ops; /* inode operations */
- void *i_arg; /* per inode private data */
- char *i_name; /* name of inode */
- int i_flags; /* flags for inode */
- uint8_t type; /* type for inode */
- uint8_t refs; /* refs for inode */
-} inode_t;
-
因为VFS虚拟文件系统将文件和目录都当做文件来看待,上述的数据结构是索引节点类型,其具有节点具有的操作方法、节点的数据存放指针、节点的名称(即节点路径名/dev/null)、节点类型、节点被引用的次数。
-在inode_
t结构体当中,ops是针对索引节点的操作方法,具体如下:
union inode_ops_t {
-
- const file_ops_t *i_ops; /* char driver operations */
-
- const fs_ops_t *i_fops; /* FS operations */
-
-};
-typedef const struct file_ops file_ops_t; /* 针对文件的操作方法 */
-typedef const struct fs_ops fs_ops_t; /* 针对目录的操作方法 */
-struct file_ops {
- int (*open) (inode_t *node, file_t *fp);
- int (*close) (file_t *fp);
- ssize_t (*read) (file_t *fp, void *buf, size_t nbytes);
- ssize_t (*write) (file_t *fp, const void *buf, size_t nbytes);
- int (*ioctl) (file_t *fp, int cmd, unsigned long arg);
-#ifdef AOS_CONFIG_VFS_POLL_SUPPORT
- int (*poll) (file_t *fp, bool flag, poll_notify_t notify, struct pollfd *fd, void *arg);
-#endif
-};
-struct fs_ops {
- int (*open) (file_t *fp, const char *path, int flags);
- int (*close) (file_t *fp);
- ssize_t (*read) (file_t *fp, char *buf, size_t len);
- ssize_t (*write) (file_t *fp, const char *buf, size_t len);
- off_t (*lseek) (file_t *fp, off_t off, int whence);
- int (*sync) (file_t *fp);
- int (*stat) (file_t *fp, const char *path, struct stat *st);
- int (*unlink) (file_t *fp, const char *path);
- int (*rename) (file_t *fp, const char *oldpath, const char *newpath);
- aos_dir_t *(*opendir) (file_t *fp, const char *path);
- aos_dirent_t *(*readdir) (file_t *fp, aos_dir_t *dir);
- int (*closedir) (file_t *fp, aos_dir_t *dir);
- int (*mkdir) (file_t *fp, const char *path);
- int (*rmdir) (file_t *fp, const char *path);
- void (*rewinddir)(file_t *fp, aos_dir_t *dir);
- long (*telldir) (file_t *fp, aos_dir_t *dir);
- void (*seekdir) (file_t *fp, aos_dir_t *dir, long loc);
- int (*ioctl) (file_t *fp, int cmd, unsigned long arg);
- int (*statfs) (file_t *fp, const char *path, struct statfs *suf);
- int (*access) (file_t *fp, const char *path, int amode);
-};
-
file_t
数据结构
typedef struct {
- inode_t *node; /* node for file */
- void *f_arg; /* f_arg for file */
- size_t offset; /* offset for file */
-} file_t;
-
上述的file_t
数据结构用于描述一个被打开的文件,因为系统当中同一个系统当中,同一个文件可能被多个程序打开,但是打开的每一个文件都会唯一的执行特定的索引节点,即最终的物理文件只有一份。
aos_open
是对外的接口,外部函数可以直接使用该接口实现对于文件的打开操作,而不用去关心底层文件系统的实现细节。其代码如下所示:
其输入参数为:
-const char *path; 即文件路径名
-int flags; 即操作标志 比如只读 只写 读写等
-
int aos_open(const char *path, int flags)
-{
- file_t *file;
- inode_t *node;
- size_t len = 0;
- int ret = VFS_SUCCESS;
-
- if (path == NULL) {
- return -EINVAL;
- }
-
- len = strlen(path);
- if (len > PATH_MAX) { /* 文件路径名不允许超过256个字节 */
- return -ENAMETOOLONG;
- }
- /* 获取互斥锁,该互斥锁在vfs_init函数中创建 */
- if ((ret = krhino_mutex_lock(&g_vfs_mutex, RHINO_WAIT_FOREVER)) != 0) {
- return ret;
- }
- /* 根据路径名传参,打开索引节点,具体函数实现会在下文介绍 */
- node = inode_open(path);
-
- if (node == NULL) {
- krhino_mutex_unlock(&g_vfs_mutex);
-
-#ifdef IO_NEED_TRAP
- return trap_open(path, flags);
-#else
- return -ENOENT;
-#endif
- }
-
- node->i_flags = flags;
- /*因为用户操作的文件都是在内存中新建立的文件(文件对象会反过来指向索引节点
- 即一个文件可能被多个程序打开)。所以需要根据索引接点对象新建立一个文件对象
- */
- file = new_file(node);
- /* 释放互斥锁 */
- krhino_mutex_unlock(&g_vfs_mutex);
-
- if (file == NULL) {
- return -ENFILE;
- }
- /* 根据节点类型判断该路径名指向是一个文件还是一个目录,因为文件对象和目录对象虽然都是节点
- 但是其操作方法有些差别,见前文中的目录和文件操作方法 */
- if (INODE_IS_FS(node)) {
- if ((node->ops.i_fops->open) != NULL) {
- ret = (node->ops.i_fops->open)(file, path, flags);
- }
-
- } else {
- if ((node->ops.i_ops->open) != NULL) {
- ret = (node->ops.i_ops->open)(node, file);
- }
- }
-
- if (ret != VFS_SUCCESS) {
- del_file(file);
- return ret;
- }
- /* 获得文件句柄 */
- return get_fd(file);
-}
-
inode_open 在inode_open函数用于根据文件路径名打开对应的节点。
-其输入参数为: const char * path; 文件路径名
输出参数为:
-inode_t; 对应的节点
static inode_t g_vfs_dev_nodes[AOS_CONFIG_VFS_DEV_NODES];
-inode_t *inode_open(const char *path)
-{
- int e = 0;
- inode_t *node;
- /*AOS_CONFIG_VFS_DEV_NODES该宏定义为25.
- 即在保存节点的数组g_vfs_dev_nodes中仅仅会保存25个节点
- */
- for (e = 0; e < AOS_CONFIG_VFS_DEV_NODES; e++) {
- node = &g_vfs_dev_nodes[e];
-
- if (node->i_name == NULL) {
- continue;
- }
- /* 判断该节点是一个目录还是一个文件 */
- if (INODE_IS_TYPE(node, VFS_TYPE_FS_DEV)) {
- if ((strncmp(node->i_name, path, strlen(node->i_name)) == 0) &&
- (*(path + strlen(node->i_name)) == '/')) {
- return node;
- }
- }
- if (strcmp(node->i_name, path) == 0) {
- return node;
- }
- }
-
- return NULL;
-}
-
new_file -在new_file()函数中,完成的主要功能就是新建立一个file_t的结构体定义和初始化。 -其输入参数是: inode_t *node; 上个函数中得到的节点 输出参数是: -file_t 类型。用于后续获取文件句柄
static file_t files[MAX_FILE_NUM];
-#define MAX_FILE_NUM (AOS_CONFIG_VFS_DEV_NODES * 2)
-file_t *new_file(inode_t *node)
-{
- file_t *f;
- int idx;
- /* 在file数组当中新建立一个数据项。且保证该数组未满。即打开的文件数量是有限的 */
- for (idx = 0; idx < MAX_FILE_NUM; idx++) {
- f = &files[idx];
-
- if (f->node == NULL) {
- goto got_file;
- }
- }
-
- return NULL;
-
-got_file:
- f->node = node;
- f->f_arg = NULL;
- f->offset = 0;
- inode_ref(node);
- return f;
-}
-
所有的系统调用函数(类似于aos_open)都位于vfs.c文件中。
-在vfs_register.c文件中定义的函数:
-int aos_register_driver(const char *path, file_ops_t *ops, void *arg)
-int aos_register_fs(const char *path, fs_ops_t *ops, void *arg)
-
上述两个函数分别是将驱动文件或者是文件系统类型装载到VFS当中的函数。外部程序(例如sensor驱动程序)可以调用这两个接口将驱动文件加载的VFS当中去。
-以aos_register_driver为例进行介绍:
-其输入参数为: 驱动文件路径名 const char * path (/dev/null)
-驱动操作方法 file_ops_t *ops -(不需要实现全部的方法,实现必要的方法,其余置NULL即可)
-int aos_register_driver(const char *path, file_ops_t *ops, void *arg)
-{
- inode_t *node = NULL;
- int err, ret;
-
- err = krhino_mutex_lock(&g_vfs_mutex, RHINO_WAIT_FOREVER);
- if (err != 0) {
- return err;
- }
-//在g_vfs_dev_nodes数组中寻找一个空的数组项,返回其指针给node,并将path的路径名赋给node-->name
- ret = inode_reserve(path, &node);
- if (ret == VFS_SUCCESS) {
- /* now populate it with char specific information */
- INODE_SET_CHAR(node);
-
- node->ops.i_ops = ops;
- node->i_arg = arg;
- }
-
- /* step out critical area for type is allocated */
- err = krhino_mutex_unlock(&g_vfs_mutex);
- if (err != 0) {
- if (node->i_name != NULL) {
- krhino_mm_free(node->i_name);
- }
-
- memset(node, 0, sizeof(inode_t));
- return err;
- }
-
- return ret;
-}
-
vfs的操作类linux中操作,
-这里举例aos_open
、aos_close
、aos_read
、aos_write
void bl_test_uart0(void)
-{
- int fd;
- int length;
- char buf_recv[128];
-
- /* 首先打开相关文件,对应到UART0 */
- fd = aos_open("/dev/ttyS0", 0);
- if (fd < 0) {
- log_error("open err.\r\n");
- return;
- }
-
- while (1) {
- /* 读取UART0中的数据 */
- length = aos_read(fd, buf_recv, sizeof(buf_recv));
- if (length > 0) {
-
- log_info("recv len = %d\r\n", length);
-
- /* 直到收到'exit'才会主动结束循环,并close相关文件 */
- if (memcmp(buf_recv, "exit", 5) == 0) {
- aos_close(fd);
- break;
- }
-
- /* UART0将收到的数据回传过去 */
- aos_write(fd, buf_recv, length);
- }
- vTaskDelay(100);
- }
-}
-
VFS的一把重要的互斥锁 对VFS的相关操作都需要获取该互斥锁才能够进行。
-kmutex_t g_vfs_mutex;
VFS的两个重要的数组结构 如下所示:第一个数组是保存节点的数组结构。 -第二个数组是保存文件对象的数组结构。和用户直接相关的是第二个数组结构
static inode_t g_vfs_dev_nodes[AOS_CONFIG_VFS_DEV_NODES];
-static file_t files[MAX_FILE_NUM];
-
使用者只需关心的文件 vfs_register.c文件用于注册 vfs.c -文件用于各种标准操作。
Yloop 是AliOS -Things的异步事件框架。Yloop借鉴了,libuv及嵌入式业界常见的event -loop,综合考虑使用复杂性,性能,及footprint,实现了一个适合于MCU的事件调度机制。我们移植了相关的插件。其主要优势是所有的处理都是在主任务中执行的,不需要额外的创建任务,从而节省内存使用。同时,由于所有处理都是在主任务进行,不需要复杂的互斥操作。
-每个Yloop实例(aos_loop_t)与特定的任务上下文绑定,AliOS -Things的程序入口application_start -所在的上下文与系统的主Yloop实例绑定,该上下文也称为主任务。主任务以外的任务也可以创建自己的Yloop实例。
-Yloop实现了对IO,timer,callback,event的统一调度管理:
-IO
:最常见的是Socket,也可以是AliOS Things的vfs管理的设备
timer
:即常见的定时器
callback
:特定的执行函数
event
:包括系统事件,用户自定义事件
-当调用aos_loop_run后,当前任务将会等待上述的各类事件发生。
Yloop利用协议栈的select接口实现了对IO及timer的调度。AliOS -Things自带的协议栈又暴露一个特殊的eventfd接口,Yloop利用此接口把VFS的设备文件,和eventfd关联起来,实现了对整个系统的事件的统一调度。
-注册事件监听函数
/**
- * Register system event filter callback.
- *
- @param[in] type event type interested.
- * @param[in] cb system event callback.
- * @param[in] priv private data past to cb.
- *
- * @return the operation status, 0 is OK, others is error.
- */
-int aos_register_event_filter(uint16_t type, aos_event_cb cb, void *priv);
-
-/**
- * Unregister native event callback.
- *
- * @param[in] type event type interested.
- * @param[in] cb system event callback.
- * @param[in] priv private data past to cb.
- *
- * @return the operation status, 0 is OK, others is error.
- */
-int aos_unregister_event_filter(uint16_t type, aos_event_cb cb, void *priv);
-
发布一个 event
/**
- * Post local event.
- *
- * @param[in] type event type.
- * @param[in] code event code.
- * @param[in] value event value.
- *
- * @return the operation status, 0 is OK,others is error.
- */
-int aos_post_event(uint16_t type, uint16_t code, unsigned long value);
-
注册和取消一个 poll event
/**
- * Register a poll event in main loop.
- *
- * @param[in] fd poll fd.
- * @param[in] action action to be executed.
- * @param[in] param private data past to action.
- *
- * @return the operation status, 0 is OK,others is error.
- */
-int aos_poll_read_fd(int fd, aos_poll_call_t action, void *param);
-
-/**
- * Cancel a poll event to be executed in main loop.
- *
- * @param[in] fd poll fd.
- * @param[in] action action to be executed.
- * @param[in] param private data past to action.
- */
-void aos_cancel_poll_read_fd(int fd, aos_poll_call_t action, void *param);
-
发布和取消一个延迟执行的 action
/**static void adc_cb_read(int fd, void *param)
-{
- aos_post_event(EV_ADCKEY, CODE_ADCKEY_INT_TRIGGER, fd);
-}
- * Post a delayed action to be executed in main loop.
- *
- * @param[in] ms milliseconds to wait.
- * @param[in] action action to be executed.
- * @param[in] arg private data past to action.
- *
- * @return the operation status, 0 is OK,others is error.
- */
-int aos_post_delayed_action(int ms, aos_call_t action, void *arg);
-
-/**
- * Cancel a delayed action to be executed in main loop.
- *
- * @param[in] ms milliseconds to wait, -1 means don't care.
- * @param[in] action action to be executed.
- * @param[in] arg private data past to action.
- */
-void aos_cancel_delayed_action(int ms, aos_call_t action, void *arg);
-
安排一次回调
/**
- * Schedule a callback in next event loop.
- * Unlike aos_post_delayed_action,
- * this function can be called from non-aos-main-loop context.
-
- * @param[in] action action to be executed.
- * @param[in] arg private data past to action.
- *
- * @return the operation status, <0 is error,others is OK.
- */
-int aos_schedule_call(aos_call_t action, void *arg);
-
这里会介绍事件注册、通知、回调、取消流程、poll事件的注册取消、延迟执行一个actio)以及安排一次回调的使用方法
-aos_register_event_filter(EV_WIFI, event_cb_wifi_event, NULL);
-
用户首先调用aos_register_event_filter
注册事件监听函数,例如首先显注册一个EV_WIFI
事件的监听函数event_cb_wifi_event
aos_post_event(EV_WIFI, CODE_WIFI_ON_INIT_DONE, 0);
-
当有任务调用aos_post_event
接口,发布CODE_WIFI_ON_INIT_DONE
事件之后
static void event_cb_wifi_event(input_event_t *event, void *private_data)
-{
- switch (
- case CODE_WIFI_ON_INIT_DONE:
- {
- printf("[APP] [EVT] CODE_WIFI_ON_INIT_DONE %lld\r\n", aos_now_ms());
- }
- break;
- case CODE_WIFI_ON_PRE_GOT_IP:
- {
- printf("[APP] [EVT] connected %lld\r\n", aos_now_ms());
- }
- break;
- case CODE_WIFI_ON_GOT_IP:
- {
- printf("[APP] [EVT] GOT IP %lld\r\n", aos_now_ms());
- }
- break;
- default:
- {
- /*nothing*/
- }
- }
-}
-
event_cb_wifi_event
会被调用,并进入caseCODE_WIFI_ON_INIT_DONE
分支
aos_unregister_event_filter(EV_WIFI, event_cb_wifi_event, NULL);
-
如果用户不需要事件的监听,用户可以主动调用aos_unregister_event_filter
取消监听
/*uart*/
-fd_console = aos_open("/dev/ttyS0", 0);
-if (fd_console >= 0) {
- printf("Init CLI with event Driven\r\n");
- aos_cli_init(0);
- aos_poll_read_fd(fd_console, aos_cli_event_cb_read_get(), (void*)0x12345678);
- _cli_init();
-}
-
这里以 uart0
为例,用户首先注册一个aos_poll_read_fd
poll事件
aos_cancel_poll_read_fd(fd_console, action, (void*)0x12345678);
-
如果用户不需要事件的poll,用户可以调用aos_cancel_poll_read_fd
取消poll
aos_post_delayed_action(1000, app_delayed_action_print, NULL);
-
用户可以调用aos_post_delayed_action
做一个延迟1s
执行的事件
static void app_delayed_action_print(void *arg)
-{
- printf("test.\r\n");
-}
-
那过1s
之后会主动调用app_delayed_action_print
函数
aos_cancel_delayed_action(1000, app_delayed_action_print, NULL);
-
当用户想直接取消一个延迟动作可以调用aos_cancel_delayed_action
,其第一个ms
参数,
-当ms == -1
时,表示无需关心时间是否一致
aos_schedule_call(app_action_print, NULL);
-
用户主动调用aos_schedule_call
函数
static app_action_print(void *arg)
-{
- printf("test\r\n");
-}
-
那么会在下一次循环中主动调用app_action_print
函数
Yloop的API(include/aos/yloop.h)除了下述API,都必须在Yloop实例所绑定的任务的上下文执行:
-aos_schedule_call
aos_loop_schedule_call
aos_loop_schedule_work
aos_cancel_work
aos_post_event
本文档介绍BL_IoT SDK的WiFi联网功能。主要包括
-基站模式(即 STA 模式或 Wi-Fi 客户端模式),此时 BL_IoT 连接到接入点 (AP)。
AP 模式(即 Soft-AP 模式或接入点模式),此时基站连接到 BL_IoT。
AP-STA 共存模式(BL_IoT 既是接入点,同时又作为基站连接到另外一个接入点)。
上述模式的各种安全模式(WPA、WPA2 及 WEP(AP模式不支持))。
扫描接入点(包括主动扫描及被动扫描)。
使用混杂模式监控 IEEE802.11 Wi-Fi 数据包。
BL_IoT的实例 bl602_demo_wifi
目录下包含了一个应用程序,该demo介绍了如何使用BL_IoT模组连接到AP等一系列wifi操作。该实例实现的主要思路如下:
在主函数 bfl_main()
中创建一个 aos_loop_proc()
线程,在此线程中调用 aos_register_event_filter()
接口注册一个 EV_WIFI
事件的监听函数 event_cb_wifi_event()
;
首先用户在终端中输入 stack_wifi
命令后,在 cmd_stack_wifi()
函数中创建一个 wifi_main()
的线程,接着调用 aos_post_event()
接口发布 CODE_WIFI_ON_INIT_DONE
事件后, event_cb_wifi_event()
会被调用,并进入case CODE_WIFI_ON_INIT_DONE
分支从而调用 wifi_mgmr_start_background()
开启WiFi Manager,同时发布 CODE_WIFI_ON_MGMR_DONE
事件,进入case CODE_WIFI_ON_MGMR_DONE
分支调用 _connect_wifi()
函数,此函数先判断easyflash中是否设置了可连接的ssid,如果设置了则会自动进行wifi连接,没有设置则需手动输命令设置;
如用户在终端中输入 wifi_sta_connect
命令,会调用相应的api实现。如需实现wifi相关的其他功能可通过调用对应api来实现。
WLAN_FW_SUCCESSFUL
WiFi连接成功
-WLAN_FW_TX_AUTH_FRAME_ALLOCATE_FAIILURE
发送验证帧分配失败
-WLAN_FW_AUTHENTICATION_FAIILURE
验证失败
-WLAN_FW_AUTH_ALGO_FAIILURE
身份验证响应但身份验证算法失败
-WLAN_FW_TX_ASSOC_FRAME_ALLOCATE_FAIILURE
发送关联帧分配失败
-WLAN_FW_ASSOCIATE_FAIILURE
关联错误
-WLAN_FW_DEAUTH_BY_AP_WHEN_NOT_CONNECTION
AP取消验证,但状态错误
-WLAN_FW_DEAUTH_BY_AP_WHEN_CONNECTION
连接时由AP取消验证
-WLAN_FW_4WAY_HANDSHAKE_ERROR_PSK_TIMEOUT_FAILURE
密码错误,四次握手超时
-WLAN_FW_4WAY_HANDSHAKE_TX_DEAUTH_FRAME_TRANSMIT_FAILURE
密码错误,发送取消验证帧传输失败
-WLAN_FW_4WAY_HANDSHAKE_TX_DEAUTH_FRAME_ALLOCATE_FAIILURE
密码错误,发送取消验证帧分配失败
-WLAN_FW_TX_AUTH_OR_ASSOC_FRAME_TRANSMIT_FAILURE
发送授权或关联帧传输失败
-WLAN_FW_SCAN_NO_BSSID_AND_CHANNEL
SSID错误,扫描不到bssid和频道
-WLAN_FW_CREATE_CHANNEL_CTX_FAILURE_WHEN_JOIN_NETWORK
加入网络时创建通道上下文失败
-WLAN_FW_JOIN_NETWORK_FAILURE
加入网络失败
-WLAN_FW_ADD_STA_FAILURE
加入sta模式失败
-WLAN_FW_BEACON_LOSS
信标丢失
-头文件
API介绍
void wifi_mgmr_start_background(wifi_conf_t *conf)
/**
-* function 初始化并开启WiFi Manager。(wifi相关的操作第一步首先调用此接口)
-*
-* @param[in] conf WiFi配置
-*
-* @return 无
-*/
-
wifi_interface_t wifi_mgmr_sta_enable(void)
/**
-* function wifi sta 使能
-*
-* @param[in] 无
-*
-* @return 指向wifi sta的结构体信息的指针
-*/
-
int wifi_mgmr_sta_disable(wifi_interface_t *interface)
/**
-* function wifi sta 失能
-*
-* @param[in] interface wifi sta结构体指针
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sta_mac_set(uint8_t mac[6])
/**
-* function 设置 wifi mac 地址
-*
-* @param[in] mac[6] 存储mac地址的数组
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sta_mac_get(uint8_t mac[6])
/**
-* function 获取 wifi mac 地址
-*
-* @param[in] mac[6] 存储mac地址的数组
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sta_ip_get(uint32_t *ip, uint32_t *gw, uint32_t *mask)
/**
-* function 获取 wifi ip
-*
-* @param[in] ip 指向ip的指针
-* @param[in] gw 指向gateway的指针
-* @param[in] mask 指向mask的指针
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sta_connect(wifi_interface_t *wifi_interface, char *ssid, char *psk, char *pmk, uint8_t *mac, uint8_t band, uint16_t freq)
/**
-* function wifi sta 连接
-*
-* @param[in] wifi_interface wifi sta结构体指针(wifi_mgmr_sta_enable的返回值)
-* @param[in] ssid wifi名
-* @param[in] psk 密码
-* @param[in] pmk pmk
-* @param[in] mac mac地址
-* @param[in] band band
-* @param[in] freq freq
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sta_disconnect(void)
/**
-* function wifi sta 断开(调用此接口后需要TaskDelay 1s左右,再调用wifi_mgmr_sta_disable接口才能实现wifi disconnect)
-*
-* @param[in] 无
-*
-* @return 0:成功, 其他:失败
-*/
-
wifi_interface_t wifi_mgmr_ap_enable(void)
/**
-* function wifi ap模式使能
-*
-* @param[in] 无
-*
-* @return 指向wifi ap的结构体信息的指针
-*/
-
int wifi_mgmr_ap_start(wifi_interface_t *interface, char *ssid, int md, char *passwd, int channel)
/**
-* function 开启wifi ap模式
-*
-* @param[in] interface wifi ap结构体指针
-* @param[in] ssid wifi名
-* @param[in] md md
-* @param[in] passwd 密码
-* @param[in] channel wifi信道
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_ap_stop(wifi_interface_t *interface)
/**
-* function 关闭wifi ap模式
-*
-* @param[in] interface wifi ap结构体指针
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_scan(void *data, scan_complete_cb_t cb)
/**
-* function 开启wifi扫描
-*
-* @param[in] data scan data
-* @param[in] cb sacn cb
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sta_autoconnect_enable(void)
/**
-* function 开启wifi重连
-*
-* @param[in] 无
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sta_autoconnect_disable(void)
/**
-* function 关闭wifi重连
-*
-* @param[in] 无
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sta_powersaving(int ps)
/**
-* function 开启wifi sta省电模式
-*
-* @param[in] ps 0:关闭省电模式
- 1:开启省电模式
- 2:动态切换模式
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_ap_sta_cnt_get(uint8_t *sta_cnt)
/**
-* function 获取ap模式下允许连接的sta个数
-*
-* @param[in] sta_cnt sta的个数
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_ap_sta_info_get(struct wifi_sta_basic_info *sta_info, uint8_t idx)
/**
-* function 获取ap模式下sta连接的信息
-*
-* @param[in] sta_info 存储sta的信息
-* @param[in] idx sta编号
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sniffer_enable(void)
/**
-* function 使能sniffer
-*
-* @param[in] 无
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sniffer_disable(void)
/**
-* function 失能sniffer
-*
-* @param[in] 无
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sniffer_register(void *env, sniffer_cb_t cb)
/**
-* function 注册sniffer(注册之前需enable sniffer)
-*
-* @param[in] env env
-* @param[in] cb sniffer回调函数
-*
-* @return 0:成功, 其他:失败
-*/
-
int wifi_mgmr_sniffer_unregister(void *env)
/**
-* function 注销sniffer(注销之前需disable sniffer)
-*
-* @param[in] env env
-*
-* @return 0:成功, 其他:失败
-*/
-
Dev Cube 是博流提供的芯片集成开发工具,包含IOT程序下载、MCU程序下载和RF性能测试三种功能。本文档主要介绍IOT和MCU程序下载相关配置,RF性能测试请参考《射频性能测试使用手册》。
-Dev Cube 提供用户下载程序的功能,并且支持时钟、flash等参数配置,用户可根据自身需求决定是否对程序进行加密、添加签名、更换程序启动时的信息文件、用户资源文件、分区表等功能配置。
-具体的功能如下:
-支持IOT应用程序和MCU应用程序的下载
支持多种型号Flash 的擦、写、读;
可将各类文件下载到Flash并验证、回读;
下载通讯接口支持 UART 和 JLink 两种方式。
用户可以通过 Bouffalo Lab Dev Cube,获取最新版本的Dev Cube。
-双击解压后文件夹中的BLDevCube.exe
,在Chip Selection
对话框中选择对应的芯片型号,点击Finish
进入Dev Cube主界面。
无论是IOT程序下载还是MCU程序下载,它们的镜像组成是相同的,都如下图所示:
-如果只下载应用程序无法使芯片正常工作,必须要将引导信息下载到指定位置。引导信息包含对PLL、Boot、Flash等的配置;固件是用户自己编写的应用程序。
-以单核下载为例:根据需求选择对应的参数,将对PLL、Flash等配置的信息烧录到Bootinfo Addr对应的地址中,将应用程序经过编译后的bin文件烧录到Image Addr对应的地址中。
-在View
菜单中选择MCU选项,会进入MCU程序下载界面,主要分为程序下载方式的配置、镜像参数的配置和高级镜像参数的配置。
配置参数包括:
----
-- -
Interface:用于选择烧录的通信接口,这里选择 Uart 进行下载
- -
COM Port:当选择 UART 进行下载的时候这里选择与芯片连接的 COM 口号,可以点击 Refresh 按钮进行 COM 号的刷新
- -
Uart Speed:当选择 UART 进行下载的时候,填写波特率,推荐下载频率2MHz,不宜过高
- -
Chip Erase:默认设置为False,即下载时不擦除Flash
- -
Xtal:用于选择板子所使用的晶振类型。
配置参数包括:
----
-- -
Boot Source:默认为Flash
- -
BootInfo Addr:Flash程序启动参数的存放地址,填写0x0
- -
Image Type:默认为SingleCPU
- -
Image Addr:应用程序的存放地址,建议填写0x2000或者0x2000以后的地址
- -
Image File:将编译生成的bin文件路径添加到Image File 中
当点击click here to show advanced options
时,会展开高级镜像配置,可配置的参数包括:
---
-- -
Flash Clock:默认为XTAL
- -
PLL : PLL时钟配置,默认为160M
- -
CacheWayDis : 缓冲通道失能,默认为none
- -
Sign : 选择是否需要ECC校验,默认为none
- -
CrcIgnore : 是否需要CRC校验。当参数选择False时需要做CRC校验;参数选择True时不需要做CRC校验
- -
HashIgnore : 是否需要做Hash校验。当参数选择False时需要做Hash校验;参数选择True时不需要做Hash校验
- -
Encrypt : 选择加密方式,并根据AES加密方式在AES Key 和AES IV中输入对应的值。
将板子的BOOT引脚保持高电平,并且使得芯片复位,使其处于UART引导下载的状态。点击Creat&Program
,会自动生成应用程序镜像和启动参数配置文件,出现下图log信息,程序下载成功
注解
-若没有连接板子,只需生成应用程序镜像和启动参数配置文件,也是点击Creat&Program
按钮
下载成功后,将板子的BOOT引脚保持低电平,并且使得芯片复位,使其从Flash启动。此例子以2M波特率向PC端发送字符串报文
在View
菜单中选择IOT选项,会进入IOT程序下载界面,主要分为程序下载方式的配置和下载参数的配置。
配置参数包括:
----
-- -
Interface:用于选择烧录的通信接口,这里选择 Uart 进行下载
- -
COM Port: 当选择 UART 进行下载的时候这里选择与芯片连接的 COM 口号,可以点击 Refresh 按钮进行 COM 号的刷新
- -
Uart Rate:当选择 UART 进行下载的时候,填写波特率,推荐下载频率2MHz,不宜过高
- -
Board:选择所使用的板子型号,这里选择 IoTKitA,当板子选定后,Xtal 会自动更新成与板子匹配的默认值,当然用户也是可以再次更改的
- -
Xtal:选择下载时的晶振频率,如果电路板没有焊接晶振,此处应当选内部RC32M时钟源
- -
Chip Erase 默认设置为False,即下载时不擦除Flash
配置参数包括:
----
-- -
Partition Table:使用Dev Cube目录下对应芯片型号 partition 文件夹中的分区表,默认选择2M的文件
- -
Boot2 Bin:它是系统启动后运行的第一个Flash程序,负责建立BLSP安全环境,并引导主程序运行,使用Dev Cube目录下对应芯片型号 builtin_imgs 文件夹中的 Boot2 文件
- -
Firmware Bin:用户编译生成的bin文件路径
- -
Media/Romfs:Media和Romfs二选一,如果勾选 Media,选择的是文件,如果勾选 Romfs,则选择的是文件夹
- -
MFG Bin:选择MFG文件
- -
AES-Encrypt:如果使用加密功能,需要将AES-Encrypt选项选中,并在旁边的文本框中输入加密所使用的Key和IV。输入的是十六进制对应的“0”~“F”,一个Byte由两个字符构成,所以Key和IV分别要求输入32个字符。需要注意的是IV的最后8个字符(即4Bytes)必须全为0
- -
Single Download Config:勾选Enable后可下载单个文件,在左侧文本框填写下载的起始地址,以0x打头
将板子的BOOT引脚保持高电平,并且使得芯片复位,使其处于UART引导下载的状态。点击Creat&Download
,会自动生成应用程序镜像和启动参数配置文件,出现下图log信息,程序下载成功
注解
-若没有连接板子,只需生成应用程序镜像和启动参数配置文件,也是点击Creat&Program
按钮
下载成功后,将板子的BOOT引脚保持低电平,并且使得芯片复位,使其从Flash启动。此例子以2M波特率向PC端发送字符串报文
此目录介绍编译或下载等工具的使用。
-用户可以使用Linux平台或Windows平台进行编译,具体使用方法参考 Linux环境编译 , Windows环境编译
-用户可以使用BL自主开发的工具 BLFlashEnv
进行下载,具体使用方法参考 BLFlashEnv
用户可以在 Eclipse + OpenOCD
和 Freedom Studio + OpenOCD
两种方式中选择一种方式进行debug。具体调试方法参考 Eclipse 和 Freedom Studio 。
本文档介绍Eclipse的使用。
-首先启动 eclipse
,打开工具栏上的File > import
,选择General
菜单下的Existing Projects into Workspace
选项导入工程。
首先让板子跑起来,确认eclipse左上方的工具栏配置如下图1所示,然后点击第一个红色框框起来的图标debug
按钮,eclipse会先编译工程,完成后eclipse下方的 Console
窗口可以看到如下图2所示log。
使用快捷键 F8
resume一下,可以看到程序停在 void bfl_main()
主函数处,此时可以点击下图中的3个按钮。其含义分别为
第一个Step Into(F5) 单步执行,遇到子函数就进入并且继续单步执行;
第二个Step Over (F6)在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完在停止,也就是把子函数整个作为一步;
第三个Step Return(F7)在单步执行到子函数内时,用Step Return就可以执行完子函数余下部分,并返回上一层函数。
可以在 c代码
窗口最左边橙色条处双击增加、删除断点。
还可以通过查看右边的 Disassembly
窗口查看对应的汇编(该窗口没有的话可以通过最上方工具栏 Window > show view > Disassembly
添加)。
本文档介绍Freedom Studio的使用。
-首先启动 Freedom Studio
,打开工具栏上的File > import
,选择General
菜单下的Existing Projects into Workspace
选项导入工程。
首先让板子跑起来,使用快捷键 F11
启动 Debug,Freedom Studio会先编译工程(注意使用快捷键时确认使用的.launch文件名是bl_iot_sdk_debug_freedom_studio.launch,可以通过工具栏 Run > Debug As > 进行查看)
使用快捷键 F8
resume一下,可以看到程序停在 void bfl_main()
主函数处,此时可以点击下图中的3个按钮。其含义分别为
第一个Step Into(F5) 单步执行,遇到子函数就进入并且继续单步执行;
第二个Step Over (F6)在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完在停止,也就是把子函数整个作为一步;
第三个Step Return(F7)在单步执行到子函数内时,用Step Return就可以执行完子函数余下部分,并返回上一层函数。
可以在 c代码
窗口最左边橙色条处双击增加、删除断点。
还可以通过查看右边的 Disassembly
窗口查看对应的汇编(该窗口没有的话可以通过最上方工具栏 Window > show view > Disassembly
添加)。
该目录包含一系列示例项目的介绍与使用,这些旨在演示bl_iot模块功能的一部分。
-AES是一种对称加密算法,它的相关概念在此不赘述,本文档主要介绍AES-GCM的原理和实现。
-GCM ( Galois/Counter Mode) 指的是该对称加密采用Counter模式,并带有GMAC消息认证码。 -在详细介绍AES-GCM之前,我们先了解一些相关概念。
---在CTR模式下,我们对一个逐次累加的计数器进行加密,用加密后的比特序列与明文分组进行异或得到密文。过程如下图:
---- --
其中, IV为初始化向量,Ek表示ECB文本加密,PT表示输入的明文,CT表示输出的密文。
-在BL602中,我们可以直接使用硬件完成CTR算法,即设置key密钥后,输入IV以及需要加密的明文,硬件会自动完成累加计数加密并输出密文。
-CTR模式的优点是: -1)支持加解密并行计算,可事先进行加解密准备; -2)错误密文中的对应比特只会影响明文中的对应比特。 -但是它不能提供密文消息完整性校验的功能。
-想要校验消息的完整性,必须引入另一个概念:消息验证码。消息验证码是一种与秘钥相关的单项散列函数,过程如下图所示:
---- --
密文的收发双发需要提前共享一个秘钥。密文发送者将密文的MAC值随密文一起发送,密文接收者通过共享秘钥计算收到密文的MAC值, -这样就可以对收到的密文做完整性校验。当篡改者篡改密文后,没有共享秘钥,就无法计算出篡改后的密文的MAC值。
-对应到上图中的消息认证码,GMAC就是利用伽罗华域(Galois Field,GF,有限域)乘法运算来计算消息的MAC值。 -假设秘钥长度为128bits, 当密文大于128bits时,需要将密文按128bits进行分组。应用流程如下图:
---- --
其中,msg为需要验证的消息,Mh表示在有限域上做乘法运算,MAC即为生成的验证码。
-在BL602中,我们可以直接使用硬件完成GMAC验证。
-GCM中的G就是指GMAC,C就是指CTR。于是将CTR算法加上GMAC验证就是AES-GCM模式了。过程如下图所示:
---- --
本文主要介绍博流 AT指令集以及使用方法。指令集包含:基础 AT 指令、Wi-Fi 功能 AT 指令、TCP/IP ⼯具箱 AT 指令、BLE 相关 AT 指令。
-类型 |
-格式 |
-描述 |
-
查询指令 |
-AT+<x>? |
-该指令用于返回当前参数的值 |
-
设置指令 |
-AT+<x>=<···> |
-该指令用于设置用户自定义的参数 |
-
执行指令 |
-AT+<x> |
-该指令用于执行模块内部变参数不可变的功能 |
-
指令 |
-描述 |
-
- | 设置 UART 配置 |
-
- | 查看版本信息 |
-
- | 查看AT帮助信息 |
-
- | 重启模块 |
-
- | 恢复出厂设置 |
-
- | 进入 Deep-sleep 模式 |
-
---
-- - -- - - - - 指令
- 查询指令
-AT+UART?
-- 设置指令
-AT+UART=<baudrate>,<databits>,<stopbits>,<parity>,<flow control>
-- - - 响应
- +UART_CUR:<baudrate>,<databits>,<stopbits>,<parity>,<flow control> | OK
-OK |
-- - - 参数说明
- -
-- -
<baudrate>: UART 波特率
- -
<databits>: 数据位
--
-- -
5: 5-bit 数据位
- -
6: 6-bit 数据位
- -
7: 7-bit 数据位
- -
8: 8-bit 数据位
- -
<stopbits>: 停止位
--
-- -
1: 1-bit 停⽌位
- -
2: 1.5-bit 停⽌位
- -
3: 2-bit 停⽌位
- -
<parity>: 校验位
--
-- -
0: None
- -
1: Odd
- -
2: Even
- -
<flow control>: 流控
--
-- -
0: 不使能流控
- -
1: 使能 RTS
- -
2: 使能 CTS
- -
3: 同时使能 RTS 和 CTS
- - - - - - - - - - - - - - - - - - -
--
---
-- - -- - - - 执行指令
- AT+RST
- - - 响应
- OK
---
-- - -- - - - 执行指令
- AT+RESTORE
- - - 响应
- OK
---
-- - -- - - - 执行指令
- AT+S.HELP
- - - 响应
- OK
---
-- - -- - - - 指令
- 设置指令:
-AT+GSLP=<time>
-- - - 响应
- <time>
-OK
-- - - - 参数说明
- -
-- -
<time>: 设置 BL602 的睡眠时长,单位:秒。 BL602 会在休眠设定时长后唤醒
指令 |
-描述 |
-
- | 设置 Wi-Fi 模式 (STA/AP/STA+AP) |
-
- | 扫描附近AP |
-
- | 连接AP |
-
- | 断开AP |
-
- | 设置自动重连 |
-
- | 开启AP |
-
---
-- - -- - - - - 指令
- 查询指令
-AT+CWMODE?
-功能:查询BL602 Wi-Fi 模式
-- 设置指令
-AT+CWMODE=<mode>
-功能:设置BL602 Wi-Fi 模式
-- - - - 响应
- +CWMODE:<mode>
- OK
- - 参数说明
- -
-- -
<mode>:
----
-- -
0: 无 Wi-Fi 模式,并且关闭 Wi-Fi RF
- -
1: Station 模式
- -
2: SoftAP 模式
- -
3: SoftAP+Station 模式
- - - - -
---
-- - -- - - - 指令
- 查询指令
-AT+CWLAP
-功能:扫描附近的AP热点。
-- - - - 响应
- +CWLAP:
-<ap list>...
-OK
-- - - - - 响应说明
- -
-- -
<序号>,<SSID>,<BSSID>,<信道>,<信号强度>,<加密方式>
---
-- - -- - - - - 指令
- 查询指令
-AT+CWAUTOCONN?
-功能:查询BL602 Wi-Fi 自动重连
-- 设置指令
-AT+CWAUTOCONN=<auto_connect>
-功能:设置BL602 Wi-Fi 自动重连
-- - - - 响应
- +CWAUTOCONN:<mode>
- OK
- - 参数说明
- -
-- -
<auto_connect>:
----
-- -
0: 当WiFi模式变成Station或SoftAP+Station时,不连接WiFi
- -
1: 当WiFi模式变成Station或SoftAP+Station(默认配置)时,连接WiFi
- - -
---
-- - -- - - - - 指令
- 查询指令
-AT+CWJAP?
-功能:查询 BL602 Station 已连接的 AP 信息。
-- 设置指令
-AT+CWJAP=<ssid>,<pwd>
-功能:设置 BL602 Station 需连接的 AP。
-- - - - 响应
- +CWJAP:<ssid>,<ip>
-OK
-- OK
-+EVT:0:wifi connected
-- - - 参数说明
- -
-- -
<ssid>: 字符串串参数,AP 的 SSID
- -
<ip>: 当前获取到的ip地址
- -
-- -
<ssid>: 目标 AP 的 SSID
- -
<pwd>: 目标 AP 的 密码
--
-- -
若SSID或密码包含任何特殊字符,例如"或者,则需要转义
- - -
---
-- - -- - - - 指令
- 设置指令:
-AT+CWQAP=<link id>
-- - - - 响应
- OK
---
-- - -- - - - - 指令
- 查询指令
-AT+SOFTAP?
-功能:查看开启的AP热点信息。
-- 设置指令
-AT+SOFTAP=<ssid>,[pwd]
-功能:开启一个AP热点。
-- - - - 响应
- +SOFTAP:<ip>,<bssid>
-OK
-- OK
- - - 参数说明
- -
-- -
<ip>: 开启的AP热点的IP地址
- -
<bssid>: 当前开启的AP热点的MAC地址
- -
-- -
<ssid>: 设置AP 的 SSID
- -
[pwd]: 设置 AP 的 密码,若没有此参数,则该AP为开放式AP
--
-- -
若SSID或密码包含任何特殊字符,例如"或者,则需要转义
- - -
指令 |
-描述 |
-
- | 建立 TCP 连接,UDP 传输 |
-
- | 关闭 TCP 连接,UDP 传输 |
-
- | 删除或创建TCP服务器 |
-
- | 发送TCP/IP数据 |
-
- | 收到TCP/IP数据 |
-
设置指令 |
-AT+CIPSTART=<link id>,<type>,<remote IP>,<remote port> |
-
响应 |
-OK -或者已经建立TCP连接,响应:ALREADY CONNECTTED ERROR - |
-
参数说明 |
-
|
-
示例 |
-AT+CIPSTART=0,TCP,192.168.101,8000 -AT+CIPSTART=1,UDP,192.168.101,5000 - |
-
---
-- - -- - - - 指令
- 设置指令:
-AT+CIPCLOSE=<link id>
-- - - 响应
- OK
- - - 参数说明
- -
-- -
<link id>: 需要关闭的ID
---
-- - -- - - - 指令
- 设置指令:
-AT+CIPSERVER=<mode>[,<port>]
-- - - 响应
- OK
- - 参数说明
- -
-- -
<mode>:
----
-- -
0: 关闭服务器器
- -
1: 建立服务器器
- -
<port>: 端口号,默认为 333
- - - - - - 示例
- // 建立 TCP 服务器器
---AT+CIPSERVER=1,80
-- - -
---
-- - -- - - - 指令
- 设置指令:
-AT+CIPSEND=<link id>,<data len>
-- - - 响应
- OK
- - 参数说明
- -
-- -
<link id>: 连接ID
- -
<data len>: 需要传输的数据长度(单位:byte)
- - - - 示例
- AT+CIPSEND=0,20
---表示即将向id为0的连接发送20字节的数据
-- - -
---
-- - -- - - - 说明
- +IPD为收到TCP/UDP对端连接数据时的响应
-+IPD:<link id>,<data len>
-<data>
-- - - - 参数说明
- -
-- -
<link id>:发送数据的ID
- -
<data len>:即将接收的数据长度(单位:byte)
- -
<data>:接收数据
- - -
指令 |
-描述 |
-
- | 设置 BLE 数据包⻓度 |
-
- | 设置 BLE 设备名称 |
-
- | 设置 BLE 设备地址 |
-
---
-- - -- - - - 指令
- 设置指令:
-AT+BLEDATALEN=<conn_index>,<pkt_data_len>
-功能:设置 BLE 数据包⻓度。
-- - - - 响应
- OK
- - 参数说明
- -
-- -
<conn_index>: BLE 连接号, 范围 [0~2].
- -
<pkt_data_len>: 数据包长度,取值范围: 0x001b ~ 0x00fb
- - - 注意
- -
-- -
需要先建立 BLE 连接,才能设置数据包长度
- - 示例
- AT+BLEINIT=1 // 初始化为 client
-----AT+BLECONN=0,"24:0a:c4:09:34:23"
-AT+BLEDATALEN=0,30
-- - -
---
-- - -- - - - - 指令
- 查询指令
-AT+BLENAME?
-功能:查询 BLE 设备名称。
-- 设置指令
-AT+BLENAME=<device_name>
-功能:设置 BLE 设备名称,最大长度为32
-- - - - 响应
- +BLENAME:<device_name>
-OK
-- OK
- - - - 参数说明
- -
-- -
<device_name>: BLE 设备名称
---
-- - -- - - - - 指令
- 查询指令
-AT+BLEADDR?
-功能:查询 BLE 设备的 public address。
-- 设置指令
-AT+BLEADDR=<addr_type>[,<random_addr>]
-功能:设置 BLE 设备的地址。
-- - - - 响应
- +BLEADDR:<BLE_public_addr>
-OK
-- OK
- - - 参数说明
- -
-- -
<addr_type>:
----
-- -
0: public address
- -
1: random address
- - -
本示例主要介绍使用手机wifi连接602开发板通过UDP传输语音播报收款
-编译 customer_app/sdk_app_audio_udp
工程,勾选烧录软件中的romfs选项,
然后选中处理后的音频文件所在的文件夹并下载工程,如图所示:
---- --
板子启动后会自动开启wifi,名称为“BL60X_uAP_827302”,使用手机连接该wifi,如图所示:
---- --
打开微信小程序,IP地址设置为“192.168.169.1”,端口为“5002”,注意此时可能需要关闭数据流量,
输入需要发送播报的数字,点击“发送即可”,如图所示:
---- --
本示例主要介绍如何使用aws。
-在 customer_app/bl602_demo_ble_pds/bl602_demo_ble_pds/aws_iot_main.c
文件的头部有相关证书及配置,此处的配置只限于本示例演示使用(同时只能一处使用),用户需要根据实际情况修改文件开头的宏定义,下图是配置的一部分
--- --
编译 customer_app/bl602_demo_event
工程并下载工程;
在终端输入开启wifi的命令: stack_wifi
,输入连接wifi的命令: wifi_sta_connect <name> <key>
,并确认wifi连接成功(如输入:wifi_sta_connect bl_test_005 12345678);
--- --- --
在终端输入 aws
不断打印如下图所示log即表明连接成功。
--- --
本示例主要介绍如何使用ble。
-编译 customer_app/bl602_demo_event
或 customer_app/bl702_demo_event
工程并下载工程;
使用 stack_ble
命令初始化ble,打印的部分log如下。
--- --
依次使用 ble_init
、 ble_auth
进行相关的初始化;
--- --- --
使用 ble_start_adv 0 0 0x80 0x80
命令开启ble。
--- --
用户可以通过手机app Ble connect
scan附近的蓝牙,找到我们的设备并连接。
--- --- --
使用 ble_conn_update 0x6 0x6 0x0 0x1f4
更新连接参数。
--- --
SMP配对过程,由于security level不同,调用的命令也不相同,下面介绍level为2或者3的情况
---
-- -
连接成功后使用
-ble_security 2
进行SMP过程。--- ---
-- -
在串口打印出
-Confirm passkey for xx:xx:xx:xx:xx:xx (public)
,输入ble_auth_pairing_confirm
命令进行配对回复,打印的部分log如下。--- --- -
在串口打印出
-Bonded with xx:xx:xx:xx:xx:xx (public)
,表明SMP配对成功。--- --- -
连接成功后使用
-ble_security 3
进行SMP过程。--- ---
-- -
在串口打印出
-Confirm passkey for xx:xx:xx:xx:xx:xx (public):xxxxxx
,输入ble_auth_passkey_confirm
命令进行配对回复,打印的部分log如下。--- --- -
在串口打印出
-Bonded with xx:xx:xx:xx:xx:xx (public)
,表明SMP配对成功。--- --
ble_init
¶---
-- -
命令功能:ble通用初始化,在所有ble cli操作前,需要先输入该命令
- -
参数:无
- -
示例:输入命令
-ble_init
--- --
ble_auth
¶---
-- -
命令功能:注册SMP接口函数
- -
参数:无
- -
示例:输入命令
-ble_auth
--- --
ble_unpair
¶---
-- -
命令功能:清除配对key
- -
第一个参数表示设备地址类型
---
-- -
0:设备表示public地址类型
- -
1:表示设备地址为random类型
- -
2:表示设备地址为可解析的地址或者Public地址
- -
3:表示设备地址为可解析的地址或者random地址
-
-- -
第二个参数代表设备地址,高字节在前低字节在后,如果为0,代表清除所有设备的key
- -
示例:输入命令
-ble_unpair 0 0
--- --
ble_start_adv
¶---
-- -
命令功能表示:开启广播
- -
第一个参数表示广播类型
---
-- -
0:adv_ind 可连接可被扫描;
- -
1:adv_scan_ind 不可被连接可被扫描;
- -
2:adv_nonconn_ind 不可被连接不可被扫描;
- -
3:adv_direct_ind 可被指定的设备连接不可被扫描
-
-- -
第二个参数表示广播模式
---
-- -
0:General discoverable;
- -
1:non discoverable;
- -
2:limit discoverable;
-
-- -
第三个参数表示广播间隙最小值,其计算方式为 0.625ms * N,范围应在20 ms to 10.24 s之间
- -
第四个参数表示广播间隙最大值,其计算方式为 0.625ms * N,范围应在20 ms to 10.24 s之间
- -
示例:输入命令
-ble_start_adv 0 0 0x80 0x80
--- --
ble_stop_adv
¶---
-- -
命令功能:停止ADV广播
- -
参数:无
- -
示例:输入命令
-ble_stop_adv
--- --
ble_start_scan
¶---
-- -
命令功能:表示扫描广播设备
- -
第一个参数表示扫描类型
---
-- -
0:表示scan passive type只监听广播数据
- -
1:表示scan active,不仅监听当满足条件还会发scan_req包
-
-- -
第二个参数表示过滤设备广播包
---
-- -
0:表示不启用重复过滤
- -
1:表示启用重复过滤
- -
2:仅仅接收白名单列表发起的广播和scan response包,除了指定连接地址不是自己的adv_direct_ind广播包
- -
4:使用扩展过滤策略,过滤设备
-
-- -
第三个参数表示扫描间隙,其计算方式为 0.625ms * N,范围在2.5 ms to 10.24 s之间,其应该大于等于扫描窗口
- -
第四个参数表示扫描窗口,其计算方式为 0.625ms * N,范围在2.5 ms to 10.24 s之间,其应该小于等于扫描间隙
- -
示例:输入命令
-ble_start_scan 0 0 0x80 0x40
--- --
ble_stop_scan
¶---
-- -
命令功能:停止扫描
- -
参数:无
- -
示例:系统进入SCAN后,输入命令
-ble_stop_scan
--- --
ble_conn_update
¶---
-- -
命令功能:表示更新连接参数
- -
第一个参数表示连接间隙的最小值,其计算方式为 N * 1.25 ms,其范围在7.5 ms to 4 s
- -
第二个参数表示连接间隙的最大值,其计算方式为 N * 1.25 ms,其范围在7.5 ms to 4 s
- -
第三个参数表示从设备时延多少个连接事件范围是0~499,比如:该值设置为1,表明延时一个事件的时间进行数据交互,作用是降低交互频率更省电
- -
第四个参数表示连接超时时间,计算方式 N * 10 ms,范围是100 ms to 32 s
- -
示例:连接成功后,输入命令
-ble_conn_update 0x28 0x28 0x0 0xf4
--- --
ble_security
¶---
-- -
命令功能:设置SMP的加密等级
- -
第一个参数表示加密等级,总共有5个等级
---
-- -
0:仅用于BR/EDR,比如SDP服务;
- -
1:表示不需要加密不需要认证的过程;
- -
2:表示需要加密不需要认证的过程
- -
3:表示需要加密和认证,比如双方需要输入PIN码
- -
4:表示需要加密和认证,通过128bit的key
- -
示例:连接成功后,输入命令
-ble_security 2
- --
ble_get_device_name
¶---
-- -
命令功能:获取本地设备名称
- -
参数:无
- -
示例:输入命令
-ble_get_device_name
--- --
ble_set_device_name
¶---
-- -
命令功能:设置本地设备名称
- -
参数:需要设置的设备名字
- -
参数:无
- -
示例:输入命令
-ble_set_device_name bl602
--- --
ble_read_local_address
¶---
-- -
命令功能:读取本地设备地址
- -
参数:无
- -
示例:输入命令
-ble_read_local_address
--- --
ble_set_adv_channel
¶---
-- -
命令功能:设置ADV通道
- -
参数:需要设定的ADV通道数,其值范围为1-7,参数大小为1byte,bit0代表通道37,bit1代表通道38,bit2代表通道39
- -
示例:输入命令
-ble_set_adv_channel 4
--- --
ble_connect
¶---
-- -
命令功能:连接指定地址的设备
- -
第一个参数表示设备地址类型
---
-- -
0:设备表示public地址类型
- -
1:表示设备地址为random类型
- -
2:表示设备地址为可解析的地址或者Public地址
- -
3:表示设备地址为可解析的地址或者random地址
-
-- -
第二个参数代表设备地址,高字节在前低字节在后
- -
示例:输入命令
-ble_connect 0 18B905DE96E0
--- --
ble_disconnect
¶---
-- -
命令功能:断开指定地址的设备的连接
- -
第一个参数表示设备地址类型
---
-- -
0:设备表示public地址类型
- -
1:表示设备地址为random类型
- -
2:表示设备地址为可解析的地址或者Public地址
- -
3:表示设备地址为可解析的地址或者random地址
-
-- -
第二个参数代表设备地址,高字节在前低字节在后
- -
示例:连接成功后,输入命令
-ble_disconnect 0 18B905DE96E0
--- --
ble_select_conn
¶---
-- -
命令功能:多个连接中,将某一个连接对象设置为当前连接对象
- -
第一个参数表示设备地址类型
---
-- -
0:设备表示public地址类型
- -
1:表示设备地址为random类型
- -
2:表示设备地址为可解析的地址或者Public地址
- -
3:表示设备地址为可解析的地址或者random地址
-
-- -
第二个参数代表设备地址,高字节在前低字节在后
- -
示例:多个设备连接成功后,输入命令
-ble_select_conn 1 5F10546C8D83
,将选定的连接对象设置为当前连接对象,后续的ble_read等操作将会作用在该连接上--- --
ble_auth_cancel
¶---
-- -
命令功能:取消加密认证过程
- -
参数:无
- -
示例:当在SMP过程中,输入命令
-ble_auth_cancel
--- --
ble_auth_passkey_confirm
¶---
-- -
命令功能:接收到passkey后回复远端,并且对端设备在配对过程中也有显示该passkey; 例如:配对过程本地打印 Confirm passkey for 48:95:E6:73:1C:1A (random): 745491 -;可发送该函数进行回复
- -
参数:无
- -
示例:当在SMP过程中,对应security level为3,需要输入命令
-ble_auth_passkey_confirm
--- --
ble_auth_pairing_confirm
¶---
-- -
命令功能:接收到远端配对请求,用此函数回复远端配对请求,例如:配对过程本地打印 Confirm pairing for 00:1B:DC:F2:20:E9 (public) -;可发送该函数进行回复
- -
参数:无
- -
示例:当在SMP过程中,对应的security level为2,输入命令
-ble_auth_pairing_confirm
,--- --
ble_auth_passkey
¶---
-- -
命令功能:请求输入passkey
- -
参数:passkey值,其范围为0-999999
- -
示例:当用ble_security 3命令进行配对,且SMP配对方法为PASSKEY_INPUT(代码中实现方法:用ble_auth注册smp接口函数时,在数据结构bt_conn_auth_cb中将函数passkey_entry填充,passkey_display与passkey_confirm不填充,其它接口函数默认即可),串口将打印出Enter passkey for XX:XX:XX:XX:XX:XX (public),此时输入命令
-ble_auth_passkey 111111
完成配对--- --
ble_exchange_mtu
¶---
-- -
命令功能:交换mtu大小
- -
参数: 无
- -
示例:连接成功后,输入命令
-ble_exchange_mtu
--- --
ble_discover
¶---
-- -
命令功能:查询指定的服务或特性
- -
第一个参数表示需要查询的类型
---
-- -
0:primary
- -
1:secondary
- -
2:include
- -
3:Characteristic
- -
4:Descriptor
-
-- -
第二个参数表示2BYTES的uuid
- -
第三个参数表示起始句柄,占2BYTES
- -
第四个参数表示结束句柄,占2BYTES
- -
示例:连接成功后,输入命令
-ble_discover 0 0x1800 0x1 0xffff
--- --
ble_read
¶---
-- -
命令功能:读取指定句柄的数据
- -
第一个参数表示句柄
- -
第二个参数表示偏移量
- -
示例:连接成功后,输入命令
-ble_read 0x5 0
--- --
ble_write
¶---
-- -
命令功能:指定句柄写入相应的数据
- -
第一个参数表示句柄,占2bytes
- -
第二个参数表示偏移量,占2bytes
- -
第三个参数表示数据长度,占2bytes,最大不超过512
- -
第四个参数表示需要写入的数据
- -
示例:连接成功后,写入2个字节的数据,命令为
-ble_write 0xf 0 2 0102
,其中01为一个byte,02为一个byte--- --
ble_write_without_rsp
¶---
-- -
命令功能:指定句柄写入相应的数据并且不需要回复
- -
第一参数表示是否启动sign write命令
---
-- -
0:不使能sign write命令
- -
1:使能sign write命令
-
-- -
第二个参数表示句柄,占2bytes,
- -
第三个参数表示数据的长度,占2bytes,最大不超过512
- -
第四个参数表示写入的数据
- -
示例:连接成功后,写入2个字节的数据,命令为
-ble_write_without_rsp 0 0xf 2 0102
,其中01为一个byte,02为一个byte--- --
ble_subscribe
¶---
-- -
命令功能:订阅CCC
- -
第一个参数表示CCC句柄
- -
第二个参数表示订阅值的句柄
- -
第三个参数表示订阅类型
---
-- -
1:表示notification
- -
2:表示indication
-
-- -
示例:连接成功后,输入命令
-ble_subscribe 0xf 0xd 0x1
,表示使能CCC的notification--- --
ble_unsubscribe
¶---
-- -
命令功能:取消订阅CCC
- -
参数:无
- -
示例:输入命令
-ble_unsubscribe
--- --
ble_set_data_len
¶---
-- -
命令功能:设置pdu数据长度
- -
第一个参数表示有效荷载传输的最大值,范围为0x001B - 0x00FB
- -
第二个参数表示有效荷载传输的最大时间,范围值为0x0148 - 0x4290
- -
示例:当连接成功后,发送命令
-ble_set_data_len 0xfb 0x0848
--- --
ble_conn_info
¶---
-- -
命令功能:获取所有的连接信息
- -
参数:无
- -
示例:当连接成功后,发送命令
-ble_conn_info
,获取已连接的设备--- --
ble_disable
¶---
-- -
命令功能:注销BLE
- -
参数:无
- -
示例:当无scan/adv/connect事件,发送命令
-ble_disable
--- --
ble_set_tx_pwr
¶---
-- -
命令功能:设置发送功率
- -
第一个参数表示设置功率值
- -
示例:发送命令
-ble_set_tx_pwr 0xa
--- --
本示例主要介绍如何使用ble进行wifi配网。
-编译 customer_app/sdk_app_ble_sync
工程并下载工程固件;
固件上电运行会自动开启ble广播,等待手机APP连接配网,如下所示;
---- --
打开手机APP搜索蓝牙设备,搜索到设备名“BL602-BLE-DEV”;
---- --
点击连接设备后,点击APP中的扫描,等待数秒后APP会显示开发板扫描到的wifi设备列表;
---- --- --
用户可以通过扫描出来的设备列表对进行需要配网的wifi进行连接;
---- --
当用户确定配网完成时,不需要再使用配网功能,可以使用“blsync_ble_stop”命令将其关闭。
---- --
编译 customer_app/sdk_app_ble_sync
工程并下载工程固件;
固件上电运行会自动开启ble广播,等待手机APP连接配网,如下所示;
---- --
打开微信小程序搜索蓝牙设备,搜索到设备名“BL602-BLE-DEV”;
---- --
点击“BL602-BLE-DEV”连接设备,连接上设备BLE后会获取到BLE的服务,点击第一个服务,再选择“写通知“;
---- --
点击小程序中的”点击配网“,小程序会回显获取到的wifi列表,;
---- --
用户可以通过扫描出来的设备列表对进行需要配网的wifi进行连接,点击需要连接的wifi名称;
---- --
接着在输入框输入wifi密码,点击”发送密码“,即可连接wifi;
---- --
点击小程序中的”获取状态“按钮,获取wifi当前的连接状态;
---- --
当前已经连接wifi,则会显示”已经连接“并弹出板子的ip地址等信息;
---- --
点击”断开wifi“按钮,即可断开wifi,再次点击”获取状态“按钮可以获取当前wifi已经断开;
---- --
当用户确定配网完成时,不需要再使用配网功能,可以使用“blsync_ble_stop”命令将其关闭。
---- --
本示例主要介绍如何配置cronalarm
-使用步骤:
-编译 customer_app/sdk_app_cronalarm
工程并下载工程;
在main.c中有相关头文件的使用,main.c中aos_loop_proc 中有cronalarm相关的初始化。使用cronalarm 需要包含头文件cronalarms.h 。
命令解析
cron_alarm_create("0 30 8 * * *", MorningAlarm, 0);
-每日 8:30:0 调用MorningAlarm ;
-
-cron_alarm_create("0 30 8 * * *", MorningAlarm, 1)
-仅在将要到来的8:30:0 调用一次MorningAlarm. ;
-
-cron_alarm_create("0 15 9 * * 6", WeeklyAlarm, 0)
-每周六的9:15:0 调用WeeklyAlarm。;
-
-cron_alarm_create("*/15 * * * * *", Repeats, 0);
-每15s调用一次Repeats;
-
-cron_alarm_create("*/10 * * * * *", OnceOnly, 1);
-在创建之后,时钟的下一个秒达到10的倍数时,将调用afterOnly()函数。 且仅执行一次。
-
-create("0 0 12 4 7 *", Celebration, 0);
-每年的 7月4日 12:0:0 调用Celebration函数。
-
-cron_alarm_create("0 */1 * * * *", test_min02, 0);
-每分钟的 0s 调用test_min02
-
-cron_alarm_create("15 15 */4 * * *", test_hour02, 0);
-每4小时 15分15秒调用test_hour02
-
-cron_alarm_create("1-10/1 * * * * *", Repeats, 0);
-每分钟的前10s,每秒钟执行一次Repeats.
-
-cron_alarm_create("0 0 0 */1 * ?", test_day01, 0);
-每天的 0:0:0 执行一次test_day01
-
-cron_alarm_create("0 0 0 * * MON,WED,FRI", test_week01, 0);
-每周的周一,周三,周五,触发一次test_week01
-
-cron_alarm_create("11 23 1 1 JAN-FEB *", test_month02, 0);
-每年的一月二月 day1 01:23:11 触发test_month02.
-
本示例主要介绍如何使用hbnram的api
-1.首先进行初始化.调用hal_hbnram_init(void),进行初始化hbnram。如果是断电重启,则会清空hbnram,如果是不断点的reboot,则仅校验数据。 -2.hal_hbnram_alloc(const char *key, int len),key 必须是const char 类型的字符串,且必须小于4个字符。len是要申请的内存的长度。 -3.hal_hbnram_buffer_set(const char *key, uint8_t *buf, int length);把数据一次写入申请的buff. -4.hal_hbnram_buffer_get(const char *key, uint8_t *buf, int length);把数据一次从buff读出 -5.hal_hbnram_handle_get_fromkey(const char *key, hbnram_handle_t *handle);如果需要流读写,需要首先根据key,获取hanlde. -6.hal_hbnram_copy_from_stream(hbnram_handle_t *handle, uint8_t *buf, int len);流读出 -7.hal_hbnram_copy_to_stream(hbnram_handle_t *handle, uint8_t *buf, int len); 流写入
-具体使用方式参考 sdk_app_hbnram下的demo.c
-应用实例: -将工程sdk_app_hbnram 编译,烧写进入板子。重启板子。
-本示例主要介绍如何使用ble mesh。
-准备 手机安装APP bl_mesh_app.apk
编译 customer_app/bl602_demo_event
工程并下载工程;
在串口中运行Mesh相关命令:
---#stack_ble
-#blemesh_init
-#blemesh_pb 2 1
-
打开App,Network栏中选择点击添加
在扫描界面中,选择要添加的设备
在界面中点击IDENTIFY选项
在界面中点击PROVISION选项
在弹出的界面中选择No OOB,点击ok
在弹出的界面中,点击ok
界面自动调到Network栏中,点击已经连成功的设备
在界面中选择Elements选项,点击其下拉按钮
在界面中选择Generic on off Server选项
在界面中选择BIND KEY选项
界面中点击Application key 1
在界面中点击ONOFF选项,控制LED的开关
在串口中看到有如下信息表明控制LED成功
在界面中点击SUBSCRIBE选项,
在界面中选择Create a new group to subscribe选项,
按照同样的方法添加另外一个设备的节点,添加成功后,在Groups选项中,点击已经成功创建的group
在group中,选择ON/OFF,并且串口中打印log提示LED开关信息,说明mesh组网成功
本示例主要介绍如何配置GPIO。
-编译 customer_app/sdk_app_gpio
工程并下载工程;
使用 gpio-func <pinnum> <inputmode> <pullup> <pulldown>
命令配置指定gpio口的输入输出模式,上拉下拉情况,如输入 gpio-func 8 0 0 0
命令表示将gpio8设置为输出模式,无上下拉;
使用 gpio-set <pinnum> <val>
命令可以设置指定gpio口的电平(该gpio设置为输出模式);
使用 gpio-get <pinnum>
命令可以获取指定gpio口电平。
gpio-func命令的实现
if (5 != argc) {
- printf("Usage: %s 24 1 1 0\r\n set GPIO24 to input with pullup\r\n",
- argv[0]
- );
- return;
-}
-ionum = atoi(argv[1]);
-inputmode = atoi(argv[2]);
-pullup = atoi(argv[3]);
-pulldown = atoi(argv[4]);
-if (ionum < 0 || inputmode < 0 || pullup < 0 || pulldown < 0) {
- puts("Illegal arg\r\n");
- return;
-}
-printf("GPIO%d is set %s with %s pullup %s pulldown\r\n",
- ionum,
- inputmode ? "input" : "output",
- pullup ? "Active" : "null",
- pulldown ? "Active" : "null"
-);
-if (inputmode) {
- bl_gpio_enable_input(ionum, pullup ? 1 : 0, pulldown ? 1 : 0);
-} else {
- bl_gpio_enable_output(ionum, pullup ? 1 : 0, pulldown ? 1 : 0);
-}
-
获取命令行传入的信息,并作为参数传给 bl_gpio_enable_input(uint8, uint8, uint8)
或 bl_gpio_enable_output(uint8, uint8, uint8)
函数,从而配置对应gpio口。
gpio-set命令的实现
if (3 != argc) {
- printf("Usage: %s 24 1\r\n set GPIO24 output to high\r\n",
- argv[0]
- );
- return;
-}
-ionum = atoi(argv[1]);
-val = atoi(argv[2]);
-if (ionum < 0 || val < 0) {
- puts("Illegal arg\r\n");
- return;
-}
-printf("GPIO%d is set to %s\r\n",
- ionum,
- val ? "high" : "lo"
-);
-bl_gpio_output_set(ionum, val ? 1 : 0);
-
获取命令行传入的信息,并作为参数传给 bl_gpio_output_set(uint8, uint8)
函数,设置对应gpio口的电平。
gpio-get命令的实现
if (2 != argc) {
- printf("Usage: %s 24\r\n get GPIO24 value\r\n",
- argv[0]
- );
- return;
- }
- ionum = atoi(argv[1]);
- if (ionum < 0) {
- puts("Illegal arg\r\n");
- return;
- }
- ret = bl_gpio_input_get(ionum, &val);
- printf("GPIO%d val is %s\r\n",
- ionum,
- 0 == ret ? (val ? "high" : "low") : "Err"
- );
-
获取命令行传入的信息,并作为参数传给 bl_gpio_input_get(uint8, uint8*)
函数,获取对应gpio口的电平。
在 customer_app/sdk_app_gpio/sdk_app_gpio/main.c
中的 static void _cli_init()
函数里调用 gpio_cli_init()
初始化gpio相关的操作命令。
本示例主要介绍通过UART1将收到的数据回传给发送方的过程。
-使用之前需要准备一个 USB转TTL
串口线,并配置SDK目录下 bl_iot_sdk/tools/flash_tool/bl602/device_tree/bl_factory_params_evb_40M.dts
文件中的 uart
,具体配置可以参考本例。
uart {
- #address-cells = <1>;
- #size-cells = <1>;
- uart@4000A000 {
- status = "okay";
- id = <0>;
- compatible = "bl602_uart";
- path = "/dev/ttyS0";
- baudrate = <2000000>;
- pin {
- rx = <7>;
- tx = <16>;
- };
- feature {
- tx = "okay";
- rx = "okay";
- cts = "disable";
- rts = "disable";
- };
- };
- uart@4000A100 {
- status = "okay";
- id = <1>;
- compatible = "bl602_uart";
- path = "/dev/ttyS1";
- baudrate = <115200>;
- pin {
- rx = <3>;
- tx = <4>;
- };
- feature {
- tx = "okay";
- rx = "okay";
- cts = "disable";
- rts = "disable";
- };
- };
-};
-
使用步骤:
---
-- -
将板子的
gpio3
和gpio4
和GND
分别与USB转TTL
串口线的TXD
、RXD
、GND
分别连接起来;- -
编译
customer_app/sdk_app_uart_echo
工程并下载工程;- -
打开一个串口终端窗口A(波特率为115200,用于接收和发送uart消息),打开另一个串口终端窗口B(波特率为2000000,用于打印log)。板子上电可以看到窗口A接收到
1234567890abcdefg
,窗口B打印的log 停止在send case
处,在A窗口中输入1234567890abcdefg
(没有回显)可以在B串口看到recv case
和end
的消息,此时说明演示成功。
调用 aos_write()
接口通过UART1给终端发送数据,并等待终端返回接收到的数据,如接收与发送的数据一致,则log口将打印UART1中收发的消息内容。
aos_write(fd, send_recv_log, strlen(send_recv_log));
-log_step(ci_table_step_send);
-
-while (1) {
- length = aos_read(fd, buf_recv, strlen(send_recv_log));
- if (length != strlen(send_recv_log)) {
- continue;
- }
- if (memcmp(buf_recv, send_recv_log, strlen(send_recv_log)) == 0) {
- printf("recvbuff:%s\r\n", send_recv_log);
- log_step(ci_table_step_recv);
- break;
- }
- vTaskDelay(10);
-}
-log_step(ci_table_step_end);
-
在 customer_app/sdk_app_uart_echo/sdk_app_uart_echo/main.c
中 static void aos_loop_proc(void *pvParameters)
函数里调用ci_loop_proc()函数创建 uart_echo
的任务。
本示例主要介绍如何设置UART1的多种模式。
-配置参考 uart_echo
中的配置。
使用步骤
---
-- -
将板子的
gpio3
和gpio4
和GND
分别与USB转TTL
串口线的TXD
、RXD
、GND
分别连接起来;- -
编译
customer_app/sdk_app_uart_ctl
工程并下载工程;- -
打开一个串口终端窗口A(波特率为115200,用于接收和发送uart消息),打开另一个串口终端窗口B(波特率为2000000,用于打印log)。例如使用应用实现中case1中的配置,在窗口A中输入
123456789abcdef
,在窗口A中可以看到接收到的数据,同时窗口B中打印出接收数据的个数。
aos_ioctl选项为 IOCTL_UART_IOC_WAITRD_MODE
及 IOCTL_UART_IOC_WAITRDFULL_MODE
:
while (1) {
- //log_info("ready to read.\r\n");
- waitr_arg.buf = buf_recv;
- waitr_arg.read_size = sizeof(buf_recv);
- waitr_arg.timeout = 0;
- res = aos_ioctl(fd, IOCTL_UART_IOC_WAITRD_MODE, (unsigned long)(&waitr_arg));
- //res = aos_ioctl(fd, IOCTL_UART_IOC_WAITRDFULL_MODE, (unsigned long)(&waitr_arg));
- if (res > 0) {
- log_info("%s name.length = %d:\r\n", name, res);
- aos_write(fd, buf_recv, res);
- }
-}
-
case1: waitr_arg.timeout = 0
case1中调用 aos_ioctl(fd, IOCTL_UART_IOC_WAITRD_MODE, (unsigned long)(&waitr_arg))
表示当串口中的数据都读完或者读取到sizeof(buf_recv)长度的数据时立即返回。调用 aos_ioctl(fd, IOCTL_UART_IOC_WAITRDFULL_MODE, (unsigned long)(&waitr_arg))
用法与 IOCTL_UART_IOC_WAITRD_MODE
一致。
case2: waitr_arg.timeout = AOS_WAIT_FOREVER
case2中调用 aos_ioctl(fd, IOCTL_UART_IOC_WAITRD_MODE, (unsigned long)(&waitr_arg))
表示当串口中的数据都读完或者读取到sizeof(buf_recv)长度的数据时立即返回,串口中无数据则一直等待。调用 aos_ioctl(fd, IOCTL_UART_IOC_WAITRDFULL_MODE, (unsigned long)(&waitr_arg))
表示一直等待直到读取到sizeof(buf_recv)长度的数据时立即返回。
case3: waitr_arg.timeout = 5000
case3中调用 aos_ioctl(fd, IOCTL_UART_IOC_WAITRD_MODE, (unsigned long)(&waitr_arg))
表示当串口中的数据都读完或者读取到sizeof(buf_recv)长度的数据或者到达超时时间(超时时间从调用此接口算起,不是数据发送结束后算起)时立即返回。调用 aos_ioctl(fd, IOCTL_UART_IOC_WAITRDFULL_MODE, (unsigned long)(&waitr_arg))
表示读取到sizeof(buf_recv)长度的数据或者到达超时时间(超时时间从调用此接口算起,不是数据发送结束后算起)时立即返回。
aos_ioctl选项为 UART_IOC_BAUD_MODE
:
aos_ioctl(fd, IOCTL_UART_IOC_BAUD_MODE, 9600);
-
配置如上, 9600
表示波特率。
aos_ioctl选项为 IOCTL_UART_IOC_READ_BLOCK
及 IOCTL_UART_IOC_READ_NOBLOCK
:
while (1) {
- length = aos_read(fd, buf_recv, sizeof(buf_recv));
- if (length > 0) {
- log_info("%s name.length = %d:\r\n", name, length);
- aos_write(fd, buf_recv, length);
- }
- vTaskDelay(500);
- log_info("test.\r\n");
- count++;
-
- if (count == 5) {
- log_info("set noblock.\r\n");
- aos_ioctl(fd, IOCTL_UART_IOC_READ_NOBLOCK, 0);
- }
-
- if (count == 10) {
- log_info("set block.\r\n");
- aos_ioctl(fd, IOCTL_UART_IOC_READ_BLOCK, 0);
- }
-}
-
aos_ioctl(fd, IOCTL_UART_IOC_READ_BLOCK, 0)
表示读取到sizeof(buf_recv)长度的数据立即返回,否则一致等待。 aos_ioctl(fd, IOCTL_UART_IOC_READ_NOBLOCK, 0)
表示当串口中的数据都读完或者读取到sizeof(buf_recv)长度的数据时立即返回。
本示例主要介绍如何创建一个socket并连接到指定的Http服务器获取数据的过程。
-使用之前需要准备可用的URL以及网络。
使用步骤:
-编译 customer_app/sdk_app_http_client_socket
工程并下载工程;
在终端输入开启wifi的命令: stack_wifi
,输入连接wifi的命令: wifi_sta_connect <name> <key>
,并确认wifi连接成功(如输入:wifi_sta_connect bl_test_005 12345678);
使用 http
命令通过socket的方式进行下载。
通过 hostname
获取 hostinfo
struct hostent *hostinfo = gethostbyname(hostname);
-if (!hostinfo) {
- printf("gethostbyname Failed\r\n");
- return -1;
-}
-
创建一个 socket
连接并发送http请求。
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- printf("Error in socket\r\n");
- return -1;
-}
-/*---Initialize server address/port struct---*/
-memset(&dest, 0, sizeof(dest));
-dest.sin_family = AF_INET;
-dest.sin_port = htons(PORT);
-dest.sin_addr = *((struct in_addr *) hostinfo->h_addr);
-//char ip[16];
-uint32_t address = dest.sin_addr.s_addr;
-char *ip = inet_ntoa(address);
-
-printf("Server ip Address : %s\r\n", ip);
-/*---Connect to server---*/
-if (connect(sockfd,
- (struct sockaddr *)&dest,
- sizeof(dest)) != 0) {
- printf("Error in connect\r\n");
- return -1;
-}
-/*---Get "Hello?"---*/
-memset(buffer, 0, MAXBUF);
-char wbuf[]
- = "GET /ddm/ContentResource/music/204.mp3 HTTP/1.1\r\nHost: nf.cr.dandanman.com\r\nUser-Agent: wmsdk\r\nAccept: */*\r\n\r\n";
-write(sockfd, wbuf, sizeof(wbuf) - 1);
-
获取http响应的数据,完成时打印获取数据花费的时间和传输的速度。
while (1) {
- ret = read(sockfd, recv_buffer, BUFFER_SIZE);
- if (ret == 0) {
- printf("eof\n\r");
- break;
- } else if (ret < 0) {
- printf("ret = %d, err = %d\n\r", ret, errno);
- break;
- } else {
- total += ret;
- /*use less debug*/
- if (0 == ((debug_counter++) & 0xFF)) {
- printf("total = %d, ret = %d\n\r", total, ret);
- }
- //vTaskDelay(2);
- if (total > 82050000) {
- ticks_end = xTaskGetTickCount();
- time_consumed = ((uint32_t)(((int32_t)ticks_end) - ((int32_t)ticks_start))) / 1000;
- printf("Download comlete, total time %u s, speed %u Kbps\r\n",
- (unsigned int)time_consumed,
- (unsigned int)(total / time_consumed * 8 / 1000)
- );
- break;
- }
- }
-
关闭 socket
。
close(sockfd);
-
在 customer_app/sdk_app_http_client_socket/sdk_app_http_client_socket/demo.c
中 static void _cli_init()
的函数里调用 http_client_cli_init()
初始化http命令
本示例主要介绍如何通过tcp的方式访问Http服务器获取数据的过程。
-使用之前需要准备可用的URL以及网络。
使用步骤:
-在终端输入开启wifi的命令: stack_wifi
,会打印下图一log(部分),然后输入连接wifi的命令: wifi_sta_connect <name> <key>
,并确认wifi连接成功(如输入:wifi_sta_connect bl_test_005 12345678);
使用 httpc
命令进行下载。
主要实现过程
settings.use_proxy = 0;
- settings.result_fn = cb_httpc_result;
- settings.headers_done_fn = cb_httpc_headers_done_fn;
- httpc_get_file_dns(
- "nf.cr.dandanman.com",
- 80,
- "/ddm/ContentResource/music/204.mp3",
- &settings,
- cb_altcp_recv_fn,
- &req,
- &req
-);
-
cb_httpc_result()次回调函数会在http传输完成后调用,打印获取的消息内容长度;cb_httpc_headers_done_fn()回调函数会在接收到http headers时调用,打印headers的大小;用户可以在cb_altcp_recv_fn()回调函数中处理接收到的消息。
-本文档主要介绍PSM的使用,其主要是依赖Easyflash库来实现的,包括数据的存储、获取、dump和擦除功能。
-编译 customer_app/sdk_app_psm
工程并下载bin文件。
使用 psm_set <key> <value>
命令向指定ENV_name中写入数据,如输入 psm_set data_test 12345678
命令表示将ENV_name为 data_test
的值设为 12345678
;
使用 psm_get <key>
命令读出指定ENV_name中存储的值,如读取上面写入的数据,输入命令:psm_get data_test;
使用 psm_unset <key>
命令清除指定ENV_name中存储的值,如清除上面写入的数据,输入命令:psm_unset data_test;
使用 psm_dump
命令可以将所有ENV_name存储的信息dunmp出来,如输入命令:psm_dump,可以看到mode。size等相关信息;
使用 psm_erase
命令可以将所有ENV_name存储的信息清除。
初始化
easyflash_init();
-
在操作psm时首先需要调用easyflash的初始化接口。该函数在 customer_app/sdk_app_psm/sdk_app_psm/main.c
中的 static void aos_loop_proc(void *pvParameters)
函数里完成初始化。
写数据
ef_set_env(argv[1], argv[2]);
-ef_save_env();
-
写数据首先调用ef_set_env()接口写入数据,接着ef_save_env()接口将数据保存起来。
-读数据
ef_get_env(argv[1]);
-
调用此接口即可读取相应key的数据。
-dump数据
ef_print_env();
-
调用此接口打印所有存储在psm中的数据。
-擦除数据
ef_del_env(argv[1]);
-ef_save_env();
-
擦除ENV_name为argv[1]中的数据。
-ef_env_set_default();
-
调用此接口将擦除保存在psm中所有的数据。
-本示例主要介绍如何使用Romfs分区。
-使用之前新建目录 test/child
准备名为 aa.bin
的文件,将其放入新建的目录下。
使用步骤:
-下载时将烧写工具上的 Romfs
选项勾选起来,路径选择如下图一所示,烧写完后可以使用 ls
命令查看romfs分区中的内容;
打开文件操作:
fd = aos_open("/romfs/demo.bin", 0);
-log_info("fd = %d\r\n", fd);
-if (fd < 0) {
- log_error("open error.\r\n");
- return;
-}
-
读文件操作:
len = aos_read(fd, buf, 1);
-log_info("len = %d\r\n", len);
-log_buf(buf, 1);
-
lseek操作:
aos_lseek(fd, 1, SEEK_CUR);
-memset(buf, 0, sizeof(buf));
-len = aos_read(fd, buf, 1);
-log_info("len = %d\r\n", len);
-log_buf(buf, 1);
-
获取文件首地址和文件大小操作:
aos_ioctl(fd, IOCTL_ROMFS_GET_FILEBUF, (long unsigned int)&filebuf);
-log_info("filebuf.buf = %p\r\n", filebuf.buf);
-log_info("filebuf.bufsize = %lu\r\n", filebuf.bufsize);
-
本实例主要介绍如何增加一个cli(command-line interface)。
-编译 customer_app/sdk_app_cli
工程并下载对应的bin文件。
使用 test
命令即可在终端看到打印的 hello world
。
static void cmd_cli(char *buf, int len, int argc, char **argv)
-{
- printf("hello world\r\n");
-}
-
-const static struct cli_command cmds_user[] STATIC_CLI_CMD_ATTRIBUTE = {
- {"test", "cli test", cmd_cli},
-};
-
-int test_cli_init(void)
-{
- // static command(s) do NOT need to call aos_cli_register_command(s) to register.
- // However, calling aos_cli_register_command(s) here is OK but is of no effect as cmds_user are included in cmds list.
- // XXX NOTE: Calling this *empty* function is necessary to make cmds_user in this file to be kept in the final link.
- //return aos_cli_register_commands(cmds_user, sizeof(cmds_user)/sizeof(cmds_user[0]));
- return 0;
-}
-
用户在只需在程序中调用test_cli_init()
接口之后,就可以在shell中test
,就可以打印hello world.
如下所示:
#
-#
-# test
-hello world.
-#
-#
-
本示例主要介绍如何从fdt文件中获取相关的配置。
-编译 customer_app/sdk_app_fdt
工程并下载对应的bin文件;
使用 fdt
命令将fdt文件中的wifi配置解析出来,并且打印出整个文件内容。
本实例为了方便测试,将dts文件转换成数组的形式存放,转换命令 xxd -i demo.dts > demo.c
。
以wifi为例,通过 wifi
这个根节点获取其 offset
wifi_offset = fdt_subnode_offset(fdt, 0, "wifi");
-if (!(wifi_offset > 0)) {
- log_error("wifi NULL.\r\n");
-}
-
通过获取的 wifi_offset
获取子节点的 offset
offset1 = fdt_subnode_offset(fdt, wifi_offset, "ap");
-
通过获取的 offset1
获取相关的属性信息
// wifi->ap->ssid = string
-countindex = fdt_stringlist_count(fdt, offset1, "ssid");
-if (countindex > 0) {
- for (i = 0; i < countindex; i++) {
- result = fdt_stringlist_get(fdt, offset1, "ssid", i, &lentmp);
- if (lentmp > 0) {/* !NULL */
- log_info("ap string[%d] = %s, lentmp = %d\r\n", i, result, lentmp);
- }
- }
-} else {
- log_error("ap NULL.\r\n");
-}
-// wifi->ap->pwd = string
-countindex = fdt_stringlist_count(fdt, offset1, "pwd");
-if (countindex > 0) {
- for (i = 0; i < countindex; i++) {
- result = fdt_stringlist_get(fdt, offset1, "pwd", i, &lentmp);
- if (lentmp > 0) {/* !NULL */
- log_info("pwd string[%d] = %s, lentmp = %d\r\n", i, result, lentmp);
- }
- }
-} else {
- log_error("pwd NULL.\r\n");
-}
-
属性信息为字符串格式时参照如上code,为u32格式时参照如下code
-// wifi->ap->ap_channel = u32
-addr_prop = fdt_getprop(fdt, offset1, "ap_channel", &lentmp);
-if (addr_prop) {
- log_info("ap_channel = %ld\r\n", fdt32_to_cpu(*addr_prop));
-} else {
- log_error("ap_channel NULL.\r\n");
-}
-
dump文件信息
blfdtdump(tc_wifi_dtb, TC_WIFI_DTB_LEN, true, true);
-
其中 tc_wifi_dtb
为数组的基地址, TC_WIFI_DTB_LEN
为数组的大小。
下图为dump下来的部分信息,与源文件对应信息一致。
---- --
本示例主要介绍与wifi相关命令的功能。
-编译 customer_app/bl602_demo_wifi
工程并下载对应的bin文件;
成功启动IoT Board之后在终端输入命令 stack_wifi
创建wifi任务。
连接wifi:
命令: wifi_sta_connect <ssid> <pwd>
,如在终端输入 wifi_sta_connect bl_test_005 12345678
,成功连接wifi会打印wifi和memory相关信息,如下图中可以看到wifi的IP,MASK等信息,memory剩余大小信息 。
断开wifi:
命令: wifi_sta_disconnect
,成功断开连接后会打印断开连接的log。
扫描wifi:
命令: wifi_scan
,扫描成功后会打印scan list,用户可以看到成功搜索的wifi信息。
开启ap模式:
命令: wifi_ap_start
,成功开启后打印ssid,pwd,channel等相关信息,并且可以在手机上搜索到相应名字的wifi。
关闭ap模式:
命令: wifi_ap_stop
。成功关闭ap模式后手机无法搜索到对应wifi。
本示例主要介绍如何使用zigbee。
-编译 customer_app/bl702_demo_event
工程并下载工程;
Device1 使用 zb_set_role 0
命令设置设备类型ZC; 使用``zb_nwk_form 15 0x6666``创建信道15,PANID 0x6666的ZHA网络 ,打印的部分log如下。
--- --
Device1 使用 zb_nwk_permit 120
开放网络120秒;
--- --
Device2 使用 zb_set_role 1
命令设置设备类型ZR, 使用``zb_nwk_start`` 自动搜索zigbee网络,找到网络后打印的部分log如下。
--- --
Device1 使用 zb_zcl_onoff 0x9716 1 1 2
命令向Device2 ep1 发送zcl:toggle 命令
--- --
Device2 使用接收到zcl:toggle命令,打印的部分log如下。
--- --
本示例主要介绍Easyflash4 启动读写测试相关
-假定 ENV 分区里有 4 个扇区,以下将按照操作 ENV 的方式,逐一举例讲解不同操作下,对应的 Flash 状态及数据变化。
---- --
首次使用时,EasyFlash 会检查各个扇区的 header,如果不符合规定的格式将执行全部格式化操作,格式化后,每个扇区的顶部将被存入 header ,负责记录当前扇区的状态、魔数等信息。格式化的初始化状态为空状态。
--- --
在执行添加操作前,会先检索合适地址来存放即将添加的新 KV,这里检索策略主要是:
确定当前选择的扇区剩余容量充足
优选选择正在使用状态的扇区,最后使用空状态扇区
检查新 KV 是否有同名的 KV 存在,存在还需要额外执行删除旧值的动作
通过上图可以看出, KV1、KV2 及 KV3 已经被放入 sector1 ,添加后,扇区状态也被修改为正在使用。
--- --
修改 ENV 时,旧的 ENV 将被删除,扇区的状态也将被修改为脏状态,然后再执行新增 ENV 的操作。
执行修改 KV2 时,已经存在的 KV2 旧值被修改为已删除,sector1 状态被修改为脏状态,此后将 KV2 新值放入 sector1,发现 sector1 已经没有空间了,sector1 的状态还会被修改为已满状态;
执行修改 KV3 时,已经存在的 KV3 旧值被修改为已删除,sector1 状态已经为脏状态,无需再做修改。经过查找发现 KV3 的新值只能放到 sector2,放到 sector2 后将其修改为正在使用状态;
执行删除 KV1 时,找到 KV1 的位置,将其修改为已删除状态,sector1 状态已经为脏状态,无需再做修改;
执行添加 KV4 时,经过查找在 sector2 找到合适的存储位置,将其添加后,sector2 状态已经为正在使用状态,无需再做修改。
--- --
执行添加 KV5 操作,由于 KV5 体积较大,sector2 放不下,所以只能放在一个新扇区 sector3 上,添加后,修改 sector3 状态为正在使用 ;
执行添加 KV6 操作,KV6 也只能放在 sector3 下,将其放入 sector 3 后,发现 sector3 空间已满,所以将其修改已满状态。执行完成后,发现整个 ENV 的 4 个扇区只有 1 个状态为空的扇区了,这个扇区如果再继续使用就没法再执行 GC 操作了,所以此时触发了 GC 请求;
执行 GC 请求,EasyFlash 会找到所有被标记为已满并且为脏状态的扇区,并将其内部的 ENV 搬运至其他位置。就这样 sector1 上的 KV2 被搬运至了 sector2,腾空 sector1 后,又对其执行了格式化操作,这样整个 ENV 分区里又多了一个空状态的扇区。
测试流程为:easyflash初始化 → 读boottimes → boottimes++ → 写boottimes,反复复位重启800次。
-easyflash初始化
uint32_t timer_us;
-
-timer_us = bl_timer_now_us();
-easyflash_init();
-timer_us = bl_timer_now_us() - timer_us;
-printf("easyflash init time us %ld\r\n", timer_us);
-
读写boottimes
static void __easyflash_boottimes_dump()
-{
- char *times = NULL;
- uint32_t times_num = 0;
- char env_set[12] = {0};
-
- uint32_t timer_us;
-
- timer_us = bl_timer_now_us();
- times = ef_get_env(EASYFLASH_BOOT_TIMES);
- timer_us = bl_timer_now_us() - timer_us;
- printf("easyflash read boot_times us %ld\r\n", timer_us);
-
- if (times == NULL) {
- __easyflash_first_boottimes();
- return;
- }
- times_num = atoi(times);
- sprintf(env_set, "%ld", ++times_num);
-
- timer_us = bl_timer_now_us();
- ef_set_env(EASYFLASH_BOOT_TIMES, env_set);
- ef_save_env();
- timer_us = bl_timer_now_us() - timer_us;
- printf("easyflash write boot_times us %ld\r\n", timer_us);
-
- printf("The system now boot times %ld\r\n", times_num);
-}
-
测试结果如下图:
---
横坐标:boot times (单位:次数)
-纵坐标:时间(单位:us)
-红色线:easyflash 初始化耗时
-绿色线:easyflash 写耗时
-黄色线:读easyflash耗时
-easyflash_init过程包含读和其他操作,故初始化时间与读时间相关。图中第一次出现尖峰现象说明此时easyflash在检查并格式化扇区,详见: 首次使用。
读过程分析:由于easyflash4每write一次kv(写KV详细过程见: 添加KV),都会在old_kv地址后新增一个kv,再将old_kv标记为“delete”,所以每读一次kv,都需要遍历一遍kv,write次数越多,读耗时越长。
写过程分析:写之前都需要read找到kv(修改KV详细过程见: 修改KV),本次测试write在read之后,每read一次后easyflash会更新到cache,故write的时间并没有与read呈线性关系。
图中可见,在boottimes在688次左右时,读写操作时间“初始化”了,同时write的时间出现尖峰,此时触发了GC(触发GC过程详见: 触发GC),说明flash的大小已经快操作尽,只剩一个空闲sector。
本示例主要介绍demo_pwm相关
-dts 文件的修改
pwm {
- #address-cells = <1>;
- #size-cells = <1>;
- pwm@4000A420 {
- status = "okay";
- compatible = "bl602_pwm";
- reg = <0x4000A420 0x20>;
- path = "/dev/pwm0";
- id = <0>;
- pin = <0>;
- freq = <800000>;
- duty = <50>;
- };
-};
-
编译 customer_app/sdk_app_pwm
工程并下载对应的bin文件;
命令: pwm_task
,开启pwm_task相关测试线程,用示波器测量io0,会发现从占空比为0到100递增,到最后关闭。
本文档旨在指导用户搭建 BL602 硬件开发的软件环境。
-打开终端,安装make,命令:sudo apt-get update
、sudo apt-get install make
安装串口工具此处选用的Gtkterm
-可以执行命令:sudo apt-get install gtkterm
安装解压软件,命令:sudo apt-get install unzip
进入SDK文件所在的目录后开始解压,命令:cd work
、unzip bl_iot_sdk.zip
注意:cd
之后的文件名为SDK所在的目录名(如本例中,SDK源文件放在work
文件夹下)根据实际情况修改;unzip
之后文件名需要根据实际拿到的SDK文件名作出相应的修改
检查源代码解压之后的根目录状态,先用cd bl_iot_sdk
命令进入源文件目录,再用ls
命令检查目录状态
模块的相关引脚连接如下图所示,其中图一是模块的正面图,其标号1处用跳线帽短接,标号2处将左边两根排针短接,标号3处将上面的两根排针短接;图二是模块的背面图,将 IO8
和 LOW
两根排针短接。
进入需要编译的工程目录,命令:cd customer_app/bl602_demo_event
,进行编译,命令./genromap
查看编译生成的build_out文件夹,命令:ls build_out
进入/bl_iot_sdk/tools/flash_tool
目录下,双击名为 BLFlashEnv
的可执行文件 。
chip type
选择BL602/604,打开后界面参数参考下图配置:
点击download
,出现如下图所示表明下载成功:
下载完成后,打开串口终端Gtkterm,配置如下:
-保证终端右下角的DTR
是黑色状态, RTS
为灰色状态, DTR
可以通过快捷键 F7
控制, RTS
可以通过快捷键 F8
控制,最终配置如下图所示。
本文档旨在指导用户搭建 BL602硬件开发的软件环境。
-安装串口工具,此处选用的 ScriptCommunicator
打开MSYS2并安装make,输入命令:pacman -S make
-后回车,并根据提示直到安装完成
打开MSYS2的安装目录并将SDK源代码放入home
目录中的用户名文件夹下,下图中为igor
文件夹
注意:实例中使用的账户是igor
,实际操作时可以根据home
目录下的文件名确定当前用户名
安装解压软件,命令:pacman -S unzip
,还可选安装如下组件:pacman -S git
、pacman -S tmux
-等
对源文件压缩包进行解压,命令:unzip bl_iot_sdk.zip
注意:unzip
之后文件名需要根据实际拿到的SDK文件名作出相应的修改
模块的相关引脚连接如下图所示,其中图一是模块的正面图,其标号1处用跳线帽短接,标号2处将左边两根排针短接,标号3处将上面的两根排针短接;图二是模块的背面图,将 IO8
和 LOW
两根排针短接。
进入需要编译的工程目录,命令:cd customer_app/bl602_demo_event
进行编译,命令:./genromap
打开bl_iot_sdk/tools/flash_tool
文件中的simple_flasher.exe
程序
chip type
选择BL602/604
,打开后界面参数参考下图配置:
点击download
,出现如下图所示表明下载成功:
打开串口终端,点击 settings
配置为如下图所示,其中 DTR
需要勾选上, RTS
不勾选。
for example: we have a head File named example.h
in
-components/sys
directory,then change to docs
directory,modify
-the INPUT
configuration in the Doxyfile
file,here we should
-add a line with ../../components/sys/example.h
.
change to docs/zh_CH/API/sys
subdirectory,new a file named
-example.rst
.
reference docs/zh_CH/API/sys/cronalarms.rst
,here we replace
-cronalarms
with example
.
change to docs/zh_CH
subdirectory,modify index.rst
,add a
-line with API/sys/example
in the last line of the file.
At first,run pip3 install --user -r requirements.txt
install
-environment
Change to docs/zh_CN subdirectory and run make html
make
will probably prompt you to run a python pip install step to
-get some other Python-related prerequisites. Run the command as
-shown, then re-run make html
to build the docs.