From fc5f2b38324d7f14735a9bda8d27bfe3802d9226 Mon Sep 17 00:00:00 2001 From: "David B. Kinder" Date: Tue, 2 May 2017 17:21:56 -0700 Subject: [PATCH 01/19] doc: spelling check doxygen comments include/ fix misspellings found in doxygen comments used for API docs Signed-off-by: David B. Kinder --- include/arch/x86/arch.h | 2 +- include/bluetooth/bluetooth.h | 4 ++-- include/bluetooth/conn.h | 6 +++--- include/bluetooth/gatt.h | 10 +++++----- include/bluetooth/sdp.h | 4 ++-- include/display/grove_lcd.h | 6 +++--- include/drivers/usb/usb_dc.h | 6 +++--- include/kernel.h | 4 ++-- include/logging/kernel_event_logger.h | 2 +- include/logging/sys_log.h | 2 +- include/misc/byteorder.h | 16 ++++++++-------- include/misc/dlist.h | 4 ++-- include/misc/slist.h | 4 ++-- include/net/buf.h | 4 ++-- include/net/ieee802154_radio.h | 2 +- include/net/net_context.h | 2 +- include/net/net_mgmt.h | 4 ++-- include/net/net_offload.h | 2 +- include/net/net_pkt.h | 8 ++++---- include/net/zoap.h | 4 ++-- include/usb/usb_device.h | 4 ++-- include/usb/usbstruct.h | 4 ++-- 22 files changed, 52 insertions(+), 52 deletions(-) diff --git a/include/arch/x86/arch.h b/include/arch/x86/arch.h index 24bd9929dd57c..c088bd6966b37 100644 --- a/include/arch/x86/arch.h +++ b/include/arch/x86/arch.h @@ -440,7 +440,7 @@ extern void _arch_irq_disable(unsigned int irq); * by _Swap() it will either inherit an FPU that is guaranteed to be in a "sane" * state (if the most recent user of the FPU was cooperatively swapped out) * or the thread's own floating point context will be loaded (if the most - * recent user of the FPU was pre-empted, or if this thread is the first user + * recent user of the FPU was preempted, or if this thread is the first user * of the FPU). Thereafter, the kernel will protect the thread's FP context * so that it is not altered during a preemptive context switch. * diff --git a/include/bluetooth/bluetooth.h b/include/bluetooth/bluetooth.h index e24e352a19f53..73d1242b7d095 100644 --- a/include/bluetooth/bluetooth.h +++ b/include/bluetooth/bluetooth.h @@ -118,7 +118,7 @@ struct bt_le_adv_param { /** Maximum Advertising Interval (N * 0.625) */ u16_t interval_max; - /** Optional pre-defined (random) own address. Currently + /** Optional predefined (random) own address. Currently * the only permitted use of this is for NRPA with * non-connectable advertising. */ @@ -179,7 +179,7 @@ int bt_le_adv_stop(void); * @param addr Advertiser LE address and type. * @param rssi Strength of advertiser signal. * @param adv_type Type of advertising response from advertiser. - * @param data Buffer containig advertiser data. + * @param data Buffer containing advertiser data. */ typedef void bt_le_scan_cb_t(const bt_addr_le_t *addr, s8_t rssi, u8_t adv_type, struct net_buf_simple *buf); diff --git a/include/bluetooth/conn.h b/include/bluetooth/conn.h index 28dc5a42cd192..bd836a6d286cb 100644 --- a/include/bluetooth/conn.h +++ b/include/bluetooth/conn.h @@ -196,7 +196,7 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, /** @brief Automatically connect to remote device if it's in range. * * This function enables/disables automatic connection initiation. - * Everytime the device looses the connection with peer, this connection + * Every time the device looses the connection with peer, this connection * will be re-established if connectable advertisement from peer is received. * * @param addr Remote Bluetooth address. @@ -219,7 +219,7 @@ int bt_le_set_auto_conn(bt_addr_le_t *addr, * In case of high duty cycle this will result in a callback with * connected() with a new connection or with an error. * - * The advertising may be cancelled with bt_conn_disconnect(). + * The advertising may be canceled with bt_conn_disconnect(). * * Returns a new reference that the the caller is responsible for managing. * @@ -282,7 +282,7 @@ u8_t bt_conn_enc_key_size(struct bt_conn *conn); * * This structure is used for tracking the state of a connection. * It is registered with the help of the bt_conn_cb_register() API. - * It's premissible to register multiple instances of this @ref bt_conn_cb + * It's permissible to register multiple instances of this @ref bt_conn_cb * type, in case different modules of an application are interested in * tracking the connection state. If a callback is not of interest for * an instance, it may be set to NULL and will as a consequence not be diff --git a/include/bluetooth/gatt.h b/include/bluetooth/gatt.h index 28228768d49c6..eb5002fb0276a 100644 --- a/include/bluetooth/gatt.h +++ b/include/bluetooth/gatt.h @@ -343,7 +343,7 @@ ssize_t bt_gatt_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr, /** @brief Read Service Attribute helper. * * Read service attribute value storing the result into buffer after - * enconding it. + * encoding it. * NOTE: Only use this with attributes which user_data is a bt_uuid. * * @param conn Connection object. @@ -408,7 +408,7 @@ ssize_t bt_gatt_attr_read_service(struct bt_conn *conn, /** @brief Read Include Attribute helper. * * Read include service attribute value storing the result into buffer after - * enconding it. + * encoding it. * NOTE: Only use this with attributes which user_data is a bt_gatt_include. * * @param conn Connection object. @@ -442,7 +442,7 @@ ssize_t bt_gatt_attr_read_included(struct bt_conn *conn, /** @brief Read Characteristic Attribute helper. * * Read characteristic attribute value storing the result into buffer after - * enconding it. + * encoding it. * NOTE: Only use this with attributes which user_data is a bt_gatt_chrc. * * @param conn Connection object. @@ -497,7 +497,7 @@ struct _bt_gatt_ccc { /** @brief Read Client Characteristic Configuration Attribute helper. * * Read CCC attribute value storing the result into buffer after - * enconding it. + * encoding it. * NOTE: Only use this with attributes which user_data is a _bt_gatt_ccc. * * @param conn Connection object. @@ -943,7 +943,7 @@ int bt_gatt_write(struct bt_conn *conn, struct bt_gatt_write_params *params); /** @brief Write Attribute Value by handle without response * * This procedure write the attribute value without requiring an - * acknowledgement that the write was successfully performed + * acknowledgment that the write was successfully performed * * @param conn Connection object. * @param handle Attribute handle. diff --git a/include/bluetooth/sdp.h b/include/bluetooth/sdp.h index 35372f88010ef..0d71f4bce92c7 100644 --- a/include/bluetooth/sdp.h +++ b/include/bluetooth/sdp.h @@ -472,7 +472,7 @@ struct bt_sdp_client_result { }; /** @brief Helper enum to be used as return value of bt_sdp_discover_func_t. - * The value informs the caller to perform futher pending actions or stop them. + * The value informs the caller to perform further pending actions or stop them. */ enum { BT_SDP_DISCOVER_UUID_STOP = 0, @@ -483,7 +483,7 @@ enum { * * @brief Callback type reporting to user that there is a resolved result * on remote for given UUID and the result record buffer can be used by user - * for futher inspection. + * for further inspection. * * A function of this type is given by the user to the bt_sdp_discover_params * object. It'll be called on each valid record discovery completion for given diff --git a/include/display/grove_lcd.h b/include/display/grove_lcd.h index 5d888afe88761..8bc945876082c 100644 --- a/include/display/grove_lcd.h +++ b/include/display/grove_lcd.h @@ -50,7 +50,7 @@ void glcd_clear(struct device *port); * @brief Function to change the display state. * @details This function provides the user the ability to change the state * of the display as per needed. Controlling things like powering on or off - * the screen, the option to display the cusror or not, and the ability to + * the screen, the option to display the cursor or not, and the ability to * blink the cursor. * * @param port Pointer to device structure for driver instance. @@ -129,9 +129,9 @@ u8_t glcd_function_get(struct device *port); #define GROVE_RGB_GREEN 2 #define GROVE_RGB_BLUE 3 /** - * @brief Set LCD background to a predfined color + * @brief Set LCD background to a predefined color * @param port Pointer to device structure for driver instance. - * @param color One of the pre-defined color options + * @param color One of the predefined color options */ void glcd_color_select(struct device *port, u8_t color); diff --git a/include/drivers/usb/usb_dc.h b/include/drivers/usb/usb_dc.h index 0ae236e08940c..f248e48234359 100644 --- a/include/drivers/usb/usb_dc.h +++ b/include/drivers/usb/usb_dc.h @@ -277,7 +277,7 @@ int usb_dc_ep_read(const u8_t ep, u8_t *const data, * @brief set callback function for the specified endpoint * * Function to set callback function for notification of data received and - * available to application or trasmit done on the selected endpoint, + * available to application or transmit done on the selected endpoint, * NULL if callback not required by application code. * * @param[in] ep Endpoint address corresponding to the one @@ -291,7 +291,7 @@ int usb_dc_ep_set_callback(const u8_t ep, const usb_dc_ep_callback cb); /** * @brief read data from the specified endpoint * - * This is similar to usb_dc_ep_read, the difference being that, it doesnt + * This is similar to usb_dc_ep_read, the difference being that, it doesn't * clear the endpoint NAKs so that the consumer is not bogged down by further * upcalls till he is done with the processing of the data. The caller should * reactivate ep by invoking usb_dc_ep_read_continue() do so. @@ -316,7 +316,7 @@ int usb_dc_ep_read_wait(u8_t ep, u8_t *data, u32_t max_data_len, * Clear the endpoint NAK and enable the endpoint to accept more data * from the host. Usually called after usb_dc_ep_read_wait() when the consumer * is fine to accept more data. Thus these calls together acts as flow control - * meachanism. + * mechanism. * * @param[in] ep Endpoint address corresponding to the one * listed in the device configuration table diff --git a/include/kernel.h b/include/kernel.h index 826052ea23b75..eb864e7601923 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -1139,7 +1139,7 @@ extern s64_t k_uptime_get(void); /** * @brief Enable clock always on in tickless kernel * - * This routine enables keepng the clock running when + * This routine enables keeping the clock running when * there are no timer events programmed in tickless kernel * scheduling. This is necessary if the clock is used to track * passage of time. @@ -1159,7 +1159,7 @@ static inline int k_enable_sys_clock_always_on(void) /** * @brief Disable clock always on in tickless kernel * - * This routine disables keepng the clock running when + * This routine disables keeping the clock running when * there are no timer events programmed in tickless kernel * scheduling. To save power, this routine should be called * immediately when clock is not used to track time. diff --git a/include/logging/kernel_event_logger.h b/include/logging/kernel_event_logger.h index 3b1b803e10910..7d7908b509fb9 100644 --- a/include/logging/kernel_event_logger.h +++ b/include/logging/kernel_event_logger.h @@ -18,7 +18,7 @@ extern "C" { #endif -/* pre-defined event types */ +/* predefined event types */ #define KERNEL_EVENT_LOGGER_CONTEXT_SWITCH_EVENT_ID 0x0001 #define KERNEL_EVENT_LOGGER_INTERRUPT_EVENT_ID 0x0002 diff --git a/include/logging/sys_log.h b/include/logging/sys_log.h index ef4d06a62e9d3..f17332b1c2de8 100644 --- a/include/logging/sys_log.h +++ b/include/logging/sys_log.h @@ -156,7 +156,7 @@ void syslog_hook_install(void (*hook)(const char *, ...)); * * @details available if SYS_LOG_LEVEL is SYS_LOG_LEVEL_WARNING or higher. * It's meant to register messages related to unusual situations that are - * not necesarily errors. + * not necessarily errors. * * @param ... A string optionally containing printk valid conversion specifier, * followed by as many values as specifiers. diff --git a/include/misc/byteorder.h b/include/misc/byteorder.h index fc5654b7f0c7c..bcd160671c309 100644 --- a/include/misc/byteorder.h +++ b/include/misc/byteorder.h @@ -109,7 +109,7 @@ #endif /** - * @brief Put a 16-bit intger as big-endian to arbitrary location. + * @brief Put a 16-bit integer as big-endian to arbitrary location. * * Put a 16-bit integer, originally in host endianness, to a * potentially unaligned memory location in big-endian format. @@ -124,7 +124,7 @@ static inline void sys_put_be16(u16_t val, u8_t dst[2]) } /** - * @brief Put a 32-bit intger as big-endian to arbitrary location. + * @brief Put a 32-bit integer as big-endian to arbitrary location. * * Put a 32-bit integer, originally in host endianness, to a * potentially unaligned memory location in big-endian format. @@ -139,7 +139,7 @@ static inline void sys_put_be32(u32_t val, u8_t dst[4]) } /** - * @brief Put a 16-bit intger as little-endian to arbitrary location. + * @brief Put a 16-bit integer as little-endian to arbitrary location. * * Put a 16-bit integer, originally in host endianness, to a * potentially unaligned memory location in little-endian format. @@ -154,7 +154,7 @@ static inline void sys_put_le16(u16_t val, u8_t dst[2]) } /** - * @brief Put a 32-bit intger as little-endian to arbitrary location. + * @brief Put a 32-bit integer as little-endian to arbitrary location. * * Put a 32-bit integer, originally in host endianness, to a * potentially unaligned memory location in little-endian format. @@ -184,7 +184,7 @@ static inline void sys_put_le64(u64_t val, u8_t dst[8]) } /** - * @brief Get a 16-bit intger stored in big-endian format. + * @brief Get a 16-bit integer stored in big-endian format. * * Get a 16-bit integer, stored in big-endian format in a potentially * unaligned memory location, and convert it to the host endianness. @@ -199,7 +199,7 @@ static inline u16_t sys_get_be16(const u8_t src[2]) } /** - * @brief Get a 32-bit intger stored in big-endian format. + * @brief Get a 32-bit integer stored in big-endian format. * * Get a 32-bit integer, stored in big-endian format in a potentially * unaligned memory location, and convert it to the host endianness. @@ -214,7 +214,7 @@ static inline u32_t sys_get_be32(const u8_t src[4]) } /** - * @brief Get a 16-bit intger stored in little-endian format. + * @brief Get a 16-bit integer stored in little-endian format. * * Get a 16-bit integer, stored in little-endian format in a potentially * unaligned memory location, and convert it to the host endianness. @@ -229,7 +229,7 @@ static inline u16_t sys_get_le16(const u8_t src[2]) } /** - * @brief Get a 32-bit intger stored in little-endian format. + * @brief Get a 32-bit integer stored in little-endian format. * * Get a 32-bit integer, stored in little-endian format in a potentially * unaligned memory location, and convert it to the host endianness. diff --git a/include/misc/dlist.h b/include/misc/dlist.h index 72275238e3625..cb211488a3d94 100644 --- a/include/misc/dlist.h +++ b/include/misc/dlist.h @@ -132,7 +132,7 @@ typedef struct _dnode sys_dnode_t; /** * @brief Provide the primitive to iterate on a list under a container - * Note: the loop is unsafe and thus __cn should not be dettached + * Note: the loop is unsafe and thus __cn should not be detached * * User _MUST_ add the loop statement curly braces enclosing its own code: * @@ -150,7 +150,7 @@ typedef struct _dnode sys_dnode_t; /** * @brief Provide the primitive to safely iterate on a list under a container - * Note: __cn can be dettached, it will not break the loop. + * Note: __cn can be detached, it will not break the loop. * * User _MUST_ add the loop statement curly braces enclosing its own code: * diff --git a/include/misc/slist.h b/include/misc/slist.h index a3da0bfbbbc09..4afb8d729e530 100644 --- a/include/misc/slist.h +++ b/include/misc/slist.h @@ -138,7 +138,7 @@ typedef struct _slist sys_slist_t; /** * @brief Provide the primitive to iterate on a list under a container - * Note: the loop is unsafe and thus __cn should not be dettached + * Note: the loop is unsafe and thus __cn should not be detached * * User _MUST_ add the loop statement curly braces enclosing its own code: * @@ -156,7 +156,7 @@ typedef struct _slist sys_slist_t; /** * @brief Provide the primitive to safely iterate on a list under a container - * Note: __cn can be dettached, it will not break the loop. + * Note: __cn can be detached, it will not break the loop. * * User _MUST_ add the loop statement curly braces enclosing its own code: * diff --git a/include/net/buf.h b/include/net/buf.h index e09f29672a4be..7b2f03fe035f0 100644 --- a/include/net/buf.h +++ b/include/net/buf.h @@ -226,7 +226,7 @@ void net_buf_simple_push_u8(struct net_buf_simple *buf, u8_t val); /** * @brief Remove data from the beginning of the buffer. * - * Removes data from the beginnig of the buffer by modifying the data + * Removes data from the beginning of the buffer by modifying the data * pointer and buffer length. * * @param buf Buffer to update. @@ -826,7 +826,7 @@ static inline void *net_buf_user_data(struct net_buf *buf) * @def net_buf_pull * @brief Remove data from the beginning of the buffer. * - * Removes data from the beginnig of the buffer by modifying the data + * Removes data from the beginning of the buffer by modifying the data * pointer and buffer length. * * @param buf Buffer to update. diff --git a/include/net/ieee802154_radio.h b/include/net/ieee802154_radio.h index c2344dae3c611..a08c20776f674 100644 --- a/include/net/ieee802154_radio.h +++ b/include/net/ieee802154_radio.h @@ -74,7 +74,7 @@ extern int ieee802154_radio_send(struct net_if *iface, * @brief Radio driver ACK handling function that hw drivers should use * * @details ACK handling requires fast handling and thus such function - * helps to hook direcly the hw drivers to the radio driver. + * helps to hook directly the hw drivers to the radio driver. * * @param iface A valid pointer on a network interface that received the packet * @param pkt A valid pointer on a packet to check diff --git a/include/net/net_context.h b/include/net/net_context.h index 326cc76427102..e0d1c7cdf6ecd 100644 --- a/include/net/net_context.h +++ b/include/net/net_context.h @@ -691,7 +691,7 @@ int net_context_sendto(struct net_pkt *pkt, * called. The callback is called even if timeout was set to K_FOREVER, * the callback is called before this function will return in this case. * The callback is not called if the timeout expires. The timeout functionality - * can be compiled out if synchronous behaviour is not needed. The sync call + * can be compiled out if synchronous behavior is not needed. The sync call * logic requires some memory that can be saved if only async way of call is * used. If CONFIG_NET_CONTEXT_SYNC_RECV is not set, then the timeout parameter * value is ignored. diff --git a/include/net/net_mgmt.h b/include/net/net_mgmt.h index 6fefabe2f47c1..7be0679b476d7 100644 --- a/include/net/net_mgmt.h +++ b/include/net/net_mgmt.h @@ -199,7 +199,7 @@ void net_mgmt_event_notify(u32_t mgmt_event, struct net_if *iface); * has bit NET_MGMT_IFACE_BIT set relevantly, depending on events * the caller wants to listen to. * @param timeout a delay in milliseconds. K_FOREVER can be used to wait - * undefinitely. + * indefinitely. * * @return 0 on success, a negative error code otherwise. -ETIMEDOUT will * be specifically returned if the timeout kick-in instead of an @@ -220,7 +220,7 @@ int net_mgmt_event_wait(u32_t mgmt_event_mask, * the mask generated the event. Can be NULL if the caller is not * interested in that information. * @param timeout a delay in milliseconds. K_FOREVER can be used to wait - * undefinitely. + * indefinitely. * * @return 0 on success, a negative error code otherwise. -ETIMEDOUT will * be specifically returned if the timeout kick-in instead of an diff --git a/include/net/net_offload.h b/include/net/net_offload.h index 6e7e11bf8577b..aed1530acfb3f 100644 --- a/include/net/net_offload.h +++ b/include/net/net_offload.h @@ -369,7 +369,7 @@ static inline int net_offload_sendto(struct net_if *iface, * called. The callback is called even if timeout was set to K_FOREVER, * the callback is called before this function will return in this case. * The callback is not called if the timeout expires. The timeout functionality - * can be compiled out if synchronous behaviour is not needed. The sync call + * can be compiled out if synchronous behavior is not needed. The sync call * logic requires some memory that can be saved if only async way of call is * used. If CONFIG_NET_CONTEXT_SYNC_RECV is not set, then the timeout parameter * value is ignored. diff --git a/include/net/net_pkt.h b/include/net/net_pkt.h index e9797b25ff82e..da04c50b0a9e8 100644 --- a/include/net/net_pkt.h +++ b/include/net/net_pkt.h @@ -775,7 +775,7 @@ struct net_buf *net_pkt_frag_del(struct net_pkt *pkt, void net_pkt_frag_add(struct net_pkt *pkt, struct net_buf *frag); /** - * @brief Insert a fragment to a packet at the beginning of its framgment list + * @brief Insert a fragment to a packet at the beginning of its fragment list * * @param pkt pkt Network packet where to insert the fragment * @param frag Fragment to insert @@ -989,7 +989,7 @@ static inline bool net_pkt_append_le32(struct net_pkt *pkt, u32_t data) * @brief Get data from buffer * * @details Get N number of bytes starting from fragment's offset. If the total - * length of data is placed in multiple framgents, this function will read from + * length of data is placed in multiple fragments, this function will read from * all fragments until it reaches N number of bytes. Caller has to take care of * endianness if needed. * @@ -1011,7 +1011,7 @@ struct net_buf *net_frag_read(struct net_buf *frag, u16_t offset, * @brief Skip N number of bytes while reading buffer * * @details Skip N number of bytes starting from fragment's offset. If the total - * length of data is placed in multiple framgents, this function will skip from + * length of data is placed in multiple fragments, this function will skip from * all fragments until it reaches N number of bytes. This function is useful * when unwanted data (e.g. reserved or not supported data in message) is part * of fragment and want to skip it. @@ -1280,7 +1280,7 @@ int net_pkt_split(struct net_pkt *pkt, struct net_buf *orig_frag, struct net_buf **fragB, s32_t timeout); /** - * @brief Get information about pre-defined RX, TX and DATA pools. + * @brief Get information about predefined RX, TX and DATA pools. * * @param rx Pointer to RX pool is returned. * @param tx Pointer to TX pool is returned. diff --git a/include/net/zoap.h b/include/net/zoap.h index ca75f45f0045f..cabc96706e627 100644 --- a/include/net/zoap.h +++ b/include/net/zoap.h @@ -443,7 +443,7 @@ void zoap_pending_clear(struct zoap_pending *pending); * @brief Cancels awaiting for this reply, so it becomes available * again. * - * @param reply The reply to be cancelled + * @param reply The reply to be canceled */ void zoap_reply_clear(struct zoap_reply *reply); @@ -511,7 +511,7 @@ int zoap_packet_set_used(struct zoap_packet *zpkt, u16_t len); /** * @brief Adds an option to the packet. * - * Note: ptions must be added in numeric order of their codes. + * Note: options must be added in numeric order of their codes. * * @param zpkt Packet to be updated * @param code Option code to add to the packet, see #zoap_option_num diff --git a/include/usb/usb_device.h b/include/usb/usb_device.h index e05d6a8d32fe3..b80013c35cd98 100644 --- a/include/usb/usb_device.h +++ b/include/usb/usb_device.h @@ -263,7 +263,7 @@ int usb_ep_clear_stall(u8_t ep); /** * @brief read data from the specified endpoint * - * This is similar to usb_ep_read, the difference being that, it doesnt + * This is similar to usb_ep_read, the difference being that, it doesn't * clear the endpoint NAKs so that the consumer is not bogged down by further * upcalls till he is done with the processing of the data. The caller should * reactivate ep by invoking usb_ep_read_continue() do so. @@ -288,7 +288,7 @@ int usb_ep_read_wait(u8_t ep, u8_t *data, u32_t max_data_len, * Clear the endpoint NAK and enable the endpoint to accept more data * from the host. Usually called after usb_ep_read_wait() when the consumer * is fine to accept more data. Thus these calls together acts as flow control - * meachanism. + * mechanism. * * @param[in] ep Endpoint address corresponding to the one * listed in the device configuration table diff --git a/include/usb/usbstruct.h b/include/usb/usbstruct.h index de1fdb83fdefd..a60f44d14d1ef 100644 --- a/include/usb/usbstruct.h +++ b/include/usb/usbstruct.h @@ -28,9 +28,9 @@ /** * @file - * @brief standard USB packet stuctures and defines + * @brief standard USB packet structures and defines * - * This file contains stuctures and defines of the standard USB packets + * This file contains structures and defines of the standard USB packets */ #ifndef _USBSTRUCT_H_ From f6f8fb0f4748078fdf57e6545c1e0c32ea6a6b89 Mon Sep 17 00:00:00 2001 From: Rishi Khare Date: Wed, 3 May 2017 13:32:41 +0530 Subject: [PATCH 02/19] kernel tests: fatal: added "ignore_faults" tag This test generates a fault as part of the test,hence make the test-suite aware of that by tagging it. Signed-off-by: Rishi Khare --- tests/kernel/fatal/testcase.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/kernel/fatal/testcase.ini b/tests/kernel/fatal/testcase.ini index 914a14535fcb0..63fbe6d020c59 100644 --- a/tests/kernel/fatal/testcase.ini +++ b/tests/kernel/fatal/testcase.ini @@ -1,2 +1,2 @@ [test] -tags = core +tags = core ignore_faults From e0a643591dc35243e658b9c5d6f4c724e6b5644f Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Wed, 3 May 2017 10:14:42 +0200 Subject: [PATCH 03/19] net/net_if: Do not start TX thread if there is no network interface And print a warning if that happens. This will also avoid to raise an ASSERT on net_if_tx_thread()'s k_poll as this one will be called with no events to work with. Signed-off-by: Tomasz Bursztyka --- subsys/net/ip/net_if.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 7e15e5b54a63b..3b991b2484b9a 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -1673,6 +1673,11 @@ void net_if_init(struct k_sem *startup_sync) #endif } + if (iface == __net_if_start) { + NET_WARN("There is no network interface to work with!"); + return; + } + k_thread_spawn(tx_stack, sizeof(tx_stack), (k_thread_entry_t)net_if_tx_thread, startup_sync, NULL, NULL, K_PRIO_COOP(7), From d03b2496cd3c40d75e5bacdd15adf496948b665c Mon Sep 17 00:00:00 2001 From: Adithya Baglody Date: Wed, 3 May 2017 13:11:51 +0530 Subject: [PATCH 04/19] test: benchmarking: Timing metrics for the kernel JIRA: ZEP-1822, ZEP-1823, ZEP-1825 Signed-off-by: Adithya Baglody --- arch/arm/core/isr_wrapper.S | 18 + arch/arm/core/swap.S | 31 ++ arch/x86/core/intstub.S | 22 + arch/x86/core/swap.S | 32 ++ drivers/timer/cortex_m_systick.c | 10 + drivers/timer/loapic_timer.c | 21 +- kernel/Kconfig | 10 + kernel/init.c | 8 + tests/benchmarks/timing_info/Makefile | 4 + tests/benchmarks/timing_info/README.txt | 111 +++++ tests/benchmarks/timing_info/prj.conf | 4 + tests/benchmarks/timing_info/src/Makefile | 7 + .../timing_info/src/main_benchmark.c | 57 +++ .../timing_info/src/msg_passing_bench.c | 439 ++++++++++++++++++ .../timing_info/src/semaphore_bench.c | 183 ++++++++ .../benchmarks/timing_info/src/thread_bench.c | 347 ++++++++++++++ .../benchmarks/timing_info/src/timing_info.h | 95 ++++ .../benchmarks/timing_info/src/yield_bench.c | 85 ++++ tests/benchmarks/timing_info/testcase.ini | 3 + 19 files changed, 1486 insertions(+), 1 deletion(-) create mode 100644 tests/benchmarks/timing_info/Makefile create mode 100644 tests/benchmarks/timing_info/README.txt create mode 100644 tests/benchmarks/timing_info/prj.conf create mode 100644 tests/benchmarks/timing_info/src/Makefile create mode 100644 tests/benchmarks/timing_info/src/main_benchmark.c create mode 100644 tests/benchmarks/timing_info/src/msg_passing_bench.c create mode 100644 tests/benchmarks/timing_info/src/semaphore_bench.c create mode 100644 tests/benchmarks/timing_info/src/thread_bench.c create mode 100644 tests/benchmarks/timing_info/src/timing_info.h create mode 100644 tests/benchmarks/timing_info/src/yield_bench.c create mode 100644 tests/benchmarks/timing_info/testcase.ini diff --git a/arch/arm/core/isr_wrapper.S b/arch/arm/core/isr_wrapper.S index 28b3f6ead94ff..04bee7060fd30 100644 --- a/arch/arm/core/isr_wrapper.S +++ b/arch/arm/core/isr_wrapper.S @@ -43,6 +43,10 @@ SECTION_FUNC(TEXT, _isr_wrapper) push {lr} /* lr is now the first item on the stack */ +#ifdef CONFIG_EXECUTION_BENCHMARKING + bl read_systick_start_of_isr +#endif + #ifdef CONFIG_KERNEL_EVENT_LOGGER_INTERRUPT bl _sys_k_event_logger_interrupt #endif @@ -105,6 +109,20 @@ _idle_state_cleared: * in thumb mode */ ldm r1!,{r0,r3} /* arg in r0, ISR in r3 */ +#ifdef CONFIG_EXECUTION_BENCHMARKING +#if defined(CONFIG_ARMV6_M) + push {r3} +#endif + push {lr} + bl read_systick_end_of_isr +#if defined(CONFIG_ARMV6_M) + pop {r3} + mov lr,r3 + pop {r3} +#else + pop {lr} +#endif +#endif blx r3 /* call ISR */ #if defined(CONFIG_ARMV6_M) diff --git a/arch/arm/core/swap.S b/arch/arm/core/swap.S index e24a53d6b576d..b0ff7634b78e9 100644 --- a/arch/arm/core/swap.S +++ b/arch/arm/core/swap.S @@ -177,6 +177,23 @@ _thread_irq_disabled: msr PSP, ip +#ifdef CONFIG_EXECUTION_BENCHMARKING +#if defined(CONFIG_ARMV6_M) + push {r3} +#endif + push {lr} + + bl read_systick_end_of_swap + +#if defined(CONFIG_ARMV6_M) + pop {r3} + mov lr,r3 + pop {r3} +#else + pop {lr} +#endif +#endif + /* exc return */ bx lr @@ -292,6 +309,20 @@ _oops: SECTION_FUNC(TEXT, __swap) +#ifdef CONFIG_EXECUTION_BENCHMARKING +#if defined(CONFIG_ARMV6_M) + push {r3} +#endif + push {lr} + bl read_systick_start_of_swap +#if defined(CONFIG_ARMV6_M) + pop {r3} + mov lr,r3 + pop {r3} +#else + pop {lr} +#endif +#endif ldr r1, =_kernel ldr r2, [r1, #_kernel_offset_to_current] str r0, [r2, #_thread_offset_to_basepri] diff --git a/arch/x86/core/intstub.S b/arch/x86/core/intstub.S index 55bede1f743f9..9c6edbfa28b9a 100644 --- a/arch/x86/core/intstub.S +++ b/arch/x86/core/intstub.S @@ -78,6 +78,15 @@ */ SECTION_FUNC(TEXT, _interrupt_enter) +#ifdef CONFIG_EXECUTION_BENCHMARKING + pushl %eax + pushl %edx + rdtsc + mov %eax, __start_intr_tsc + mov %edx, __start_intr_tsc+4 + pop %edx + pop %eax +#endif /* * The gen_idt tool creates an interrupt-gate descriptor for * all connections. The processor will automatically clear the IF @@ -246,6 +255,19 @@ alreadyOnIntStack: */ push %eax #endif +#ifdef CONFIG_EXECUTION_BENCHMARKING + /* Save the eax and edx registers before reading the time stamp + * once done pop the values + */ + pushl %eax + pushl %edx + rdtsc + mov %eax,__end_intr_tsc + mov %edx,__end_intr_tsc+4 + pop %edx + pop %eax +#endif + #ifdef CONFIG_NESTED_INTERRUPTS sti /* re-enable interrupts */ #endif diff --git a/arch/x86/core/swap.S b/arch/x86/core/swap.S index 6c931637382cf..8687ebec49a6c 100644 --- a/arch/x86/core/swap.S +++ b/arch/x86/core/swap.S @@ -77,7 +77,28 @@ * */ +.macro read_tsc var_name + push %eax + push %edx + rdtsc + mov %eax,\var_name + mov %edx,\var_name+4 + pop %edx + pop %eax +.endm SECTION_FUNC(TEXT, __swap) +#ifdef CONFIG_EXECUTION_BENCHMARKING + /* Save the eax and edx registers before reading the time stamp + * once done pop the values. + */ + push %eax + push %edx + rdtsc + mov %eax,__start_swap_tsc + mov %edx,__start_swap_tsc+4 + pop %edx + pop %eax +#endif #ifdef CONFIG_X86_IAMCU /* save EFLAGS on stack right before return address, just as SYSV would * have done @@ -335,5 +356,16 @@ skipIntLatencyStop: */ popl %edx movl %edx, (%esp) +#endif + +#ifdef CONFIG_EXECUTION_BENCHMARKING + /* Save the eax and edx registers before reading the time stamp + * once done pop the values. + */ + cmp $0x1,__read_swap_end_tsc_value + jne time_read_not_needed + movw $0x2,__read_swap_end_tsc_value + read_tsc __common_var_swap_end_tsc +time_read_not_needed: #endif ret diff --git a/drivers/timer/cortex_m_systick.c b/drivers/timer/cortex_m_systick.c index 12656724225f8..fe98e17f7e8ff 100644 --- a/drivers/timer/cortex_m_systick.c +++ b/drivers/timer/cortex_m_systick.c @@ -211,6 +211,11 @@ void _timer_int_handler(void *unused) { ARG_UNUSED(unused); +#ifdef CONFIG_EXECUTION_BENCHMARKING + extern void read_systick_start_of_tick_handler(void); + read_systick_start_of_tick_handler(); +#endif + #ifdef CONFIG_KERNEL_EVENT_LOGGER_INTERRUPT extern void _sys_k_event_logger_interrupt(void); _sys_k_event_logger_interrupt(); @@ -337,6 +342,11 @@ void _timer_int_handler(void *unused) #endif /* CONFIG_SYS_POWER_MANAGEMENT */ +#ifdef CONFIG_EXECUTION_BENCHMARKING + extern void read_systick_end_of_tick_handler(void); + read_systick_end_of_tick_handler(); +#endif + extern void _ExcExit(void); _ExcExit(); } diff --git a/drivers/timer/loapic_timer.c b/drivers/timer/loapic_timer.c index 2f7d100b27870..15c008d8c5a41 100644 --- a/drivers/timer/loapic_timer.c +++ b/drivers/timer/loapic_timer.c @@ -252,6 +252,16 @@ static inline void program_max_cycles(void) void _timer_int_handler(void *unused /* parameter is not used */ ) { +#ifdef CONFIG_EXECUTION_BENCHMARKING + __asm__ __volatile__ ( + "pushl %eax\n\t" + "pushl %edx\n\t" + "rdtsc\n\t" + "mov %eax, __start_tick_tsc\n\t" + "mov %edx, __start_tick_tsc+4\n\t" + "pop %edx\n\t" + "pop %eax\n\t"); +#endif ARG_UNUSED(unused); #if defined(CONFIG_TICKLESS_KERNEL) @@ -324,7 +334,16 @@ void _timer_int_handler(void *unused /* parameter is not used */ _sys_clock_tick_announce(); #endif /*CONFIG_TICKLESS_IDLE*/ #endif - +#ifdef CONFIG_EXECUTION_BENCHMARKING + __asm__ __volatile__ ( + "pushl %eax\n\t" + "pushl %edx\n\t" + "rdtsc\n\t" + "mov %eax, __end_tick_tsc\n\t" + "mov %edx, __end_tick_tsc+4\n\t" + "pop %edx\n\t" + "pop %eax\n\t"); +#endif /* CONFIG_EXECUTION_BENCHMARKING */ } #ifdef CONFIG_TICKLESS_KERNEL diff --git a/kernel/Kconfig b/kernel/Kconfig index 03e586bbc46c9..ec0bc471fec43 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -204,6 +204,16 @@ config INT_LATENCY_BENCHMARK The metrics are displayed (and a new sampling interval is started) each time int_latency_show() is called thereafter. +config EXECUTION_BENCHMARKING + bool + prompt "Timing metrics " + default n + help + This option enables the tracking of various times inside the kernel + the exact set of metrics being tracked is board-dependent. + All timing measurements are enabled for X86 and ARM based architectures. + In other architectures only a subset are enabled. + config THREAD_MONITOR bool prompt "Thread monitoring [EXPERIMENTAL]" diff --git a/kernel/init.c b/kernel/init.c index 4037db246c3cb..63d27af1a0d57 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -56,6 +56,14 @@ u64_t __noinit __main_tsc; /* timestamp when main task starts */ u64_t __noinit __idle_tsc; /* timestamp when CPU goes idle */ #endif +#ifdef CONFIG_EXECUTION_BENCHMARKING +u64_t __noinit __start_swap_tsc; +u64_t __noinit __end_swap_tsc; +u64_t __noinit __start_intr_tsc; +u64_t __noinit __end_intr_tsc; +u64_t __noinit __start_tick_tsc; +u64_t __noinit __end_tick_tsc; +#endif /* init/main and idle threads */ #define IDLE_STACK_SIZE CONFIG_IDLE_STACK_SIZE diff --git a/tests/benchmarks/timing_info/Makefile b/tests/benchmarks/timing_info/Makefile new file mode 100644 index 0000000000000..4de50f93d4d3b --- /dev/null +++ b/tests/benchmarks/timing_info/Makefile @@ -0,0 +1,4 @@ +BOARD ?= qemu_x86 +CONF_FILE = prj.conf + +include ${ZEPHYR_BASE}/Makefile.inc diff --git a/tests/benchmarks/timing_info/README.txt b/tests/benchmarks/timing_info/README.txt new file mode 100644 index 0000000000000..1586b1a9ea2e7 --- /dev/null +++ b/tests/benchmarks/timing_info/README.txt @@ -0,0 +1,111 @@ +Title: Timing Information + +Description: + +Timing measurements for the following features of the OS. +1. Context switch + Time taken to compete the context switch, i.e time spent in _Swap function. +2. Interrupt latency + Time taken from the start of the common interrupt handler till the + actual ISR handler being called. +3. Tick overhead + Time spent by the cpu in the tick handler. +4. Thread Creation + Time spent in creating a thread. +5. Thread cancel + Time taken to cancel the thread which is not yet started execution. + So the time taken to complete the function call is measured. +6. Thread abort + Time taken to abort the thread which has already started execution. + So the time measured is from the start of the function call until the + another thread is swapped in. +7. Thread Suspend + The time measured is from the start of the function call until the current + thread is suspended and another thread is swapped in. +8. Thread Resume + The time measured is from the start of the function call until the required + thread is resumed by swap operation. +9. Thread Yield + The time measured is from the start of the function call until the higher priority + thread is swapped in. +10. Thread Sleep + The time measured is from the start of the function call until the current + thread is put on the timeout queue and another thread is swapped in. +11. Heap Malloc + The time to allocate heap memory in fixed size chunks. Continuously allocate + the memory from the pool. Average time taken to complete the function call + is measured. +12. Heap Free + Time to free heap memory in fixed size chunks. Continuously free + the memory that was allocated. Average time taken to complete the function call + is measured. +13. Semaphore Take with context switch + Taking a semaphore causes a thread waiting on the semaphore to be swapped in. + Thus Time measured is the time taken from the function call till the waiting + thread is swapped in. +14. Semaphore Give with context switch + Giving a semaphore causes a thread waiting on the semaphore to be swapped + in (higher priority). + Thus Time measured is the time taken from the function call till the waiting + thread is swapped in. +15. Semaphore Take without context switch + Time taken to take the semaphore. Thus time to complete the function + call is measured. +16. Semaphore Give without context switch + Time taken to give the semaphore. Thus time to complete the function + call is measured. +17. Mutex lock + Time taken to lock the mutex. Thus time to complete the function + call is measured. +18. Mutex unlock + Time taken to unlock the mutex. Thus time to complete the function + call is measured. +19. Message Queue Put with context switch + A thread is waiting for a message to arrive. The time taken from the start + of the function call till the waiting thread is swapped in is measured. +20. Message Queue Put without context switch + The time taken to complete the function call is measured. +21. Message Queue get with context switch + A thread has gone into waiting because the message queue is full. + When a get occurs this thread gets free to execute. The time taken from + the start of the function call till the waiting thread is + swapped in is measured. +22. Message Queue get without context switch + The time taken to complete the function call is measured. +23. MailBox synchronous put + The time taken from the start of the function call till the waiting thread + is swapped in is measured. +24. MailBox synchronous get + The time taken from the start of the function call till the waiting thread + is swapped in is measured. +25. MailBox asynchronous put + The time taken to complete the function call is measured. +26. MailBox get without context switch + The time taken to complete the function call is measured. + + +-------------------------------------------------------------------------------- + +Building and Running Project: + +This benchmark outputs to the console. It can be built and executed +on QEMU as follows: + + make qemu + +-------------------------------------------------------------------------------- + +Troubleshooting: + +Problems caused by out-dated project information can be addressed by +issuing one of the following commands then rebuilding the project: + + make clean # discard results of previous builds + # but keep existing configuration info +or + make pristine # discard results of previous builds + # and restore pre-defined configuration info + +-------------------------------------------------------------------------------- + +Sample Output: diff --git a/tests/benchmarks/timing_info/prj.conf b/tests/benchmarks/timing_info/prj.conf new file mode 100644 index 0000000000000..4cd820b63eeeb --- /dev/null +++ b/tests/benchmarks/timing_info/prj.conf @@ -0,0 +1,4 @@ +CONFIG_EXECUTION_BENCHMARKING=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_HEAP_MEM_POOL_SIZE=256 +CONFIG_MAIN_STACK_SIZE=2048 \ No newline at end of file diff --git a/tests/benchmarks/timing_info/src/Makefile b/tests/benchmarks/timing_info/src/Makefile new file mode 100644 index 0000000000000..5219ad793c368 --- /dev/null +++ b/tests/benchmarks/timing_info/src/Makefile @@ -0,0 +1,7 @@ +ccflags-y += -I$(ZEPHYR_BASE)/tests/include + +obj-$(CONFIG_EXECUTION_BENCHMARKING) += main_benchmark.o +obj-$(CONFIG_EXECUTION_BENCHMARKING) += thread_bench.o +obj-$(CONFIG_EXECUTION_BENCHMARKING) += yield_bench.o +obj-$(CONFIG_EXECUTION_BENCHMARKING) += semaphore_bench.o +obj-$(CONFIG_EXECUTION_BENCHMARKING) += msg_passing_bench.o diff --git a/tests/benchmarks/timing_info/src/main_benchmark.c b/tests/benchmarks/timing_info/src/main_benchmark.c new file mode 100644 index 0000000000000..2dec607142755 --- /dev/null +++ b/tests/benchmarks/timing_info/src/main_benchmark.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013-2015 Wind River Systems, Inc. + * Copyright (c) 2016 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Measure time + * + */ +#include +#include +#include +#include +#include "timing_info.h" + +void main(void) +{ + u32_t freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000000; + + TC_START("Time Measurement"); + TC_PRINT("Timing Results: Clock Frequency: %d MHz\n", freq); + + /*******************************************************************/ + /* System parameters and thread Benchmarking*/ + system_thread_bench(); + + /*******************************************************************/ + /* Thread yield*/ + yield_bench(); + + /*******************************************************************/ + /* heap Memory benchmarking*/ + heap_malloc_free_bench(); + + /*******************************************************************/ + /* Semaphore take and get*/ + semaphore_bench(); + + /*******************************************************************/ + /* mutex lock and unlock*/ + mutex_bench(); + + /*******************************************************************/ + /* mutex lock and unlock*/ + msg_passing_bench(); + + + TC_PRINT("Timing Measurement finished\n"); + + /* for sanity regression test utility. */ + TC_END_RESULT(TC_PASS); + TC_END_REPORT(TC_PASS); + +} \ No newline at end of file diff --git a/tests/benchmarks/timing_info/src/msg_passing_bench.c b/tests/benchmarks/timing_info/src/msg_passing_bench.c new file mode 100644 index 0000000000000..91bc447bbb7fd --- /dev/null +++ b/tests/benchmarks/timing_info/src/msg_passing_bench.c @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2013-2015 Wind River Systems, Inc. + * Copyright (c) 2016 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "timing_info.h" + +extern char sline[]; + +/* mailbox*/ +/* K_MBOX_DEFINE(test_msg_queue) */ +K_MSGQ_DEFINE(benchmark_q, sizeof(int), 10, 4); +K_MSGQ_DEFINE(benchmark_q_get, sizeof(int), 3, 4); +K_MBOX_DEFINE(benchmark_mbox); + +/* Declare a semaphore for the msgq*/ +K_SEM_DEFINE(mbox_sem, 1, 1); + +/* common location for the swap to write the tsc data*/ +extern u32_t __read_swap_end_tsc_value; +extern u64_t __common_var_swap_end_tsc; + +/* location of the time stamps*/ +u64_t __msg_q_put_state; +u64_t __msg_q_get_state; + +u64_t __msg_q_put_w_cxt_start_tsc; +u64_t __msg_q_put_w_cxt_end_tsc; + +u64_t __msg_q_put_wo_cxt_start_tsc; /* without context switch */ +u64_t __msg_q_put_wo_cxt_end_tsc; + +u64_t __msg_q_get_w_cxt_start_tsc; +u64_t __msg_q_get_w_cxt_end_tsc; + +u64_t msg_q_get_wo_cxt_start_tsc; +u64_t msg_q_get_wo_cxt_end_tsc; + +u32_t __mbox_sync_put_state; +u64_t mbox_sync_put_start_tsc; +u64_t mbox_sync_put_end_tsc; + +u32_t __mbox_sync_get_state; +u64_t mbox_sync_get_start_tsc; +u64_t mbox_sync_get_end_tsc; + +u64_t mbox_async_put_start_tsc; +u64_t mbox_async_put_end_tsc; + +u64_t mbox_get_w_cxt_start_tsc; +u64_t mbox_get_w_cxt_end_tsc; + +/*For benchmarking msg queues*/ +k_tid_t producer_w_cxt_switch_tid; +k_tid_t producer_wo_cxt_switch_tid; +k_tid_t producer_get_w_cxt_switch_tid; +k_tid_t consumer_get_w_cxt_switch_tid; +k_tid_t consumer_tid; +k_tid_t thread_mbox_sync_put_send_tid; +k_tid_t thread_mbox_sync_put_receive_tid; +k_tid_t thread_mbox_sync_get_send_tid; +k_tid_t thread_mbox_sync_get_receive_tid; +k_tid_t thread_mbox_async_put_send_tid; +k_tid_t thread_mbox_async_put_receive_tid; + +/* To time thread creation*/ +#define STACK_SIZE 500 +extern char __noinit __stack my_stack_area[STACK_SIZE]; +extern char __noinit __stack my_stack_area_0[STACK_SIZE]; + +/* thread functions*/ +void thread_producer_msgq_w_cxt_switch(void *p1, void *p2, void *p3); +void thread_producer_msgq_wo_cxt_switch(void *p1, void *p2, void *p3); + +void thread_producer_get_msgq_w_cxt_switch(void *p1, void *p2, void *p3); +void thread_consumer_get_msgq_w_cxt_switch(void *p1, void *p2, void *p3); + +void thread_mbox_sync_put_send(void *p1, void *p2, void *p3); +void thread_mbox_sync_put_receive(void *p1, void *p2, void *p3); + +void thread_mbox_sync_get_send(void *p1, void *p2, void *p3); +void thread_mbox_sync_get_receive(void *p1, void *p2, void *p3); + +void thread_mbox_async_put_send(void *p1, void *p2, void *p3); +void thread_mbox_async_put_receive(void *p1, void *p2, void *p3); + +volatile u64_t time_check; +int received_data_get; +int received_data_consumer; +int data_to_send; + +void msg_passing_bench(void) +{ + DECLARE_VAR(msg_q, put_w_cxt) + DECLARE_VAR(msg_q, put_wo_cxt) + + DECLARE_VAR(msg_q, get_w_cxt) + DECLARE_VAR(msg_q, get_wo_cxt) + + DECLARE_VAR(mbox, sync_put) + DECLARE_VAR(mbox, sync_get) + DECLARE_VAR(mbox, async_put) + + DECLARE_VAR(mbox, get_w_cxt) + + + /*******************************************************************/ + /* Msg queue for put*/ + int received_data = 0; + + producer_w_cxt_switch_tid = + k_thread_spawn(my_stack_area, STACK_SIZE, + thread_producer_msgq_w_cxt_switch, NULL, + NULL, NULL, 2 /*priority*/, 0, 50); + + u32_t msg_status = k_msgq_get(&benchmark_q, &received_data, 300); + + producer_wo_cxt_switch_tid = + k_thread_spawn(my_stack_area_0, STACK_SIZE, + thread_producer_msgq_wo_cxt_switch, + NULL, NULL, NULL, -2 /*priority*/, 0, 0); + + k_thread_abort(producer_w_cxt_switch_tid); + k_thread_abort(producer_wo_cxt_switch_tid); + __msg_q_put_w_cxt_end_tsc = ((u32_t)__common_var_swap_end_tsc); + ARG_UNUSED(msg_status); + + /*******************************************************************/ + + /* Msg queue for get*/ + + producer_get_w_cxt_switch_tid = + k_thread_spawn(my_stack_area, + STACK_SIZE, + thread_producer_get_msgq_w_cxt_switch, NULL, + NULL, NULL, 1 /*priority*/, 0, 50); + consumer_get_w_cxt_switch_tid = + k_thread_spawn(my_stack_area_0, + STACK_SIZE, + thread_consumer_get_msgq_w_cxt_switch, + NULL, NULL, NULL, + 2 /*priority*/, 0, 50); + k_sleep(2000); /* make the main thread sleep */ + k_thread_abort(producer_get_w_cxt_switch_tid); + __msg_q_get_w_cxt_end_tsc = (__common_var_swap_end_tsc); + + /*******************************************************************/ + + /* Msg queue for get*/ + /* from previous step got the msg_q full now just do a simple read*/ + msg_q_get_wo_cxt_start_tsc = OS_GET_TIME(); + + received_data_get = k_msgq_get(&benchmark_q_get, + &received_data_consumer, + K_NO_WAIT); + + msg_q_get_wo_cxt_end_tsc = OS_GET_TIME(); + + + /*******************************************************************/ + + /* Msg box to benchmark sync put */ + + thread_mbox_sync_put_send_tid = + k_thread_spawn(my_stack_area, + STACK_SIZE, + thread_mbox_sync_put_send, + NULL, NULL, NULL, + 2 /*priority*/, 0, 0); + thread_mbox_sync_put_receive_tid = + k_thread_spawn(my_stack_area_0, + STACK_SIZE, + thread_mbox_sync_put_receive, + NULL, NULL, NULL, + 1 /*priority*/, 0, 0); + k_sleep(1000); /* make the main thread sleep */ + mbox_sync_put_end_tsc = (__common_var_swap_end_tsc); + + /*******************************************************************/ + + /* Msg box to benchmark sync get */ + + thread_mbox_sync_get_send_tid = + k_thread_spawn(my_stack_area, + STACK_SIZE, + thread_mbox_sync_get_send, + NULL, NULL, NULL, + 1 /*prio*/, 0, 0); + thread_mbox_sync_get_receive_tid = + k_thread_spawn(my_stack_area_0, + STACK_SIZE, + thread_mbox_sync_get_receive, NULL, + NULL, NULL, 2 /*priority*/, 0, 0); + k_sleep(1000); /* make the main thread sleep */ + mbox_sync_get_end_tsc = (__common_var_swap_end_tsc); + + /*******************************************************************/ + + /* Msg box to benchmark async put */ + + thread_mbox_async_put_send_tid = + k_thread_spawn(my_stack_area, + STACK_SIZE, + thread_mbox_async_put_send, + NULL, NULL, NULL, + 2 /*prio*/, 0, 0); + thread_mbox_async_put_receive_tid = + k_thread_spawn(my_stack_area_0, + STACK_SIZE, + thread_mbox_async_put_receive, + NULL, NULL, NULL, + 3 /*priority*/, 0, 0); + k_sleep(1000); /* make the main thread sleep */ + + /*******************************************************************/ + int single_element_buffer = 0; + struct k_mbox_msg rx_msg = { + .size = sizeof(int), + .rx_source_thread = K_ANY, + .tx_target_thread = K_ANY + }; + mbox_get_w_cxt_start_tsc = OS_GET_TIME(); + + k_mbox_get(&benchmark_mbox, &rx_msg, &single_element_buffer, 300); + + mbox_get_w_cxt_end_tsc = OS_GET_TIME(); + + /*******************************************************************/ + + /* calculation for msg put with context switch */ + CALCULATE_TIME(__, msg_q, put_w_cxt) + + /* calculation for msg put without context switch */ + CALCULATE_TIME(__, msg_q, put_wo_cxt) + + /* calculation for msg get */ + CALCULATE_TIME(__, msg_q, get_w_cxt) + + /* calculation for msg get without context switch */ + CALCULATE_TIME(, msg_q, get_wo_cxt) + + /*calculation for msg box for sync put + * (i.e with a context to make the pending rx ready) + */ + CALCULATE_TIME(, mbox, sync_put) + + /*calculation for msg box for sync get + * (i.e with a context to make the pending tx ready) + */ + CALCULATE_TIME(, mbox, sync_get) + + /* calculation for msg box for async put */ + CALCULATE_TIME(, mbox, async_put) + + /* calculation for msg box for get without any context switch */ + CALCULATE_TIME(, mbox, get_w_cxt) + + /*******************************************************************/ + + /* Only print lower 32bit of time result */ + PRINT_F("Message Queue Put with context switch", + (u32_t)((__msg_q_put_w_cxt_end_tsc - + __msg_q_put_w_cxt_start_tsc) & 0xFFFFFFFFULL), + (u32_t) (total_msg_q_put_w_cxt_time & 0xFFFFFFFFULL)); + + PRINT_F("Message Queue Put without context switch", + (u32_t)((__msg_q_put_wo_cxt_end_tsc - + __msg_q_put_wo_cxt_start_tsc) & 0xFFFFFFFFULL), + (u32_t) (total_msg_q_put_wo_cxt_time & 0xFFFFFFFFULL)); + + PRINT_F("Message Queue get with context switch", + (u32_t)((__msg_q_get_w_cxt_end_tsc - + __msg_q_get_w_cxt_start_tsc) & 0xFFFFFFFFULL), + (u32_t) (total_msg_q_get_w_cxt_time & 0xFFFFFFFFULL)); + + PRINT_F("Message Queue get without context switch", + (u32_t)((msg_q_get_wo_cxt_end_tsc - + msg_q_get_wo_cxt_start_tsc) & 0xFFFFFFFFULL), + (u32_t) (total_msg_q_get_wo_cxt_time & 0xFFFFFFFFULL)); + + PRINT_F("MailBox synchronous put", + (u32_t)((mbox_sync_put_end_tsc - mbox_sync_put_start_tsc) + & 0xFFFFFFFFULL), + (u32_t) (total_mbox_sync_put_time & 0xFFFFFFFFULL)); + + PRINT_F("MailBox synchronous get", + (u32_t)((mbox_sync_get_end_tsc - mbox_sync_get_start_tsc) + & 0xFFFFFFFFULL), + (u32_t) (total_mbox_sync_get_time & 0xFFFFFFFFULL)); + + PRINT_F("MailBox asynchronous put", + (u32_t)((mbox_async_put_end_tsc - mbox_async_put_start_tsc) + & 0xFFFFFFFFULL), + (u32_t) (total_mbox_async_put_time & 0xFFFFFFFFULL)); + + PRINT_F("MailBox get without context switch", + (u32_t)((mbox_get_w_cxt_end_tsc - mbox_get_w_cxt_start_tsc) + & 0xFFFFFFFFULL), + (u32_t) (total_mbox_get_w_cxt_time & 0xFFFFFFFFULL)); + +} + +void thread_producer_msgq_w_cxt_switch(void *p1, void *p2, void *p3) +{ + int data_to_send = 5050; + + __read_swap_end_tsc_value = 1; + __msg_q_put_w_cxt_start_tsc = (u32_t) OS_GET_TIME(); + k_msgq_put(&benchmark_q, &data_to_send, K_NO_WAIT); +} + + +void thread_producer_msgq_wo_cxt_switch(void *p1, void *p2, void *p3) +{ + int data_to_send = 5050; + + __msg_q_put_wo_cxt_start_tsc = OS_GET_TIME(); + k_msgq_put(&benchmark_q, &data_to_send, K_NO_WAIT); + __msg_q_put_wo_cxt_end_tsc = OS_GET_TIME(); +} + + +void thread_producer_get_msgq_w_cxt_switch(void *p1, void *p2, void *p3) +{ + int status = 0; + + while (1) { + if (status == 0) { + data_to_send++; + } + status = k_msgq_put(&benchmark_q_get, &data_to_send, 20); + } +} + +void thread_consumer_get_msgq_w_cxt_switch(void *p1, void *p2, void *p3) +{ + producer_get_w_cxt_switch_tid->base.timeout.delta_ticks_from_prev = + _EXPIRED; + __read_swap_end_tsc_value = 1; + __msg_q_get_w_cxt_start_tsc = OS_GET_TIME(); + received_data_get = k_msgq_get(&benchmark_q_get, + &received_data_consumer, + 300); + time_check = OS_GET_TIME(); +} + + +void thread_mbox_sync_put_send(void *p1, void *p2, void *p3) +{ + int single_element_buffer = 1234; + struct k_mbox_msg tx_msg = { + .size = sizeof(int), + .info = 5050, + .tx_data = &single_element_buffer, + .rx_source_thread = K_ANY, + .tx_target_thread = K_ANY, + }; + + mbox_sync_put_start_tsc = OS_GET_TIME(); + __read_swap_end_tsc_value = 1; + k_mbox_put(&benchmark_mbox, &tx_msg, 300); + time_check = OS_GET_TIME(); +} + +void thread_mbox_sync_put_receive(void *p1, void *p2, void *p3) +{ + int single_element_buffer = 1234; + struct k_mbox_msg rx_msg = { + .size = sizeof(int), + .rx_source_thread = K_ANY, + .tx_target_thread = K_ANY + }; + + k_mbox_get(&benchmark_mbox, &rx_msg, &single_element_buffer, 300); +} + +void thread_mbox_sync_get_send(void *p1, void *p2, void *p3) +{ + int single_element_buffer = 1234; + struct k_mbox_msg tx_msg = { + .size = sizeof(int), + .info = 5050, + .tx_data = &single_element_buffer, + .rx_source_thread = K_ANY, + .tx_target_thread = K_ANY, + }; + + k_mbox_put(&benchmark_mbox, &tx_msg, 300); +} + +void thread_mbox_sync_get_receive(void *p1, void *p2, void *p3) +{ + int single_element_buffer; + struct k_mbox_msg rx_msg = { + .size = sizeof(int), + .rx_source_thread = K_ANY, + .tx_target_thread = K_ANY + }; + + __read_swap_end_tsc_value = 1; + mbox_sync_get_start_tsc = OS_GET_TIME(); + k_mbox_get(&benchmark_mbox, &rx_msg, &single_element_buffer, 300); +} + +void thread_mbox_async_put_send(void *p1, void *p2, void *p3) +{ + int single_element_buffer = 1234; + struct k_mbox_msg tx_msg = { + .size = sizeof(int), + .info = 5050, + .tx_data = &single_element_buffer, + .rx_source_thread = K_ANY, + .tx_target_thread = K_ANY, + }; + + mbox_async_put_start_tsc = OS_GET_TIME(); + k_mbox_async_put(&benchmark_mbox, &tx_msg, &mbox_sem); + mbox_async_put_end_tsc = OS_GET_TIME(); + k_mbox_async_put(&benchmark_mbox, &tx_msg, &mbox_sem); +} + +void thread_mbox_async_put_receive(void *p1, void *p2, void *p3) +{ + int single_element_buffer; + struct k_mbox_msg rx_msg = { + .size = sizeof(int), + .rx_source_thread = K_ANY, + .tx_target_thread = K_ANY + }; + + k_mbox_get(&benchmark_mbox, &rx_msg, &single_element_buffer, 300); + +} \ No newline at end of file diff --git a/tests/benchmarks/timing_info/src/semaphore_bench.c b/tests/benchmarks/timing_info/src/semaphore_bench.c new file mode 100644 index 0000000000000..dda7febcc7fe3 --- /dev/null +++ b/tests/benchmarks/timing_info/src/semaphore_bench.c @@ -0,0 +1,183 @@ +#include +#include +#include +#include +#include "timing_info.h" + + +extern char sline[]; + +K_SEM_DEFINE(sem_bench, 0, 1); +K_SEM_DEFINE(sem_bench_1, 0, 1); + +/* To time thread creation*/ +#define STACK_SIZE 500 +extern char __noinit __stack my_stack_area[STACK_SIZE]; +extern char __noinit __stack my_stack_area_0[STACK_SIZE]; + +/* u64_t thread_yield_start_tsc[1000]; */ +/* u64_t thread_yield_end_tsc[1000]; */ +u64_t thread_start_time; +u64_t thread_end_time; +u64_t sem_start_time; +u64_t sem_end_time; +u64_t sem_give_start_time; +u64_t sem_give_end_time; + +u32_t swap_called; +u64_t test_time2; +u64_t test_time1; + +void thread_sem0_test(void *p1, void *p2, void *p3); +void thread_sem1_test(void *p1, void *p2, void *p3); +void thread_sem0_give_test(void *p1, void *p2, void *p3); +void thread_sem1_give_test(void *p1, void *p2, void *p3); + +k_tid_t sem0_tid; +k_tid_t sem1_tid; + +extern u64_t __common_var_swap_end_tsc; +extern u32_t __read_swap_end_tsc_value; + +void semaphore_bench(void) +{ + + /* Thread yield*/ + + sem0_tid = k_thread_spawn(my_stack_area, + STACK_SIZE, + thread_sem0_test, NULL, NULL, NULL, + 2 /*priority*/, 0, 0); + sem1_tid = k_thread_spawn(my_stack_area_0, + STACK_SIZE, thread_sem1_test, + NULL, NULL, NULL, + 2 /*priority*/, 0, 0); + + k_sleep(1000); + + + /* u64_t test_time1 = _tsc_read(); */ + sem_end_time = (__common_var_swap_end_tsc); + u32_t sem_cycles = sem_end_time - sem_start_time; + + sem0_tid = k_thread_spawn(my_stack_area, + STACK_SIZE, thread_sem0_give_test, + NULL, NULL, NULL, + 2 /*priority*/, 0, 0); + sem1_tid = k_thread_spawn(my_stack_area_0, + STACK_SIZE, thread_sem1_give_test, + NULL, NULL, NULL, + 2 /*priority*/, 0, 0); + + k_sleep(1000); + sem_give_end_time = (__common_var_swap_end_tsc); + u32_t sem_give_cycles = sem_give_end_time - sem_give_start_time; + + + /* Semaphore without context switch*/ + u32_t sem_give_wo_cxt_start = OS_GET_TIME(); + + k_sem_give(&sem_bench); + u32_t sem_give_wo_cxt_end = OS_GET_TIME(); + u32_t sem_give_wo_cxt_cycles = sem_give_wo_cxt_end - + sem_give_wo_cxt_start; + + u32_t sem_take_wo_cxt_start = OS_GET_TIME(); + + k_sem_take(&sem_bench, 10); + u32_t sem_take_wo_cxt_end = OS_GET_TIME(); + u32_t sem_take_wo_cxt_cycles = sem_take_wo_cxt_end - + sem_take_wo_cxt_start; + + /* TC_PRINT("test_time1 , %d cycles\n", (u32_t)test_time1); */ + /* TC_PRINT("test_time2 , %d cycles\n", (u32_t)test_time2); */ + + PRINT_F("Semaphore Take with context switch", + sem_cycles, SYS_CLOCK_HW_CYCLES_TO_NS(sem_cycles)); + PRINT_F("Semaphore Give with context switch", + sem_give_cycles, SYS_CLOCK_HW_CYCLES_TO_NS(sem_give_cycles)); + + PRINT_F("Semaphore Take without context switch", + sem_take_wo_cxt_cycles, + SYS_CLOCK_HW_CYCLES_TO_NS(sem_take_wo_cxt_cycles)); + PRINT_F("Semaphore Give without context switch", + sem_give_wo_cxt_cycles, + SYS_CLOCK_HW_CYCLES_TO_NS(sem_give_wo_cxt_cycles)); + +} +/******************************************************************************/ +K_MUTEX_DEFINE(mutex0); +void mutex_bench(void) +{ + u32_t mutex_lock_start_tsc; + u32_t mutex_lock_end_tsc; + u32_t mutex_lock_diff = 0; + + u32_t mutex_unlock_start_tsc; + u32_t mutex_unlock_end_tsc; + u32_t mutex_unlock_diff = 0; + + for (int i = 0; i < 1000; i++) { + mutex_lock_start_tsc = OS_GET_TIME(); + k_mutex_lock(&mutex0, 100); + mutex_lock_end_tsc = OS_GET_TIME(); + + mutex_unlock_start_tsc = OS_GET_TIME(); + k_mutex_unlock(&mutex0); + mutex_unlock_end_tsc = OS_GET_TIME(); + + mutex_lock_diff += (mutex_lock_end_tsc - mutex_lock_start_tsc); + mutex_unlock_diff += (mutex_unlock_end_tsc - + mutex_unlock_start_tsc); + } + + PRINT_F("Mutex lock", mutex_lock_diff / 1000, + SYS_CLOCK_HW_CYCLES_TO_NS(mutex_lock_diff / 1000)); + + PRINT_F("Mutex unlock", mutex_unlock_diff / 1000, + SYS_CLOCK_HW_CYCLES_TO_NS(mutex_unlock_diff / 1000)); + +} + +/******************************************************************************/ +void thread_sem1_test(void *p1, void *p2, void *p3) +{ + + k_sem_give(&sem_bench); /* sync the 2 threads*/ + + __read_swap_end_tsc_value = 1; + sem_start_time = OS_GET_TIME(); + k_sem_take(&sem_bench, 10); +} + +u32_t sem_count; +void thread_sem0_test(void *p1, void *p2, void *p3) +{ + k_sem_take(&sem_bench, 10);/* To sync threads */ + + k_sem_give(&sem_bench); + sem_count++; + k_thread_abort(sem0_tid); +} +/******************************************************************************/ +void thread_sem1_give_test(void *p1, void *p2, void *p3) +{ + k_sem_give(&sem_bench); /* sync the 2 threads*/ + + k_sem_take(&sem_bench_1, 1000); /* clear the previous sem_give*/ + /* test_time1 = OS_GET_TIME(); */ +} + +void thread_sem0_give_test(void *p1, void *p2, void *p3) +{ + k_sem_take(&sem_bench, 10);/* To sync threads */ + /* test_time2 = OS_GET_TIME(); */ + + /* To make sure that the sem give will cause a swap to occur */ + k_thread_priority_set(sem1_tid, 1); + + __read_swap_end_tsc_value = 1; + sem_give_start_time = OS_GET_TIME(); + k_sem_give(&sem_bench_1); + +} \ No newline at end of file diff --git a/tests/benchmarks/timing_info/src/thread_bench.c b/tests/benchmarks/timing_info/src/thread_bench.c new file mode 100644 index 0000000000000..d99dc1a69d1b6 --- /dev/null +++ b/tests/benchmarks/timing_info/src/thread_bench.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2013-2015 Wind River Systems, Inc. + * Copyright (c) 2016 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Measure time + * + */ +#include +#include +#include +#include +#include "timing_info.h" + +char sline[256]; +/* FILE *output_file = stdout; */ + +/* location of the time stamps*/ +u32_t __read_swap_end_tsc_value; +u64_t __common_var_swap_end_tsc; + +volatile u64_t thread_abort_end_tsc; +volatile u64_t thread_abort_start_tsc; + +/* Thread suspend*/ +volatile u64_t thread_suspend_start_tsc; +volatile u64_t thread_suspend_end_tsc; + +/* Thread resume*/ +volatile u64_t thread_resume_start_tsc; +volatile u64_t thread_resume_end_tsc; + +/* Thread sleep*/ +volatile u64_t thread_sleep_start_tsc; +volatile u64_t thread_sleep_end_tsc; + +/*For benchmarking msg queues*/ +k_tid_t producer_tid; +k_tid_t consumer_tid; + +/* To time thread creation*/ +#define STACK_SIZE 500 +char __noinit __stack my_stack_area[STACK_SIZE]; +char __noinit __stack my_stack_area_0[STACK_SIZE]; + +u32_t __read_swap_end_tsc_value_test = 1; +u64_t dummy_time; +u64_t start_time; +u64_t test_end_time; + +#if CONFIG_X86 +u32_t benchmarking_overhead_swap(void) +{ + + __asm__ __volatile__ ( + "pushl %eax\n\t" + "pushl %edx\n\t" + "rdtsc\n\t" + "mov %eax,start_time\n\t" + "mov %edx,start_time+4\n\t" + "cmp $0x1,__read_swap_end_tsc_value_test\n\t" + "jne time_read_not_needed_test\n\t" + "movw $0x2,__read_swap_end_tsc_value\n\t" + "pushl %eax\n\t" + "pushl %edx\n\t" + "rdtsc\n\t" + "mov %eax,dummy_time\n\t" + "mov %edx,dummy_time+4\n\t" + "pop %edx\n\t" + "pop %eax\n\t" + "time_read_not_needed_test:\n\t" + "rdtsc\n\t" + "mov %eax,test_end_time\n\t" + "mov %edx,test_end_time+4\n\t" + "pop %edx\n\t" + "pop %eax\n\t"); + + /* u64_t end_time = OS_GET_TIME(); */ + return(test_end_time - start_time); +} +#endif + +#if CONFIG_ARM +void read_systick_start_of_swap(void) +{ + __start_swap_tsc = (u32_t)SysTick->VAL; +} + +void read_systick_end_of_swap(void) +{ + if (__read_swap_end_tsc_value == 1) { + __read_swap_end_tsc_value = 2; + __common_var_swap_end_tsc = OS_GET_TIME(); + } +} + +void read_systick_start_of_isr(void) +{ + __start_intr_tsc = (u32_t)SysTick->VAL; +} + +void read_systick_end_of_isr(void) +{ + __end_intr_tsc = (u32_t)SysTick->VAL; +} + +void read_systick_start_of_tick_handler(void) +{ + __start_tick_tsc = (u32_t)SysTick->VAL; +} + +void read_systick_end_of_tick_handler(void) +{ + __end_tick_tsc = (u32_t)SysTick->VAL; +} + +#endif + + + +void test_thread_entry(void *p, void *p1, void *p2) +{ + static int i; + + i++; +} + + +void thread_swap_test(void *p1, void *p2, void *p3) +{ + __read_swap_end_tsc_value = 1; + thread_abort_start_tsc = OS_GET_TIME(); + k_thread_abort(_current); +} + +void thread_suspend_test(void *p1, void *p2, void *p3); +void yield_bench(void); +void heap_malloc_free_bench(void); +void main_sem_bench(void); +void main_mutex_bench(void); +void main_msg_bench(void); + +void system_thread_bench(void) +{ + u64_t total_intr_time; + u64_t total_tick_time; + + /*Thread create*/ + u64_t thread_create_start_tsc; + u64_t thread_create_end_tsc; + + DECLARE_VAR(thread, create) + + /*Thread cancel*/ + u64_t thread_cancel_start_tsc; + u64_t thread_cancel_end_tsc; + DECLARE_VAR(thread, cancel) + + /* Thread Abort*/ + DECLARE_VAR(thread, abort) + + /* Thread Suspend*/ + DECLARE_VAR(thread, suspend) + + /* Thread Resume*/ + DECLARE_VAR(thread, resume) + + + /* to measure context switch time */ + k_thread_spawn(my_stack_area_0, + STACK_SIZE, + thread_swap_test, + NULL, NULL, NULL, + -1 /*priority*/, 0, 0); + + thread_abort_end_tsc = (__common_var_swap_end_tsc); + __end_swap_tsc = __common_var_swap_end_tsc; + + + u32_t total_swap_cycles = __end_swap_tsc - + SUBTRACT_CLOCK_CYCLES(__start_swap_tsc); + + /* Interrupt latency*/ + total_intr_time = SYS_CLOCK_HW_CYCLES_TO_NS(__end_intr_tsc - + __start_intr_tsc); + + /* tick overhead*/ + total_tick_time = SYS_CLOCK_HW_CYCLES_TO_NS(__end_tick_tsc - + __start_tick_tsc); + + /*******************************************************************/ + /* thread create*/ + thread_create_start_tsc = OS_GET_TIME(); + + k_tid_t my_tid = k_thread_spawn(my_stack_area, + STACK_SIZE, + thread_swap_test, + NULL, NULL, NULL, + 5 /*priority*/, 0, 10); + + thread_create_end_tsc = OS_GET_TIME(); + + /* thread Termination*/ + thread_cancel_start_tsc = OS_GET_TIME(); + s32_t ret_value_thread_cancel = k_thread_cancel(my_tid); + + thread_cancel_end_tsc = OS_GET_TIME(); + ARG_UNUSED(ret_value_thread_cancel); + + /* Thread suspend*/ + k_tid_t sus_res_tid = k_thread_spawn(my_stack_area, + STACK_SIZE, + thread_suspend_test, + NULL, NULL, NULL, + -1 /*priority*/, 0, 0); + + thread_suspend_end_tsc = OS_GET_TIME(); + /* At this point test for resume*/ + k_thread_resume(sus_res_tid); + + /* calculation for creation */ + CALCULATE_TIME(, thread, create) + + /* calculation for cancel */ + CALCULATE_TIME(, thread, cancel) + + /* calculation for abort */ + CALCULATE_TIME(, thread, abort) + + /* calculation for suspend */ + CALCULATE_TIME(, thread, suspend) + + /* calculation for resume */ + thread_resume_start_tsc = thread_suspend_end_tsc; + CALCULATE_TIME(, thread, resume) + + /*******************************************************************/ + + /* Only print lower 32bit of time result */ + + PRINT_F("Context switch", + (u32_t)(total_swap_cycles & 0xFFFFFFFFULL), + (u32_t)SYS_CLOCK_HW_CYCLES_TO_NS(total_swap_cycles)); + + /*TC_PRINT("Swap Overhead:%d cycles\n", benchmarking_overhead_swap());*/ + + /*Interrupt latency */ + u32_t intr_latency_cycles = SUBTRACT_CLOCK_CYCLES(__end_intr_tsc) - + SUBTRACT_CLOCK_CYCLES(__start_intr_tsc); + + PRINT_F("Interrupt latency", + (u32_t)(intr_latency_cycles), + (u32_t) (SYS_CLOCK_HW_CYCLES_TO_NS(intr_latency_cycles))); + + /*tick overhead*/ + u32_t tick_overhead_cycles = SUBTRACT_CLOCK_CYCLES(__end_tick_tsc) - + SUBTRACT_CLOCK_CYCLES(__start_tick_tsc); + PRINT_F("Tick overhead", + (u32_t)(tick_overhead_cycles), + (u32_t) (SYS_CLOCK_HW_CYCLES_TO_NS(tick_overhead_cycles))); + + /*thread creation*/ + PRINT_F("Thread Creation", + (u32_t)((thread_create_end_tsc - thread_create_start_tsc) & + 0xFFFFFFFFULL), + (u32_t) (total_thread_create_time & 0xFFFFFFFFULL)); + + /*thread cancel*/ + PRINT_F("Thread cancel", + (u32_t)((thread_cancel_end_tsc - thread_cancel_start_tsc) & + 0xFFFFFFFFULL), + (u32_t) (total_thread_cancel_time & 0xFFFFFFFFULL)); + + /*thread abort*/ + PRINT_F("Thread abort", + (u32_t)((thread_abort_end_tsc - thread_abort_start_tsc) & + 0xFFFFFFFFULL), + (u32_t) (total_thread_abort_time & 0xFFFFFFFFULL)); + + /*thread suspend*/ + PRINT_F("Thread Suspend", + (u32_t)((thread_suspend_end_tsc - thread_suspend_start_tsc) & + 0xFFFFFFFFULL), + (u32_t) (total_thread_suspend_time & 0xFFFFFFFFULL)); + + /*thread resume*/ + PRINT_F("Thread Resume", + (u32_t)((thread_resume_end_tsc - thread_suspend_end_tsc) + & 0xFFFFFFFFULL), + (u32_t) (total_thread_resume_time & 0xFFFFFFFFULL)); + + +} + +void thread_suspend_test(void *p1, void *p2, void *p3) +{ + thread_suspend_start_tsc = OS_GET_TIME(); + k_thread_suspend(_current); + + /* comes to this line once its resumed*/ + thread_resume_end_tsc = OS_GET_TIME(); + + /* k_thread_suspend(_current); */ +} + +void heap_malloc_free_bench(void) +{ + /* heap malloc*/ + u64_t heap_malloc_start_tsc = 0; + u64_t heap_malloc_end_tsc = 0; + + /* heap free*/ + u64_t heap_free_start_tsc = 0; + u64_t heap_free_end_tsc = 0; + + s32_t count = 0; + u32_t sum_malloc = 0; + u32_t sum_free = 0; + + while (count++ != 100) { + heap_malloc_start_tsc = OS_GET_TIME(); + void *allocated_mem = k_malloc(10); + + heap_malloc_end_tsc = OS_GET_TIME(); + if (allocated_mem == NULL) { + TC_PRINT("\n Malloc failed at count %d\n", count); + break; + } + heap_free_start_tsc = OS_GET_TIME(); + k_free(allocated_mem); + heap_free_end_tsc = OS_GET_TIME(); + sum_malloc += heap_malloc_end_tsc - heap_malloc_start_tsc; + sum_free += heap_free_end_tsc - heap_free_start_tsc; + } + + PRINT_F("Heap Malloc", + (u32_t)((sum_malloc / count) & 0xFFFFFFFFULL), + (u32_t)(SYS_CLOCK_HW_CYCLES_TO_NS(sum_malloc / count))); + PRINT_F("Heap Free", + (u32_t)((sum_free / count) & 0xFFFFFFFFULL), + (u32_t)(SYS_CLOCK_HW_CYCLES_TO_NS(sum_free / count))); + +} \ No newline at end of file diff --git a/tests/benchmarks/timing_info/src/timing_info.h b/tests/benchmarks/timing_info/src/timing_info.h new file mode 100644 index 0000000000000..3f69b16ecfb78 --- /dev/null +++ b/tests/benchmarks/timing_info/src/timing_info.h @@ -0,0 +1,95 @@ +#include + + +#define CALCULATE_TIME(special_char, profile, name) \ + { \ + total_##profile##_##name##_time = SYS_CLOCK_HW_CYCLES_TO_NS( \ + special_char##profile##_##name##_end_tsc - \ + special_char##profile##_##name##_start_tsc); \ + } + +/*total_##profile##_##name##_time = + * profile##_##name##_end_us - profile##_##name##_start_us; + */ + +#define DECLARE_VAR(profile, name) \ + u64_t total_##profile##_##name##_time; + +extern u64_t __start_swap_tsc; +extern u64_t __end_swap_tsc; +extern u64_t __start_intr_tsc; +extern u64_t __end_intr_tsc; +extern u64_t __start_tick_tsc; +extern u64_t __end_tick_tsc; + + + +/* Function prototypes */ +void system_thread_bench(void); +void yield_bench(void); +void heap_malloc_free_bench(void); +void semaphore_bench(void); +void mutex_bench(void); +void msg_passing_bench(void); + +/* PRINT_F + * Macro to print a formatted output string. fprintf is used when + * Assumed that sline character array of SLINE_LEN + 1 characters + * is defined in the main file + */ + +/* #define CSV_FORMAT_OUTPUT */ +/* printf format defines. */ +#ifdef CSV_FORMAT_OUTPUT +#define FORMAT "%-45s,%4u,%5u\n" +#else +#define FORMAT "%-45s:%4u cycles , %5u ns\n" +#endif +#include + +#define GET_2ND_ARG(first, second, ...) (second) +#define GET_3ND_ARG(first, second, third, ...) (third) + +/* Enable this macro to print all the measurements. + * Note: Some measurements in few architectures are not valid + */ +/* #define PRINT_ALL_MEASUREMENTS */ +#ifndef PRINT_ALL_MEASUREMENTS +/*If the measured cycles is greater than 10000 then one of the following is + * possible. + * 1. the selected measurement is not supported in the architecture + * 2. The measurement went wrong somewhere.(less likely to happen) + */ +#define PRINT_F(...) \ + { \ + if ((GET_2ND_ARG(__VA_ARGS__) <= 20000) && \ + (GET_2ND_ARG(__VA_ARGS__) != 0)) { \ + snprintf(sline, 254, FORMAT, ##__VA_ARGS__); \ + TC_PRINT("%s", sline); \ + } \ + } +#else +/* Prints all outputs*/ +#define PRINT_F(...) \ + { \ + snprintf(sline, 254, FORMAT, ##__VA_ARGS__); \ + TC_PRINT("%s", sline); \ + } + +#endif + + +/* If we are using x86 based controller we tend to read the tsc value which is + * always incrementing i.e count up counter. + * If we are using the ARM based controllers the systick is a + * count down counter. + * Hence to calculate the cycles taken up by the code we need to adjust the + * values accordingly. + * + * NOTE: Needed only when reading value from end of swap operation + */ +#if CONFIG_ARM +#define SUBTRACT_CLOCK_CYCLES(val) (SysTick->LOAD - (u32_t)val) +#else +#define SUBTRACT_CLOCK_CYCLES(val) (val) +#endif diff --git a/tests/benchmarks/timing_info/src/yield_bench.c b/tests/benchmarks/timing_info/src/yield_bench.c new file mode 100644 index 0000000000000..8da053cbe41c3 --- /dev/null +++ b/tests/benchmarks/timing_info/src/yield_bench.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include "timing_info.h" + +K_SEM_DEFINE(yield_sem, 0, 1); + +/* To time thread creation*/ +#define STACK_SIZE 500 +extern char __noinit __stack my_stack_area[STACK_SIZE]; +extern char __noinit __stack my_stack_area_0[STACK_SIZE]; + +/* u64_t thread_yield_start_tsc[1000]; */ +/* u64_t thread_yield_end_tsc[1000]; */ +/* location of the time stamps*/ +extern u32_t __read_swap_end_tsc_value; +extern u64_t __common_var_swap_end_tsc; +extern char sline[]; + +u64_t thread_sleep_start_tsc; +u64_t thread_sleep_end_tsc; +u64_t thread_start_time; +u64_t thread_end_time; +static u32_t count; + +void thread_yield0_test(void *p1, void *p2, void *p3); +void thread_yield1_test(void *p1, void *p2, void *p3); + +k_tid_t yield0_tid; +k_tid_t yield1_tid; +void yield_bench(void) +{ + + /* Thread yield*/ + + yield0_tid = k_thread_spawn(my_stack_area, + STACK_SIZE, + thread_yield0_test, + NULL, NULL, NULL, + 0 /*priority*/, 0, 0); + + yield1_tid = k_thread_spawn(my_stack_area_0, + STACK_SIZE, + thread_yield1_test, + NULL, NULL, NULL, + 0 /*priority*/, 0, 0); + + /*read the time of start of the sleep till the swap happens */ + __read_swap_end_tsc_value = 1; + + thread_sleep_start_tsc = OS_GET_TIME(); + k_sleep(1000); + thread_sleep_end_tsc = ((u32_t)__common_var_swap_end_tsc); + + u32_t yield_cycles = (thread_end_time - thread_start_time) / 2000; + u32_t sleep_cycles = thread_sleep_end_tsc - thread_sleep_start_tsc; + + PRINT_F("Thread Yield", yield_cycles, + SYS_CLOCK_HW_CYCLES_TO_NS(yield_cycles)); + PRINT_F("Thread Sleep", sleep_cycles, + SYS_CLOCK_HW_CYCLES_TO_NS(sleep_cycles)); + +} + + +void thread_yield0_test(void *p1, void *p2, void *p3) +{ + k_sem_take(&yield_sem, 10); + thread_start_time = OS_GET_TIME(); + while (count != 1000) { + count++; + k_yield(); + } + thread_end_time = OS_GET_TIME(); + k_thread_abort(yield1_tid); +} + +void thread_yield1_test(void *p1, void *p2, void *p3) +{ + k_sem_give(&yield_sem); + while (1) { + k_yield(); + } +} \ No newline at end of file diff --git a/tests/benchmarks/timing_info/testcase.ini b/tests/benchmarks/timing_info/testcase.ini new file mode 100644 index 0000000000000..717188e0d5d69 --- /dev/null +++ b/tests/benchmarks/timing_info/testcase.ini @@ -0,0 +1,3 @@ +[test] +tags = benchmark +arch_whitelist = x86 arm From 6a52a30b7d88a95dd5d6ab8a5b7c1b718cb931bc Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 24 Apr 2017 17:21:14 +0300 Subject: [PATCH 05/19] net: tcp: Mark ACK timer as cancelled This is related to commit "net: tcp: Make sure ACK timer is not run if cancelled" which did not set the cancel flag when the timer was cancelled from tcp.c. Signed-off-by: Jukka Rissanen --- subsys/net/ip/tcp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index eaa77a2370904..0447b81c07a68 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -216,6 +216,7 @@ int net_tcp_release(struct net_tcp *tcp) net_pkt_unref(pkt); } + tcp->ack_timer_cancelled = true; k_delayed_work_cancel(&tcp->ack_timer); k_timer_stop(&tcp->retry_timer); k_sem_reset(&tcp->connect_wait); From 08eb5fc42876b3c42adc88d6dc117faa38067e38 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 2 May 2017 10:01:47 +0300 Subject: [PATCH 06/19] net: bt: Fix not setting lladdr type When adding link-local address to the cache the type needs to be properly set as net_ipv6_addr_create_iid will attempt to use it when generating the IPv6 address. Jira: ZEP-2077 Signed-off-by: Luiz Augusto von Dentz --- subsys/net/ip/l2/bluetooth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/net/ip/l2/bluetooth.c b/subsys/net/ip/l2/bluetooth.c index 103555b18f410..1ce112f914f8a 100644 --- a/subsys/net/ip/l2/bluetooth.c +++ b/subsys/net/ip/l2/bluetooth.c @@ -138,6 +138,7 @@ static void ipsp_connected(struct bt_l2cap_chan *chan) ll.addr = ctxt->dst.val; ll.len = sizeof(ctxt->dst.val); + ll.type = NET_LINK_BLUETOOTH; /* Add remote link-local address to the nbr cache to avoid sending ns: * https://tools.ietf.org/html/rfc7668#section-3.2.3 From 7a0588ac9f6f29e07ef2b1738048c275c44f42d3 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Wed, 3 May 2017 10:33:42 +0200 Subject: [PATCH 07/19] samples: bluetooth: Set DT baud rate for nRF5x boards Since most of nRF5x-based boards can be used either as a standalone development kit or as a BLE controller to connect to an external host, add DT overlays so that the baud rate is correctly set to 1Mbit/s whenever building the hci_uart sample application. Signed-off-by: Carles Cufi --- samples/bluetooth/hci_uart/96b_nitrogen.overlay | 5 +++++ samples/bluetooth/hci_uart/nrf51_blenano.overlay | 5 +++++ samples/bluetooth/hci_uart/nrf51_pca10028.overlay | 5 +++++ samples/bluetooth/hci_uart/nrf52840_pca10056.overlay | 5 +++++ samples/bluetooth/hci_uart/nrf52_blenano2.overlay | 5 +++++ samples/bluetooth/hci_uart/nrf52_pca10040.overlay | 5 +++++ 6 files changed, 30 insertions(+) create mode 100644 samples/bluetooth/hci_uart/96b_nitrogen.overlay create mode 100644 samples/bluetooth/hci_uart/nrf51_blenano.overlay create mode 100644 samples/bluetooth/hci_uart/nrf51_pca10028.overlay create mode 100644 samples/bluetooth/hci_uart/nrf52840_pca10056.overlay create mode 100644 samples/bluetooth/hci_uart/nrf52_blenano2.overlay create mode 100644 samples/bluetooth/hci_uart/nrf52_pca10040.overlay diff --git a/samples/bluetooth/hci_uart/96b_nitrogen.overlay b/samples/bluetooth/hci_uart/96b_nitrogen.overlay new file mode 100644 index 0000000000000..4113eafe1d36c --- /dev/null +++ b/samples/bluetooth/hci_uart/96b_nitrogen.overlay @@ -0,0 +1,5 @@ +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "ok"; +}; diff --git a/samples/bluetooth/hci_uart/nrf51_blenano.overlay b/samples/bluetooth/hci_uart/nrf51_blenano.overlay new file mode 100644 index 0000000000000..4113eafe1d36c --- /dev/null +++ b/samples/bluetooth/hci_uart/nrf51_blenano.overlay @@ -0,0 +1,5 @@ +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "ok"; +}; diff --git a/samples/bluetooth/hci_uart/nrf51_pca10028.overlay b/samples/bluetooth/hci_uart/nrf51_pca10028.overlay new file mode 100644 index 0000000000000..4113eafe1d36c --- /dev/null +++ b/samples/bluetooth/hci_uart/nrf51_pca10028.overlay @@ -0,0 +1,5 @@ +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "ok"; +}; diff --git a/samples/bluetooth/hci_uart/nrf52840_pca10056.overlay b/samples/bluetooth/hci_uart/nrf52840_pca10056.overlay new file mode 100644 index 0000000000000..4113eafe1d36c --- /dev/null +++ b/samples/bluetooth/hci_uart/nrf52840_pca10056.overlay @@ -0,0 +1,5 @@ +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "ok"; +}; diff --git a/samples/bluetooth/hci_uart/nrf52_blenano2.overlay b/samples/bluetooth/hci_uart/nrf52_blenano2.overlay new file mode 100644 index 0000000000000..4113eafe1d36c --- /dev/null +++ b/samples/bluetooth/hci_uart/nrf52_blenano2.overlay @@ -0,0 +1,5 @@ +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "ok"; +}; diff --git a/samples/bluetooth/hci_uart/nrf52_pca10040.overlay b/samples/bluetooth/hci_uart/nrf52_pca10040.overlay new file mode 100644 index 0000000000000..4113eafe1d36c --- /dev/null +++ b/samples/bluetooth/hci_uart/nrf52_pca10040.overlay @@ -0,0 +1,5 @@ +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "ok"; +}; From cdbae26ac56d9cdda6658e78c8213efb9bebe8c9 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Wed, 3 May 2017 15:51:18 +0300 Subject: [PATCH 08/19] ipm: Trivial space adjustment Change-Id: I3182c2df5ffc9e2b6f1fc0d1ed4b401b030b9711 Signed-off-by: Andrei Emeltchenko --- drivers/ipm/ipm_quark_se.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ipm/ipm_quark_se.h b/drivers/ipm/ipm_quark_se.h index e6480a3efc769..05ecf822b612e 100644 --- a/drivers/ipm/ipm_quark_se.h +++ b/drivers/ipm/ipm_quark_se.h @@ -20,20 +20,20 @@ extern "C" { #endif -#define QUARK_SE_IPM_OUTBOUND 0 +#define QUARK_SE_IPM_OUTBOUND 0 #define QUARK_SE_IPM_INBOUND 1 #if defined(CONFIG_SOC_QUARK_SE_C1000) /* First byte of the QUARK_SE_IPM_MASK register is for the Lakemont */ #define QUARK_SE_IPM_MASK_START_BIT 0 -#define QUARK_SE_IPM_INTERRUPT 21 +#define QUARK_SE_IPM_INTERRUPT 21 #define QUARK_SE_IPM_ARC_LMT_DIR QUARK_SE_IPM_INBOUND #define QUARK_SE_IPM_LMT_ARC_DIR QUARK_SE_IPM_OUTBOUND #elif defined(CONFIG_SOC_QUARK_SE_C1000_SS) /* Second byte is for ARC */ #define QUARK_SE_IPM_MASK_START_BIT 8 -#define QUARK_SE_IPM_INTERRUPT 57 +#define QUARK_SE_IPM_INTERRUPT 57 #define QUARK_SE_IPM_ARC_LMT_DIR QUARK_SE_IPM_OUTBOUND #define QUARK_SE_IPM_LMT_ARC_DIR QUARK_SE_IPM_INBOUND From c445c425189dee76a1d00550114b074d391c1cb3 Mon Sep 17 00:00:00 2001 From: kontais Date: Tue, 2 May 2017 14:04:42 +0000 Subject: [PATCH 09/19] board stm3210c_eval openocd cfg file Signed-off-by: kontais --- boards/arm/stm3210c_eval/support/openocd.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/arm/stm3210c_eval/support/openocd.cfg b/boards/arm/stm3210c_eval/support/openocd.cfg index bcf95398b28e2..afa40b0c66725 100644 --- a/boards/arm/stm3210c_eval/support/openocd.cfg +++ b/boards/arm/stm3210c_eval/support/openocd.cfg @@ -1,4 +1,4 @@ -source [find board/st3210c_eval.cfg] +source [find board/stm3210c_eval.cfg] $_TARGETNAME configure -event gdb-attach { echo "Debugger attaching: halting execution" From ed6eba7f4f4a1140c6c0d151bd4429659e7d1591 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Wed, 3 May 2017 12:52:05 -0400 Subject: [PATCH 10/19] CI: show commit range in log Also print range in the test report. Signed-off-by: Anas Nashif --- .shippable.yml | 1 + scripts/ci/check-compliance.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.shippable.yml b/.shippable.yml index ff6883c339f5a..22bf2ce298b1f 100644 --- a/.shippable.yml +++ b/.shippable.yml @@ -27,6 +27,7 @@ build: ci: - export CCACHE_DIR=${SHIPPABLE_BUILD_DIR}/ccache/.ccache - export COMMIT_RANGE=${SHIPPABLE_COMMIT_RANGE} + - echo ${SHIPPABLE_COMMIT_RANGE} - source zephyr-env.sh - ccache -s --max-size=2000M - make host-tools diff --git a/scripts/ci/check-compliance.py b/scripts/ci/check-compliance.py index 11fd2d1d65d59..779f006afc557 100755 --- a/scripts/ci/check-compliance.py +++ b/scripts/ci/check-compliance.py @@ -19,7 +19,7 @@ def run_gitlint(tc): msg = proc.stdout.read() if msg != "": - failure = ET.SubElement(tc, 'failure', type="failure", message="commit message error") + failure = ET.SubElement(tc, 'failure', type="failure", message="commit message error on range: %s" %commit_range) failure.text = (str(msg)) return 1 From 1c1507d4cddc74e6d8a59b5e439baffd31327249 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Mon, 24 Apr 2017 16:11:21 +0100 Subject: [PATCH 11/19] i2c: i2c_sbcon: Driver for ARM's SBCon 2-wire serial interface SBCon is a simple device which allows directly setting and getting the hardware state of two-bit serial interfaces like I2C. Therefore to be useable we need to drive the lines with the appropriate protocol under software control. Change-Id: If9000bb75f7b0ad7bbb256b1cb38cc70fa6ca8ea Signed-off-by: Jon Medhurst --- drivers/i2c/Kconfig | 2 + drivers/i2c/Kconfig.sbcon | 51 ++++++++++++++ drivers/i2c/Makefile | 1 + drivers/i2c/i2c_sbcon.c | 140 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 drivers/i2c/Kconfig.sbcon create mode 100644 drivers/i2c/i2c_sbcon.c diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index f8f869395aabd..afd85b06c0588 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -111,6 +111,8 @@ config I2C_BITBANG help Enable library used for software driven (bit banging) I2C support +source "drivers/i2c/Kconfig.sbcon" + source "drivers/i2c/Kconfig.gpio" config I2C_INIT_PRIORITY diff --git a/drivers/i2c/Kconfig.sbcon b/drivers/i2c/Kconfig.sbcon new file mode 100644 index 0000000000000..10241711604f2 --- /dev/null +++ b/drivers/i2c/Kconfig.sbcon @@ -0,0 +1,51 @@ +# +# Copyright (c) 2016 Linaro Ltd. +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig I2C_SBCON + bool "I2C driver for ARM's SBCon two-wire serial bus interface" + depends on I2C + select I2C_BITBANG + default n + +if I2C_SBCON + +config I2C_SBCON_0 + bool "Enable SBCon device 0" + default n + +config I2C_SBCON_0_NAME + depends on I2C_SBCON_0 + string "SBCon device 0 Device Name" + default "SBCON_0" + +config I2C_SBCON_1 + bool "Enable SBCon device 1" + default n + +config I2C_SBCON_1_NAME + depends on I2C_SBCON_1 + string "SBCon device 1 Device Name" + default "SBCON_1" + +config I2C_SBCON_2 + bool "Enable SBCon device 2" + default n + +config I2C_SBCON_2_NAME + depends on I2C_SBCON_2 + string "SBCon device 2 Device Name" + default "SBCON_2" + +config I2C_SBCON_3 + bool "Enable SBCon device 3" + default n + +config I2C_SBCON_3_NAME + depends on I2C_SBCON_3 + string "SBCon device 0 Device Name" + default "SBCON_3" + +endif diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index b3db3e81d31cb..c998d3cfd9386 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_I2C_MCUX) += i2c_mcux.o obj-$(CONFIG_I2C_NRF5) += i2c_nrf5.o obj-$(CONFIG_I2C_QMSI) += i2c_qmsi.o obj-$(CONFIG_I2C_QMSI_SS) += i2c_qmsi_ss.o +obj-$(CONFIG_I2C_SBCON) += i2c_sbcon.o obj-$(CONFIG_I2C_STM32LX) += i2c_stm32lx.o obj-$(CONFIG_TWIHS_SAM) += twihs_sam.o diff --git a/drivers/i2c/i2c_sbcon.c b/drivers/i2c/i2c_sbcon.c new file mode 100644 index 0000000000000..ed256cebe96b2 --- /dev/null +++ b/drivers/i2c/i2c_sbcon.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2017 Linaro Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Driver for ARM's SBCon 2-wire serial bus interface + * + * SBCon is a simple device which allows directly setting and getting the + * hardware state of two-bit serial interfaces like I2C. + */ + +#include +#include +#include +#include +#include + +/* SBCon hardware registers layout */ +struct sbcon { + union { + volatile u32_t SB_CONTROLS; /* Write to set pins high */ + volatile u32_t SB_CONTROL; /* Read for state of pins */ + }; + volatile u32_t SB_CONTROLC; /* Write to set pins low */ +}; + +/* Bits values for SCL and SDA lines in struct sbcon registers */ +#define SCL BIT(0) +#define SDA BIT(1) + +/* Driver config */ +struct i2c_sbcon_config { + struct sbcon *sbcon; /* Address of hardware registers */ +}; + +/* Driver instance data */ +struct i2c_sbcon_context { + struct i2c_bitbang bitbang; /* Bit-bang library data */ +}; + +static void i2c_sbcon_set_scl(void *io_context, int state) +{ + struct sbcon *sbcon = io_context; + + if (state) { + sbcon->SB_CONTROLS = SCL; + } else { + sbcon->SB_CONTROLC = SCL; + } +} + +static void i2c_sbcon_set_sda(void *io_context, int state) +{ + struct sbcon *sbcon = io_context; + + if (state) { + sbcon->SB_CONTROLS = SDA; + } else { + sbcon->SB_CONTROLC = SDA; + } +} + +static int i2c_sbcon_get_sda(void *io_context) +{ + struct sbcon *sbcon = io_context; + + return sbcon->SB_CONTROL & SDA; +} + +static const struct i2c_bitbang_io io_fns = { + .set_scl = &i2c_sbcon_set_scl, + .set_sda = &i2c_sbcon_set_sda, + .get_sda = &i2c_sbcon_get_sda, +}; + +static int i2c_sbcon_configure(struct device *dev, u32_t dev_config) +{ + struct i2c_sbcon_context *context = dev->driver_data; + + return i2c_bitbang_configure(&context->bitbang, dev_config); +} + +static int i2c_sbcon_transfer(struct device *dev, struct i2c_msg *msgs, + u8_t num_msgs, u16_t slave_address) +{ + struct i2c_sbcon_context *context = dev->driver_data; + + return i2c_bitbang_transfer(&context->bitbang, msgs, num_msgs, + slave_address); +} + +static struct i2c_driver_api api = { + .configure = i2c_sbcon_configure, + .transfer = i2c_sbcon_transfer, +}; + +static int i2c_sbcon_init(struct device *dev) +{ + struct i2c_sbcon_context *context = dev->driver_data; + const struct i2c_sbcon_config *config = dev->config->config_info; + + i2c_bitbang_init(&context->bitbang, &io_fns, config->sbcon); + + dev->driver_api = &api; + + return 0; +} + +#define DEFINE_I2C_SBCON(_num) \ + \ +static struct i2c_sbcon_context i2c_sbcon_dev_data_##_num; \ + \ +static const struct i2c_sbcon_config i2c_sbcon_dev_cfg_##_num = { \ + .sbcon = (void *)I2C_SBCON_##_num##_BASE_ADDR, \ +}; \ + \ +DEVICE_INIT(i2c_sbcon_##_num, CONFIG_I2C_SBCON_##_num##_NAME, \ + i2c_sbcon_init, \ + &i2c_sbcon_dev_data_##_num, \ + &i2c_sbcon_dev_cfg_##_num, \ + PRE_KERNEL_2, CONFIG_I2C_INIT_PRIORITY) + +#ifdef CONFIG_I2C_SBCON_0 +DEFINE_I2C_SBCON(0); +#endif + +#ifdef CONFIG_I2C_SBCON_1 +DEFINE_I2C_SBCON(1); +#endif + +#ifdef CONFIG_I2C_SBCON_2 +DEFINE_I2C_SBCON(2); +#endif + +#ifdef CONFIG_I2C_SBCON_3 +DEFINE_I2C_SBCON(3); +#endif From 14ce362972f98812eb80cd13ca2ecb2fe40c2c15 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Fri, 24 Mar 2017 16:32:38 +0000 Subject: [PATCH 12/19] boards: mps2_an385: Enable I2C devices The FPGA on the MPS2 board implements 4 SBCon devices for I2C which are connected to: - a touchscreen controller - the audio device (for configuration) - both shield connectors Change-Id: I55ca985e18b45d68f5e7421c4768dfc9bf2fcb3f Signed-off-by: Jon Medhurst --- arch/arm/soc/arm/mps2/soc_devices.h | 7 +++++ arch/arm/soc/arm/mps2/soc_memory_map.h | 6 ++++- boards/arm/mps2_an385/Kconfig.defconfig | 31 ++++++++++++++++++++++ boards/arm/mps2_an385/mps2_an385_defconfig | 2 ++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/arch/arm/soc/arm/mps2/soc_devices.h b/arch/arm/soc/arm/mps2/soc_devices.h index 5afa2b6171a43..e87e0698986a9 100644 --- a/arch/arm/soc/arm/mps2/soc_devices.h +++ b/arch/arm/soc/arm/mps2/soc_devices.h @@ -58,6 +58,13 @@ #define CMSDK_APB_DUALTIMER_IRQ IRQ_DUAL_TIMER #endif /* CONFIG_COUNTER */ +#if defined(CONFIG_I2C_SBCON) +#define I2C_SBCON_0_BASE_ADDR I2C_TOUCH_BASE_ADDR +#define I2C_SBCON_1_BASE_ADDR I2C_AUDIO_CONF_BASE_ADDR +#define I2C_SBCON_2_BASE_ADDR I2C_SHIELD0_BASE_ADDR +#define I2C_SBCON_3_BASE_ADDR I2C_SHIELD1_BASE_ADDR +#endif + #ifndef _ASMLANGUAGE #include "soc_registers.h" diff --git a/arch/arm/soc/arm/mps2/soc_memory_map.h b/arch/arm/soc/arm/mps2/soc_memory_map.h index 4fd95234dad49..a80ea8c19c6bd 100644 --- a/arch/arm/soc/arm/mps2/soc_memory_map.h +++ b/arch/arm/soc/arm/mps2/soc_memory_map.h @@ -35,6 +35,10 @@ #define UART_4_BASE_ADDR (MPS2_APB_BASE_ADDR + 0x9000) /* MPS2 peripherals in FPGA APB subsystem */ -#define FPGAIO_BASE_ADDR (MPS2_FPGA_APB_BASE_ADDR + 0x8000) +#define I2C_TOUCH_BASE_ADDR (MPS2_FPGA_APB_BASE_ADDR + 0x2000) +#define I2C_AUDIO_CONF_BASE_ADDR (MPS2_FPGA_APB_BASE_ADDR + 0x3000) +#define FPGAIO_BASE_ADDR (MPS2_FPGA_APB_BASE_ADDR + 0x8000) +#define I2C_SHIELD0_BASE_ADDR (MPS2_FPGA_APB_BASE_ADDR + 0x9000) +#define I2C_SHIELD1_BASE_ADDR (MPS2_FPGA_APB_BASE_ADDR + 0xa000) #endif /* _SOC_MEMORY_MAP_H_ */ diff --git a/boards/arm/mps2_an385/Kconfig.defconfig b/boards/arm/mps2_an385/Kconfig.defconfig index 1ada42a138931..f8cf08b0d396d 100644 --- a/boards/arm/mps2_an385/Kconfig.defconfig +++ b/boards/arm/mps2_an385/Kconfig.defconfig @@ -105,4 +105,35 @@ endif # TIMER_DTMR_CMSDK_APB endif # COUNTER +if I2C + +config I2C_SBCON + def_bool y + +config I2C_SBCON_0 + def_bool y + +config I2C_SBCON_0_NAME + default I2C_TOUCH + +config I2C_SBCON_1 + def_bool y + +config I2C_SBCON_1_NAME + default I2C_AUDIO_CONF + +config I2C_SBCON_2 + def_bool y + +config I2C_SBCON_2_NAME + default I2C_SHIELD0 + +config I2C_SBCON_3 + def_bool y + +config I2C_SBCON_3_NAME + default I2C_SHIELD1 + +endif # I2C + endif diff --git a/boards/arm/mps2_an385/mps2_an385_defconfig b/boards/arm/mps2_an385/mps2_an385_defconfig index 2a1485df4a8d3..427e50246df48 100644 --- a/boards/arm/mps2_an385/mps2_an385_defconfig +++ b/boards/arm/mps2_an385/mps2_an385_defconfig @@ -28,3 +28,5 @@ CONFIG_UART_CONSOLE_ON_DEV_NAME="UART_0" # Watchdog CONFIG_WATCHDOG=y + +CONFIG_I2C=y \ No newline at end of file From 558281b0962f602b3f621d90a73ebcec1c275ae9 Mon Sep 17 00:00:00 2001 From: Justin Watson Date: Mon, 1 May 2017 14:57:26 -0700 Subject: [PATCH 13/19] arch: sam3x: update Kconfig options after move to SAM SoC family tree The files for the Arduino Due needed to be updated to use the new configuration when the SoC moved from the atmel_sam3 directory to the atmel_sam/sam3x directory. Jira: ZEP-2067 Signed-off-by: Justin Watson --- arch/arm/soc/atmel_sam/Kconfig | 5 -- arch/arm/soc/atmel_sam/Kconfig.defconfig | 2 +- .../atmel_sam/sam3x/Kconfig.defconfig.series | 59 ++----------------- arch/arm/soc/atmel_sam/sam3x/Kconfig.series | 10 ---- arch/arm/soc/atmel_sam/sam3x/Kconfig.soc | 4 +- arch/arm/soc/atmel_sam/sam3x/soc.c | 4 +- boards/arm/arduino_due/Kconfig.board | 7 ++- boards/arm/arduino_due/Kconfig.defconfig | 45 ++++++++++++++ boards/arm/arduino_due/arduino_due_defconfig | 7 ++- drivers/gpio/Kconfig.atmel_sam3 | 2 +- drivers/i2c/Kconfig | 5 +- drivers/pinmux/dev/Kconfig | 2 +- drivers/serial/Kconfig.atmel_sam3 | 2 +- samples/drivers/gpio/src/main.c | 2 +- samples/drivers/lcd_hd44780/src/main.c | 4 +- samples/drivers/lcd_hd44780/testcase.ini | 2 +- tests/kernel/test_tickless/src/timestamps.c | 2 +- tests/kernel/test_tickless/testcase.ini | 2 +- 18 files changed, 78 insertions(+), 88 deletions(-) diff --git a/arch/arm/soc/atmel_sam/Kconfig b/arch/arm/soc/atmel_sam/Kconfig index 759f70525c702..1988dd2005ab0 100644 --- a/arch/arm/soc/atmel_sam/Kconfig +++ b/arch/arm/soc/atmel_sam/Kconfig @@ -4,10 +4,5 @@ # SPDX-License-Identifier: Apache-2.0 # -config SOC_ATMEL_SAM3 - bool - depends on ARM - default n - # Select SoC Part No. and configuration options source "arch/arm/soc/atmel_sam/*/Kconfig.soc" diff --git a/arch/arm/soc/atmel_sam/Kconfig.defconfig b/arch/arm/soc/atmel_sam/Kconfig.defconfig index 1f5550b230c4d..bdddffc438751 100644 --- a/arch/arm/soc/atmel_sam/Kconfig.defconfig +++ b/arch/arm/soc/atmel_sam/Kconfig.defconfig @@ -16,7 +16,7 @@ config SOC_FAMILY default atmel_sam config WATCHDOG - def_bool y if !SOC_ATMEL_SAM3X8E + def_bool y endif #SOC_FAMILY_SAM diff --git a/arch/arm/soc/atmel_sam/sam3x/Kconfig.defconfig.series b/arch/arm/soc/atmel_sam/sam3x/Kconfig.defconfig.series index 30159e2ebf0d6..8ed2fecfcf417 100644 --- a/arch/arm/soc/atmel_sam/sam3x/Kconfig.defconfig.series +++ b/arch/arm/soc/atmel_sam/sam3x/Kconfig.defconfig.series @@ -6,7 +6,7 @@ # SPDX-License-Identifier: Apache-2.0 # -if SOC_SERIES_SAM3X || SOC_ATMEL_SAM3X8E +if SOC_SERIES_SAM3X config SOC_SERIES string @@ -14,7 +14,7 @@ config SOC_SERIES config SOC_PART_NUMBER string - default sam3x8e if SOC_PART_NUMBER_SAM3X8E || SOC_ATMEL_SAM3X8E + default sam3x8e if SOC_PART_NUMBER_SAM3X8E config NUM_IRQ_PRIO_BITS int @@ -42,66 +42,19 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC # to provide one continuous 96K block. # config SRAM_SIZE - default 96 if SOC_PART_NUMBER_SAM3X8E || SOC_ATMEL_SAM3X8E + default 96 if SOC_PART_NUMBER_SAM3X8E config SRAM_BASE_ADDRESS - default 0x20000000 if !SOC_PART_NUMBER_SAM3X8E && !SOC_ATMEL_SAM3X8E - default 0x20070000 if SOC_PART_NUMBER_SAM3X8E || SOC_ATMEL_SAM3X8E + default 0x20000000 if !SOC_PART_NUMBER_SAM3X8E + default 0x20070000 if SOC_PART_NUMBER_SAM3X8E # # Atmel SAM3X family has flash starting @ 0x00080000. # config FLASH_SIZE - default 512 if SOC_PART_NUMBER_SAM3X8E || SOC_ATMEL_SAM3X8E + default 512 if SOC_PART_NUMBER_SAM3X8E config FLASH_BASE_ADDRESS default 0x00080000 -if UART_ATMEL_SAM3 - -config UART_ATMEL_SAM3_BAUD_RATE - default 115200 - -config UART_ATMEL_SAM3_CLK_FREQ - default 84000000 - -endif # UART_ATMEL_SAM3 - -if GPIO - -config GPIO_ATMEL_SAM3 - def_bool y - -config GPIO_ATMEL_SAM3_PORTA - default y - -config GPIO_ATMEL_SAM3_PORTB - default y - -config GPIO_ATMEL_SAM3_PORTC - default y - -config GPIO_ATMEL_SAM3_PORTD - default y - -endif # GPIO - -if I2C - -config I2C_ATMEL_SAM3 - def_bool y - -config I2C_0 - default y -config I2C_0_IRQ_PRI - default 0 - -config I2C_1 - default y - -config I2C_1_IRQ_PRI - default 0 - -endif # I2C - endif # SOC_SERIES_SAM3X diff --git a/arch/arm/soc/atmel_sam/sam3x/Kconfig.series b/arch/arm/soc/atmel_sam/sam3x/Kconfig.series index 59bb0f4ea8672..9d77cb7a8e814 100644 --- a/arch/arm/soc/atmel_sam/sam3x/Kconfig.series +++ b/arch/arm/soc/atmel_sam/sam3x/Kconfig.series @@ -16,13 +16,3 @@ config SOC_SERIES_SAM3X help Enable support for Atmel SAM3X Cortex-M3 microcontrollers. Part No.: SAM3X8E - -config SOC_ATMEL_SAM3X8E - bool "Atmel SAM3X8E Processor" - select SOC_PART_NUMBER_SAM3X8E - select CPU_CORTEX_M - select CPU_CORTEX_M3 - select SOC_FAMILY_SAM - select SYS_POWER_LOW_POWER_STATE_SUPPORTED - select CPU_HAS_SYSTICK - select SOC_ATMEL_SAM3 diff --git a/arch/arm/soc/atmel_sam/sam3x/Kconfig.soc b/arch/arm/soc/atmel_sam/sam3x/Kconfig.soc index 06bf046725faa..1277d9e53b9c5 100644 --- a/arch/arm/soc/atmel_sam/sam3x/Kconfig.soc +++ b/arch/arm/soc/atmel_sam/sam3x/Kconfig.soc @@ -15,7 +15,7 @@ choice bool "SAM3X8E" endchoice -if SOC_SERIES_SAM3X || SOC_ATMEL_SAM3X8E +if SOC_SERIES_SAM3X config SOC_ATMEL_SAM3X_EXT_SLCK bool "Atmel SAM3 to use external crystal oscillator for slow clock" @@ -75,7 +75,7 @@ config SOC_ATMEL_SAM3X_PLLA_DIVA config SOC_ATMEL_SAM3X_WAIT_MODE bool "Atmel SAM3 goes to Wait mode instead of Sleep mode" - depends on SOC_ATMEL_SAM3_EXT_MAINCK + depends on SOC_ATMEL_SAM3X_EXT_MAINCK default y if DEBUG help For JTAG debugging CPU clock (HCLK) should not stop. In order diff --git a/arch/arm/soc/atmel_sam/sam3x/soc.c b/arch/arm/soc/atmel_sam/sam3x/soc.c index 1e8b01fb400e3..98215571a1b52 100644 --- a/arch/arm/soc/atmel_sam/sam3x/soc.c +++ b/arch/arm/soc/atmel_sam/sam3x/soc.c @@ -50,7 +50,7 @@ static ALWAYS_INLINE void clock_init(void) /* Wait for oscillator to be stablized */ while (!(__SUPC->sr & SUPC_SR_OSCSEL)) ; -#endif /* CONFIG_SOC_ATMEL_SAM3_EXT_SLCK */ +#endif /* CONFIG_SOC_ATMEL_SAM3X_EXT_SLCK */ #ifdef CONFIG_SOC_ATMEL_SAM3X_EXT_MAINCK /* Start the external main oscillator */ @@ -88,7 +88,7 @@ static ALWAYS_INLINE void clock_init(void) /* Wait for main fast RC oscillator to be stablized */ while (!(__PMC->sr & PMC_INT_MOSCRCS)) ; -#endif /* CONFIG_SOC_ATMEL_SAM3_EXT_MAINCK */ +#endif /* CONFIG_SOC_ATMEL_SAM3X_EXT_MAINCK */ /* Use PLLA as master clock. * According to datasheet, PMC_MCKR must not be programmed in diff --git a/boards/arm/arduino_due/Kconfig.board b/boards/arm/arduino_due/Kconfig.board index 552742e6fb6bf..5818773a88228 100644 --- a/boards/arm/arduino_due/Kconfig.board +++ b/boards/arm/arduino_due/Kconfig.board @@ -1,4 +1,9 @@ +# Kconfig - Arduino Due Board configuration +# +# Copyright (c) 2017 Justin Watson +# SPDX-License-Identifier: Apache-2.0 +# config BOARD_ARDUINO_DUE bool "Arduino Due Board" - depends on SOC_ATMEL_SAM3X8E + depends on SOC_PART_NUMBER_SAM3X8E diff --git a/boards/arm/arduino_due/Kconfig.defconfig b/boards/arm/arduino_due/Kconfig.defconfig index 952d4e0d3e2c6..b5d1d0ebcacd2 100644 --- a/boards/arm/arduino_due/Kconfig.defconfig +++ b/boards/arm/arduino_due/Kconfig.defconfig @@ -1,14 +1,59 @@ +# Kconfig - Arduino Due Board configuration +# +# Copyright (c) 2017 Justin Watson +# SPDX-License-Identifier: Apache-2.0 +# if BOARD_ARDUINO_DUE config BOARD default arduino_due +if UART_ATMEL_SAM3 + +config UART_ATMEL_SAM3_BAUD_RATE + default 115200 + +config UART_ATMEL_SAM3_CLK_FREQ + default 84000000 + +endif # UART_ATMEL_SAM3 + +if GPIO + +config GPIO_ATMEL_SAM3 + def_bool y + +config GPIO_ATMEL_SAM3_PORTA + default y + +config GPIO_ATMEL_SAM3_PORTB + default y + +config GPIO_ATMEL_SAM3_PORTC + default y + +config GPIO_ATMEL_SAM3_PORTD + default y + +endif # GPIO + if I2C config I2C_ATMEL_SAM3 + def_bool y + +config I2C_0 + default y +config I2C_0_IRQ_PRI + default 0 + +config I2C_1 default y +config I2C_1_IRQ_PRI + default 0 + endif # I2C endif # BOARD_ARDUINO_DUE diff --git a/boards/arm/arduino_due/arduino_due_defconfig b/boards/arm/arduino_due/arduino_due_defconfig index 625064ef5be85..73b61fd8844a3 100644 --- a/boards/arm/arduino_due/arduino_due_defconfig +++ b/boards/arm/arduino_due/arduino_due_defconfig @@ -1,10 +1,13 @@ CONFIG_ARM=y -CONFIG_SOC_ATMEL_SAM3X8E=y +CONFIG_SOC_FAMILY_SAM=y +CONFIG_SOC_SERIES_SAM3X=y +CONFIG_SOC_PART_NUMBER_SAM3X8E=y CONFIG_BOARD_ARDUINO_DUE=y CONFIG_CORTEX_M_SYSTICK=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_ATMEL_SAM3=y -CONFIG_SOC_ATMEL_SAM3_EXT_MAINCK=y +CONFIG_SOC_ATMEL_SAM3X_EXT_MAINCK=y CONFIG_PINMUX=y +CONFIG_WATCHDOG=n diff --git a/drivers/gpio/Kconfig.atmel_sam3 b/drivers/gpio/Kconfig.atmel_sam3 index 8413a8b606ce0..584b6aef0c171 100644 --- a/drivers/gpio/Kconfig.atmel_sam3 +++ b/drivers/gpio/Kconfig.atmel_sam3 @@ -8,7 +8,7 @@ menuconfig GPIO_ATMEL_SAM3 bool "Atmel SAM3 PIO Controllers" - depends on GPIO && SOC_ATMEL_SAM3 + depends on GPIO && SOC_SERIES_SAM3X default n help Enable config options to support the PIO controllers diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index afd85b06c0588..9b4993892f9ed 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -45,12 +45,11 @@ config I2C_QMSI provided by the QMSI BSP. config I2C_ATMEL_SAM3 - bool "Atmel SAM3 I2C Driver" - depends on SOC_ATMEL_SAM3 + bool "Atmel SAM3X I2C Driver" + depends on SOC_SERIES_SAM3X default n help Enable I2C support on the Atmel SAM3 family processor. - Says y to enable additional options to enable support for individual controllers. diff --git a/drivers/pinmux/dev/Kconfig b/drivers/pinmux/dev/Kconfig index 418b5eaa3cc45..87a93cb9db9f4 100644 --- a/drivers/pinmux/dev/Kconfig +++ b/drivers/pinmux/dev/Kconfig @@ -24,7 +24,7 @@ config PINMUX_DEV_NAME config PINMUX_DEV_ATMEL_SAM3X bool "Enable pinmux dev driver for Atmel SAM3X boards" - depends on PINMUX_DEV && SOC_ATMEL_SAM3X8E + depends on PINMUX_DEV && SOC_SERIES_SAM3X help Enables the pinmux dev driver for boards based on the Atmel SAM3X family of microcontrollers. diff --git a/drivers/serial/Kconfig.atmel_sam3 b/drivers/serial/Kconfig.atmel_sam3 index ef678fd30e298..d87e92da9314b 100644 --- a/drivers/serial/Kconfig.atmel_sam3 +++ b/drivers/serial/Kconfig.atmel_sam3 @@ -2,7 +2,7 @@ menuconfig UART_ATMEL_SAM3 bool "Atmel SAM3 family processor UART driver" default n select SERIAL_HAS_DRIVER - depends on SOC_ATMEL_SAM3 + depends on SOC_SERIES_SAM3X help This option enables the UART driver for Atmel SAM3 family processors. Note that there is only one diff --git a/samples/drivers/gpio/src/main.c b/samples/drivers/gpio/src/main.c index 8a19726bb1fb9..07ce642339d32 100644 --- a/samples/drivers/gpio/src/main.c +++ b/samples/drivers/gpio/src/main.c @@ -114,7 +114,7 @@ #define GPIO_OUT_PIN 16 #define GPIO_INT_PIN 19 #define GPIO_NAME "GPIO_" -#elif defined(CONFIG_SOC_ATMEL_SAM3) +#elif defined(CONFIG_SOC_PART_NUMBER_SAM3X8E) #define GPIO_OUT_PIN 25 #define GPIO_INT_PIN 27 #define GPIO_NAME "GPIO_" diff --git a/samples/drivers/lcd_hd44780/src/main.c b/samples/drivers/lcd_hd44780/src/main.c index 1ed57a7a5d10f..4b015bea08f51 100644 --- a/samples/drivers/lcd_hd44780/src/main.c +++ b/samples/drivers/lcd_hd44780/src/main.c @@ -71,13 +71,13 @@ #include -#if defined(CONFIG_GPIO_ATMEL_SAM3) +#if defined(CONFIG_SOC_PART_NUMBER_SAM3X8E) #define GPIO_DRV_NAME CONFIG_GPIO_ATMEL_SAM3_PORTC_DEV_NAME #else #error "Unsupported GPIO driver" #endif -#if defined(CONFIG_SOC_ATMEL_SAM3) +#if defined(CONFIG_SOC_PART_NUMBER_SAM3X8E) /* Define GPIO OUT to LCD */ #define GPIO_PIN_PC12_D0 12 /* PC12 - pin 51 */ #define GPIO_PIN_PC13_D1 13 /* PC13 - pin 50 */ diff --git a/samples/drivers/lcd_hd44780/testcase.ini b/samples/drivers/lcd_hd44780/testcase.ini index c0d4933d98dc5..2d8e8587b8ecf 100644 --- a/samples/drivers/lcd_hd44780/testcase.ini +++ b/samples/drivers/lcd_hd44780/testcase.ini @@ -1,5 +1,5 @@ [test] tags = samples build_only = true -filter = CONFIG_SOC_ATMEL_SAM3 +filter = CONFIG_SOC_SERIES_SAM3X diff --git a/tests/kernel/test_tickless/src/timestamps.c b/tests/kernel/test_tickless/src/timestamps.c index 8c097c4b324f2..ff8bac1da06a7 100644 --- a/tests/kernel/test_tickless/src/timestamps.c +++ b/tests/kernel/test_tickless/src/timestamps.c @@ -237,7 +237,7 @@ void _TimestampClose(void) _TIMESTAMP_CTRL = 0x0; /* disable oscillator */ } -#elif defined(CONFIG_SOC_ATMEL_SAM3) +#elif defined(CONFIG_SOC_SERIES_SAM3X) /* Atmel SAM3 family processor - use RTT (Real-time Timer) */ #include diff --git a/tests/kernel/test_tickless/testcase.ini b/tests/kernel/test_tickless/testcase.ini index d217bfd1d61ae..8903dde6c3fbd 100644 --- a/tests/kernel/test_tickless/testcase.ini +++ b/tests/kernel/test_tickless/testcase.ini @@ -2,5 +2,5 @@ tags = core arch_exclude = nios2 filter = CONFIG_X86 or (CONFIG_ARM and - (CONFIG_SOC_MK64F12 or CONFIG_SOC_ATMEL_SAM3)) or + (CONFIG_SOC_MK64F12 or CONFIG_SOC_SERIES_SAM3X)) or (CONFIG_ARC and CONFIG_SOC_QUARK_SE_C1000_SS) From 2a6f9daae45e05d00d236d185ef541e98fea7ecc Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Tue, 2 May 2017 14:28:50 +0200 Subject: [PATCH 14/19] boards: disco_l475_iot1: Remove unexpected I2C address for HTS221 I2C address could not be configured for HTS221. Remove non existing configuration in disco_l475_iot1 board Change-Id: Ib5ed8e0f770c16b124cf918bdf9ecd42cdd9b213 Signed-off-by: Erwan Gouriou --- boards/arm/disco_l475_iot1/disco_l475_iot1_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boards/arm/disco_l475_iot1/disco_l475_iot1_defconfig b/boards/arm/disco_l475_iot1/disco_l475_iot1_defconfig index 63e0d7409836d..2863475c4324b 100644 --- a/boards/arm/disco_l475_iot1/disco_l475_iot1_defconfig +++ b/boards/arm/disco_l475_iot1/disco_l475_iot1_defconfig @@ -55,4 +55,3 @@ CONFIG_I2C_STM32LX=y #configure HTS221 sensor CONFIG_HTS221_I2C_MASTER_DEV_NAME="I2C_2" CONFIG_HTS221_TRIGGER_NONE=y -CONFIG_HTS221_I2C_ADDR=0x5F From 79917842970bb325f7bb7fa79831fcf6640533c2 Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Fri, 28 Apr 2017 13:44:07 +0200 Subject: [PATCH 15/19] samples: sensor: hts221 This commit provides sample application for sensor hts221. By default, it is enabled on board disco_l475_iot1 Change-Id: I535fac8a670fa89cc1cae15ea1abe9cfe4b6c56b Signed-off-by: Erwan Gouriou --- samples/sensor/hts221/Makefile | 4 +++ samples/sensor/hts221/README.rst | 47 +++++++++++++++++++++++++++++ samples/sensor/hts221/prj.conf | 4 +++ samples/sensor/hts221/src/Makefile | 1 + samples/sensor/hts221/src/main.c | 48 ++++++++++++++++++++++++++++++ samples/sensor/hts221/testcase.ini | 4 +++ 6 files changed, 108 insertions(+) create mode 100644 samples/sensor/hts221/Makefile create mode 100644 samples/sensor/hts221/README.rst create mode 100644 samples/sensor/hts221/prj.conf create mode 100644 samples/sensor/hts221/src/Makefile create mode 100644 samples/sensor/hts221/src/main.c create mode 100644 samples/sensor/hts221/testcase.ini diff --git a/samples/sensor/hts221/Makefile b/samples/sensor/hts221/Makefile new file mode 100644 index 0000000000000..63cb452ce0e06 --- /dev/null +++ b/samples/sensor/hts221/Makefile @@ -0,0 +1,4 @@ +BOARD ?= disco_l475_iot1 +CONF_FILE = prj.conf + +include ${ZEPHYR_BASE}/Makefile.inc diff --git a/samples/sensor/hts221/README.rst b/samples/sensor/hts221/README.rst new file mode 100644 index 0000000000000..bdd91fbc51dcd --- /dev/null +++ b/samples/sensor/hts221/README.rst @@ -0,0 +1,47 @@ +.. _hts221: + +HTS221: Temperature and Humidity Monitor +######################################## + +Overview +******** +This sample periodically reads temperature and humidity from the HTS221 +Temperature & Humidity Sensor and displays it on the console + + +Requirements +************ + +This sample uses the HTS221 sensor controlled using the I2C interface. + +References +********** + + - HTS211: http://www.st.com/en/mems-and-sensors/hts221.html + +Building and Running +******************** + + This project outputs sensor data to the console. It requires an HTS221 + sensor, which is present on the disco_l475_iot1 board. + + .. code-block:: console + + $ cd samples/sensors/hts221 + $ make BOARD=disco_l475_iot1 + +Sample Output +============= + + .. code-block:: console + + Temperature:25.3 C + Relative Humidity:40% + Temperature:25.3 C + Relative Humidity:40% + Temperature:25.3 C + Relative Humidity:40% + Temperature:25.3 C + Relative Humidity:40% + + diff --git a/samples/sensor/hts221/prj.conf b/samples/sensor/hts221/prj.conf new file mode 100644 index 0000000000000..6031b70dff747 --- /dev/null +++ b/samples/sensor/hts221/prj.conf @@ -0,0 +1,4 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_I2C=y +CONFIG_SENSOR=y +CONFIG_HTS221=y diff --git a/samples/sensor/hts221/src/Makefile b/samples/sensor/hts221/src/Makefile new file mode 100644 index 0000000000000..b666967fd5706 --- /dev/null +++ b/samples/sensor/hts221/src/Makefile @@ -0,0 +1 @@ +obj-y += main.o diff --git a/samples/sensor/hts221/src/main.c b/samples/sensor/hts221/src/main.c new file mode 100644 index 0000000000000..2a5f856ad9dee --- /dev/null +++ b/samples/sensor/hts221/src/main.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +void main(void) +{ + struct sensor_value temp, hum; + struct device *dev = device_get_binding("HTS221"); + + if (dev == NULL) { + printf("Could not get HTS221 device\n"); + return; + } + + while (1) { + if (sensor_sample_fetch(dev) < 0) { + printf("Sensor sample update error\n"); + return; + } + + if (sensor_channel_get(dev, SENSOR_CHAN_TEMP, &temp) < 0) { + printf("Cannot read HTS221 temperature channel\n"); + return; + } + + if (sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &hum) < 0) { + printf("Cannot read HTS221 humidity channel\n"); + return; + } + + /* display temperature */ + printf("Temperature:%.1f C\n", sensor_value_to_double(&temp)); + + /* display humidity (converted from millipercent) */ + printf("Relative Humidity:%.0f%%\n", + sensor_value_to_double(&hum) / 1000); + + k_sleep(2000); + } +} diff --git a/samples/sensor/hts221/testcase.ini b/samples/sensor/hts221/testcase.ini new file mode 100644 index 0000000000000..7260b929f7194 --- /dev/null +++ b/samples/sensor/hts221/testcase.ini @@ -0,0 +1,4 @@ +[test] +build_only = true +tags = samples sensor +platform_whitelist = disco_l475_iot1 From 4088530a129fb92257a0b64f4fa0ee98ea17a7dd Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Wed, 3 May 2017 10:20:50 -0400 Subject: [PATCH 16/19] lib: json: add JSON_OBJ_DESCR_PRIM There are already helper macros for declaring descriptor fields of object and array type. Add one for primitive types as well. The fact that the JSON test code defines one proves that it's useful, so there should be one provided for other users. Signed-off-by: Marti Bolivar --- lib/json/json.h | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/lib/json/json.h b/lib/json/json.h index 30edd5b618d0d..09026237395e9 100644 --- a/lib/json/json.h +++ b/lib/json/json.h @@ -67,6 +67,37 @@ struct json_obj_descr { typedef int (*json_append_bytes_t)(const u8_t *bytes, size_t len, void *data); + +/** + * @brief Helper macro to declare a descriptor for supported primitive + * values. + * + * @param struct_ Struct packing the values + * + * @param field_name_ Field name in the struct + * + * @param type_ Token type for JSON value corresponding to a primitive + * type. Must be one of: JSON_TOK_STRING for strings, JSON_TOK_NUMBER + * for numbers, JSON_TOK_TRUE (or JSON_TOK_FALSE) for booleans. + * + * Here's an example of use: + * + * struct foo { + * int some_int; + * }; + * + * struct json_obj_descr foo[] = { + * JSON_OBJ_DESCR_PRIM(struct foo, some_int, JSON_TOK_NUMBER), + * }; + */ +#define JSON_OBJ_DESCR_PRIM(struct_, field_name_, type_) \ + { \ + .field_name = (#field_name_), \ + .field_name_len = sizeof(#field_name_) - 1, \ + .offset = offsetof(struct_, field_name_), \ + .type = type_, \ + } + /** * @brief Helper macro to declare a descriptor for an object value * @@ -148,14 +179,8 @@ typedef int (*json_append_bytes_t)(const u8_t *bytes, size_t len, * * struct s { int foo; char *bar; } * struct json_obj_descr descr[] = { - * { .field_name = "foo", - * .field_name_len = 3, - * .offset = offsetof(struct s, foo), - * .type = JSON_TOK_NUMBER }, - * { .field_name = "bar", - * .field_name_len = 3, - * .offset = offsetof(struct s, bar), - * .type = JSON_TOK_STRING } + * JSON_OBJ_DESCR_PRIM(struct s, foo, JSON_TOK_NUMBER), + * JSON_OBJ_DESCR_PRIM(struct s, bar, JSON_TOK_STRING), * }; * * Since this parser is designed for machine-to-machine communications, some From 7e7a045fa9a5ff9cc9e611f57982a786487c8992 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Wed, 3 May 2017 10:26:56 -0400 Subject: [PATCH 17/19] tests: json: use JSON_OBJ_DESCR_PRIM Signed-off-by: Marti Bolivar --- tests/lib/json/src/main.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/tests/lib/json/src/main.c b/tests/lib/json/src/main.c index 6100c622f074d..945d8ace52bb7 100644 --- a/tests/lib/json/src/main.c +++ b/tests/lib/json/src/main.c @@ -24,28 +24,22 @@ struct test_struct { size_t some_array_len; }; -#define FIELD(struct_, member_, type_) { \ - .field_name = #member_, \ - .field_name_len = sizeof(#member_) - 1, \ - .offset = offsetof(struct_, member_), \ - .type = type_ \ -} static const struct json_obj_descr nested_descr[] = { - FIELD(struct test_nested, nested_int, JSON_TOK_NUMBER), - FIELD(struct test_nested, nested_bool, JSON_TOK_TRUE), - FIELD(struct test_nested, nested_string, JSON_TOK_STRING), + JSON_OBJ_DESCR_PRIM(struct test_nested, nested_int, JSON_TOK_NUMBER), + JSON_OBJ_DESCR_PRIM(struct test_nested, nested_bool, JSON_TOK_TRUE), + JSON_OBJ_DESCR_PRIM(struct test_nested, nested_string, + JSON_TOK_STRING), }; static const struct json_obj_descr test_descr[] = { - FIELD(struct test_struct, some_string, JSON_TOK_STRING), - FIELD(struct test_struct, some_int, JSON_TOK_NUMBER), - FIELD(struct test_struct, some_bool, JSON_TOK_TRUE), + JSON_OBJ_DESCR_PRIM(struct test_struct, some_string, JSON_TOK_STRING), + JSON_OBJ_DESCR_PRIM(struct test_struct, some_int, JSON_TOK_NUMBER), + JSON_OBJ_DESCR_PRIM(struct test_struct, some_bool, JSON_TOK_TRUE), JSON_OBJ_DESCR_OBJECT(struct test_struct, some_nested_struct, nested_descr), JSON_OBJ_DESCR_ARRAY(struct test_struct, some_array, 16, some_array_len, JSON_TOK_NUMBER), }; -#undef FIELD static void test_json_encoding(void) { From 7ebe7da736d475f889437cc7a3115e157d215f5b Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 7 Apr 2017 09:53:02 +0200 Subject: [PATCH 18/19] Bluetooth: controller: Controller to Host flow control The Bluetooth Specification allows for optional Controller to Host flow control based on the same credit-based mechanism as the Host to Controller one. This is particularly useful in 2-chip solutions where the Host and the Controller are connected via a physical link (UART, SPI or similar) where the Host is sometimes required to ask the Controller to throttle its data traffic while still making sure that relevant events get through the line. This implementation is based on a simple queue of pending events and data that is populated whenever the Controller detects that the Host is out of buffers and then emptied whenever the Host notifies the Controller that is ready to receive data again. Events relevant to the connections are also queued to preserve the order of arrival. At this point the Controller ignores the connection handle sent by the Host and treats all connections equally, and it also queues events even for connections that have no data pending in the queue. Both this items can be improved if necessity arises. Note that Number of Completed Packets will still flow freely from the Controller to the Host regardless of the pending ACL data packets, which might lead to inconsistencies in the sequential order of certain operations that include bi-directional data transfer. Jira: ZEP-1735 Signed-off-by: Carles Cufi --- include/bluetooth/hci.h | 4 + subsys/bluetooth/controller/Kconfig | 9 + subsys/bluetooth/controller/hci/hci.c | 201 +++++++++++++- subsys/bluetooth/controller/hci/hci_driver.c | 259 +++++++++++++++--- .../bluetooth/controller/hci/hci_internal.h | 21 +- subsys/bluetooth/controller/ll_sw/ctrl.h | 1 + tests/bluetooth/init/prj_controller.conf | 1 + 7 files changed, 452 insertions(+), 44 deletions(-) diff --git a/include/bluetooth/hci.h b/include/bluetooth/hci.h index 14d1125b38ccd..924dce13b09ff 100644 --- a/include/bluetooth/hci.h +++ b/include/bluetooth/hci.h @@ -491,8 +491,12 @@ struct bt_hci_write_local_name { #define BT_BREDR_SCAN_INQUIRY 0x01 #define BT_BREDR_SCAN_PAGE 0x02 +#define BT_HCI_CTL_TO_HOST_FLOW_DISABLE 0x00 #define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01 #define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) +struct bt_hci_cp_set_ctl_to_host_flow { + u8_t flow_enable; +} __packed; #define BT_HCI_OP_HOST_BUFFER_SIZE BT_OP(BT_OGF_BASEBAND, 0x0033) struct bt_hci_cp_host_buffer_size { diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 44fa3ad278f55..d0c7a09e44f02 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -30,6 +30,15 @@ endchoice comment "BLE Controller configuration" +config BLUETOOTH_CONTROLLER_TO_HOST_FC + bool "Controller to Host Flow Control" + depends on BLUETOOTH_CONN + default n + default y if BLUETOOTH_HCI_RAW + select POLL + help + Enable Controller to Host flow control. + config BLUETOOTH_CONTROLLER_DUP_FILTER_LEN prompt "Number of addresses in the scan duplicate filter" int diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 4709057d9218d..fa3fa5f2d8a48 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,18 @@ static s32_t dup_count; static u32_t dup_curr; #endif +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) +s32_t hci_hbuf_total; +u32_t hci_hbuf_sent; +u32_t hci_hbuf_acked; +atomic_t hci_state_mask; +static struct k_poll_signal *hbuf_signal; +#endif + +#if defined(CONFIG_BLUETOOTH_CONN) +static u32_t conn_count; +#endif + #define DEFAULT_EVENT_MASK 0x1fffffffffff #define DEFAULT_LE_EVENT_MASK 0x1f @@ -159,8 +172,6 @@ static void reset(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_evt_cc_status *ccst; - ll_reset(); - #if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0 dup_count = -1; #endif @@ -168,9 +179,112 @@ static void reset(struct net_buf *buf, struct net_buf **evt) event_mask = DEFAULT_EVENT_MASK; le_event_mask = DEFAULT_LE_EVENT_MASK; + if (buf) { + ll_reset(); + ccst = cmd_complete(evt, sizeof(*ccst)); + ccst->status = 0x00; + } +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) + hci_hbuf_total = 0; + hci_hbuf_sent = 0; + hci_hbuf_acked = 0; + conn_count = 0; + atomic_set_bit(&hci_state_mask, HCI_STATE_BIT_RESET); + k_poll_signal(hbuf_signal, 0x0); +#endif +} + +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) +static void set_ctl_to_host_flow(struct net_buf *buf, struct net_buf **evt) +{ + struct bt_hci_cp_set_ctl_to_host_flow *cmd = (void *)buf->data; + struct bt_hci_evt_cc_status *ccst; + ccst = cmd_complete(evt, sizeof(*ccst)); - ccst->status = 0x00; + + /* require host buffer size before enabling flow control, and + * disallow if any connections are up + */ + if (!hci_hbuf_total || conn_count) { + ccst->status = BT_HCI_ERR_CMD_DISALLOWED; + return; + } else { + ccst->status = 0x00; + } + + switch (cmd->flow_enable) { + case BT_HCI_CTL_TO_HOST_FLOW_DISABLE: + if (hci_hbuf_total < 0) { + /* already disabled */ + return; + } + break; + case BT_HCI_CTL_TO_HOST_FLOW_ENABLE: + if (hci_hbuf_total > 0) { + /* already enabled */ + return; + } + break; + default: + ccst->status = BT_HCI_ERR_INVALID_PARAM; + return; + } + + hci_hbuf_sent = 0; + hci_hbuf_acked = 0; + hci_hbuf_total = -hci_hbuf_total; +} + +static void host_buffer_size(struct net_buf *buf, struct net_buf **evt) +{ + struct bt_hci_cp_host_buffer_size *cmd = (void *)buf->data; + struct bt_hci_evt_cc_status *ccst; + + ccst = cmd_complete(evt, sizeof(*ccst)); + + if (hci_hbuf_total) { + ccst->status = BT_HCI_ERR_CMD_DISALLOWED; + return; + } + /* fragmentation from controller to host not supported, require + * ACL MTU to be at least the LL MTU + */ + if (cmd->acl_mtu < RADIO_LL_LENGTH_OCTETS_RX_MAX) { + ccst->status = BT_HCI_ERR_INVALID_PARAM; + return; + } + + hci_hbuf_total = -cmd->acl_pkts; +} + +static void host_num_completed_packets(struct net_buf *buf, + struct net_buf **evt) +{ + struct bt_hci_cp_host_num_completed_packets *cmd = (void *)buf->data; + struct bt_hci_evt_cc_status *ccst; + u32_t count = 0; + int i; + + /* special case, no event returned except for error conditions */ + if (hci_hbuf_total <= 0) { + ccst = cmd_complete(evt, sizeof(*ccst)); + ccst->status = BT_HCI_ERR_CMD_DISALLOWED; + return; + } else if (!conn_count) { + ccst = cmd_complete(evt, sizeof(*ccst)); + ccst->status = BT_HCI_ERR_INVALID_PARAM; + return; + } + + /* leave *evt == NULL so no event is generated */ + for (i = 0; i < cmd->num_handles; i++) { + count += cmd->h[i].count; + } + + hci_hbuf_acked += count; + k_poll_signal(hbuf_signal, 0x0); } +#endif static int ctrl_bb_cmd_handle(u8_t ocf, struct net_buf *cmd, struct net_buf **evt) @@ -184,6 +298,19 @@ static int ctrl_bb_cmd_handle(u8_t ocf, struct net_buf *cmd, reset(cmd, evt); break; +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) + case BT_OCF(BT_HCI_OP_SET_CTL_TO_HOST_FLOW): + set_ctl_to_host_flow(cmd, evt); + break; + + case BT_OCF(BT_HCI_OP_HOST_BUFFER_SIZE): + host_buffer_size(cmd, evt); + break; + + case BT_OCF(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS): + host_num_completed_packets(cmd, evt); + break; +#endif default: return -EINVAL; } @@ -1082,6 +1209,7 @@ static void le_advertising_report(struct pdu_data *pdu_data, u8_t *b, } +#if defined(CONFIG_BLUETOOTH_CONN) static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle, struct net_buf *buf) { @@ -1106,6 +1234,8 @@ static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle, sep->latency = sys_cpu_to_le16(radio_cc->latency); sep->supv_timeout = sys_cpu_to_le16(radio_cc->timeout); sep->clock_accuracy = radio_cc->mca; + + conn_count++; } static void disconn_complete(struct pdu_data *pdu_data, u16_t handle, @@ -1123,6 +1253,8 @@ static void disconn_complete(struct pdu_data *pdu_data, u16_t handle, ep->status = 0x00; ep->handle = sys_cpu_to_le16(handle); ep->reason = *((u8_t *)pdu_data); + + conn_count--; } static void le_conn_update_complete(struct pdu_data *pdu_data, u16_t handle, @@ -1163,6 +1295,7 @@ static void enc_refresh_complete(struct pdu_data *pdu_data, u16_t handle, ep->status = 0x00; ep->handle = sys_cpu_to_le16(handle); } +#endif #if defined(CONFIG_BLUETOOTH_CONTROLLER_LE_PING) static void auth_payload_timeout_exp(struct pdu_data *pdu_data, u16_t handle, @@ -1212,6 +1345,7 @@ static void encode_control(struct radio_pdu_node_rx *node_rx, le_advertising_report(pdu_data, b, buf); break; +#if defined(CONFIG_BLUETOOTH_CONN) case NODE_RX_TYPE_CONNECTION: le_conn_complete(pdu_data, handle, buf); break; @@ -1227,6 +1361,7 @@ static void encode_control(struct radio_pdu_node_rx *node_rx, case NODE_RX_TYPE_ENC_REFRESH: enc_refresh_complete(pdu_data, handle, buf); break; +#endif #if defined(CONFIG_BLUETOOTH_CONTROLLER_LE_PING) case NODE_RX_TYPE_APTO: @@ -1460,6 +1595,7 @@ static void encode_data_ctrl(struct radio_pdu_node_rx *node_rx, } } +#if defined(CONFIG_BLUETOOTH_CONN) void hci_acl_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf) { struct bt_hci_acl_hdr *acl; @@ -1484,6 +1620,13 @@ void hci_acl_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf) acl->len = sys_cpu_to_le16(pdu_data->len); data = (void *)net_buf_add(buf, pdu_data->len); memcpy(data, &pdu_data->payload.lldata[0], pdu_data->len); +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) + if (hci_hbuf_total > 0) { + LL_ASSERT((hci_hbuf_sent - hci_hbuf_acked) < + hci_hbuf_total); + hci_hbuf_sent++; + } +#endif break; default: @@ -1492,6 +1635,7 @@ void hci_acl_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf) } } +#endif void hci_evt_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf) { @@ -1534,3 +1678,54 @@ bool hci_evt_is_discardable(struct radio_pdu_node_rx *node_rx) return false; } } + +s8_t hci_get_class(struct radio_pdu_node_rx *node_rx) +{ + struct pdu_data *pdu_data; + + pdu_data = (struct pdu_data *)node_rx->pdu_data; + + if (node_rx->hdr.type != NODE_RX_TYPE_DC_PDU) { + + switch (node_rx->hdr.type) { + case NODE_RX_TYPE_REPORT: +#if defined(CONFIG_BLUETOOTH_CONTROLLER_ADV_INDICATION) + case NODE_RX_TYPE_ADV_INDICATION: +#endif +#if defined(CONFIG_BLUETOOTH_CONTROLLER_PROFILE_ISR) + case NODE_RX_TYPE_PROFILE: +#endif + return HCI_CLASS_EVT_DISCARDABLE; + case NODE_RX_TYPE_CONNECTION: + return HCI_CLASS_EVT_REQUIRED; + case NODE_RX_TYPE_TERMINATE: + case NODE_RX_TYPE_CONN_UPDATE: + case NODE_RX_TYPE_ENC_REFRESH: +#if defined(CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI) + case NODE_RX_TYPE_RSSI: +#endif +#if defined(CONFIG_BLUETOOTH_CONTROLLER_LE_PING) + case NODE_RX_TYPE_APTO: +#endif +#if defined(CONFIG_BLUETOOTH_CONTROLLER_CHAN_SEL_2) + case NODE_RX_TYPE_CHAN_SEL_ALGO: +#endif + return HCI_CLASS_EVT_CONNECTION; + default: + return -1; + } + + } else if (pdu_data->ll_id == PDU_DATA_LLID_CTRL) { + return HCI_CLASS_EVT_CONNECTION; + } else { + return HCI_CLASS_ACL_DATA; + } +} + +void hci_init(struct k_poll_signal *signal_host_buf) +{ +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) + hbuf_signal = signal_host_buf; +#endif + reset(NULL, NULL); +} diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index 19c6476bbb900..58224cabb14e7 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,9 @@ #include "hal/debug.h" +#define NODE_RX(_node) CONTAINER_OF(_node, struct radio_pdu_node_rx, \ + hdr.onion.node) + static K_SEM_DEFINE(sem_prio_recv, 0, UINT_MAX); static K_FIFO_DEFINE(recv_fifo); @@ -51,23 +55,30 @@ static u32_t prio_ts; static u32_t rx_ts; #endif +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) +static struct k_poll_signal hbuf_signal = K_POLL_SIGNAL_INITIALIZER(); +static sys_slist_t hbuf_pend; +static s32_t hbuf_count; +#endif + static void prio_recv_thread(void *p1, void *p2, void *p3) { while (1) { struct radio_pdu_node_rx *node_rx; - struct net_buf *buf; u8_t num_cmplt; u16_t handle; while ((num_cmplt = radio_rx_get(&node_rx, &handle))) { +#if defined(CONFIG_BLUETOOTH_CONN) + struct net_buf *buf; buf = bt_buf_get_rx(K_FOREVER); bt_buf_set_type(buf, BT_BUF_EVT); hci_num_cmplt_encode(buf, handle, num_cmplt); BT_DBG("Num Complete: 0x%04x:%u", handle, num_cmplt); bt_recv_prio(buf); - k_yield(); +#endif } if (node_rx) { @@ -95,44 +106,209 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) } } -static void recv_thread(void *p1, void *p2, void *p3) +static inline struct net_buf *encode_node(struct radio_pdu_node_rx *node_rx, + s8_t class) { - while (1) { - struct radio_pdu_node_rx *node_rx; - struct pdu_data *pdu_data; - struct net_buf *buf; + struct net_buf *buf = NULL; + + /* Check if we need to generate an HCI event or ACL data */ + switch (class) { + case HCI_CLASS_EVT_DISCARDABLE: + case HCI_CLASS_EVT_REQUIRED: + case HCI_CLASS_EVT_CONNECTION: + if (class == HCI_CLASS_EVT_DISCARDABLE) { + buf = bt_buf_get_rx(K_NO_WAIT); + } else { + buf = bt_buf_get_rx(K_FOREVER); + } + if (buf) { + bt_buf_set_type(buf, BT_BUF_EVT); + hci_evt_encode(node_rx, buf); + } + break; +#if defined(CONFIG_BLUETOOTH_CONN) + case HCI_CLASS_ACL_DATA: + /* generate ACL data */ + buf = bt_buf_get_rx(K_FOREVER); + bt_buf_set_type(buf, BT_BUF_ACL_IN); + hci_acl_encode(node_rx, buf); + break; +#endif + default: + LL_ASSERT(0); + break; + } - BT_DBG("RX node get"); - node_rx = k_fifo_get(&recv_fifo, K_FOREVER); - BT_DBG("RX node dequeued"); - - pdu_data = (void *)node_rx->pdu_data; - /* Check if we need to generate an HCI event or ACL - * data - */ - if (node_rx->hdr.type != NODE_RX_TYPE_DC_PDU || - pdu_data->ll_id == PDU_DATA_LLID_CTRL) { - /* generate a (non-priority) HCI event */ - if (hci_evt_is_discardable(node_rx)) { - buf = bt_buf_get_rx(K_NO_WAIT); - } else { - buf = bt_buf_get_rx(K_FOREVER); + radio_rx_fc_set(node_rx->hdr.handle, 0); + node_rx->hdr.onion.next = 0; + radio_rx_mem_release(&node_rx); + + return buf; +} + +static inline struct net_buf *process_node(struct radio_pdu_node_rx *node_rx) +{ + s8_t class = hci_get_class(node_rx); + struct net_buf *buf = NULL; + +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) + if (hbuf_count != -1) { + bool pend = !sys_slist_is_empty(&hbuf_pend); + + /* controller to host flow control enabled */ + switch (class) { + case HCI_CLASS_EVT_DISCARDABLE: + case HCI_CLASS_EVT_REQUIRED: + break; + case HCI_CLASS_EVT_CONNECTION: + /* for conn-related events, only pend is relevant */ + hbuf_count = 1; + /* fallthrough */ + case HCI_CLASS_ACL_DATA: + if (pend || !hbuf_count) { + sys_slist_append(&hbuf_pend, + &node_rx->hdr.onion.node); + return NULL; + } + break; + default: + LL_ASSERT(0); + break; + } + } +#endif + + /* process regular node from radio */ + buf = encode_node(node_rx, class); + + return buf; +} + +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) +static inline struct net_buf *process_hbuf(void) +{ + /* shadow total count in case of preemption */ + s32_t hbuf_total = hci_hbuf_total; + struct net_buf *buf = NULL; + int reset; + + reset = atomic_test_and_clear_bit(&hci_state_mask, HCI_STATE_BIT_RESET); + if (reset) { + /* flush queue, no need to free, the LL has already done it */ + sys_slist_init(&hbuf_pend); + } + + if (hbuf_total > 0) { + struct radio_pdu_node_rx *node_rx = NULL; + s8_t class, next_class = -1; + sys_snode_t *node = NULL; + + /* available host buffers */ + hbuf_count = hbuf_total - (hci_hbuf_sent - hci_hbuf_acked); + + /* host acked ACL packets, try to dequeue from hbuf */ + node = sys_slist_peek_head(&hbuf_pend); + if (node) { + node_rx = NODE_RX(node); + class = hci_get_class(node_rx); + switch (class) { + case HCI_CLASS_EVT_CONNECTION: + node = sys_slist_get(&hbuf_pend); + break; + case HCI_CLASS_ACL_DATA: + if (hbuf_count) { + node = sys_slist_get(&hbuf_pend); + hbuf_count--; + } else { + /* no buffers, HCI will signal */ + node = NULL; + } + break; + case HCI_CLASS_EVT_DISCARDABLE: + case HCI_CLASS_EVT_REQUIRED: + default: + LL_ASSERT(0); + break; } - if (buf) { - bt_buf_set_type(buf, BT_BUF_EVT); - hci_evt_encode(node_rx, buf); + if (node) { + struct radio_pdu_node_rx *next; + bool empty = true; + + node_rx = NODE_RX(node); + node = sys_slist_peek_head(&hbuf_pend); + if (node) { + next = NODE_RX(node); + next_class = hci_get_class(next); + } + empty = sys_slist_is_empty(&hbuf_pend); + + buf = encode_node(node_rx, class); + if (!empty && (class == HCI_CLASS_EVT_CONNECTION || + (class == HCI_CLASS_ACL_DATA && + hbuf_count))) { + /* more to process, schedule an + * iteration + */ + + k_poll_signal(&hbuf_signal, 0x0); + } } - } else { - /* generate ACL data */ - buf = bt_buf_get_rx(K_FOREVER); - bt_buf_set_type(buf, BT_BUF_ACL_IN); - hci_acl_encode(node_rx, buf); } + } else { + hbuf_count = -1; + } + + return buf; +} +#endif - radio_rx_fc_set(node_rx->hdr.handle, 0); - node_rx->hdr.onion.next = 0; - radio_rx_mem_release(&node_rx); +static void recv_thread(void *p1, void *p2, void *p3) +{ +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) + /* @todo: check if the events structure really needs to be static */ + static struct k_poll_event events[2] = { + K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SIGNAL, + K_POLL_MODE_NOTIFY_ONLY, + &hbuf_signal, 0), + K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, + K_POLL_MODE_NOTIFY_ONLY, + &recv_fifo, 0), + }; +#endif + + while (1) { + struct radio_pdu_node_rx *node_rx = NULL; + struct net_buf *buf = NULL; + + BT_DBG("blocking"); +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) + int err; + + err = k_poll(events, 2, K_FOREVER); + LL_ASSERT(err == 0); + if (events[0].state == K_POLL_STATE_SIGNALED) { + events[0].signal->signaled = 0; + } else if (events[1].state == + K_POLL_STATE_FIFO_DATA_AVAILABLE) { + node_rx = k_fifo_get(events[1].fifo, 0); + } + + events[0].state = K_POLL_STATE_NOT_READY; + events[1].state = K_POLL_STATE_NOT_READY; + + /* process host buffers first if any */ + buf = process_hbuf(); + +#else + node_rx = k_fifo_get(&recv_fifo, K_FOREVER); +#endif + BT_DBG("unblocked"); + + if (node_rx && !buf) { + /* process regular node from radio */ + buf = process_node(node_rx); + } if (buf) { if (buf->len) { @@ -161,13 +337,11 @@ static int cmd_handle(struct net_buf *buf) struct net_buf *evt; evt = hci_cmd_handle(buf); - if (!evt) { - return -EINVAL; + if (evt) { + BT_DBG("Replying with event of %u bytes", evt->len); + bt_recv_prio(evt); } - BT_DBG("Replying with event of %u bytes", evt->len); - bt_recv_prio(evt); - return 0; } @@ -185,9 +359,11 @@ static int hci_driver_send(struct net_buf *buf) type = bt_buf_get_type(buf); switch (type) { +#if defined(CONFIG_BLUETOOTH_CONN) case BT_BUF_ACL_OUT: err = hci_acl_handle(buf); break; +#endif case BT_BUF_CMD: err = cmd_handle(buf); break; @@ -212,12 +388,17 @@ static int hci_driver_open(void) DEBUG_INIT(); err = ll_init(&sem_prio_recv); - if (err) { BT_ERR("LL initialization failed: %u", err); return err; } +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) + hci_init(&hbuf_signal); +#else + hci_init(NULL); +#endif + k_thread_spawn(prio_recv_thread_stack, sizeof(prio_recv_thread_stack), prio_recv_thread, NULL, NULL, NULL, K_PRIO_COOP(6), 0, K_NO_WAIT); diff --git a/subsys/bluetooth/controller/hci/hci_internal.h b/subsys/bluetooth/controller/hci/hci_internal.h index 679ce4ea5e96a..eba9198b21bf7 100644 --- a/subsys/bluetooth/controller/hci/hci_internal.h +++ b/subsys/bluetooth/controller/hci/hci_internal.h @@ -8,10 +8,27 @@ #ifndef _HCI_CONTROLLER_H_ #define _HCI_CONTROLLER_H_ +#if defined(CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC) +extern s32_t hci_hbuf_total; +extern u32_t hci_hbuf_sent; +extern u32_t hci_hbuf_acked; +extern atomic_t hci_state_mask; + +#define HCI_STATE_BIT_RESET 0 +#endif + +#define HCI_CLASS_EVT_REQUIRED 0 +#define HCI_CLASS_EVT_DISCARDABLE 1 +#define HCI_CLASS_EVT_CONNECTION 2 +#define HCI_CLASS_ACL_DATA 3 + +void hci_init(struct k_poll_signal *signal_host_buf); struct net_buf *hci_cmd_handle(struct net_buf *cmd); -int hci_acl_handle(struct net_buf *acl); void hci_evt_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf); +s8_t hci_get_class(struct radio_pdu_node_rx *node_rx); +#if defined(CONFIG_BLUETOOTH_CONN) +int hci_acl_handle(struct net_buf *acl); void hci_acl_encode(struct radio_pdu_node_rx *node_rx, struct net_buf *buf); void hci_num_cmplt_encode(struct net_buf *buf, u16_t handle, u8_t num); -bool hci_evt_is_discardable(struct radio_pdu_node_rx *node_rx); +#endif #endif /* _HCI_CONTROLLER_H_ */ diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.h b/subsys/bluetooth/controller/ll_sw/ctrl.h index c6fdb37428539..fcb0351cdd070 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.h +++ b/subsys/bluetooth/controller/ll_sw/ctrl.h @@ -250,6 +250,7 @@ struct radio_le_chan_sel_algo { struct radio_pdu_node_rx_hdr { union { + sys_snode_t node; /* used by slist */ void *next; /* used also by k_fifo once pulled */ void *link; u8_t packet_release_last; diff --git a/tests/bluetooth/init/prj_controller.conf b/tests/bluetooth/init/prj_controller.conf index 43c1ebd22e9ab..31da439215574 100644 --- a/tests/bluetooth/init/prj_controller.conf +++ b/tests/bluetooth/init/prj_controller.conf @@ -4,6 +4,7 @@ CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO=0 CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO=0 CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=y CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED=y +CONFIG_BLUETOOTH_CONTROLLER_TO_HOST_FC=y CONFIG_BLUETOOTH_PERIPHERAL=y CONFIG_BLUETOOTH_CENTRAL=y CONFIG_BLUETOOTH_SMP=y From a1c74b74d214f10fb314aeda93c2b796b18a26e8 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Wed, 3 May 2017 15:18:03 -0400 Subject: [PATCH 19/19] ci: update path to theme repo Signed-off-by: Anas Nashif --- scripts/ci/build-docs.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ci/build-docs.sh b/scripts/ci/build-docs.sh index 12bf5d662fbab..f6b587a6129fd 100755 --- a/scripts/ci/build-docs.sh +++ b/scripts/ci/build-docs.sh @@ -5,10 +5,10 @@ echo "- Install dependencies" sudo apt-get install doxygen make sudo pip install breathe sphinx awscli sphinx_rtd_theme -cd ${TESTING_REPO_STATE} +cd ${MAIN_REPO_STATE} source zephyr-env.sh -cp -a /build/IN/docs-theme-repo/gitRepo doc/themes/zephyr-docs-theme +cp -a /build/IN/docs_theme_repo/gitRepo doc/themes/zephyr-docs-theme ls -la doc/themes echo "- Building docs..."