stm32f1xx_it.c
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
/* USER CODE BEGIN SysTick_IRQn 1 */
RA_Task();
static uint8_t ctr=0;
if(ctr<(1000/HZ))
{
ctr++;
}
else
{
ctr=0;
jiffies_64+=1;
timer_update(&timer_base);
}
/* USER CODE END SysTick_IRQn 1 */
}
list.h
/*此代码移植自linux kernel*/
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
#include "mytype.h"
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#define LIST_POISON1 NULL
#define LIST_POISON2 NULL
#define prefetch(x) x
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next);
#endif
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
#else
extern void list_del(struct list_head *entry);
#endif
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
/**
* list_rotate_left - rotate the list to the left
* @head: the head of the list
*/
static inline void list_rotate_left(struct list_head *head)
{
struct list_head *first;
if (!list_empty(head)) {
first = head->next;
list_move_tail(first, head);
}
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
struct list_head *new_first = entry->next;
list->next = head->next;
list->next->prev = list;
list->prev = entry;
entry->next = list;
head->next = new_first;
new_first->prev = head;
}
/**
* list_cut_position - cut a list into two
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
* and if so we won't cut the list
*
* This helper moves the initial part of @head, up to and
* including @entry, from @head to @list. You should
* pass on @entry an element you know is on @head. @list
* should be an empty list or a list you do not care about
* losing its data.
*
*/
static inline void list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
if (list_empty(head))
return;
if (list_is_singular(head) &&
(head->next != entry && head != entry))
return;
if (entry == head)
INIT_LIST_HEAD(list);
else
__list_cut_position(list, head, entry);
}
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
/**
* list_splice - join two lists, this is designed for stacks
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head, head->next);
}
/**
* list_splice_tail - join two lists, each list being a queue
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice_tail(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head->prev, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head, head->next);
INIT_LIST_HEAD(list);
}
}
/**
* list_splice_tail_init - join two lists and reinitialise the emptied list
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* Each of the lists is a queue.
* The list at @list is reinitialised
*/
static inline void list_splice_tail_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head->prev, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
/**
* __list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*
* This variant differs from list_for_each() in that it's the
* simplest possible list iteration code, no prefetching is done.
* Use this for code that knows the list to be very short (empty
* or 1 entry) most of the time.
*/
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
for (pos = (head)->prev, n = pos->prev; \
prefetch(pos->prev), pos != (head); \
pos = n, n = pos->prev)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
prefetch(pos->member.prev), &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, typeof(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, head, member) \
for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
prefetch(pos->member.prev), &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
for (; prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_continue - continue list iteration safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_from - iterate over list from current point safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member), \
n = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/**
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
* @pos: the loop cursor used in the list_for_each_entry_safe loop
* @n: temporary storage used in list_for_each_entry_safe
* @member: the name of the list_struct within the struct.
*
* list_safe_reset_next is not safe to use in general if the list may be
* modified concurrently (eg. the lock is dropped in the loop body). An
* exception to this is if the cursor element (pos) is pinned in the list,
* and list_safe_reset_next is called after re-taking the lock and before
* completing the current iteration of the loop body.
*/
#define list_safe_reset_next(pos, n, member) \
n = list_entry(pos->member.next, typeof(*pos), member)
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
/*
* Move a list from one list head to another. Fixup the pprev
* reference of the first entry if it exists.
*/
static inline void hlist_move_list(struct hlist_head *old,
struct hlist_head *new)
{
new->first = old->first;
if (new->first)
new->first->pprev = &new->first;
old->first = NULL;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member) \
for (pos = (pos)->next; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member) \
for (; pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
#endif
timer.h
#ifndef _LINUX_TIMER_H
#define _LINUX_TIMER_H
#include "list.h"
#include "typecheck.h"
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#define HZ 100
#define time_after(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)(b) - (long)(a) < 0))
#define time_before(a,b) time_after(b,a)
#define time_after_eq(a,b) \
(typecheck(unsigned long, a) && \
typecheck(unsigned long, b) && \
((long)(a) - (long)(b) >= 0))
#define time_before_eq(a,b) time_after_eq(b,a)
#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
#define CONFIG_BASE_SMALL 0
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)
struct timer_list {
struct list_head entry;//用于把一组定时器组成一个链表
unsigned long expires;//指出了该定时器的到期时刻,也就是期望定时器到期时刻的jiffies计数值
struct tvec_base *base;//每个cpu拥有一个自己的用于管理定时器的tvec_base结构,该字段指向该定时器所属的cpu所对应tvec_base结构
void (*function)(unsigned long);//指向一个可执行函数。当定时器到期时,内核就执行function所指定的函数
unsigned long data;//data域则被内核用作function函数的调用参数
};
struct tvec {
struct list_head vec[TVN_SIZE];
};
struct tvec_root {
struct list_head vec[TVR_SIZE];
};
struct tvec_base {
//spinlock_t lock;
struct timer_list *running_timer;//指向当前cpu正在处理的定时器所对应的timer_list结构
unsigned long timer_jiffies;//表示当前cpu定时器所经历过的jiffies数,大多数情况下,该值和jiffies计数值相等,当cpu的idle状态连续持续了多个jiffies时间时,当退出idle状态时,jiffies计数值就会大于该字段,在接下来的tick中断后,定时器系统会让该字段的值追赶上jiffies值
unsigned long next_timer;//指向该cpu下一个即将到期的定时器
struct tvec_root tv1;
struct tvec tv2;
struct tvec tv3;
struct tvec tv4;
struct tvec tv5;
};
#define TIMER_INITIALIZER(_function, _expires, _data) {.entry = { .prev = NULL },.function = _function,.expires = _expires,.data = _data,.base = &timer_base}
#define DEFINE_TIMER(_name, _function, _expires, _data) struct timer_list _name = TIMER_INITIALIZER(_function, _expires, _data)
static inline void set_running_timer(struct tvec_base *base,
struct timer_list *timer)
{
base->running_timer = timer;
}
static inline void detach_timer(struct timer_list *timer,
int clear_pending)
{
struct list_head *entry = &timer->entry;
//debug_deactivate(timer);
__list_del(entry->prev, entry->next);
if (clear_pending)
entry->next = NULL;
entry->prev = LIST_POISON2;
}
#define jiffies *pjiffies
extern unsigned long jiffies;
extern uint64_t jiffies_64;
extern uint32_t sys_start_rtc_time;
extern struct tvec_base timer_base;
void init_timers(void);
void timer_update(struct tvec_base *base);
#define init_timer(timer)\
init_timer_key((timer), NULL)
void init_timer_key(struct timer_list *timer,
const char *name);
int mod_timer(struct timer_list *timer, unsigned long expires);
void add_timer(struct timer_list *timer);
int del_timer(struct timer_list * timer);
static inline void setup_timer_key(struct timer_list * timer,
const char *name,
void (*function)(unsigned long),
unsigned long data)
{
timer->function = function;
timer->data = data;
init_timer_key(timer, name);
}
#define setup_timer(timer, fn, data)\
setup_timer_key((timer), NULL, (fn), (data))
#endif
timer.c
/*默认情况下,没有使能CONFIG_BASE_SMALL,TVR_SIZE的大小是256,TVN_SIZE的大小则是64,当需要节省内存空间时,也可以使能CONFIG_BASE_SMALL,这时TVR_SIZE的大小是64,TVN_SIZE的大小则是16,以下的讨论我都是基于没有使能CONFIG_BASE_SMALL的情况。当有一个新的定时器要加入时,系统根据定时器到期的jiffies值和timer_jiffies字段的差值来决定该定时器被放入tv1至tv5中的哪一个数组中*/
#include "timer.h"
#include "rtc.h"
#ifndef __ARMEB__
unsigned long *pjiffies=((unsigned long *)(&jiffies_64));
#else
unsigned long *pjiffies=((unsigned long *)(&jiffies_64))+4;
#endif
uint64_t jiffies_64=0;
struct tvec_base timer_base;
uint32_t sys_start_rtc_time;
static struct timer_list rtc_timer;
/**
* @brief Read the time counter available in RTC_CNT registers.
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
* the configuration information for RTC.
* @retval Time counter
*/
static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef* hrtc)
{
uint16_t high1 = 0U, high2 = 0U, low = 0U;
uint32_t timecounter = 0U;
high1 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
low = READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT);
high2 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
if (high1 != high2)
{ /* In this case the counter roll over during reading of CNTL and CNTH registers,
read again CNTL register then return the counter value */
timecounter = (((uint32_t) high2 << 16U) | READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT));
}
else
{ /* No counter roll over during reading of CNTL and CNTH registers, counter
value is equal to first value of CNTL and CNTH */
timecounter = (((uint32_t) high1 << 16U) | low);
}
return timecounter;
}
void init_timers()
{
//读取RTC
sys_start_rtc_time=RTC_ReadTimeCounter(&hrtc);
for(int i=0;i<TVR_SIZE;i++)
{
INIT_LIST_HEAD(&(timer_base.tv1.vec[i]));
}
for(int i=0;i<TVN_SIZE;i++)
{
INIT_LIST_HEAD(&(timer_base.tv2.vec[i]));
}
for(int i=0;i<TVN_SIZE;i++)
{
INIT_LIST_HEAD(&(timer_base.tv3.vec[i]));
}
for(int i=0;i<TVN_SIZE;i++)
{
INIT_LIST_HEAD(&(timer_base.tv4.vec[i]));
}
for(int i=0;i<TVN_SIZE;i++)
{
INIT_LIST_HEAD(&(timer_base.tv5.vec[i]));
}
}
static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
unsigned long data)
{
fn(data);
}
//确定要插入的链表数组以及数组的哪一项链表中
static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
{
unsigned long expires = timer->expires;
unsigned long idx = expires - base->timer_jiffies;//也即timer->expires-base->timer_jiffies,差值范围可以大致判断属于哪一个分组
struct list_head *vec;
if (idx < TVR_SIZE) { //tv1
int i = expires & TVR_MASK;
vec = base->tv1.vec + i;
} else if (idx < 1 << (TVR_BITS + TVN_BITS)) { //tv2
int i = (expires >> TVR_BITS) & TVN_MASK;
vec = base->tv2.vec + i;
} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) { //tv3
int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
vec = base->tv3.vec + i;
} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) { //tv4
int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
vec = base->tv4.vec + i;
} else if ((signed long) idx < 0) {//异常处理,随机取了一个0~255之间的数值
/*
* Can happen if you add a timer with expires == jiffies,
* or you set a timer to go off in the past
*/
vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
} else {
int i;
/* If the timeout is larger than 0xffffffff on 64-bit
* architectures then we use the maximum timeout:
*/
if (idx > 0xffffffffUL) {
idx = 0xffffffffUL;
expires = idx + base->timer_jiffies;
}
i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
vec = base->tv5.vec + i; //tv5
}
/*
* Timers are FIFO:
*/
list_add_tail(&timer->entry, vec);//相同vec的timer采取FIFO策略
}
//定时器的到期时的迁移代码
//参数index为事先计算好的高一级tv的需要迁移的数组索引
static int cascade(struct tvec_base *base, struct tvec *tv, int index)
{
/* cascade all the timers from tv up one level */
struct timer_list *timer, *tmp;
struct list_head tv_list;
list_replace_init(tv->vec + index, &tv_list);//用tv_list替换tv->vec+index表头,将tv->vec+index重新初始化,即为空,链表不会有timer存在。
/*
* We are removing _all_ timers from the list, so we
* don't have to detach them individually.
*/
list_for_each_entry_safe(timer, tmp, &tv_list, entry) {//遍历刚取出的tv_list里的timer
//BUG_ON(tbase_get_base(timer->base) != base);
internal_add_timer(base, timer);//重新加入到定时器系统中,实际上将会迁移到下一级的tv数组中
}
return index;
}
static inline void __run_timers(struct tvec_base *base)
{
struct timer_list *timer;
//spin_lock_irq(&base->lock);
while (time_after_eq(jiffies, base->timer_jiffies)) {//同步jiffies,在NO_HZ情况下,base->timer_jiffies可能落后不止一个tick
struct list_head work_list;
struct list_head *head = &work_list;
int index = base->timer_jiffies & TVR_MASK;//计算到期定时器链表在tv1中的索引
/*
* Cascade timers:
*/
if (!index && //index为0时,表示有进位到tv2
(!cascade(base, &(base->tv2), INDEX(0))) && //返回为0时,表示有进位到tv3
(!cascade(base, &(base->tv3), INDEX(1))) && //返回为0时,表示有进位到tv4
!cascade(base, &(base->tv4), INDEX(2))) //返回为0时,表示有进位到tv5
cascade(base, &(base->tv5), INDEX(3)); //从低位到高位逐级进位的迁移,在进位时将高位timer_list插入到低位
++base->timer_jiffies;//该cpu定时器系统运行时间递增一个tick
list_replace_init(base->tv1.vec + index, &work_list);//取出到期的定时器链表
while (!list_empty(head)) {//遍历所有的到期定时器
void (*fn)(unsigned long);
unsigned long data;
timer = list_first_entry(head, struct timer_list,entry);
fn = timer->function;
data = timer->data;
set_running_timer(base, timer);//标记正在处理的定时器
detach_timer(timer, 1);
//spin_unlock_irq(&base->lock);
call_timer_fn(timer, fn, data);//调用定时器的回调函数
//spin_lock_irq(&base->lock);
}
}
set_running_timer(base, NULL);
//spin_unlock_irq(&base->lock);
}
void timer_update(struct tvec_base *base)
{
if (time_after_eq(jiffies, base->timer_jiffies))
__run_timers(base);
}
static void __init_timer(struct timer_list *timer,
const char *name)
{
timer->entry.next = NULL;
timer->base = &timer_base;
}
void init_timer_key(struct timer_list *timer,
const char *name)
{
__init_timer(timer, name);
}
static inline int timer_pending(const struct timer_list * timer)
{
return timer->entry.next != NULL;
}
static inline int
__mod_timer(struct timer_list *timer, unsigned long expires)
{
struct tvec_base *base;
int ret = 0;
base=timer->base;
if (timer_pending(timer)) {
detach_timer(timer, 0);
if (timer->expires == base->next_timer)
base->next_timer = base->timer_jiffies;
ret = 1;
} else {}
timer->expires = expires;
if (time_before(timer->expires, base->next_timer))
base->next_timer = timer->expires;
internal_add_timer(base, timer);
return ret;
}
int mod_timer(struct timer_list *timer, unsigned long expires)
{
/*
* This is a common optimization triggered by the
* networking code - if the timer is re-modified
* to be the same thing then just return:
*/
if (timer_pending(timer) && timer->expires == expires)
return 1;
return __mod_timer(timer, expires);
}
void add_timer(struct timer_list *timer)
{
mod_timer(timer, timer->expires);
}
/**
* del_timer - deactive a timer.
* @timer: the timer to be deactivated
*
* del_timer() deactivates a timer - this works on both active and inactive
* timers.
*
* The function returns whether it has deactivated a pending timer or not.
* (ie. del_timer() of an inactive timer returns 0, del_timer() of an
* active timer returns 1.)
*/
int del_timer(struct timer_list *timer)
{
struct tvec_base *base;
int ret = 0;
if (timer_pending(timer)) {
detach_timer(timer, 1);
if (timer->expires == base->next_timer)
base->next_timer = base->timer_jiffies;
ret = 1;
}
return ret;
}
sys.h
#ifndef __SYS_H__
#define __SYS_H__
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "list.h"
#define my_assert_param(expr) ((expr) ? (void)0U : my_assert_failed((uint8_t *)__FILE__, __LINE__))
inline void my_assert_failed(uint8_t* file, uint32_t line)
{
printf("file:%s\r\nline:%d",file,line);
}
typedef void (*VOID_FUNC)(void);
typedef struct RA
{
VOID_FUNC func;
uint32_t tickstart;//起始时间
uint32_t wait_ms;//等待时间
uint32_t cycle_index;//循环次数
}RA_st;
typedef struct IC
{
VOID_FUNC func;
uint32_t cycle_index;//循环次数
}IC_st;
typedef struct IC_Tab
{
IC_st **IC_table;
uint8_t tabsize;
uint8_t counter;//注册个数计数
}IC_Tab_st;
extern HAL_TickFreqTypeDef uwTickFreq;
int8_t Run_Aftertimer_creat(VOID_FUNC func,uint32_t wait_ms,uint8_t index,uint32_t cycle_index);
int8_t Run_Aftertimer_release(uint8_t index);
void RA_Task(void);
int8_t Interrupt_Callback_creat(IC_Tab_st *IC_Tab,VOID_FUNC func,uint8_t index,uint32_t cycle_index);
int8_t Interrupt_Callback_release(IC_Tab_st *IC_Tab,uint8_t index);
int8_t Interrupt_Callback_Tab_creat(IC_Tab_st *IC_Tab,uint8_t tabsize);
int8_t Interrupt_Callback_Tab_release(IC_Tab_st *IC_Tab);
void IC_Task(IC_Tab_st *IC_Tab);
#endif
sys.c
#include "sys.h"
#include <stdlib.h>
/*******************************Run_Aftertimer*********************************/
#define RA_TABLE_SIZE 5
RA_st *RA_table[RA_TABLE_SIZE]={NULL};
int8_t Run_Aftertimer_register(RA_st *ra,uint8_t index)
{
/*index为0时自动分配index*/
if(index==0)
{
for(int i=1;i<RA_TABLE_SIZE;i++)
{
if(RA_table[i]==NULL)
{
index=i;
}
if(i>=RA_TABLE_SIZE)
{
free(ra);
return -1;
}
}
}
if(RA_table[index]!=NULL)
{
free(ra);
return -1;
}
RA_table[index]=ra;
RA_table[index]->tickstart = HAL_GetTick();
/* Add a freq to guarantee minimum wait */
if (RA_table[index]->wait_ms < HAL_MAX_DELAY)
{
RA_table[index]->wait_ms += (uint32_t)(uwTickFreq);
}
return index;
}
int8_t Run_Aftertimer_creat(VOID_FUNC func,uint32_t wait_ms,uint8_t index,uint32_t cycle_index)
{
if(RA_table[index]!=NULL)
{
return -1;
}
RA_st *ra=malloc(sizeof(RA_st));
ra->func=func;
ra->wait_ms=wait_ms;
ra->cycle_index=cycle_index;
return Run_Aftertimer_register(ra,index);
}
int8_t Run_Aftertimer_release(uint8_t index)
{
__set_PRIMASK(1); /* 禁止全局中断*/
if(RA_table[index]==NULL)
{
__set_PRIMASK(0); /* 使能全局中断 */
return -1;
}
/*释放内存*/
free(RA_table[index]);
RA_table[index]=NULL;
__set_PRIMASK(0); /* 使能全局中断 */
return 0;
}
void RA_Task()
{
for(int i=1;i<RA_TABLE_SIZE;i++)
{
if(RA_table[i]==NULL)
continue;
if ((HAL_GetTick() - RA_table[i]->tickstart) >= RA_table[i]->wait_ms)
{
RA_table[i]->func();
if(RA_table[i]->cycle_index==1)
{
/*释放内存*/
free(RA_table[i]);
RA_table[i]=NULL;
continue;
}
RA_table[i]->tickstart = HAL_GetTick();
if(RA_table[i]->cycle_index!=0)
{
RA_table[i]->cycle_index--;
}
}
}
}
/*******************************中断任务*********************************/
int8_t Interrupt_Callback_register(IC_Tab_st *IC_Tab,IC_st *ic,uint8_t index)
{
/*错误判断*/
/*index为0时自动分配index*/
if(index==0)
{
for(int i=1;i<IC_Tab->tabsize;i++)
{
if(IC_Tab->IC_table[i]==NULL)
{
index=i;
}
if(i>=IC_Tab->tabsize)
{
free(ic);
return -1;
}
}
}
/*该位置已被使用*/
if(IC_Tab->IC_table[index]!=NULL)
{
free(ic);
return -1;
}
/*正文*/
IC_Tab->counter++;
IC_Tab->IC_table[index]=ic;
return index;
}
int8_t Interrupt_Callback_creat(IC_Tab_st *IC_Tab,VOID_FUNC func,uint8_t index,uint32_t cycle_index)
{
/*错误判断*/
/*Tab未创建*/
if(IC_Tab->IC_table==NULL)
{
return -1;
}
/*该位置已被使用*/
if(IC_Tab->IC_table[index]!=NULL)
{
return -1;
}
/*正文*/
IC_st *ic=malloc(sizeof(IC_st));
if(ic==NULL)return -1;
ic->func=func;
ic->cycle_index=cycle_index;
return Interrupt_Callback_register(IC_Tab,ic,index);
}
int8_t Interrupt_Callback_release(IC_Tab_st *IC_Tab,uint8_t index)
{
__set_PRIMASK(1); /* 禁止全局中断*/
/*错误判断*/
/*该位置为NULL不用释放*/
if(IC_Tab->IC_table[index]==NULL)
{
__set_PRIMASK(0); /* 使能全局中断 */
return -1;
}
/*index为0(不支持一次释放全部)*/
if(index==0)
{
__set_PRIMASK(0); /* 使能全局中断 */
return -1;
}
/*正文*/
/*释放内存*/
IC_Tab->counter--;
free(IC_Tab->IC_table[index]);
IC_Tab->IC_table[index]=NULL;
__set_PRIMASK(0); /* 使能全局中断 */
return 0;
}
int8_t Interrupt_Callback_Tab_creat(IC_Tab_st *IC_Tab,uint8_t tabsize)
{
/*错误判断*/
/*Tab已经创建*/
if(IC_Tab->IC_table!=NULL)
{
return -1;
}
/*tabsize不满足要求*/
if(tabsize==0)
{
return -1;
}
/*正文*/
tabsize+=1;
IC_Tab->tabsize=tabsize;
IC_Tab->IC_table=malloc(tabsize*sizeof(IC_st *));
if(IC_Tab==NULL)return -1;
return tabsize;
}
int8_t Interrupt_Callback_Tab_release(IC_Tab_st *IC_Tab)
{
__set_PRIMASK(1); /* 禁止全局中断*/
/*错误判断*/
/*未创建Tab或重复释放*/
if(IC_Tab->IC_table==NULL)
{
__set_PRIMASK(0); /* 使能全局中断 */
return -1;
}
/*Tab中还有未释放的项目*/
if(IC_Tab->counter!=0)
{
__set_PRIMASK(0); /* 使能全局中断 */
return -1;
}
/*正文*/
/*释放内存*/
free(IC_Tab->IC_table);
IC_Tab->IC_table=NULL;
IC_Tab->tabsize=0;
__set_PRIMASK(0); /* 使能全局中断 */
return 0;
}
void IC_Task(IC_Tab_st *IC_Tab)
{
for(int i=1;i<IC_Tab->tabsize;i++)
{
if(IC_Tab->IC_table[i]==NULL)
continue;
IC_Tab->IC_table[i]->func();
if(IC_Tab->IC_table[i]->cycle_index==1)
{
/*释放内存*/
free(IC_Tab->IC_table[i]);
IC_Tab->IC_table[i]=NULL;
continue;
}
if(IC_Tab->IC_table[i]->cycle_index!=0)
{
IC_Tab->IC_table[i]->cycle_index--;
}
}
}
debug.h
#ifndef _DEBUG_H
#define _DEBUG_H
#include "stdio.h"
#include "stm32f1xx.h"
#include "main.h"
#include "usart.h"
/**
* @brief DEBUG 常量文本索引
*/
enum DEBUG
{
DEBUG_TEXT_INFO, /* debug信息 */
DEBUG_TEXT_CMD_TOO_LONG, /* 命令过长 */
DEBUG_TEXT_BACK, /* 退格 */
DEBUG_TEXT_INPUT_HEAD, /* 输入前置打印 */
DEBUG_TEXT_HELP, /* help 命令打印 */
DEBUG_TEXT_CMD_UNKNOWN, /* 未知命令类型 */
};
extern uint8_t byTmpData;
extern const char *pDebugText[];
void debug_analyze(void);
#endif /* DEBUG_H */
debug.c
#include "debug.h"
#include "string.h"
#define DEBUG_BUFF_SIZE 36
uint8_t byDebugBuff[DEBUG_BUFF_SIZE];
uint8_t byTmpData;
static uint8_t byCurrentDebugCursor = 0;
int dwTmpPara[6];
int i;
const char *pDebugText[] =
{
// [DEBUG_TEXT_INFO] =
"\r\n======================================================================"
"\r\n= (C) COPYRIGHT 2020 STMicroelectronics ="
"\r\n= ="
"\r\n= STM32F4xx Application For Motion (Version xxxxx) ="
"\r\n= ="
"\r\n= By Alight Team ="
"\r\n======================================================================\r\n",
// [DEBUG_TEXT_CMD_TOO_LONG] =
"\r\nCommand is too long\r\n",
// [DEBUG_TEXT_BACK] =
"\b \b",
// [DEBUG_TEXT_INPUT_HEAD] =
">",
// [DEBUG_TEXT_HELP] =
"\r\nCommand List :"
"\r\nreboot reset mcu"
"\r\nsm step motor control(speed angle break)"
"\r\npm push motor control(speed time break)"
"\r\nhelp show command info\r\n",
// [DEBUG_TEXT_CMD_UNKNOWN] =
"\r\nCommand unknown\r\n"
};
/*
*********************************************************************************************************
* 函 数 名: debug_analyze
* 功能说明: DEBUG数据解析
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void debug_analyze(void)
{
if('\b' == byTmpData)
{
if(byCurrentDebugCursor <= 0)
{
byCurrentDebugCursor = 0;
}
else
{
printf("%s", pDebugText[DEBUG_TEXT_BACK]);
byCurrentDebugCursor--;
}
return;
}
if('\r' == byTmpData || '\n' == byTmpData)
{
byDebugBuff[byCurrentDebugCursor] = '\0';
if(0 == byCurrentDebugCursor)
{
printf("\r\n");
}
else if(strcmp("reboot", (const char *)byDebugBuff) == 0)
{
HAL_NVIC_SystemReset();
printf("\r\nreset mcu\r\n");
}
else if(strncmp("sm", (const char *)byDebugBuff,strlen("sm")) == 0)
{
sscanf((const char *)byDebugBuff, "sm %d %d %d",&dwTmpPara[0],&dwTmpPara[1],&dwTmpPara[2]);
printf("\r\n%d,%d,%d\r\n",dwTmpPara[0],dwTmpPara[1],dwTmpPara[2]);
}
else if(strcmp("help", (const char *)byDebugBuff) == 0)
{
printf("%s",pDebugText[DEBUG_TEXT_HELP]);
}
else
{
printf("%s",pDebugText[DEBUG_TEXT_CMD_UNKNOWN]);
}
byCurrentDebugCursor = 0;
printf("%s", pDebugText[DEBUG_TEXT_INPUT_HEAD]);
}
else
{
HAL_UART_Transmit(&huart1,&byTmpData,1,0xff);
byDebugBuff[byCurrentDebugCursor] = byTmpData;
byCurrentDebugCursor++;
if(byCurrentDebugCursor >= DEBUG_BUFF_SIZE)
{
byCurrentDebugCursor = 0;
printf("%s", pDebugText[DEBUG_TEXT_CMD_TOO_LONG]);
printf("%s", pDebugText[DEBUG_TEXT_INPUT_HEAD]);
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
debug_analyze();
HAL_UART_Receive_IT(&huart1,&byTmpData,1);
}
/*添加了GNU extensions后会默认定义__GNUC__,使得printf不正确,所以这里去掉该定义*/
#undef __GNUC__
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}