diff --git a/Doxyfile b/Doxyfile index abcb7cb..1e226c7 100755 --- a/Doxyfile +++ b/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "HARMcksL: ARM HAL toolbox (yet STM32 oriented)" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.6 +PROJECT_NUMBER = 0.7 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/FctERR.c b/FctERR.c index 327900a..82e8274 100755 --- a/FctERR.c +++ b/FctERR.c @@ -1,6 +1,6 @@ /*!\file FctERR.c ** \author SMFSW -** \version v0.6 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief errors to SMFSW FctERR code @@ -11,11 +11,11 @@ #include "FctERR.h" -FctERR HALERRtoFCTERR(HAL_StatusTypeDef st) +FctERR HALERRtoFCTERR(HAL_StatusTypeDef status) { - if (st == HAL_OK) return ERR_OK; - else if (st == HAL_ERROR) return ERR_FAULT; - else if (st == HAL_BUSY) return ERR_BUSY; - else if (st == HAL_TIMEOUT) return ERR_TIMEOUT; - else return ERR_FAULT; + if (status == HAL_OK) return ERR_OK; + else if (status == HAL_ERROR) return ERR_FAULT; + else if (status == HAL_BUSY) return ERR_BUSY; + else if (status == HAL_TIMEOUT) return ERR_TIMEOUT; + else return ERR_FAULT; } diff --git a/FctERR.h b/FctERR.h index 8ddf783..5f7e096 100755 --- a/FctERR.h +++ b/FctERR.h @@ -1,6 +1,6 @@ /*!\file FctERR.h ** \author SMFSW -** \version v0.6 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief errors to SMFSW FctERR declarations @@ -17,10 +17,10 @@ // ***************************************************************************** // Section: Types // ***************************************************************************** -/*!\enum EnumFctERR -** \brief Enum of high level functions return state +/*!\enum FctERR +** \brief Enum of low/mid level functions return state **/ -typedef enum PACK__ EnumFctERR{ +typedef enum PACK__ FctERR{ ERR_OK = 0U, //!< OK ERR_SPEED = 1U, //!< This device does not work in the active speed mode. ERR_RANGE = 2U, //!< Parameter out of range. @@ -62,10 +62,10 @@ typedef enum PACK__ EnumFctERR{ // Section: Interface Routines // ***************************************************************************** /*!\brief Convert HAL_StatusTypeDef to FctERR -** \param[in] st - HAL_StatusTypeDef status +** \param[in] status - HAL_StatusTypeDef status ** \return FctERR status **/ -FctERR HALERRtoFCTERR(HAL_StatusTypeDef st); +FctERR HALERRtoFCTERR(HAL_StatusTypeDef status); /****************************************************************/ diff --git a/GPIO_ex.c b/GPIO_ex.c index 2824236..cd01904 100755 --- a/GPIO_ex.c +++ b/GPIO_ex.c @@ -1,6 +1,6 @@ /*!\file GPIO_ex.c ** \author SMFSW -** \version v0.6 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief Simple extension for GPIOs diff --git a/GPIO_ex.h b/GPIO_ex.h index 3251840..f775f44 100755 --- a/GPIO_ex.h +++ b/GPIO_ex.h @@ -1,6 +1,6 @@ /*!\file GPIO_ex.h ** \author SMFSW -** \version v0.6 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief Simple extension for GPIOs @@ -61,18 +61,21 @@ typedef struct GPIO_in { **/ void GPIO_in_init(GPIO_in * in, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint16_t filter); + /*!\brief Handles GPIO_in read and treatment ** \param[in,out] in - input instance to handle ** \return Nothing **/ void GPIO_in_handler(GPIO_in * in); + /*!\brief Get GPIO_in input value ** \param[in] in - input instance ** \return Input value **/ __INLINE bool INLINE__ get_GPIO_in(GPIO_in * in) { return in->in; } + /*!\brief Get GPIO_in input edge ** \param[in] in - input instance ** \return Input edge @@ -80,7 +83,6 @@ __INLINE bool INLINE__ get_GPIO_in(GPIO_in * in) { return in->in; } __INLINE bool INLINE__ get_GPIO_in_edge(GPIO_in * in) { return in->edge; } - /*!\brief Get name from Port, Pin ** \param[in,out] name - pointer to string for name ** \param[in] GPIOx - port to write to @@ -115,6 +117,7 @@ __INLINE void INLINE__ write_GPIO(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, eActOu } } + /*!\brief Read GPIO ** \param[in] GPIOx - port to read from ** \param[in] GPIO_Pin - pin to read from @@ -136,6 +139,7 @@ __INLINE GPIO_PinState INLINE__ read_GPIO(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin #endif } + /****************************************************************/ #endif /* __GPIO_EX_H */ /****************************************************************/ diff --git a/HARMcksL_v0_6.pdf b/HARMcksL_v0_7.pdf similarity index 52% rename from HARMcksL_v0_6.pdf rename to HARMcksL_v0_7.pdf index 11e6647..0210233 100755 Binary files a/HARMcksL_v0_6.pdf and b/HARMcksL_v0_7.pdf differ diff --git a/PWM.c b/PWM.c index 18bc304..27f6780 100755 --- a/PWM.c +++ b/PWM.c @@ -1,16 +1,15 @@ /*!\file PWM.c ** \author SMFSW -** \version v0.6 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW -** \brief Simple PWM handling +** \brief Straightforward PWM handling **/ /****************************************************************/ -/****************************************************************/ - #include "PWM.h" #if defined(HAL_TIM_MODULE_ENABLED) +/****************************************************************/ HAL_StatusTypeDef set_PWM_Freq(TIM_HandleTypeDef * pTim, uint32_t freq) @@ -23,7 +22,7 @@ HAL_StatusTypeDef set_PWM_Freq(TIM_HandleTypeDef * pTim, uint32_t freq) if (freq > coreCLK / 100) { return HAL_ERROR; } - // TODO: find prescaler & period with i++ instead of shifts + // TODO: find prescaler & period with i++ instead of shifts for more accuracy (despite of time passed) for (i = 1 ; i < (uint16_t) -1 ; i <<= 1) { per = (coreCLK / (freq * (i + 1))) - 1; @@ -41,7 +40,10 @@ HAL_StatusTypeDef set_PWM_Freq(TIM_HandleTypeDef * pTim, uint32_t freq) return HAL_TIM_Base_Init(pTim); } + +/*******************/ /*** PWM DRIVING ***/ +/*******************/ /*!\brief Low level TIM module PWM duty cycle write ** \param[in,out] pTim - pointer to TIM instance for PWM generation ** \param[in] chan - Channel to write @@ -64,6 +66,7 @@ __STATIC_INLINE HAL_StatusTypeDef INLINE__ write_CCR(TIM_HandleTypeDef * pTim, u return HAL_OK; } + HAL_StatusTypeDef set_PWM_Duty_Scaled(TIM_HandleTypeDef * pTim, uint32_t chan, uint16_t duty, uint16_t scale) { float tmp = ((float) min(scale, duty) / (float) scale) * pTim->Instance->ARR; @@ -71,4 +74,6 @@ HAL_StatusTypeDef set_PWM_Duty_Scaled(TIM_HandleTypeDef * pTim, uint32_t chan, u } +/****************************************************************/ #endif +/****************************************************************/ diff --git a/PWM.h b/PWM.h index f59cbdd..e53f005 100755 --- a/PWM.h +++ b/PWM.h @@ -1,9 +1,9 @@ /*!\file PWM.h ** \author SMFSW -** \version v0.6 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW -** \brief Simple PWM handling +** \brief Straightforward PWM handling **/ /****************************************************************/ #ifndef __PWM_H @@ -27,6 +27,7 @@ **/ HAL_StatusTypeDef set_PWM_Freq(TIM_HandleTypeDef * pTim, uint32_t freq); + /*!\brief Set TIM module PWM duty cycle (scaled) ** \param[in,out] pTim - pointer to TIM instance for PWM generation ** \param[in] chan - Channel to write @@ -36,6 +37,7 @@ HAL_StatusTypeDef set_PWM_Freq(TIM_HandleTypeDef * pTim, uint32_t freq); **/ HAL_StatusTypeDef set_PWM_Duty_Scaled(TIM_HandleTypeDef * pTim, uint32_t chan, uint16_t duty, uint16_t scale); + /*!\brief Set TIM module PWM duty cycle (percents) ** \param[in,out] pTim - pointer to TIM instance for PWM generation ** \param[in] chan - Channel to write @@ -45,6 +47,7 @@ HAL_StatusTypeDef set_PWM_Duty_Scaled(TIM_HandleTypeDef * pTim, uint32_t chan, u __INLINE HAL_StatusTypeDef INLINE__ set_PWM_Duty_Perc(TIM_HandleTypeDef * pTim, uint32_t chan, uint16_t duty) { return set_PWM_Duty_Scaled(pTim, chan, duty, 100); } + /*!\brief Set TIM module PWM duty cycle (u16-bit value) ** \param[in,out] pTim - pointer to TIM instance for PWM generation ** \param[in] chan - Channel to write @@ -54,6 +57,7 @@ __INLINE HAL_StatusTypeDef INLINE__ set_PWM_Duty_Perc(TIM_HandleTypeDef * pTim, __INLINE HAL_StatusTypeDef INLINE__ set_PWM_Duty_Word(TIM_HandleTypeDef * pTim, uint32_t chan, uint16_t duty) { return set_PWM_Duty_Scaled(pTim, chan, duty, (uint16_t) -1); } + /*!\brief Set TIM module PWM duty cycle (u8-bit value) ** \param[in,out] pTim - pointer to TIM instance for PWM generation ** \param[in] chan - Channel to write diff --git a/exceptions.c b/exceptions.c index 10ca06a..0e62b56 100755 --- a/exceptions.c +++ b/exceptions.c @@ -1,6 +1,6 @@ /*!\file exceptions.c ** \author SMFSW -** \version v0.6 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief Debug tool helpers functions @@ -19,6 +19,7 @@ void stackDump(uint32_t stack[]) { enum { r0, r1, r2, r3, r12, lr, pc, psr}; + printf("stack addr = %lx\r\n", stack); printf("r0 = 0x%08lx\r\n", stack[r0]); printf("r1 = 0x%08lx\r\n", stack[r1]); printf("r2 = 0x%08lx\r\n", stack[r2]); diff --git a/exceptions.h b/exceptions.h index 8281550..218903d 100755 --- a/exceptions.h +++ b/exceptions.h @@ -1,6 +1,6 @@ /*!\file exceptions.h ** \author SMFSW -** \version v0.5 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief Debug tool and helpers declaration @@ -18,27 +18,52 @@ // ***************************************************************************** // Section: Interface Routines // ***************************************************************************** +//! \note The exception_Handler should be called with corresponding exception name \b e as parameter #define exception_Handler(e) \ - __asm( "tst lr, #4 \n" \ - "ite EQ \n" \ - "mrseq r0, MSP \n" \ - "mrsne r0, PSP \n" \ - "b " #e "_Handler_callback \n") //!< The exception_Handler should be called with corresponding exception name \b e as parameter - - -#define dump_stack() \ - __asm( "tst lr, #4 \n" \ - "ite EQ \n" \ - "mrseq r0, MSP \n" \ - "mrsne r0, PSP \n" \ - "b stackDump \n") - - -/* Handled callbacks for reference -** (not really needed as called by assembly from macro) -** use macros to pass stack pointer properly */ -void HardFault_Handler_callback(uint32_t stack[]); // HardFault handler -void Error_Handler_callback(uint32_t stack[]); // HAL Error handler + __asm( "tst lr, #4 \r\n" \ + "ite EQ \r\n" \ + "mrseq r0, MSP \r\n" \ + "mrsne r0, PSP \r\n" \ + "b " #e "_Handler_callback \r\n") //!< Exception handler asm caller + + +#define dump_stack() \ + __asm( "tst lr, #4 \r\n" \ + "ite EQ \r\n" \ + "mrseq r0, MSP \r\n" \ + "mrsne r0, PSP \r\n" \ + "b stackDump \r\n") //!< Dump stack asm caller + + +/*!\brief prints contents of stack +** \param[in] stack - pointer to stack address +** \note stackDump should not be called directly, unless a particular stack is needed +** use dump_stack() which prepares pointer to current stack instead +** \return Nothing +**/ +void stackDump(uint32_t stack[]); + + +/*!\brief prints informations about current Hard Fault exception +** \param[in] stack - pointer to stack address +** \note HardFault_Handler_callback should not be called directly +** use exception_Handler() which prepares pointer to current stack instead +** \warning Depending how arm is fucked up, informations may not be printed, +** at least, you could inspect exception and stack through debug breakpoint +** \return Never (anyways, arm fubared!) +**/ +void HardFault_Handler_callback(uint32_t stack[]); + + +/*!\brief prints informations about current Hard Fault exception +** \param[in] stack - pointer to stack address +** \note HardFault_Handler_callback should not be called directly +** use exception_Handler() which prepares pointer to current stack instead +** \warning Depending how arm is fucked up, informations may not be printed, +** at least, you could inspect exception and stack through debug breakpoint +** \return Never (anyways, arm fubared!) +**/ +void Error_Handler_callback(uint32_t stack[]); /****************************************************************/ diff --git a/stdream_rdir.c b/stdream_rdir.c index 05fc822..04696ae 100755 --- a/stdream_rdir.c +++ b/stdream_rdir.c @@ -1,13 +1,11 @@ /*!\file stdream_rdir.c ** \author SMFSW -** \version v0.6 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief Stream redirection */ /****************************************************************/ -/****************************************************************/ - #include #include #include @@ -15,11 +13,14 @@ #include "stdream_rdir.h" #include "arm_stdclib.h" +/****************************************************************/ -static char buf_stream[128] = ""; +//! \warning Buffer for stdream is limited to \b 128B +static char buf_stream[128] = ""; //!< stdream buffer for output +/****************************************************************/ #if defined(HAL_UART_MODULE_ENABLED) #include "usart.h" @@ -27,30 +28,53 @@ static char buf_stream[128] = ""; #warning "You have to define DBG_SERIAL in usart.h with an UART instance for this to work!" #endif -__STATIC_INLINE HAL_StatusTypeDef INLINE__ print_uart(char* ptr, int len) +//#define STDREAM__UART_IT //!< To be defined to send to uart using interrupts + +/*!\brief Sends string to UART +** \note define STDREAM__UART_IT in compiler defines to send strings using interruptions +** \param[in] str - pointer to string to send +** \param[in] len - length of string +** \return HAL Status +**/ +__STATIC_INLINE HAL_StatusTypeDef INLINE__ print_uart(char * str, int len) { // TODO: find a way to determine if UART interrupts are enabled or not - return HAL_UART_Transmit(DBG_SERIAL, (uint8_t *) ptr, len, 30); - //return HAL_UART_Transmit_IT(DBG_SERIAL, (uint8_t *) ptr, len); + #if defined(STDREAM__UART_IT) + return HAL_UART_Transmit_IT(DBG_SERIAL, (uint8_t *) str, len); + #else + return HAL_UART_Transmit(DBG_SERIAL, (uint8_t *) str, len, 30); + #endif } #endif +/****************************************************************/ -static void print_itm(const char * msg, int len) +/*!\brief Sends string to ITM0 port +** \param[in] str - pointer to string to send +** \param[in] len - length of string +** \return Nothing +**/ +static void print_itm(const char * str, int len) { - //while (*msg != '\0') + //while (*str != '\0') for (int i = 0 ; i < len ; i++) - ITM_SendChar(*msg++); + ITM_SendChar(*str++); } -void print_itm_port(int port, const char * msg, int len) +/*!\brief Sends string to chosen ITM port +** \param[in] port - ITM port number +** \param[in] str - pointer to string to send +** \param[in] len - length of string +** \return Nothing +**/ +void print_itm_port(int port, const char * str, int len) { for (int i = 0 ; i < len ; i++) { - while (ITM->PORT[port].u32 == 0); - ITM->PORT[port].u8 = *msg++; + while (ITM->PORT[port].u32 == 0); // Wait for port to be ready + ITM->PORT[port].u8 = *str++; } } @@ -60,35 +84,35 @@ void print_itm_port(int port, const char * msg, int len) /********************/ /*** ITM ***/ -int printf_ITM(char * string, ...) +int printf_ITM(char * str, ...) { va_list args; - va_start(args, string); - vsprintf(buf_stream, string, args); + va_start(args, str); + vsprintf(buf_stream, str, args); va_end(args); print_itm(buf_stream, strlen(buf_stream)); - str_clr(buf_stream); // Erase string + str_clr(buf_stream); // Empty string return 0; } -int vprintf_ITM(char * string, va_list args) +int vprintf_ITM(char * str, va_list args) { - vsprintf(buf_stream, string, args); + vsprintf(buf_stream, str, args); print_itm(buf_stream, strlen(buf_stream)); - str_clr(buf_stream); // Erase string + str_clr(buf_stream); // Empty string return 0; } /*** GENERAL REDIRECTION ***/ -int printf_rdir(char * string, ...) +int printf_rdir(char * str, ...) { uint16_t len; va_list args; - va_start(args, string); - vsprintf(buf_stream, string, args); + va_start(args, str); + vsprintf(buf_stream, str, args); va_end(args); len = strlen(buf_stream); @@ -100,16 +124,16 @@ int printf_rdir(char * string, ...) print_uart(buf_stream, len); #endif - str_clr(buf_stream); // Erase string + str_clr(buf_stream); // Empty string return 0; } -int vprintf_rdir(char * string, va_list args) +int vprintf_rdir(char * str, va_list args) { uint16_t len; - vsprintf(buf_stream, string, args); + vsprintf(buf_stream, str, args); len = strlen(buf_stream); #if defined(ITM_ENABLED) @@ -120,7 +144,17 @@ int vprintf_rdir(char * string, va_list args) print_uart(buf_stream, len); #endif - str_clr(buf_stream); // Erase string + str_clr(buf_stream); // Empty string return 0; } + +int32_t get_fp_dec(float f, uint8_t nb) +{ + int32_t mul = 1; + f -= (int32_t) f; + while(nb-- != 0) { mul *= 10; } + return (int32_t) (f * mul); +} + + diff --git a/stdream_rdir.h b/stdream_rdir.h index 25f2482..878423f 100755 --- a/stdream_rdir.h +++ b/stdream_rdir.h @@ -1,9 +1,11 @@ /*!\file stdream_rdir.h ** \author SMFSW -** \version v0.6 +** \version v0.7 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief Stream redirection header +** \note define DBG_SERIAL in compiler defines with an UART instance to send printf likes strings to UART +** otherwise, stings will be printed to ITM0 port only */ /****************************************************************/ #ifndef __STREAM_REDIRECT_H @@ -23,22 +25,38 @@ // ***************************************************************************** // #define ITM_ENABLED //!< Enable ITM send if defined -#define printf printf_rdir //!< Shadowing printf use -#define vprintf vprintf_rdir //!< Shadowing vprintf use +#define printf printf_rdir //!< Shadowing printf +#define vprintf vprintf_rdir //!< Shadowing vprintf // ***************************************************************************** // Section: Interface Routines // ***************************************************************************** -void print_itm_port(int port, const char * msg, int len); +/*!\brief Get floating point number decimal part +** \param[in] port - ITM port number +** \param[in] str - pointer to message to send +** \param[in] len - length of message to send +** \return Nothing +**/ +void print_itm_port(int port, const char * str, int len); // printf_ITM & vprintf_ITM will be redirected to ITM port 0 (ITM_SendChar used) -int printf_ITM(char * string, ...); -int vprintf_ITM(char * string, va_list args); +int printf_ITM(char * str, ...); +int vprintf_ITM(char * str, va_list args); // General printf & vprintf redirection, will flood all enabled ports (at the cost of speed) -int printf_rdir(char * string, ...); -int vprintf_rdir(char * string, va_list args); +int printf_rdir(char * str, ...); +int vprintf_rdir(char * str, va_list args); + + +/*!\brief Get floating point number decimal part +** \note in need to print floats, add '-u _printf_float' in Linker options +** \warning enabling floating point support from linker seems to fubar printing long variables +** \param[in] f - floating point value +** \param[in] nb - Number of decimal to get after floating point +** \return nb decimal part as integer +**/ +int32_t get_fp_dec(float f, uint8_t nb); /****************************************************************/