diff --git a/GPIO_ex.c b/GPIO_ex.c index bde11ce..86ea671 100755 --- a/GPIO_ex.c +++ b/GPIO_ex.c @@ -1,11 +1,12 @@ /*!\file GPIO_ex.c ** \author SMFSW -** \version v0.2 +** \version v0.3 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief Simple extension for GPIOs **/ #include +#include #include "GPIO_ex.h" @@ -14,21 +15,41 @@ int str_GPIO_name(char * name, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { - const char *port, prt[][7] = { "GPIOA", "GPIOB", "GPIOC", "GPIOD", "GPIOF", "GPIO?" }; - char pin; + const char *port, prt[][7] = { "GPIOA", "GPIOB", "GPIOC", "GPIOD", "GPIOE", "GPIOF", "GPIOG", "GPIOH", "GPIO?" }; + + /* Check the parameters */ + assert_param(name); + assert_param(IS_GPIO_PIN(GPIO_Pin)); if (!name) { return -1; } // pointer for storage is not defined // Find port comparing address - if (GPIOx == GPIOA) { port = prt[0]; } - else if (GPIOx == GPIOB) { port = prt[1]; } - else if (GPIOx == GPIOC) { port = prt[2]; } - else if (GPIOx == GPIOD) { port = prt[3]; } - else if (GPIOx == GPIOF) { port = prt[4]; } - else { port = prt[5]; } + if (GPIOx == GPIOA) port = prt[0]; +#if defined(GPIOB) + else if (GPIOx == GPIOB) port = prt[1]; +#endif +#if defined(GPIOC) + else if (GPIOx == GPIOC) port = prt[2]; +#endif +#if defined(GPIOD) + else if (GPIOx == GPIOD) port = prt[3]; +#endif +#if defined(GPIOE) + else if (GPIOx == GPIOE) port = prt[4]; +#endif +#if defined(GPIOF) + else if (GPIOx == GPIOF) port = prt[5]; +#endif +#if defined(GPIOG) + else if (GPIOx == GPIOG) port = prt[6]; +#endif +#if defined(GPIOH) + else if (GPIOx == GPIOH) port = prt[7]; +#endif + else port = prt[8]; // Find pin shifting values to get pin index - for (pin = 0 ; pin < MAX_PINS_PORT ; pin++) + for (int pin = 0 ; pin < MAX_PINS_PORT ; pin++) { if (1U << pin == GPIO_Pin) { diff --git a/PWM.c b/PWM.c index b761188..fc5e13b 100755 --- a/PWM.c +++ b/PWM.c @@ -22,11 +22,11 @@ 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 - for (i = 1 ; i < (uint16_t) -1 ; i<<=1) + for (i = 1 ; i < (uint16_t) -1 ; i <<= 1) { per = (coreCLK / (Freq * (i + 1))) - 1; if (per <= (uint16_t) -1) { break; } // If in 16b range - if (i == 1<<15) { return HAL_ERROR; } // If nothing has been found (last iteration) + if (i == 1 << 15) { return HAL_ERROR; } // If nothing has been found (last iteration) } pTim->Init.Period = per; diff --git a/exceptions.c b/exceptions.c new file mode 100755 index 0000000..61657c5 --- /dev/null +++ b/exceptions.c @@ -0,0 +1,77 @@ +/*!\file exceptions.c +** \author SMFSW +** \version v0.3 +** \date 2017 +** \copyright MIT (c) 2017, SMFSW +** \brief Debug tool helpers functions +**/ + +#include + +#include "exceptions.h" + +#include "stdream_rdir.h" + + +void stackDump(uint32_t stack[]) +{ + enum { r0, r1, r2, r3, r12, lr, pc, psr}; + + printf("r0 = 0x%08lx\n", stack[r0]); + printf("r1 = 0x%08lx\n", stack[r1]); + printf("r2 = 0x%08lx\n", stack[r2]); + printf("r3 = 0x%08lx\n", stack[r3]); + printf("r12 = 0x%08lx\n", stack[r12]); + printf("lr = 0x%08lx\n", stack[lr]); + printf("pc = 0x%08lx\n", stack[pc]); + printf("psr = 0x%08lx\n", stack[psr]); +} + + +void HardFault_Handler_callback(uint32_t stack[]) +{ + printf("Hard Fault handler\t"); + printf("SCB->HFSR = 0x%08lx\n", SCB->HFSR); + + if ((SCB->HFSR & (1 << 30)) != 0) + { + uint32_t CFSRValue = SCB->CFSR; + + printf("Hard Fault\t"); + printf("SCB->CFSR = 0x%08lx\n", CFSRValue); + if ((SCB->CFSR & 0xFFFF0000) != 0) + { + printf("Usage fault: "); + CFSRValue >>= 16; // right shift to lsb + if((CFSRValue & (1 << 9)) != 0) { printf("Zero div\n"); } + } + + if ((SCB->CFSR & 0xFF00) != 0) + { + CFSRValue = ((CFSRValue & 0x0000FF00) >> 8); // mask and shift + printf("Bus fault: 0x%02lx\n", CFSRValue); + } + + if ((SCB->CFSR & 0xFF) != 0) { + CFSRValue &= 0x000000FF; // mask other faults + printf("Memory Management fault: 0x%02lx\n", CFSRValue); + } + } + + stackDump(stack); + + __BKPT(01); + while(1); +} + + +void Error_Handler_callback(uint32_t stack[]) +{ + // TODO: maybe pass by another asm code to retrieve HAL error code if not in stack + printf("Error handler\t"); + stackDump(stack); + +// __BKPT(01); +// while(1); +} + diff --git a/exceptions.h b/exceptions.h new file mode 100755 index 0000000..704f5c0 --- /dev/null +++ b/exceptions.h @@ -0,0 +1,43 @@ +/*!\file exceptions.h +** \author SMFSW +** \version v0.3 +** \date 2017 +** \copyright MIT (c) 2017, SMFSW +** \brief Debug tool and helpers declaration +**/ +/****************************************************************/ +#ifndef __EXCEPTIONS_H + #define __EXCEPTIONS_H +/****************************************************************/ + +#include "sarmfsw.h" +#include CMSIS_INC +#include CMSIS_CFG + + +#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 + + +/****************************************************************/ +#endif +/****************************************************************/ diff --git a/stdream_rdir.c b/stdream_rdir.c index 1f25541..f64737b 100755 --- a/stdream_rdir.c +++ b/stdream_rdir.c @@ -1,6 +1,6 @@ /*!\file stream_redirect.c ** \author SMFSW -** \version v0.2 +** \version v0.3 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief Stream redirection @@ -12,55 +12,111 @@ #include "stdream_rdir.h" +#include "arm_stdclib.h" + + +static char buf_stream[128] = ""; + #if defined(HAL_UART_MODULE_ENABLED) +#include "usart.h" #if !defined(DBG_SERIAL) -#error "You have to define DBG_SERIAL in usart.h with an UART instance for this to work!" +#warning "You have to define DBG_SERIAL in usart.h with an UART instance for this to work!" #endif +__STATIC_INLINE void __attribute__((always_inline)) print_uart(char* ptr, int len) +{ + HAL_UART_Transmit(DBG_SERIAL, (uint8_t *) ptr, len, 30); +} -static char buf_stream[128] = ""; +#endif -// Used to redirect stuff printed with printf and puts -/*int _write(int file, char *ptr, int len) +static void print_itm(const char * msg, int len) { - int i=0; - for(i=0 ; iPORT[port].u32 == 0); + ITM->PORT[port].u8 = *msg++; + } } -int uart_printf(char *string, ...) +/********************/ +/*** PRINTF LIKES ***/ +/********************/ + +/*** ITM ***/ +int printf_ITM(char * string, ...) { va_list args; va_start(args, string); vsprintf(buf_stream, string, args); va_end(args); - uart_prt(buf_stream, strlen(buf_stream)); - buf_stream[0] = '\0'; // Erase string + print_itm(buf_stream, strlen(buf_stream)); + str_clr(buf_stream); // Erase string + return 0; +} +int vprintf_ITM(char * string, va_list args) +{ + vsprintf(buf_stream, string, args); + print_itm(buf_stream, strlen(buf_stream)); + str_clr(buf_stream); // Erase string return 0; } -int uart_vprintf(char *string, va_list args) +/*** GENERAL REDIRECTION ***/ +int printf_rdir(char * string, ...) { + uint16_t len; + va_list args; + + va_start(args, string); vsprintf(buf_stream, string, args); - uart_prt(buf_stream, strlen(buf_stream)); - buf_stream[0] = '\0'; // Erase string + va_end(args); + len = strlen(buf_stream); + +#if defined(ITM_ENABLED) + print_itm(buf_stream, len); +#endif +#if defined(DBG_SERIAL) + print_uart(buf_stream, len); +#endif + + str_clr(buf_stream); // Erase string return 0; } +int vprintf_rdir(char * string, va_list args) +{ + uint16_t len; + + vsprintf(buf_stream, string, args); + len = strlen(buf_stream); + +#if defined(ITM_ENABLED) + print_itm(buf_stream, len); +#endif + +#if defined(DBG_SERIAL) + print_uart(buf_stream, len); #endif + + str_clr(buf_stream); // Erase string + return 0; +} + diff --git a/stdream_rdir.h b/stdream_rdir.h index 16538e7..41942e1 100755 --- a/stdream_rdir.h +++ b/stdream_rdir.h @@ -1,6 +1,6 @@ /*!\file stream_redirect.h ** \author SMFSW -** \version v0.1 +** \version v0.3 ** \date 2017 ** \copyright MIT (c) 2017, SMFSW ** \brief Stream redirection header @@ -18,17 +18,22 @@ #include CMSIS_CFG -#if defined(HAL_UART_MODULE_ENABLED) -#include "usart.h" +#define ITM_ENABLED // Enable ITM send if defined -#define printf uart_printf // Shadowing printf use -#define vprintf uart_vprintf // Shadowing vprintf use +#define printf printf_rdir // Shadowing printf use +#define vprintf vprintf_rdir // Shadowing vprintf use -int uart_printf(char *string, ...); -int uart_vprintf(char *string, va_list args); -#endif +void print_itm_port(int port, const char * msg, 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); + +// 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); /****************************************************************/