stm32f0: Various fixes according to comment: (#1453)

* Copyright in log.c
* GPIO check completely removed
* generic/timer_irq added
* Change in doc section

Signed-off-by: Eugene Krashtan <eug.krashtan@gmail.com>
This commit is contained in:
Eugene Krashtan 2019-03-28 16:21:51 +02:00 committed by KevinOConnor
parent 312cabc3f7
commit c7330e07a4
8 changed files with 25 additions and 124 deletions

BIN
docs/img/canhat.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

@ -7,6 +7,8 @@ Required components
#### MCP2515 module
![MCP2515](img/mcp2515.jpg)
or this
![CAN/RS485 hat](img/canhat.jpg)
#### St-link dongle
@ -17,7 +19,7 @@ Adding CAN bus to Raspberry Pi
==============================
(Based on Quick Guide https://www.raspberrypi.org/forums/viewtopic.php?f=44&t=141052)
First of all, its necessary to modify the CAN-module from ebay, because it has
First of all, (only if you have small CAN module) its necessary to modify the CAN-module from ebay, because it has
only one VCC pin, but the MCP2515 needs to be powered from 3V3 and the TJA1050
CAN-transceiver needs to be powered from 5V. Powering both chips from 5V would
work, but then a level-shifter for the SPI would be needed. The Pi's GPIO pins
@ -135,5 +137,6 @@ Now "make flash" command can upload HEX into connected board
Pins allocation
===============
Configurations with CAN and Serial port uses different pins, and firmware contains only
actual pins initialization.
Configurations with CAN and Serial port uses different pins, and during enumeration
process firmware reports all possible pin names. But actually you can use only
existing pins, not involved in communication. Wrong pins will generate shutdown.

View File

@ -25,6 +25,7 @@ src-$(CONFIG_CANSERIAL) += stm32f0/can.c
src-$(CONFIG_DEBUG_OUT) += stm32f0/log.c
src-$(CONFIG_SERIAL) += stm32f0/serial.c
src-y += generic/serial_irq.c
src-y += generic/timer_irq.c
src-$(CONFIG_HAVE_GPIO_ADC) += stm32f0/adc.c
src-$(CONFIG_HAVE_GPIO_I2C) += stm32f0/i2c.c
src-$(CONFIG_HAVE_GPIO_SPI) += stm32f0/spi.c

View File

@ -51,7 +51,6 @@ uint8_t const avail_pins[] = {
static uint8_t
gpio_check_pin(uint8_t pin)
{
gpio_check_busy(pin);
int i;
for(i=0; i<ARRAY_SIZE(avail_pins); i++) {
if (avail_pins[i] == pin)
@ -140,22 +139,3 @@ void gpio_init(void)
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
}
void gpio_check_busy(uint8_t pin)
{
// Increase to uint32_t and assert <32 on bigger chips
static uint16_t pinmap;
assert_param(sizeof(avail_pins)<16);
for (int i = 0; i<sizeof(avail_pins); i++) {
if(avail_pins[i]==pin) {
if(pinmap&(1<<i)) {
break;
} else {
pinmap |= 1<<i;
return;
}
}
}
shutdown("GPIO check failed");
}

View File

@ -11,6 +11,7 @@
#include "board/gpio.h" // i2c_setup
#include "sched.h" // sched_shutdown
#include "command.h" // shutdown
#include "board/misc.h" // timer_is_before
I2C_HandleTypeDef hi2c1;
@ -21,9 +22,6 @@ struct i2c_config i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr)
PF0-OSC_IN ------> I2C1_SDA
PF1-OSC_OUT ------> I2C1_SCL
*/
gpio_check_busy(0x30); //PF0
gpio_check_busy(0x31); //PF1
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
@ -50,19 +48,29 @@ struct i2c_config i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr)
return (struct i2c_config){ .addr = addr };
}
static void
i2c_to_check(uint32_t timeout)
{
if (!timer_is_before(timer_read_time(), timeout))
shutdown("i2c timeout");
}
void i2c_write(struct i2c_config config, uint8_t write_len, uint8_t *write)
{
uint32_t timeout = timer_read_time() + timer_from_us(5000);
while(HAL_I2C_Master_Transmit(&hi2c1, config.addr, write,
(uint16_t)write_len, (uint32_t)1000)!= HAL_OK) {
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) {
shutdown("Buffer error");
}
i2c_to_check(timeout);
}
}
void i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg
, uint8_t read_len, uint8_t *read)
{
uint32_t timeout = timer_read_time() + timer_from_us(5000);
i2c_write(config, reg_len, reg);
while(HAL_I2C_Master_Receive(&hi2c1, config.addr, read,
(uint16_t)read_len, (uint32_t)1000)!= HAL_OK) {
@ -70,6 +78,7 @@ void i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg
shutdown("Buffer error");
}
}
i2c_to_check(timeout);
}
/**

View File

@ -3,8 +3,8 @@
* This file not required for regular Klipper usage, but hw/sw developer
* can use USART TX pin instead SWO for debugging purposes
*
* Created on: Jan 17, 2019
* Author: eug
* Copyright (C) 2019 Eug Krashtan <eug.krashtan@gmail.com>
* This file may be distributed under the terms of the GNU GPLv3 license.
*/
#include "string.h"

