diff --git a/Software/.vscode/settings.json b/Software/.vscode/settings.json index faad003..c1c2686 100644 --- a/Software/.vscode/settings.json +++ b/Software/.vscode/settings.json @@ -1,4 +1,4 @@ { - "cortex-debug.armToolchainPath": "/home/chiangni/.config/VSCodium/User/globalStorage/bmd.stm32-for-vscode/@xpack-dev-tools/arm-none-eabi-gcc/13.2.1-1.1.1/.content/bin", - "cortex-debug.openocdPath": "/home/chiangni/Documents/STM32/OpenOCD/xpacks/@xpack-dev-tools/openocd/.content/bin/openocd" + "cortex-debug.armToolchainPath": "/home/chiangni/.config/Code/User/globalStorage/bmd.stm32-for-vscode/@xpack-dev-tools/arm-none-eabi-gcc/13.3.1-1.1.1/.content/bin", + "cortex-debug.openocdPath": "/home/chiangni/.config/Code/User/globalStorage/bmd.stm32-for-vscode/@xpack-dev-tools/openocd/0.12.0-4.1/.content/bin/openocd" } \ No newline at end of file diff --git a/Software/Core/Inc/adc.h b/Software/Core/Inc/adc.h new file mode 100644 index 0000000..391e3e9 --- /dev/null +++ b/Software/Core/Inc/adc.h @@ -0,0 +1,9 @@ +#ifndef INC_ADC +#define INC_ADC +#include "stm32f0xx_hal_adc.h" + +void adc_init(ADC_HandleTypeDef* hadc); +void adc_loop(ADC_HandleTypeDef* hadc); +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc); + +#endif \ No newline at end of file diff --git a/Software/Core/Inc/stm32f0xx_hal_conf.h b/Software/Core/Inc/stm32f0xx_hal_conf.h index 9db9553..0babd97 100644 --- a/Software/Core/Inc/stm32f0xx_hal_conf.h +++ b/Software/Core/Inc/stm32f0xx_hal_conf.h @@ -73,7 +73,7 @@ * (when HSE is used as system clock source, directly or through the PLL). */ #if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */ + #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ /** diff --git a/Software/Core/Inc/stm32f0xx_it.h b/Software/Core/Inc/stm32f0xx_it.h index 317e5aa..29d1034 100644 --- a/Software/Core/Inc/stm32f0xx_it.h +++ b/Software/Core/Inc/stm32f0xx_it.h @@ -51,7 +51,6 @@ void HardFault_Handler(void); void SVC_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); -void ADC1_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/Software/Core/Lib/can-halal/README.md b/Software/Core/Lib/can-halal/README.md new file mode 100644 index 0000000..823df03 --- /dev/null +++ b/Software/Core/Lib/can-halal/README.md @@ -0,0 +1,77 @@ +# FaSTTUBe CAN HAL Abstraction Layer + +This repository contains an abstraction layer to provide a simplified & unified +interface to the STM32 bxCAN and FDCAN peripherals. + +## Installation + +Simply add the repository to your `Core/Lib` directory. You can also add it as a +git submodule: + + mkdir -p Core/Lib + cd Core/Lib + git submodule add ssh://git@git.fasttube.de:313/FaSTTUBe/can-halal.git + +The library needs to be told what STM family you're using, so make sure one of +the following symbols is defined when `can-halal.c` is compiled or `can-halal.h` +is included: + +- `STM32F3` +- `STM32H7` + +When using the FDCAN peripheral (H7 series), you also need to define +`FTCAN_NUM_FILTERS` (and set it to the value of "Std Filters Nbr" you configured +in your `.ioc`). + +If you use +[VSCode with the stm-32-for-vscode extension](https://podio.com/fasttubede/modulubergreifend/apps/tech-tutorials/items/57), +you can add these definitions in the `STM32-for-VSCode-config.yaml` file, e.g.: + +```yaml +# Compiler definitions. The -D prefix for the compiler will be automatically added. +cDefinitions: + - STM32H7 + - FTCAN_NUM_FILTERS=32 +``` + +## Usage + +1. Include `can-halal.h` +2. Call `ftcan_init()` with the appropriate handle +3. Call `ftcan_add_filter()` with all your filters +4. To transmit messages, call `ftcan_transmit()` +5. When a message is received, `ftcan_msg_received_cb()` is called. It has a + default empty implementation, which you can simply override. + +## Enabling CAN in STM32CubeMX + +This isn't specific to `can-halal`, but for completeness sake is included here. + +### bxCAN (e.g. STM32F3xx) + +1. Enable the CAN peripheral + ![Connectivity -> CAN -> Activated](doc/bxcan-activate.png) +2. Setup the [bit timings](http://bittiming.can-wiki.info/). + **Note:** the baud rate depends on your system clock, so make sure that is + setup correctly first! + ![Connectivity -> CAN -> Parameter Settings -> Bit Timings Parameters](doc/bxcan-bittimings.png) +3. Make sure the CAN_RX0 interrupt is enabled + ![Connectivity -> CAN -> NVIC Settings -> CAN_RX0 interrupt](doc/bxcan-interrupt.png) + +### FDCAN (e.g. STM32H7xx) + +1. Enable the CAN peripheral + ![Connectivity -> FDCAN(1)](doc/fdcan-activate.png) +2. Setup the frame format, nominal SJW, filters, and FIFOs. The numbers for + filters/FIFOs in the screenshot are examples. + **Note:** You need to tell `can-halal` about the number of filters by + defining `FTCAN_NUM_FILTERS` (see above). + ![Connectivity -> FDCAN(1) -> Parameter Settings -> Basic Parameters](doc/fdcan-basic.png) +3. Setup the [bit timings](http://bittiming.can-wiki.info/). We only use CAN in + classic mode, not FD mode, so we only need to worry about the nominal bit + timings + **Note:** the baud rate depends on your system clock, so make sure that is + setup correctly first! + ![Connectivity -> FDCAN(1) -> Parameter Settings -> Bit Timings Parameters](doc/fdcan-bittimings.png) +4. Make sure the interrupts are enabled + ![Connectivity -> FDCAN(1) -> NVIC Settings](doc/fdcan-interrupt.png) diff --git a/Software/Core/Lib/can-halal.c b/Software/Core/Lib/can-halal/can-halal.c similarity index 96% rename from Software/Core/Lib/can-halal.c rename to Software/Core/Lib/can-halal/can-halal.c index 7c85c0c..a99303a 100644 --- a/Software/Core/Lib/can-halal.c +++ b/Software/Core/Lib/can-halal/can-halal.c @@ -1,273 +1,273 @@ -#include "can-halal.h" - -#include - -#if defined(FTCAN_IS_BXCAN) -static CAN_HandleTypeDef *hcan; - -HAL_StatusTypeDef ftcan_init(CAN_HandleTypeDef *handle) { - hcan = handle; - - HAL_StatusTypeDef status = - HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING); - if (status != HAL_OK) { - return status; - } - - return HAL_CAN_Start(hcan); -} - -HAL_StatusTypeDef ftcan_transmit(uint16_t id, const uint8_t *data, - size_t datalen) { - static CAN_TxHeaderTypeDef header; - header.StdId = id; - header.IDE = CAN_ID_STD; - header.RTR = CAN_RTR_DATA; - header.DLC = datalen; - uint32_t mailbox; - return HAL_CAN_AddTxMessage(hcan, &header, data, &mailbox); -} - -HAL_StatusTypeDef ftcan_add_filter(uint16_t id, uint16_t mask) { - static uint32_t next_filter_no = 0; - static CAN_FilterTypeDef filter; - if (next_filter_no % 2 == 0) { - filter.FilterIdHigh = id << 5; - filter.FilterMaskIdHigh = mask << 5; - filter.FilterIdLow = id << 5; - filter.FilterMaskIdLow = mask << 5; - } else { - // Leave high filter untouched from the last configuration - filter.FilterIdLow = id << 5; - filter.FilterMaskIdLow = mask << 5; - } - filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; - filter.FilterBank = next_filter_no / 2; - if (filter.FilterBank > FTCAN_NUM_FILTERS + 1) { - return HAL_ERROR; - } - filter.FilterMode = CAN_FILTERMODE_IDMASK; - filter.FilterScale = CAN_FILTERSCALE_16BIT; - filter.FilterActivation = CAN_FILTER_ENABLE; - - // Disable slave filters - // TODO: Some STM32 have multiple CAN peripherals, and one uses the slave - // filter bank - filter.SlaveStartFilterBank = FTCAN_NUM_FILTERS; - - HAL_StatusTypeDef status = HAL_CAN_ConfigFilter(hcan, &filter); - if (status == HAL_OK) { - next_filter_no++; - } - return status; -} - -void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *handle) { - if (handle != hcan) { - return; - } - CAN_RxHeaderTypeDef header; - uint8_t data[8]; - if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &header, data) != HAL_OK) { - return; - } - - if (header.IDE != CAN_ID_STD) { - return; - } - - ftcan_msg_received_cb(header.StdId, header.DLC, data); -} -#elif defined(FTCAN_IS_FDCAN) -static FDCAN_HandleTypeDef *hcan; - -HAL_StatusTypeDef ftcan_init(FDCAN_HandleTypeDef *handle) { - hcan = handle; - - HAL_StatusTypeDef status = - HAL_FDCAN_ActivateNotification(hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); - if (status != HAL_OK) { - return status; - } - // Reject non-matching messages - status = - HAL_FDCAN_ConfigGlobalFilter(hcan, FDCAN_REJECT, FDCAN_REJECT, - FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE); - if (status != HAL_OK) { - return status; - } - - return HAL_FDCAN_Start(hcan); -} - -HAL_StatusTypeDef ftcan_transmit(uint16_t id, const uint8_t *data, - size_t datalen) { - static FDCAN_TxHeaderTypeDef header; - header.Identifier = id; - header.IdType = FDCAN_STANDARD_ID; - header.TxFrameType = FDCAN_DATA_FRAME; - switch (datalen) { - case 0: - header.DataLength = FDCAN_DLC_BYTES_0; - break; - case 1: - header.DataLength = FDCAN_DLC_BYTES_1; - break; - case 2: - header.DataLength = FDCAN_DLC_BYTES_2; - break; - case 3: - header.DataLength = FDCAN_DLC_BYTES_3; - break; - case 4: - header.DataLength = FDCAN_DLC_BYTES_4; - break; - case 5: - header.DataLength = FDCAN_DLC_BYTES_5; - break; - case 6: - header.DataLength = FDCAN_DLC_BYTES_6; - break; - case 7: - header.DataLength = FDCAN_DLC_BYTES_7; - break; - case 8: - default: - header.DataLength = FDCAN_DLC_BYTES_8; - break; - } - header.ErrorStateIndicator = FDCAN_ESI_PASSIVE; - header.BitRateSwitch = FDCAN_BRS_OFF; - header.FDFormat = FDCAN_CLASSIC_CAN; - header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; - - // HAL_FDCAN_AddMessageToTxFifoQ doesn't modify the data, but it's not marked - // as const for some reason. - uint8_t *data_nonconst = (uint8_t *)data; - return HAL_FDCAN_AddMessageToTxFifoQ(hcan, &header, data_nonconst); -} - -HAL_StatusTypeDef ftcan_add_filter(uint16_t id, uint16_t mask) { - static uint32_t next_filter_no = 0; - static FDCAN_FilterTypeDef filter; - filter.IdType = FDCAN_STANDARD_ID; - filter.FilterIndex = next_filter_no; - if (filter.FilterIndex > FTCAN_NUM_FILTERS + 1) { - return HAL_ERROR; - } - filter.FilterType = FDCAN_FILTER_MASK; - filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; - filter.FilterID1 = id; - filter.FilterID2 = mask; - - HAL_StatusTypeDef status = HAL_FDCAN_ConfigFilter(hcan, &filter); - if (status == HAL_OK) { - next_filter_no++; - } - return status; -} - -void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *handle, - uint32_t RxFifo0ITs) { - if (handle != hcan || (RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) == RESET) { - return; - } - - static FDCAN_RxHeaderTypeDef header; - static uint8_t data[8]; - if (HAL_FDCAN_GetRxMessage(hcan, FDCAN_RX_FIFO0, &header, data) != HAL_OK) { - return; - } - - if (header.FDFormat != FDCAN_CLASSIC_CAN || - header.RxFrameType != FDCAN_DATA_FRAME || - header.IdType != FDCAN_STANDARD_ID) { - return; - } - - size_t datalen; - switch (header.DataLength) { - case FDCAN_DLC_BYTES_0: - datalen = 0; - break; - case FDCAN_DLC_BYTES_1: - datalen = 1; - break; - case FDCAN_DLC_BYTES_2: - datalen = 2; - break; - case FDCAN_DLC_BYTES_3: - datalen = 3; - break; - case FDCAN_DLC_BYTES_4: - datalen = 4; - break; - case FDCAN_DLC_BYTES_5: - datalen = 5; - break; - case FDCAN_DLC_BYTES_6: - datalen = 6; - break; - case FDCAN_DLC_BYTES_7: - datalen = 7; - break; - case FDCAN_DLC_BYTES_8: - datalen = 8; - break; - default: - return; - } - - ftcan_msg_received_cb(header.Identifier, datalen, data); -} -#endif - -__weak void ftcan_msg_received_cb(uint16_t id, size_t datalen, - const uint8_t *data) {} - -uint64_t ftcan_unmarshal_unsigned(const uint8_t **data_ptr, size_t num_bytes) { - if (num_bytes > 8) { - num_bytes = 8; - } - - const uint8_t *data = *data_ptr; - uint64_t result = 0; - for (size_t i = 0; i < num_bytes; i++) { - result <<= 8; - result |= data[i]; - } - *data_ptr += num_bytes; - return result; -} - -int64_t ftcan_unmarshal_signed(const uint8_t **data_ptr, size_t num_bytes) { - if (num_bytes > 8) { - num_bytes = 8; - } - - uint64_t result_unsigned = ftcan_unmarshal_unsigned(data_ptr, num_bytes); - // Sign extend by shifting left, then copying to a signed int and shifting - // back to the right - size_t diff_to_64 = 64 - num_bytes * 8; - result_unsigned <<= diff_to_64; - int64_t result; - memcpy(&result, &result_unsigned, 8); - return result >> diff_to_64; -} - -uint8_t *ftcan_marshal_unsigned(uint8_t *data, uint64_t val, size_t num_bytes) { - if (num_bytes > 8) { - num_bytes = 8; - } - - for (int i = num_bytes - 1; i >= 0; i--) { - data[i] = val & 0xFF; - val >>= 8; - } - - return data + num_bytes; -} - -uint8_t *ftcan_marshal_signed(uint8_t *data, int64_t val, size_t num_bytes) { - return ftcan_marshal_unsigned(data, val, num_bytes); -} +#include "can-halal.h" + +#include + +#if defined(FTCAN_IS_BXCAN) +static CAN_HandleTypeDef *hcan; + +HAL_StatusTypeDef ftcan_init(CAN_HandleTypeDef *handle) { + hcan = handle; + + HAL_StatusTypeDef status = + HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING); + if (status != HAL_OK) { + return status; + } + + return HAL_CAN_Start(hcan); +} + +HAL_StatusTypeDef ftcan_transmit(uint16_t id, const uint8_t *data, + size_t datalen) { + static CAN_TxHeaderTypeDef header; + header.StdId = id; + header.IDE = CAN_ID_STD; + header.RTR = CAN_RTR_DATA; + header.DLC = datalen; + uint32_t mailbox; + return HAL_CAN_AddTxMessage(hcan, &header, data, &mailbox); +} + +HAL_StatusTypeDef ftcan_add_filter(uint16_t id, uint16_t mask) { + static uint32_t next_filter_no = 0; + static CAN_FilterTypeDef filter; + if (next_filter_no % 2 == 0) { + filter.FilterIdHigh = id << 5; + filter.FilterMaskIdHigh = mask << 5; + filter.FilterIdLow = id << 5; + filter.FilterMaskIdLow = mask << 5; + } else { + // Leave high filter untouched from the last configuration + filter.FilterIdLow = id << 5; + filter.FilterMaskIdLow = mask << 5; + } + filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; + filter.FilterBank = next_filter_no / 2; + if (filter.FilterBank > FTCAN_NUM_FILTERS + 1) { + return HAL_ERROR; + } + filter.FilterMode = CAN_FILTERMODE_IDMASK; + filter.FilterScale = CAN_FILTERSCALE_16BIT; + filter.FilterActivation = CAN_FILTER_ENABLE; + + // Disable slave filters + // TODO: Some STM32 have multiple CAN peripherals, and one uses the slave + // filter bank + filter.SlaveStartFilterBank = FTCAN_NUM_FILTERS; + + HAL_StatusTypeDef status = HAL_CAN_ConfigFilter(hcan, &filter); + if (status == HAL_OK) { + next_filter_no++; + } + return status; +} + +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *handle) { + if (handle != hcan) { + return; + } + CAN_RxHeaderTypeDef header; + uint8_t data[8]; + if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &header, data) != HAL_OK) { + return; + } + + if (header.IDE != CAN_ID_STD) { + return; + } + + ftcan_msg_received_cb(header.StdId, header.DLC, data); +} +#elif defined(FTCAN_IS_FDCAN) +static FDCAN_HandleTypeDef *hcan; + +HAL_StatusTypeDef ftcan_init(FDCAN_HandleTypeDef *handle) { + hcan = handle; + + HAL_StatusTypeDef status = + HAL_FDCAN_ActivateNotification(hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); + if (status != HAL_OK) { + return status; + } + // Reject non-matching messages + status = + HAL_FDCAN_ConfigGlobalFilter(hcan, FDCAN_REJECT, FDCAN_REJECT, + FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE); + if (status != HAL_OK) { + return status; + } + + return HAL_FDCAN_Start(hcan); +} + +HAL_StatusTypeDef ftcan_transmit(uint16_t id, const uint8_t *data, + size_t datalen) { + static FDCAN_TxHeaderTypeDef header; + header.Identifier = id; + header.IdType = FDCAN_STANDARD_ID; + header.TxFrameType = FDCAN_DATA_FRAME; + switch (datalen) { + case 0: + header.DataLength = FDCAN_DLC_BYTES_0; + break; + case 1: + header.DataLength = FDCAN_DLC_BYTES_1; + break; + case 2: + header.DataLength = FDCAN_DLC_BYTES_2; + break; + case 3: + header.DataLength = FDCAN_DLC_BYTES_3; + break; + case 4: + header.DataLength = FDCAN_DLC_BYTES_4; + break; + case 5: + header.DataLength = FDCAN_DLC_BYTES_5; + break; + case 6: + header.DataLength = FDCAN_DLC_BYTES_6; + break; + case 7: + header.DataLength = FDCAN_DLC_BYTES_7; + break; + case 8: + default: + header.DataLength = FDCAN_DLC_BYTES_8; + break; + } + header.ErrorStateIndicator = FDCAN_ESI_PASSIVE; + header.BitRateSwitch = FDCAN_BRS_OFF; + header.FDFormat = FDCAN_CLASSIC_CAN; + header.TxEventFifoControl = FDCAN_NO_TX_EVENTS; + + // HAL_FDCAN_AddMessageToTxFifoQ doesn't modify the data, but it's not marked + // as const for some reason. + uint8_t *data_nonconst = (uint8_t *)data; + return HAL_FDCAN_AddMessageToTxFifoQ(hcan, &header, data_nonconst); +} + +HAL_StatusTypeDef ftcan_add_filter(uint16_t id, uint16_t mask) { + static uint32_t next_filter_no = 0; + static FDCAN_FilterTypeDef filter; + filter.IdType = FDCAN_STANDARD_ID; + filter.FilterIndex = next_filter_no; + if (filter.FilterIndex > FTCAN_NUM_FILTERS + 1) { + return HAL_ERROR; + } + filter.FilterType = FDCAN_FILTER_MASK; + filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; + filter.FilterID1 = id; + filter.FilterID2 = mask; + + HAL_StatusTypeDef status = HAL_FDCAN_ConfigFilter(hcan, &filter); + if (status == HAL_OK) { + next_filter_no++; + } + return status; +} + +void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *handle, + uint32_t RxFifo0ITs) { + if (handle != hcan || (RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) == RESET) { + return; + } + + static FDCAN_RxHeaderTypeDef header; + static uint8_t data[8]; + if (HAL_FDCAN_GetRxMessage(hcan, FDCAN_RX_FIFO0, &header, data) != HAL_OK) { + return; + } + + if (header.FDFormat != FDCAN_CLASSIC_CAN || + header.RxFrameType != FDCAN_DATA_FRAME || + header.IdType != FDCAN_STANDARD_ID) { + return; + } + + size_t datalen; + switch (header.DataLength) { + case FDCAN_DLC_BYTES_0: + datalen = 0; + break; + case FDCAN_DLC_BYTES_1: + datalen = 1; + break; + case FDCAN_DLC_BYTES_2: + datalen = 2; + break; + case FDCAN_DLC_BYTES_3: + datalen = 3; + break; + case FDCAN_DLC_BYTES_4: + datalen = 4; + break; + case FDCAN_DLC_BYTES_5: + datalen = 5; + break; + case FDCAN_DLC_BYTES_6: + datalen = 6; + break; + case FDCAN_DLC_BYTES_7: + datalen = 7; + break; + case FDCAN_DLC_BYTES_8: + datalen = 8; + break; + default: + return; + } + + ftcan_msg_received_cb(header.Identifier, datalen, data); +} +#endif + +__weak void ftcan_msg_received_cb(uint16_t id, size_t datalen, + const uint8_t *data) {} + +uint64_t ftcan_unmarshal_unsigned(const uint8_t **data_ptr, size_t num_bytes) { + if (num_bytes > 8) { + num_bytes = 8; + } + + const uint8_t *data = *data_ptr; + uint64_t result = 0; + for (size_t i = 0; i < num_bytes; i++) { + result <<= 8; + result |= data[i]; + } + *data_ptr += num_bytes; + return result; +} + +int64_t ftcan_unmarshal_signed(const uint8_t **data_ptr, size_t num_bytes) { + if (num_bytes > 8) { + num_bytes = 8; + } + + uint64_t result_unsigned = ftcan_unmarshal_unsigned(data_ptr, num_bytes); + // Sign extend by shifting left, then copying to a signed int and shifting + // back to the right + size_t diff_to_64 = 64 - num_bytes * 8; + result_unsigned <<= diff_to_64; + int64_t result; + memcpy(&result, &result_unsigned, 8); + return result >> diff_to_64; +} + +uint8_t *ftcan_marshal_unsigned(uint8_t *data, uint64_t val, size_t num_bytes) { + if (num_bytes > 8) { + num_bytes = 8; + } + + for (int i = num_bytes - 1; i >= 0; i--) { + data[i] = val & 0xFF; + val >>= 8; + } + + return data + num_bytes; +} + +uint8_t *ftcan_marshal_signed(uint8_t *data, int64_t val, size_t num_bytes) { + return ftcan_marshal_unsigned(data, val, num_bytes); +} diff --git a/Software/Core/Lib/can-halal.h b/Software/Core/Lib/can-halal/can-halal.h similarity index 74% rename from Software/Core/Lib/can-halal.h rename to Software/Core/Lib/can-halal/can-halal.h index 57c155f..766b1cd 100644 --- a/Software/Core/Lib/can-halal.h +++ b/Software/Core/Lib/can-halal/can-halal.h @@ -1,61 +1,71 @@ -#ifndef CAN_HALAL_H -#define CAN_HALAL_H - -// Define family macros if none are defined and we recognize a chip macro -#if !defined(STM32F3) && !defined(STM32H7) -#if defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xB) || \ - defined(STM32F302xC) -#define STM32F3 -#endif -#if defined(STM32H7A3xx) -#define STM32H7 -#endif -#endif - -#if defined(STM32F3) -#include "stm32f3xx_hal.h" -#define FTCAN_IS_BXCAN -#define FTCAN_NUM_FILTERS 13 -#elif defined(STM32H7) -#include "stm32h7xx_hal.h" -#define FTCAN_IS_FDCAN -#else -#error "Couldn't detect STM family" -#endif - -#if defined(FTCAN_IS_BXCAN) -HAL_StatusTypeDef ftcan_init(CAN_HandleTypeDef *handle); -#elif defined(FTCAN_IS_FDCAN) -HAL_StatusTypeDef ftcan_init(FDCAN_HandleTypeDef *handle); -#else -#error "Unknown CAN peripheral" -#endif - -HAL_StatusTypeDef ftcan_transmit(uint16_t id, const uint8_t *data, - size_t datalen); - -HAL_StatusTypeDef ftcan_add_filter(uint16_t id, uint16_t mask); - -/** - * Define this function to be notified of incoming CAN messages - */ -void ftcan_msg_received_cb(uint16_t id, size_t datalen, const uint8_t *data); - -/** - * Read num_bytes bytes from a message (unmarshalled network byte order). The - * msg pointer is advanced by the corresponding number of bytes. - * - * Both methods return a 64-bit integer, but you can safely cast it to a smaller - * integer type. - */ -uint64_t ftcan_unmarshal_unsigned(const uint8_t **data, size_t num_bytes); -int64_t ftcan_unmarshal_signed(const uint8_t **data, size_t num_bytes); - -/** - * Write num_bytes to a message (marshalled in network byte order). The pointer - * is advanced by the corresponding number of bytes and returned. - */ -uint8_t *ftcan_marshal_unsigned(uint8_t *data, uint64_t val, size_t num_bytes); -uint8_t *ftcan_marshal_signed(uint8_t *data, int64_t val, size_t num_bytes); - -#endif // CAN_HALAL_H +#ifndef CAN_HALAL_H +#define CAN_HALAL_H + +// Define family macros if none are defined and we recognize a chip macro +#if !defined(STM32F3) && !defined(STM32H7) && !defined(STM32F0) +#if defined(STM32F302x6) || defined(STM32F302x8) || defined(STM32F302xB) || \ + defined(STM32F302xC) +#define STM32F3 +#endif +#if defined(STM32H7A3xx) +#define STM32H7 +#endif +#if defined(STM32F042x6) +#define STM32F0 +#endif +#endif + +#if defined(STM32F3) + #include "stm32f3xx_hal.h" + #define FTCAN_IS_BXCAN + #define FTCAN_NUM_FILTERS 13 +#elif defined(STM32H7) + #include "stm32h7xx_hal.h" + #define FTCAN_IS_FDCAN + #ifndef FTCAN_NUM_FILTERS + #error "Please configure the number of filters in CubeMX, and then add a compiler define for FTCAN_NUM_FILTERS" + #endif +#elif defined(STM32F0) + #include "stm32f0xx_hal.h" + #define FTCAN_IS_BXCAN + #define FTCAN_NUM_FILTERS 13 +#else + #error "Couldn't detect STM family" +#endif + +#if defined(FTCAN_IS_BXCAN) +HAL_StatusTypeDef ftcan_init(CAN_HandleTypeDef *handle); +#elif defined(FTCAN_IS_FDCAN) +HAL_StatusTypeDef ftcan_init(FDCAN_HandleTypeDef *handle); +#else +#error "Unknown CAN peripheral" +#endif + +HAL_StatusTypeDef ftcan_transmit(uint16_t id, const uint8_t *data, + size_t datalen); + +HAL_StatusTypeDef ftcan_add_filter(uint16_t id, uint16_t mask); + +/** + * Define this function to be notified of incoming CAN messages + */ +void ftcan_msg_received_cb(uint16_t id, size_t datalen, const uint8_t *data); + +/** + * Read num_bytes bytes from a message (unmarshalled network byte order). The + * msg pointer is advanced by the corresponding number of bytes. + * + * Both methods return a 64-bit integer, but you can safely cast it to a smaller + * integer type. + */ +uint64_t ftcan_unmarshal_unsigned(const uint8_t **data, size_t num_bytes); +int64_t ftcan_unmarshal_signed(const uint8_t **data, size_t num_bytes); + +/** + * Write num_bytes to a message (marshalled in network byte order). The pointer + * is advanced by the corresponding number of bytes and returned. + */ +uint8_t *ftcan_marshal_unsigned(uint8_t *data, uint64_t val, size_t num_bytes); +uint8_t *ftcan_marshal_signed(uint8_t *data, int64_t val, size_t num_bytes); + +#endif // CAN_HALAL_H diff --git a/Software/Core/Lib/can-halal/doc/bxcan-activate.png b/Software/Core/Lib/can-halal/doc/bxcan-activate.png new file mode 100644 index 0000000..c24851f Binary files /dev/null and b/Software/Core/Lib/can-halal/doc/bxcan-activate.png differ diff --git a/Software/Core/Lib/can-halal/doc/bxcan-bittimings.png b/Software/Core/Lib/can-halal/doc/bxcan-bittimings.png new file mode 100644 index 0000000..e594d30 Binary files /dev/null and b/Software/Core/Lib/can-halal/doc/bxcan-bittimings.png differ diff --git a/Software/Core/Lib/can-halal/doc/bxcan-interrupt.png b/Software/Core/Lib/can-halal/doc/bxcan-interrupt.png new file mode 100644 index 0000000..1959520 Binary files /dev/null and b/Software/Core/Lib/can-halal/doc/bxcan-interrupt.png differ diff --git a/Software/Core/Lib/can-halal/doc/fdcan-activate.png b/Software/Core/Lib/can-halal/doc/fdcan-activate.png new file mode 100644 index 0000000..2d31913 Binary files /dev/null and b/Software/Core/Lib/can-halal/doc/fdcan-activate.png differ diff --git a/Software/Core/Lib/can-halal/doc/fdcan-basic.png b/Software/Core/Lib/can-halal/doc/fdcan-basic.png new file mode 100644 index 0000000..d21c3aa Binary files /dev/null and b/Software/Core/Lib/can-halal/doc/fdcan-basic.png differ diff --git a/Software/Core/Lib/can-halal/doc/fdcan-bittimings.png b/Software/Core/Lib/can-halal/doc/fdcan-bittimings.png new file mode 100644 index 0000000..060cd9e Binary files /dev/null and b/Software/Core/Lib/can-halal/doc/fdcan-bittimings.png differ diff --git a/Software/Core/Lib/can-halal/doc/fdcan-interrupt.png b/Software/Core/Lib/can-halal/doc/fdcan-interrupt.png new file mode 100644 index 0000000..400f7ed Binary files /dev/null and b/Software/Core/Lib/can-halal/doc/fdcan-interrupt.png differ diff --git a/Software/Core/Src/adc.c b/Software/Core/Src/adc.c index e69de29..51acbf6 100644 --- a/Software/Core/Src/adc.c +++ b/Software/Core/Src/adc.c @@ -0,0 +1,24 @@ +#include + +#include "can-halal.h" +#include "stm32f0xx_hal_adc.h" + +int16_t id = 0x200; +int32_t adcRes = 0; + +void adc_init(ADC_HandleTypeDef* hadc){ + HAL_ADCEx_Calibration_Start(hadc); +} + +void adc_loop(ADC_HandleTypeDef* hadc){ + HAL_ADC_Start_IT(hadc); + static uint8_t data[8]; + ftcan_marshal_unsigned(data, adcRes, 4); + ftcan_transmit(id, data, sizeof(data)); + HAL_Delay(5); + //testing gitignore +} + +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){ + adcRes = HAL_ADC_GetValue(hadc); +} \ No newline at end of file diff --git a/Software/Core/Src/main.c b/Software/Core/Src/main.c index 0095a8f..023a9be 100644 --- a/Software/Core/Src/main.c +++ b/Software/Core/Src/main.c @@ -21,7 +21,7 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ - +#include "adc.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -71,7 +71,6 @@ static void MX_TIM2_Init(void); */ int main(void) { - /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ @@ -98,7 +97,7 @@ int main(void) MX_CAN_Init(); MX_TIM2_Init(); /* USER CODE BEGIN 2 */ - + adc_init(&hadc); /* USER CODE END 2 */ /* Infinite loop */ @@ -108,7 +107,7 @@ int main(void) /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ - ADCMeasureLooooop(); + adc_loop(&hadc); } /* USER CODE END 3 */ } @@ -125,14 +124,12 @@ void SystemClock_Config(void) /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI14|RCC_OSCILLATORTYPE_HSE; - RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI14; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSI14State = RCC_HSI14_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.HSI14CalibrationValue = 16; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4; - RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV3; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); @@ -142,7 +139,7 @@ void SystemClock_Config(void) */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; @@ -230,15 +227,15 @@ static void MX_CAN_Init(void) /* USER CODE END CAN_Init 1 */ hcan.Instance = CAN; - hcan.Init.Prescaler = 2; + hcan.Init.Prescaler = 16; hcan.Init.Mode = CAN_MODE_NORMAL; hcan.Init.SyncJumpWidth = CAN_SJW_1TQ; - hcan.Init.TimeSeg1 = CAN_BS1_13TQ; - hcan.Init.TimeSeg2 = CAN_BS2_2TQ; + hcan.Init.TimeSeg1 = CAN_BS1_1TQ; + hcan.Init.TimeSeg2 = CAN_BS2_1TQ; hcan.Init.TimeTriggeredMode = DISABLE; - hcan.Init.AutoBusOff = ENABLE; + hcan.Init.AutoBusOff = DISABLE; hcan.Init.AutoWakeUp = DISABLE; - hcan.Init.AutoRetransmission = ENABLE; + hcan.Init.AutoRetransmission = DISABLE; hcan.Init.ReceiveFifoLocked = DISABLE; hcan.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan) != HAL_OK) diff --git a/Software/Core/Src/stm32f0xx_hal_msp.c b/Software/Core/Src/stm32f0xx_hal_msp.c index f0d0afe..f04d789 100644 --- a/Software/Core/Src/stm32f0xx_hal_msp.c +++ b/Software/Core/Src/stm32f0xx_hal_msp.c @@ -20,6 +20,7 @@ /* Includes ------------------------------------------------------------------*/ #include "main.h" + /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ @@ -64,7 +65,6 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); */ void HAL_MspInit(void) { - /* USER CODE BEGIN MspInit 0 */ /* USER CODE END MspInit 0 */ @@ -106,9 +106,6 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - /* ADC1 interrupt Init */ - HAL_NVIC_SetPriority(ADC1_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(ADC1_IRQn); /* USER CODE BEGIN ADC1_MspInit 1 */ /* USER CODE END ADC1_MspInit 1 */ @@ -138,8 +135,6 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc) */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1); - /* ADC1 interrupt DeInit */ - HAL_NVIC_DisableIRQ(ADC1_IRQn); /* USER CODE BEGIN ADC1_MspDeInit 1 */ /* USER CODE END ADC1_MspDeInit 1 */ diff --git a/Software/Core/Src/stm32f0xx_it.c b/Software/Core/Src/stm32f0xx_it.c index 0b67aee..db62670 100644 --- a/Software/Core/Src/stm32f0xx_it.c +++ b/Software/Core/Src/stm32f0xx_it.c @@ -55,7 +55,7 @@ /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ -extern ADC_HandleTypeDef hadc; + /* USER CODE BEGIN EV */ /* USER CODE END EV */ @@ -140,20 +140,6 @@ void SysTick_Handler(void) /* please refer to the startup file (startup_stm32f0xx.s). */ /******************************************************************************/ -/** - * @brief This function handles ADC interrupt. - */ -void ADC1_IRQHandler(void) -{ - /* USER CODE BEGIN ADC1_IRQn 0 */ - - /* USER CODE END ADC1_IRQn 0 */ - HAL_ADC_IRQHandler(&hadc); - /* USER CODE BEGIN ADC1_IRQn 1 */ - - /* USER CODE END ADC1_IRQn 1 */ -} - /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/Software/Core/Src/syscalls.c b/Software/Core/Src/syscalls.c deleted file mode 100644 index e33a849..0000000 --- a/Software/Core/Src/syscalls.c +++ /dev/null @@ -1,176 +0,0 @@ -/** - ****************************************************************************** - * @file syscalls.c - * @author Auto-generated by STM32CubeMX - * @brief Minimal System calls file - * - * For more information about which c-functions - * need which of these lowlevel functions - * please consult the Newlib libc-manual - ****************************************************************************** - * @attention - * - * Copyright (c) 2020-2024 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes */ -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Variables */ -extern int __io_putchar(int ch) __attribute__((weak)); -extern int __io_getchar(void) __attribute__((weak)); - - -char *__env[1] = { 0 }; -char **environ = __env; - - -/* Functions */ -void initialise_monitor_handles() -{ -} - -int _getpid(void) -{ - return 1; -} - -int _kill(int pid, int sig) -{ - (void)pid; - (void)sig; - errno = EINVAL; - return -1; -} - -void _exit (int status) -{ - _kill(status, -1); - while (1) {} /* Make sure we hang here */ -} - -__attribute__((weak)) int _read(int file, char *ptr, int len) -{ - (void)file; - int DataIdx; - - for (DataIdx = 0; DataIdx < len; DataIdx++) - { - *ptr++ = __io_getchar(); - } - - return len; -} - -__attribute__((weak)) int _write(int file, char *ptr, int len) -{ - (void)file; - int DataIdx; - - for (DataIdx = 0; DataIdx < len; DataIdx++) - { - __io_putchar(*ptr++); - } - return len; -} - -int _close(int file) -{ - (void)file; - return -1; -} - - -int _fstat(int file, struct stat *st) -{ - (void)file; - st->st_mode = S_IFCHR; - return 0; -} - -int _isatty(int file) -{ - (void)file; - return 1; -} - -int _lseek(int file, int ptr, int dir) -{ - (void)file; - (void)ptr; - (void)dir; - return 0; -} - -int _open(char *path, int flags, ...) -{ - (void)path; - (void)flags; - /* Pretend like we always fail */ - return -1; -} - -int _wait(int *status) -{ - (void)status; - errno = ECHILD; - return -1; -} - -int _unlink(char *name) -{ - (void)name; - errno = ENOENT; - return -1; -} - -int _times(struct tms *buf) -{ - (void)buf; - return -1; -} - -int _stat(char *file, struct stat *st) -{ - (void)file; - st->st_mode = S_IFCHR; - return 0; -} - -int _link(char *old, char *new) -{ - (void)old; - (void)new; - errno = EMLINK; - return -1; -} - -int _fork(void) -{ - errno = EAGAIN; - return -1; -} - -int _execve(char *name, char **argv, char **env) -{ - (void)name; - (void)argv; - (void)env; - errno = ENOMEM; - return -1; -} diff --git a/Software/Core/Src/sysmem.c b/Software/Core/Src/sysmem.c deleted file mode 100644 index 246470e..0000000 --- a/Software/Core/Src/sysmem.c +++ /dev/null @@ -1,79 +0,0 @@ -/** - ****************************************************************************** - * @file sysmem.c - * @author Generated by STM32CubeMX - * @brief System Memory calls file - * - * For more information about which C functions - * need which of these lowlevel functions - * please consult the newlib libc manual - ****************************************************************************** - * @attention - * - * Copyright (c) 2024 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes */ -#include -#include - -/** - * Pointer to the current high watermark of the heap usage - */ -static uint8_t *__sbrk_heap_end = NULL; - -/** - * @brief _sbrk() allocates memory to the newlib heap and is used by malloc - * and others from the C library - * - * @verbatim - * ############################################################################ - * # .data # .bss # newlib heap # MSP stack # - * # # # # Reserved by _Min_Stack_Size # - * ############################################################################ - * ^-- RAM start ^-- _end _estack, RAM end --^ - * @endverbatim - * - * This implementation starts allocating at the '_end' linker symbol - * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack - * The implementation considers '_estack' linker symbol to be RAM end - * NOTE: If the MSP stack, at any point during execution, grows larger than the - * reserved size, please increase the '_Min_Stack_Size'. - * - * @param incr Memory size - * @return Pointer to allocated memory - */ -void *_sbrk(ptrdiff_t incr) -{ - extern uint8_t _end; /* Symbol defined in the linker script */ - extern uint8_t _estack; /* Symbol defined in the linker script */ - extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ - const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; - const uint8_t *max_heap = (uint8_t *)stack_limit; - uint8_t *prev_heap_end; - - /* Initialize heap end at first call */ - if (NULL == __sbrk_heap_end) - { - __sbrk_heap_end = &_end; - } - - /* Protect heap from growing into the reserved MSP stack */ - if (__sbrk_heap_end + incr > max_heap) - { - errno = ENOMEM; - return (void *)-1; - } - - prev_heap_end = __sbrk_heap_end; - __sbrk_heap_end += incr; - - return (void *)prev_heap_end; -}