/**
 @file+   RtoS_cortex_m7.S
 @author  AVI-crak
 @version V-45%
 @date    28-декабря-2016
 @brief   Аxis sRtoS, Cortex-M7 ARM GCC EmBitz

 license
 Million helicopters and one cent.

 форум для обсуждения
 http://forum.ixbt.com/topic.cgi?id=48:11735

 репозиторий
 https://bitbucket.org/AVI-crak/rtos-cortex-m3-gcc
*/

#include <stdint.h>  // типы данных
/// _estack  Общий адрес стека до модификаций
/// _irqsize  Размер стека прерываний
///_ebss  Последний используемый адрес памяти (.data + .bss)





#ifdef _RtoS_
 extern "C" {
#endif /* _RtoS_ */

#include "stm32f7xx.h"




struct _os_basic
{
    struct task* activ;                     ///#00- Список активных
    struct task* delay;                     ///#04- Список спящих
    struct task* hold;                      ///#08- Список замороженных
    volatile struct task* service;          ///#12- Список обслуживания
	struct task* task_switch;				///#16- Новый/старый таск
    const uint32_t nvic_stack;              ///#20- Адрес стека прерываний, Task maximum NVIC used stack
    const uint16_t nvic_size;               ///#24- Размер стека прерываний,
    volatile uint16_t use_nvic_size;        ///#26- Использованный стек прерываний
    const struct task* main_task;			///#28- Адрес стека main
    volatile uint32_t* use_task_stop;       ///#32- Последний адрес стека, Stack last address
    const uint32_t tick_1ms;				///#36- Таймер активности задачи 100%, Task activity timer 100%
    const volatile int32_t system_us;       ///#40- Системное время, System time counter
    const uint32_t* malloc0_start;           ///#44- Первый адрес malloc0, First malloc0 address
    volatile uint32_t* malloc0_stop;          ///#48- Последний адрес malloc0, Last malloc0 address
    const uint32_t* malloc1_start;           ///#52- Первый адрес malloc1, First malloc1 address
    volatile uint32_t* malloc1_stop;          ///#56- Последний адрес malloc1, Last malloc1 address
}os_data;



typedef enum
{
    task_activ =0,
    activ_error,
    task_delay,
    delay_error,
    task_hold,
    hold_error,
    serv,
    serv_error,
    new_task,
    new_task_error,
    delete_task,
    delete_task_error,
    new_ram,
    new_ram_error,
    delete_ram,
    delete_ram_error,
}task_status_TypeDef;

struct  task   /// новое 40b
{
    struct task*            task_head;          /// 0x00, #00  *32b,- Адрес новой задачи,
    struct task*            task_tail;          /// 0x04, #04, *32b,- Адрес старой задачи,
    struct task*            task_form_head;		/// 0x08, #08, *32b,- Задачи в общем стеке,
    uint32_t       top_stack;          /// 0x0C, #12, 32b,- Cтек задачи, Stack pointer
    uint32_t       swap_data;          /// 0x10, #16, 32b,- Внешние данные,
    char*    		task_names;         /// 0x14, #20, 32b,- Имя задачи, Task name
    uint16_t       stack_area_size;    /// 0x18, #24, 16b,- Размер стека, Task stack size
    uint16_t       stack_area_used;    /// 0x1A, #26, 16b,- Рабочий стек, Task maximum used stack
    struct
        {
            uint32_t   activ_time:24;      /// 0x1C, #28, 24b,- Таймер активности задачи, Task activity timer
            uint32_t	task_nomer:8;       /// 0x1F, #31, 8b,- Номер таска, Task unique ID
        };
    uint8_t*       link_data;          /// 0x20, #32, *32b,- Буфер обмена 256b, Ring clipboard
    uint8_t        link_head;          /// 0x24, #36, 8b,- Голова, Head
    uint8_t        link_tail;          /// 0x25, #37, 8b,- Хвост, Tail
    uint8_t        link_task_nomer;    /// 0x26, #38, 8b,- Номер звонка, Call number
    task_status_TypeDef     task_mode;          /// 0x27, #39, 8b,- Режим таска, Task mode
};




//void __attribute__ ((weak))Start_task(void);
//void __attribute__ ((weak))SVC_Handler(void);








/// Запрос ресурса, бесконечный цикл - пока не освободится
/// Resource request, endless loop while resource not released
//void sTask_resource_ask (uint32_t *name_resource);


/// Освободить ресурс
/// Release resourse
//void sTask_resource_free (uint32_t *name_resource);


/// Функция отложенного события по циклическому таймеру
/// пример
/// static int32_t alarm_mc2;
/// if (sTask_alarm_mc(&alarm_mc1,1000)) { действие каждую новую секунду }
//int32_t sTask_alarm_mc(int32_t * timer_name, int32_t timer_mc);


/// Функция фиксированного времени сна по циклическому таймеру
/// пример
/// static int32_t alarm_mc1; sTask_wake_mc(&alarm_mc1,1000);
/// активное состояние 0-999мс, сон 999-1мс, цикл 1с
//int32_t sTask_wake_mc(int32_t * timer_name, int32_t timer_mc);

//int32_t Tim_alarm_mc(int32_t * timer_name, int32_t timer_mc);



/// Выделить память (размер)
void *os_malloc(int32_t size );



/// Удалить память (адрес)
void os_free (void* malloc_adres);


/// sTask_wake (& глобальный флаг) разбудить задачу
//void sTask_wake(volatile uint32_t* task_global_flag);



/// sTask_wait (& глобальный флаг) остановить задачу в ожидание пинка
//void sTask_wait(volatile uint32_t* task_global_flag);




/// sDelay_mc (в миллисекундах)
void os_Delay_ms(uint32_t delay_mc);



//void __attribute__ ((weak))___sRandom(void);


/// Старт ОS
/// частота ядра в гц, размер стека майна,
///       > размер стека прерываний, стартовое время задачи в микросекундах
void os_Run(const uint16_t main_size );



/// Барьер оптимизатора GCC
static inline void __memory(void){asm volatile ("nop" : : : "memory");}

/// Измерение рабочего размера стека прерываний
//void __attribute__ ((weak)) sHandler_zize(void);


/// Включить прерывание, преоритет (от 14 до 0)
void  os_EnableIRQ(IRQn_Type IRQn, uint8_t priority);




/// Отключить прерывание - после запуска ос
void os_DisableIRQ(IRQn_Type IRQn);





/// Новая задача - после запуска ос
uint32_t os_Task_new (void (*taskS_func),uint16_t task_size,uint8_t task_time_rate,char* const task_func_name);




/// Уступить время - только внутри работающей задачи
__attribute__( ( always_inline ) ) static inline void os_pass (void)
{
    asm volatile    ("push   {r3}               \n\t"
                     "mov   r3, #0		\n\t" // __switch
                    "svc    0x0         \n\t"
                    "pop    {r3}                \n\t"
                    :::"memory");
}

/// Убить задачу - только внутри работающей задачи
void os_Task_del(void);



uint32_t os_Ranlom(uint32_t range);






/// Bit operation, 1 in the mask resets the data
__attribute__( ( always_inline ) ) static inline uint32_t __BIC (uint32_t data, uint32_t mask)
{
  uint32_t result;
  asm volatile ("bic %0, %1, %2" : "=l" (result) : "l" (data), "l" (mask) );
  return(result);
}





/*
Обратите внимание, что для ARM вы можете указать тип прерывания, которое нужно обработать, добавив необязательный параметр к атрибуту прерывания, например:

          void f () __attribute__ ((interrupt ("IRQ")));

Допустимыми значениями для этого параметра являются: IRQ, FIQ, SWI, ABORT и UNDEF.
 */




#ifdef _RtoS_
}
#endif /* _RtoS_ */

#define _RtoS_






