Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
NuttX RTOS
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
f4grx
NuttX RTOS
Commits
d9d32ac8
Commit
d9d32ac8
authored
7 years ago
by
David Sidrane
Browse files
Options
Downloads
Patches
Plain Diff
samv7:twihs driver add reference counting
parent
d8da8135
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
arch/arm/src/samv7/sam_twihs.c
+41
-25
41 additions, 25 deletions
arch/arm/src/samv7/sam_twihs.c
with
41 additions
and
25 deletions
arch/arm/src/samv7/sam_twihs.c
+
41
−
25
View file @
d9d32ac8
...
...
@@ -151,7 +151,7 @@ struct twi_dev_s
struct
i2c_msg_s
*
msg
;
/* Message list */
uint32_t
twiclk
;
/* TWIHS input clock frequency */
uint32_t
frequency
;
/* TWIHS transfer clock frequency */
bool
initd
;
/*
True :device has been initialized
*/
int
refs
;
/*
Reference count
*/
uint8_t
msgc
;
/* Number of message in the message list */
sem_t
exclsem
;
/* Only one thread can access at a time */
...
...
@@ -1118,6 +1118,10 @@ static int twi_reset(FAR struct i2c_master_s *dev)
DEBUGASSERT
(
priv
!=
NULL
);
/* Our caller must own a ref */
DEBUGASSERT
(
priv
->
refs
>
0
);
/* Get exclusive access to the TWIHS device */
twi_takesem
(
&
priv
->
exclsem
);
...
...
@@ -1342,6 +1346,7 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus)
{
struct
twi_dev_s
*
priv
;
uint32_t
frequency
;
const
struct
twi_attr_s
*
attr
=
0
;
irqstate_t
flags
;
int
ret
;
...
...
@@ -1352,8 +1357,8 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus)
{
/* Select up TWIHS0 and setup invariant attributes */
priv
=
&
g_twi0
;
priv
->
attr
=
&
g_twi0attr
;
priv
=
&
g_twi0
;
attr
=
&
g_twi0attr
;
/* Select the (initial) TWIHS frequency */
...
...
@@ -1366,8 +1371,8 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus)
{
/* Select up TWIHS1 and setup invariant attributes */
priv
=
&
g_twi1
;
priv
->
attr
=
&
g_twi1attr
;
priv
=
&
g_twi1
;
attr
=
&
g_twi1attr
;
/* Select the (initial) TWIHS frequency */
...
...
@@ -1380,8 +1385,8 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus)
{
/* Select up TWIHS2 and setup invariant attributes */
priv
=
&
g_twi2
;
priv
->
attr
=
&
g_twi2attr
;
priv
=
&
g_twi2
;
attr
=
&
g_twi2attr
;
/* Select the (initial) TWIHS frequency */
...
...
@@ -1394,14 +1399,16 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus)
return
NULL
;
}
/* Perform one-time TWIHS initialization */
flags
=
enter_critical_section
();
/* Has the device already been initialized? */
if
(
!
priv
->
initd
)
if
(
(
volatile
int
)
priv
->
refs
++
==
0
)
{
/* Perform one-time TWIHS initialization */
priv
->
attr
=
attr
;
/* Allocate a watchdog timer */
priv
->
timeout
=
wd_create
();
...
...
@@ -1438,10 +1445,6 @@ struct i2c_master_s *sam_i2cbus_initialize(int bus)
/* Perform repeatable TWIHS hardware initialization */
twi_hw_initialize
(
priv
,
frequency
);
/* Now it has been initialized */
priv
->
initd
=
true
;
}
leave_critical_section
(
flags
);
...
...
@@ -1452,6 +1455,7 @@ errout_with_wdog:
priv
->
timeout
=
NULL
;
errout_with_irq:
priv
->
refs
--
;
leave_critical_section
(
flags
);
return
NULL
;
}
...
...
@@ -1469,28 +1473,40 @@ int sam_i2cbus_uninitialize(FAR struct i2c_master_s *dev)
struct
twi_dev_s
*
priv
=
(
struct
twi_dev_s
*
)
dev
;
irqstate_t
flags
;
i2cinfo
(
"TWIHS%d Un-initializing
\n
"
,
priv
->
attr
->
twi
);
DEBUGASSERT
(
priv
);
/* Decrement reference count and check for underflow */
if
(
priv
->
refs
==
0
)
{
return
ERROR
;
}
i2cinfo
(
"TWIHS%d Un-initializing refs:%d
\n
"
,
priv
->
attr
->
twi
,
priv
->
refs
);
/* Disable TWIHS interrupts */
flags
=
enter_critical_section
();
up_disable_irq
(
priv
->
attr
->
irq
);
/* Reset data structures */
if
(
--
priv
->
refs
==
0
)
{
up_disable_irq
(
priv
->
attr
->
irq
);
sem_destroy
(
&
priv
->
exclsem
);
sem_destroy
(
&
priv
->
waitsem
);
/* Reset data structures */
/* Free the watchdog timer */
sem_destroy
(
&
priv
->
exclsem
);
sem_destroy
(
&
priv
->
waitsem
);
wd_delete
(
priv
->
timeout
);
priv
->
timeout
=
NULL
;
/* Free the watchdog timer */
/* Detach Interrupt Handler */
wd_delete
(
priv
->
timeout
);
priv
->
timeout
=
NULL
;
(
void
)
irq_detach
(
priv
->
attr
->
irq
);
/* Detach Interrupt Handler */
(
void
)
irq_detach
(
priv
->
attr
->
irq
);
}
priv
->
initd
=
false
;
leave_critical_section
(
flags
);
return
OK
;
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment