aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChunyan Zhang <zhang.chunyan@linaro.org>2016-08-19 17:32:11 +0800
committerChunyan Zhang <zhang.chunyan@linaro.org>2016-08-19 21:05:42 +0800
commit8eb9940ca4591dd6b92788b2aad6d4056cd74ec7 (patch)
treebeca7c252cba467efff8dff25dc977009e581033
parentd56178f9af7aa6803e8f6d59084a3a13d4f4c2e5 (diff)
downloadsample-app-8eb9940ca4591dd6b92788b2aad6d4056cd74ec7.tar.gz
stm-write: added a sample of writing STM device
This sample shows how to collect trace via write STM device. This is the first version of this sample. In this patch, before writing STM device we chose to set policy in the program, actually setting a policy before writing STM is not the only one choice, if no policy assigned to the STM device a policy named 'default' will be applied. Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>
-rw-r--r--write-stm-device/Makefile15
-rw-r--r--write-stm-device/example.c37
-rw-r--r--write-stm-device/readme25
-rw-r--r--write-stm-device/stm_user_api.c126
-rw-r--r--write-stm-device/stm_user_api.h58
5 files changed, 261 insertions, 0 deletions
diff --git a/write-stm-device/Makefile b/write-stm-device/Makefile
new file mode 100644
index 0000000..09c0437
--- /dev/null
+++ b/write-stm-device/Makefile
@@ -0,0 +1,15 @@
+CROSS_COMPILE := /home/zcy/tools/gcc-linaro-aarch64-linux-gnu-4.9-2014.09_linux/bin/aarch64-linux-gnu-
+CC := $(CROSS_COMPILE)gcc
+CFLAGS := --static
+
+STM_USER = stm_sample_write
+
+OBJS_STM_USER_API= example.o stm_user_api.o
+
+all: $(STM_USER)
+
+$(STM_USER):$(OBJS_STM_USER_API)
+ $(CC) $(CFLAGS) -o $@ $^
+
+clean:
+ rm *.o $(STM_USER)
diff --git a/write-stm-device/example.c b/write-stm-device/example.c
new file mode 100644
index 0000000..dd58b0e
--- /dev/null
+++ b/write-stm-device/example.c
@@ -0,0 +1,37 @@
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "stm_user_api.h"
+
+extern struct stm_dev g_stm_dev;
+
+void main()
+{
+ unsigned int chan_start = 0;
+ unsigned int width = PAGE_SIZE / BYTES_PER_CHANNEL;
+ unsigned int wrbytes = sizeof(unsigned int) * TEST_DATA_SIZE;
+ unsigned int real_wrbytes;
+ unsigned int trace_data[TEST_DATA_SIZE] = {0x5555aaaa, 0xaaaa5555, 0x66666666, 0x99999999};
+
+ if (request_stm_resource(&g_stm_dev, chan_start, width))
+ return;
+
+ /*
+ * You can use any channel between [g_stm_dev.policy->channel ...
+ * (g_stm_dev.policy->channel + g_stm_dev.policy->width)]
+ */
+ real_wrbytes = stm_char_write(g_stm_dev.fd, (char *)trace_data, wrbytes);
+ if (real_wrbytes != wrbytes)
+ printf("write %d bytes and left % bytes data\n", real_wrbytes, wrbytes - real_wrbytes);
+
+ printf("Success to write %d bytes\n", real_wrbytes);
+
+ release_stm_resource(&g_stm_dev);
+}
diff --git a/write-stm-device/readme b/write-stm-device/readme
new file mode 100644
index 0000000..6bd7dd9
--- /dev/null
+++ b/write-stm-device/readme
@@ -0,0 +1,25 @@
+Before compiling the program, you must change the items below accroding to your environment:
+
+- 'CROSS_COMPILE' in Makefile
+- STM device name in stm_user_api.h
+- TMC device name in stm_user_api.h
+
+
+And then you may need to mount configfs manually:
+/ # mount -t configfs none /config
+
+
+Create policy directory for STM:
+/ # mkdir /config/stp-policy/20100000.stm.abc
+
+NOTE:
+The STM directory name consists of the device name to which it applies and the actual policy name,
+separated by a dot.
+The device name (say 20100000.stm) have to be matched the name of STM device under /dev.
+The suffix is a random string without any dot
+
+
+Create policy:
+/ # mkdir /config/stp-policy/20100000.stm.abc/test
+
+
diff --git a/write-stm-device/stm_user_api.c b/write-stm-device/stm_user_api.c
new file mode 100644
index 0000000..776f20c
--- /dev/null
+++ b/write-stm-device/stm_user_api.c
@@ -0,0 +1,126 @@
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "stm_user_api.h"
+
+void release_stm_resource(struct stm_dev *dev);
+
+static void enable_sink(const char *dev_name, unsigned int enable)
+{
+ char buf[256] = {0};
+ sprintf(buf, "echo %u > /sys/bus/coresight/devices/%s/enable_sink",
+ enable, dev_name);
+ system(buf);
+}
+
+static void enable_source(const char *dev_name, unsigned int enable)
+{
+ char buf[256] = {0};
+ sprintf(buf, "echo %u > /sys/bus/coresight/devices/%s/enable_source",
+ enable, dev_name);
+ system(buf);
+}
+
+static int set_policy(int fd, struct stp_policy_id *policy,
+ unsigned int chan, unsigned int width)
+{
+ unsigned int chan_perpage = PAGE_SIZE / BYTES_PER_CHANNEL;
+
+ if(width % chan_perpage || chan % chan_perpage) {
+ chan = chan / chan_perpage;
+ width = (width / chan_perpage + 1) * BYTES_PER_CHANNEL;
+ }
+
+ policy->channel = chan;
+ policy->__reserved_0 = 0;
+ policy->__reserved_1 = 0;
+ policy->width = width;
+ policy->size = sizeof(struct stp_policy_id) + POLICY_NAME_LEN;
+ memcpy(policy->id, STP_POLICY_NAME, POLICY_NAME_LEN);
+
+ if (ioctl(fd, STP_POLICY_ID_SET, policy) == -1) {
+ printf("STP_POLICY_ID_SET failed %s %d\n",
+ strerror(errno), errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * dev - storing the information of stimulus resources and STM device
+ * chan - the start index of channels
+ * width- the number of channels for request, it must be not larger than
+ * (PAGE_SIZE / BYTES_PER_CHANNEL) due to a limitation in STM driver
+ * http://lxr.free-electrons.com/source/drivers/hwtracing/stm/core.c?v=4.6#L542
+ */
+int request_stm_resource(struct stm_dev *dev, unsigned int chan,
+ unsigned int width)
+{
+ int fd;
+ int ret = 0;
+ struct stp_policy_id *policy;
+
+ if ((fd = open(STM_DEVICE_NAME, O_RDWR | O_SYNC)) == -1) {
+ printf("Failed to open %s %s\n", STM_DEVICE_NAME,
+ strerror(errno));
+ return -1;
+ }
+ dev->fd = fd;
+
+ /*
+ * Before allocating a policy for STM, the sink connected with STM must
+ * be enabled.
+ */
+ enable_sink(ETF_SYS_NAME, 1);
+
+ /* set a master/channel policy for this STM device, this
+ * is because that kernel have to know how many channels
+ * would be mapped, and the size of mapped memory must be
+ * a multiple of page size.
+ */
+ dev->policy = malloc(sizeof(struct stp_policy_id) + POLICY_NAME_LEN);
+ if (!dev->policy) {
+ ret = -1;
+ printf("Failed to malloc policy.\n");
+ goto out;
+ }
+
+ if (set_policy(fd, dev->policy, chan, width)) {
+ ret = -1;
+ printf("Failed to set policy.\n");
+ goto out;
+ }
+
+ return ret;
+
+out:
+ release_stm_resource(dev);
+ return ret;
+}
+
+void release_stm_resource(struct stm_dev *dev)
+{
+ if (dev->policy) {
+ free(dev->policy);
+ dev->policy = NULL;
+ }
+ if (dev->fd) {
+ close(dev->fd);
+ dev->fd = 0;
+ }
+
+ //enable_source(STM_SYS_NAME, 0);
+}
+
+unsigned int stm_char_write(int fd, const char *data, unsigned int size)
+{
+ write(fd, data, size);
+}
diff --git a/write-stm-device/stm_user_api.h b/write-stm-device/stm_user_api.h
new file mode 100644
index 0000000..0f9299e
--- /dev/null
+++ b/write-stm-device/stm_user_api.h
@@ -0,0 +1,58 @@
+#ifndef __STM_USER_API_H
+#define __STM_USER_API_H
+
+#define BYTES_PER_CHANNEL 256
+#define PAGE_SIZE sysconf(_SC_PAGE_SIZE) //4096
+#define MAP_MASK (PAGE_SIZE - 1)
+#define STM_MAP_SIZE PAGE_SIZE
+
+#define STM_DEVICE_NAME "/dev/20100000.stm"
+#define ETF_SYS_NAME "20010000.etf"
+#define ETR_SYS_NAME "20070000.etr"
+#define STM_SYS_NAME "20100000.stm"
+
+#define STP_POLICY_NAME "test"
+#define TEST_DATA_SIZE 4
+#define POLICY_NAME_LEN 8
+
+#define STP_POLICY_ID_SET _IOWR('%', 0, struct stp_policy_id)
+
+enum stm_flags {
+ STM_FLAG_TIMESTAMPED = 0x08,
+ STM_FLAG_MARKED = 0x10,
+ STM_FLAG_GUARANTEED = 0x80,
+};
+
+enum stm_pkt_type {
+ STM_PKT_TYPE_DATA = 0x98,
+ STM_PKT_TYPE_FLAG = 0xE8,
+ STM_PKT_TYPE_TRIG = 0xF8,
+};
+
+enum error_no {
+ E_COMMON = -1,
+};
+
+struct stp_policy_id {
+ unsigned int size;
+ unsigned short master;
+ unsigned short channel;
+ unsigned short width;
+ /* padding */
+ unsigned short __reserved_0;
+ unsigned int __reserved_1;
+ /* policy name */
+ char id[0];
+};
+
+struct stm_dev {
+ int fd;
+ struct stp_policy_id *policy;
+} g_stm_dev;
+
+int request_stm_resource(struct stm_dev *dev, unsigned int chan,
+ unsigned int width);
+void release_stm_reaource(struct stm_dev *dev);
+unsigned int stm_char_write(int fd, const char *data, unsigned int size);
+
+#endif /* __STM_USER_API_H */