Skip to content

fix #3863 Add an mbed API that allows the init of the CAN at the bus frequency #4165

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions drivers/CAN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ CAN::CAN(PinName rd, PinName td) : _can(), _irq() {
can_irq_init(&_can, (&CAN::_irq_handler), (uint32_t)this);
}

CAN::CAN(PinName rd, PinName td, int hz) : _can(), _irq() {
// No lock needed in constructor

for (int i = 0; i < sizeof _irq / sizeof _irq[0]; i++) {
_irq[i].attach(donothing);
}

can_init_freq(&_can, rd, td, hz);
can_irq_init(&_can, (&CAN::_irq_handler), (uint32_t)this);
}

CAN::~CAN() {
// No lock needed in destructor
can_irq_free(&_can);
Expand Down
9 changes: 9 additions & 0 deletions drivers/CAN.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ class CAN {
* @endcode
*/
CAN(PinName rd, PinName td);

/** Initialize CAN interface and set the frequency
*
* @param rd the rd pin
* @param td the td pin
* @param hz the bus frequency in hertz
*/
CAN(PinName rd, PinName td, int hz);

virtual ~CAN();

/** Set the frequency of the CAN interface
Expand Down
100 changes: 100 additions & 0 deletions features/unsupported/tests/mbed/can_api/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add license header to this file

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I will.
(by the way there are no license headers anywhere in unsupported/tests/mbed directory)

#include "test_env.h"

#if !DEVICE_CAN
#error [NOT_SUPPORTED] CAN not supported
#endif

#if defined(TARGET_LPC1549)
#define CAN_RD D9
#define CAN_TD D8
#elif defined(TARGET_LPC1768) || defined(TARGET_LPC4088)
#define CAN_RD p9
#define CAN_TD p10
#elif defined(TARGET_B96B_F446VE)
#define CAN_RD PD_0
#define CAN_TD PD_1
#elif defined(TARGET_VK_RZ_A1H)
#define CAN_RD P5_9
#define CAN_TD P5_10
#elif defined(TARGET_NUCLEO_F042K6) || \
defined(TARGET_NUCLEO_F072RB) || \
defined(TARGET_NUCLEO_F091RC) || \
defined(TARGET_NUCLEO_F302R8) || \
defined(TARGET_NUCLEO_F303RE) || \
defined(TARGET_NUCLEO_F303K8) || \
defined(TARGET_NUCLEO_F334R8) || \
defined(TARGET_NUCLEO_F412ZG) || \
defined(TARGET_DISCO_F429ZI) || \
defined(TARGET_NUCLEO_F446RE) || \
defined(TARGET_NUCLEO_F746ZG) || \
defined(TARGET_NUCLEO_L432KC) || \
defined(TARGET_DISCO_L476VG) || \
defined(TARGET_NUCLEO_L476RG)
#define CAN_RD PA_11
#define CAN_TD PA_12
#elif defined(TARGET_NUCLEO_F103RB) || \
defined(TARGET_NUCLEO_F207ZG) || \
defined(TARGET_DISCO_F303VC) || \
defined(TARGET_NUCLEO_F303ZE) || \
defined(TARGET_NUCLEO_F412ZG) || \
defined(TARGET_NUCLEO_F429ZI) || \
defined(TARGET_NUCLEO_F439ZI) || \
defined(TARGET_NUCLEO_F446ZE) || \
defined(TARGET_DISCO_F469NI) || \
defined(TARGET_DISCO_F746NG) || \
defined(TARGET_NUCLEO_F756ZG) || \
defined(TARGET_NUCLEO_F767ZI) || \
defined(TARGET_DISCO_F769NI) || \
defined(TARGET_NUCLEO_L486RG)
#define CAN_RD PB_8
#define CAN_TD PB_9
#endif

int result = true;

void Check_CAN_Frequency(int CanFrequency)
{
printf("Init CAN at %d Hz\n", CanFrequency);

CAN can_object(CAN_RD, CAN_TD, CanFrequency);

#if !defined(TARGET_VK_RZ_A1H)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this exclusion ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi
It is a copy from can_loopback test...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is inherited from test/mbed/can_loopback/main.cpp (ie MBED_A27)
We don't have the material to test it, we did not want to take the responsibility of removing a code we don't know.
Cheers

can_object.mode(CAN::Reset);
#endif

if (!can_object.mode(CAN::LocalTest)) {
printf("CAN MODE_TEST_LOCAL failed\n");
result = false;
}
}

int main()
{
MBED_HOSTTEST_TIMEOUT(20);
MBED_HOSTTEST_SELECT(dev_null);
MBED_HOSTTEST_DESCRIPTION(CAN API at different frequency);
MBED_HOSTTEST_START("MBED_A30");

const int frequency_table[] = {10000, 50000, 100000, 500000, 1000000};
for (uint32_t i = 0; i < sizeof(frequency_table)/sizeof(int); i++) {
Check_CAN_Frequency(frequency_table[i]);
}

MBED_HOSTTEST_RESULT(result);
}
7 changes: 4 additions & 3 deletions hal/can_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ typedef void (*can_irq_handler)(uint32_t id, CanIrqType type);

typedef struct can_s can_t;

void can_init (can_t *obj, PinName rd, PinName td);
void can_free (can_t *obj);
int can_frequency(can_t *obj, int hz);
void can_init (can_t *obj, PinName rd, PinName td);
void can_init_freq (can_t *obj, PinName rd, PinName td, int hz);
void can_free (can_t *obj);
int can_frequency (can_t *obj, int hz);

void can_irq_init (can_t *obj, can_irq_handler handler, uint32_t id);
void can_irq_free (can_t *obj);
Expand Down
16 changes: 11 additions & 5 deletions targets/TARGET_NUVOTON/TARGET_M451/can_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
};


void can_init(can_t *obj, PinName rd, PinName td)
{
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
{
uint32_t can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
uint32_t can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
obj->can = (CANName)pinmap_merge(can_td, can_rd);
Expand All @@ -69,12 +69,18 @@
PA0 = 0x00;
PA1 = 0x00;

CAN_Open((CAN_T *)NU_MODBASE(obj->can), 500000, CAN_NORMAL_MODE);
CAN_Open((CAN_T *)NU_MODBASE(obj->can), hz, CAN_NORMAL_MODE);

can_filter(obj, 0, 0, CANStandard, 0);
}




void can_init(can_t *obj, PinName rd, PinName td)
{
can_init_freq(obj, rd, td, 500000);
}


void can_free(can_t *obj)
{

Expand Down
16 changes: 11 additions & 5 deletions targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
};

void can_init(can_t *obj, PinName rd, PinName td)

void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
{
uint32_t can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
uint32_t can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
Expand Down Expand Up @@ -75,12 +75,18 @@
PA2 = 0x00;
PA3 = 0x00;

CAN_Open((CAN_T *)NU_MODBASE(obj->can), 500000, CAN_NORMAL_MODE);
CAN_Open((CAN_T *)NU_MODBASE(obj->can), hz, CAN_NORMAL_MODE);

can_filter(obj, 0, 0, CANStandard, 0);
}




void can_init(can_t *obj, PinName rd, PinName td)
{
can_init_freq(obj, rd, td, 500000);
}


void can_free(can_t *obj)
{

Expand Down
16 changes: 10 additions & 6 deletions targets/TARGET_NXP/TARGET_LPC11XX_11CXX/TARGET_LPC11CXX/can_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,26 +268,30 @@ int can_config_rxmsgobj(can_t *obj) {
}


void can_init(can_t *obj, PinName rd, PinName td) {
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
// Enable power and clock
LPC_SYSCON->PRESETCTRL |= PRESETCTRL_CAN_RST_N;
LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_CAN;

// Enable Initialization mode
if (!(LPC_CAN->CNTL & CANCNTL_INIT)) {
LPC_CAN->CNTL |= CANCNTL_INIT;
}
can_frequency(obj, 125000);

can_frequency(obj, hz);

// Resume operation
LPC_CAN->CNTL &= ~CANCNTL_INIT;
while ( LPC_CAN->CNTL & CANCNTL_INIT );

// Initialize RX message object
can_config_rxmsgobj(obj);
}

void can_init(can_t *obj, PinName rd, PinName td) {
can_init_freq(obj, rd, td, 125000);
}

void can_free(can_t *obj) {
LPC_SYSCON->SYSAHBCLKCTRL &= ~(SYSAHBCLKCTRL_CAN);
LPC_SYSCON->PRESETCTRL &= ~(PRESETCTRL_CAN_RST_N);
Expand Down
9 changes: 6 additions & 3 deletions targets/TARGET_NXP/TARGET_LPC15XX/can_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,7 @@ int can_config_txmsgobj(can_t *obj) {
return 1;
}


void can_init(can_t *obj, PinName rd, PinName td) {
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
// Enable power and clock
LPC_SYSCON->SYSAHBCLKCTRL1 |= (1UL << 7);
LPC_SYSCON->PRESETCTRL1 |= (1UL << 7);
Expand All @@ -430,7 +429,7 @@ void can_init(can_t *obj, PinName rd, PinName td) {
LPC_SWM->PINASSIGN[6] &= ~(0x00FFFF00L);
LPC_SWM->PINASSIGN[6] |= (rd << 16) | (td << 8);

can_frequency(obj, 100000);
can_frequency(obj, hz);

// Resume operation
LPC_C_CAN0->CANCNTL &= ~(1UL << 0);
Expand All @@ -442,6 +441,10 @@ void can_init(can_t *obj, PinName rd, PinName td) {
can_config_txmsgobj(obj);
}

void can_init(can_t *obj, PinName rd, PinName td) {
can_init_freq(obj, rd, td, 100000);
}

void can_free(can_t *obj) {
LPC_SYSCON->SYSAHBCLKCTRL1 &= ~(1UL << 7);
LPC_SYSCON->PRESETCTRL1 &= ~(1UL << 7);
Expand Down
8 changes: 6 additions & 2 deletions targets/TARGET_NXP/TARGET_LPC176X/can_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ static unsigned int can_speed(unsigned int sclk, unsigned int pclk, unsigned int

}

void can_init(can_t *obj, PinName rd, PinName td) {
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
Expand All @@ -313,11 +313,15 @@ void can_init(can_t *obj, PinName rd, PinName td) {

can_reset(obj);
obj->dev->IER = 0; // Disable Interrupts
can_frequency(obj, 100000);
can_frequency(obj, hz);

LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
}

void can_init(can_t *obj, PinName rd, PinName td) {
can_init_freq(obj, rd, td, 100000);
}

void can_free(can_t *obj) {
switch ((int)obj->dev) {
case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;
Expand Down
12 changes: 8 additions & 4 deletions targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088/can_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ static unsigned int can_speed(unsigned int pclk, unsigned int cclk, unsigned cha

}

void can_init(can_t *obj, PinName rd, PinName td) {
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
Expand All @@ -252,19 +252,23 @@ void can_init(can_t *obj, PinName rd, PinName td) {

pinmap_pinout(rd, PinMap_CAN_RD);
pinmap_pinout(td, PinMap_CAN_TD);

switch ((int)obj->dev) {
case CAN_1: obj->index = 0; break;
case CAN_2: obj->index = 1; break;
}

can_reset(obj);
obj->dev->IER = 0; // Disable Interrupts
can_frequency(obj, 100000);
can_frequency(obj, hz);

LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
}

void can_init(can_t *obj, PinName rd, PinName td) {
can_init_freq(obj, rd, td, 100000);
}

void can_free(can_t *obj) {
switch ((int)obj->dev) {
case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;
Expand Down
8 changes: 6 additions & 2 deletions targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088_DM/can_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ static unsigned int can_speed(unsigned int pclk, unsigned int cclk, unsigned cha

}

void can_init(can_t *obj, PinName rd, PinName td) {
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
obj->dev = (LPC_CAN_TypeDef *)pinmap_merge(can_rd, can_td);
Expand All @@ -257,11 +257,15 @@ void can_init(can_t *obj, PinName rd, PinName td) {

can_reset(obj);
obj->dev->IER = 0; // Disable Interrupts
can_frequency(obj, 100000);
can_frequency(obj, hz);

LPC_CANAF->AFMR = ACCF_BYPASS; // Bypass Filter
}

void can_init(can_t *obj, PinName rd, PinName td) {
can_init_freq(obj, rd, td, 100000);
}

void can_free(can_t *obj) {
switch ((int)obj->dev) {
case CAN_1: LPC_SC->PCONP &= ~(1 << 13); break;
Expand Down
9 changes: 8 additions & 1 deletion targets/TARGET_RENESAS/TARGET_RZ_A1H/can_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ static void can4_bus_err_irq(void) {
can_err_irq(CAN_4, IRQ_BUS);
}

void can_init(can_t *obj, PinName rd, PinName td) {
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
__IO uint32_t *dmy_ctr;

/* determine the CAN to use */
Expand Down Expand Up @@ -573,6 +573,13 @@ void can_init(can_t *obj, PinName rd, PinName td) {
/* pin out the can pins */
pinmap_pinout(rd, PinMap_CAN_RD);
pinmap_pinout(td, PinMap_CAN_TD);

/* set can frequency */
can_frequency(obj, hz);
}

void can_init(can_t *obj, PinName rd, PinName td) {
can_init_freq(obj, rd, td, 100000);
}

void can_free(can_t *obj) {
Expand Down
Loading