View File

@ -13,8 +13,6 @@
#include "sched.h" // sched_shutdown
#include "log.h"
//static SPI_HandleTypeDef hspi1;
void spi_hw_setup(uint32_t rate)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
@ -28,9 +26,6 @@ void spi_hw_setup(uint32_t rate)
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
gpio_check_busy(0x05); //PA5
gpio_check_busy(0x06); //PA6
gpio_check_busy(0x07); //PA7
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
@ -52,22 +47,6 @@ void spi_hw_setup(uint32_t rate)
SPI_RXFIFO_THRESHOLD_QF;
SPI1->CR1 |= SPI_CR1_SPE; // Enable
//hspi1.Instance = SPI1;
//hspi1.Init.Mode = SPI_MODE_MASTER;
//hspi1.Init.Direction = SPI_DIRECTION_2LINES;
//hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
//hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
//hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
//hspi1.Init.NSS = SPI_NSS_SOFT;
//hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
//hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
//hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
//hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
//hspi1.Init.CRCPolynomial = 7;
//hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
//hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
//HAL_SPI_Init(&hspi1);
}
struct spi_config

View File

@ -16,30 +16,13 @@
#include "log.h"
#include "sched.h" // DECL_INIT
#include "command.h" // shutdown
DECL_CONSTANT("CLOCK_FREQ", CONFIG_CLOCK_FREQ);
// Return the number of clock ticks for a given number of microseconds
uint32_t
timer_from_us(uint32_t us)
{
return us * (CONFIG_CLOCK_FREQ / 1000000);
}
// Return true if time1 is before time2. Always use this function to
// compare times as regular C comparisons can fail if the counter
// rolls over.
uint8_t
timer_is_before(uint32_t time1, uint32_t time2)
{
return (int32_t)(time1 - time2) < 0;
}
#include "board/timer_irq.h" // timer_dispatch_many
// Set the next irq time
static void
timer_set_diff(uint32_t value)
{
SysTick->LOAD = value;
SysTick->LOAD = value & SysTick_LOAD_RELOAD_Msk;
SysTick->VAL = 0;
SysTick->LOAD = 0;
}
@ -84,70 +67,16 @@ timer_read_time(void)
return TIM2->CNT;
}
static uint32_t timer_repeat_until;
#define TIMER_IDLE_REPEAT_TICKS timer_from_us(500)
#define TIMER_REPEAT_TICKS timer_from_us(100)
#define TIMER_MIN_TRY_TICKS timer_from_us(2)
#define TIMER_DEFER_REPEAT_TICKS timer_from_us(5)
// Invoke timers
static uint32_t
timer_dispatch_many(void)
{
uint32_t tru = timer_repeat_until;
for (;;) {
// Run the next software timer
uint32_t next = sched_timer_dispatch();
uint32_t now = timer_read_time();
int32_t diff = next - now;
if (diff > (int32_t)TIMER_MIN_TRY_TICKS)
// Schedule next timer normally.
return diff;
if (unlikely(timer_is_before(tru, now))) {
// Check if there are too many repeat timers
if (diff < (int32_t)(-timer_from_us(1000)))
try_shutdown("Rescheduled timer in the past");
if (sched_tasks_busy()) {
timer_repeat_until = now + TIMER_REPEAT_TICKS;
return TIMER_DEFER_REPEAT_TICKS;
}
timer_repeat_until = tru = now + TIMER_IDLE_REPEAT_TICKS;
}
// Next timer in the past or near future - wait for it to be ready
irq_enable();
while (unlikely(diff > 0))
diff = next - timer_read_time();
irq_disable();
}
}
// IRQ handler
void __visible __aligned(16) // aligning helps stabilize perf benchmarks
SysTick_Handler(void)
{
irq_disable();
uint32_t diff = timer_dispatch_many();
timer_set_diff(diff);
uint32_t next = timer_dispatch_many();
timer_set_diff(next-timer_read_time());
irq_enable();
}
// Make sure timer_repeat_until doesn't wrap 32bit comparisons
void
timer_task(void)
{
uint32_t now = timer_read_time();
irq_disable();
if (timer_is_before(timer_repeat_until, now))
timer_repeat_until = now;
irq_enable();
}
DECL_TASK(timer_task);
void TIM2_IRQHandler(void)
{
if(TIM2->SR & TIM_SR_UIF) {